1 /* $NetBSD: procfs_vnops.c,v 1.106 2003/06/29 22:31:47 fvdl Exp $ */ 2 3 /* 4 * Copyright (c) 1993 Jan-Simon Pendry 5 * Copyright (c) 1993, 1995 6 * The Regents of the University of California. All rights reserved. 7 * 8 * This code is derived from software contributed to Berkeley by 9 * Jan-Simon Pendry. 10 * 11 * Redistribution and use in source and binary forms, with or without 12 * modification, are permitted provided that the following conditions 13 * are met: 14 * 1. Redistributions of source code must retain the above copyright 15 * notice, this list of conditions and the following disclaimer. 16 * 2. Redistributions in binary form must reproduce the above copyright 17 * notice, this list of conditions and the following disclaimer in the 18 * documentation and/or other materials provided with the distribution. 19 * 3. All advertising materials mentioning features or use of this software 20 * must display the following acknowledgement: 21 * This product includes software developed by the University of 22 * California, Berkeley and its contributors. 23 * 4. Neither the name of the University nor the names of its contributors 24 * may be used to endorse or promote products derived from this software 25 * without specific prior written permission. 26 * 27 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 28 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 29 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 30 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 31 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 32 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 33 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 34 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 35 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 36 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 37 * SUCH DAMAGE. 38 * 39 * @(#)procfs_vnops.c 8.18 (Berkeley) 5/21/95 40 */ 41 42 /* 43 * procfs vnode interface 44 */ 45 46 #include <sys/cdefs.h> 47 __KERNEL_RCSID(0, "$NetBSD: procfs_vnops.c,v 1.106 2003/06/29 22:31:47 fvdl Exp $"); 48 49 #include <sys/param.h> 50 #include <sys/systm.h> 51 #include <sys/time.h> 52 #include <sys/kernel.h> 53 #include <sys/file.h> 54 #include <sys/filedesc.h> 55 #include <sys/proc.h> 56 #include <sys/vnode.h> 57 #include <sys/namei.h> 58 #include <sys/malloc.h> 59 #include <sys/mount.h> 60 #include <sys/dirent.h> 61 #include <sys/resourcevar.h> 62 #include <sys/stat.h> 63 #include <sys/ptrace.h> 64 65 #include <uvm/uvm_extern.h> /* for PAGE_SIZE */ 66 67 #include <machine/reg.h> 68 69 #include <miscfs/genfs/genfs.h> 70 #include <miscfs/procfs/procfs.h> 71 72 /* 73 * Vnode Operations. 74 * 75 */ 76 77 static int procfs_validfile_linux __P((struct proc *, struct mount *)); 78 79 /* 80 * This is a list of the valid names in the 81 * process-specific sub-directories. It is 82 * used in procfs_lookup and procfs_readdir 83 */ 84 static const struct proc_target { 85 u_char pt_type; 86 u_char pt_namlen; 87 const char *pt_name; 88 pfstype pt_pfstype; 89 int (*pt_valid) __P((struct proc *, struct mount *)); 90 } proc_targets[] = { 91 #define N(s) sizeof(s)-1, s 92 /* name type validp */ 93 { DT_DIR, N("."), Pproc, NULL }, 94 { DT_DIR, N(".."), Proot, NULL }, 95 { DT_DIR, N("fd"), Pfd, NULL }, 96 { DT_REG, N("file"), Pfile, procfs_validfile }, 97 { DT_REG, N("mem"), Pmem, NULL }, 98 { DT_REG, N("regs"), Pregs, procfs_validregs }, 99 { DT_REG, N("fpregs"), Pfpregs, procfs_validfpregs }, 100 { DT_REG, N("ctl"), Pctl, NULL }, 101 { DT_REG, N("stat"), Pstat, procfs_validfile_linux }, 102 { DT_REG, N("status"), Pstatus, NULL }, 103 { DT_REG, N("note"), Pnote, NULL }, 104 { DT_REG, N("notepg"), Pnotepg, NULL }, 105 { DT_REG, N("map"), Pmap, procfs_validmap }, 106 { DT_REG, N("maps"), Pmaps, procfs_validmap }, 107 { DT_REG, N("cmdline"), Pcmdline, NULL }, 108 { DT_REG, N("exe"), Pfile, procfs_validfile_linux }, 109 #ifdef __HAVE_PROCFS_MACHDEP 110 PROCFS_MACHDEP_NODETYPE_DEFNS 111 #endif 112 #undef N 113 }; 114 static const int nproc_targets = sizeof(proc_targets) / sizeof(proc_targets[0]); 115 116 /* 117 * List of files in the root directory. Note: the validate function will 118 * be called with p == NULL for these ones. 119 */ 120 static const struct proc_target proc_root_targets[] = { 121 #define N(s) sizeof(s)-1, s 122 /* name type validp */ 123 { DT_REG, N("meminfo"), Pmeminfo, procfs_validfile_linux }, 124 { DT_REG, N("cpuinfo"), Pcpuinfo, procfs_validfile_linux }, 125 { DT_REG, N("uptime"), Puptime, procfs_validfile_linux }, 126 #undef N 127 }; 128 static const int nproc_root_targets = 129 sizeof(proc_root_targets) / sizeof(proc_root_targets[0]); 130 131 int procfs_lookup __P((void *)); 132 #define procfs_create genfs_eopnotsupp 133 #define procfs_mknod genfs_eopnotsupp 134 int procfs_open __P((void *)); 135 int procfs_close __P((void *)); 136 int procfs_access __P((void *)); 137 int procfs_getattr __P((void *)); 138 int procfs_setattr __P((void *)); 139 #define procfs_read procfs_rw 140 #define procfs_write procfs_rw 141 #define procfs_fcntl genfs_fcntl 142 #define procfs_ioctl genfs_enoioctl 143 #define procfs_poll genfs_poll 144 #define procfs_revoke genfs_revoke 145 #define procfs_fsync genfs_nullop 146 #define procfs_seek genfs_nullop 147 #define procfs_remove genfs_eopnotsupp 148 int procfs_link __P((void *)); 149 #define procfs_rename genfs_eopnotsupp 150 #define procfs_mkdir genfs_eopnotsupp 151 #define procfs_rmdir genfs_eopnotsupp 152 int procfs_symlink __P((void *)); 153 int procfs_readdir __P((void *)); 154 int procfs_readlink __P((void *)); 155 #define procfs_abortop genfs_abortop 156 int procfs_inactive __P((void *)); 157 int procfs_reclaim __P((void *)); 158 #define procfs_lock genfs_lock 159 #define procfs_unlock genfs_unlock 160 #define procfs_bmap genfs_badop 161 #define procfs_strategy genfs_badop 162 int procfs_print __P((void *)); 163 int procfs_pathconf __P((void *)); 164 #define procfs_islocked genfs_islocked 165 #define procfs_advlock genfs_einval 166 #define procfs_blkatoff genfs_eopnotsupp 167 #define procfs_valloc genfs_eopnotsupp 168 #define procfs_vfree genfs_nullop 169 #define procfs_truncate genfs_eopnotsupp 170 #define procfs_update genfs_nullop 171 #define procfs_bwrite genfs_eopnotsupp 172 #define procfs_putpages genfs_null_putpages 173 174 static int atoi __P((const char *, size_t)); 175 176 /* 177 * procfs vnode operations. 178 */ 179 int (**procfs_vnodeop_p) __P((void *)); 180 const struct vnodeopv_entry_desc procfs_vnodeop_entries[] = { 181 { &vop_default_desc, vn_default_error }, 182 { &vop_lookup_desc, procfs_lookup }, /* lookup */ 183 { &vop_create_desc, procfs_create }, /* create */ 184 { &vop_mknod_desc, procfs_mknod }, /* mknod */ 185 { &vop_open_desc, procfs_open }, /* open */ 186 { &vop_close_desc, procfs_close }, /* close */ 187 { &vop_access_desc, procfs_access }, /* access */ 188 { &vop_getattr_desc, procfs_getattr }, /* getattr */ 189 { &vop_setattr_desc, procfs_setattr }, /* setattr */ 190 { &vop_read_desc, procfs_read }, /* read */ 191 { &vop_write_desc, procfs_write }, /* write */ 192 { &vop_fcntl_desc, procfs_fcntl }, /* fcntl */ 193 { &vop_ioctl_desc, procfs_ioctl }, /* ioctl */ 194 { &vop_poll_desc, procfs_poll }, /* poll */ 195 { &vop_revoke_desc, procfs_revoke }, /* revoke */ 196 { &vop_fsync_desc, procfs_fsync }, /* fsync */ 197 { &vop_seek_desc, procfs_seek }, /* seek */ 198 { &vop_remove_desc, procfs_remove }, /* remove */ 199 { &vop_link_desc, procfs_link }, /* link */ 200 { &vop_rename_desc, procfs_rename }, /* rename */ 201 { &vop_mkdir_desc, procfs_mkdir }, /* mkdir */ 202 { &vop_rmdir_desc, procfs_rmdir }, /* rmdir */ 203 { &vop_symlink_desc, procfs_symlink }, /* symlink */ 204 { &vop_readdir_desc, procfs_readdir }, /* readdir */ 205 { &vop_readlink_desc, procfs_readlink }, /* readlink */ 206 { &vop_abortop_desc, procfs_abortop }, /* abortop */ 207 { &vop_inactive_desc, procfs_inactive }, /* inactive */ 208 { &vop_reclaim_desc, procfs_reclaim }, /* reclaim */ 209 { &vop_lock_desc, procfs_lock }, /* lock */ 210 { &vop_unlock_desc, procfs_unlock }, /* unlock */ 211 { &vop_bmap_desc, procfs_bmap }, /* bmap */ 212 { &vop_strategy_desc, procfs_strategy }, /* strategy */ 213 { &vop_print_desc, procfs_print }, /* print */ 214 { &vop_islocked_desc, procfs_islocked }, /* islocked */ 215 { &vop_pathconf_desc, procfs_pathconf }, /* pathconf */ 216 { &vop_advlock_desc, procfs_advlock }, /* advlock */ 217 { &vop_blkatoff_desc, procfs_blkatoff }, /* blkatoff */ 218 { &vop_valloc_desc, procfs_valloc }, /* valloc */ 219 { &vop_vfree_desc, procfs_vfree }, /* vfree */ 220 { &vop_truncate_desc, procfs_truncate }, /* truncate */ 221 { &vop_update_desc, procfs_update }, /* update */ 222 { &vop_putpages_desc, procfs_putpages }, /* putpages */ 223 { NULL, NULL } 224 }; 225 const struct vnodeopv_desc procfs_vnodeop_opv_desc = 226 { &procfs_vnodeop_p, procfs_vnodeop_entries }; 227 /* 228 * set things up for doing i/o on 229 * the pfsnode (vp). (vp) is locked 230 * on entry, and should be left locked 231 * on exit. 232 * 233 * for procfs we don't need to do anything 234 * in particular for i/o. all that is done 235 * is to support exclusive open on process 236 * memory images. 237 */ 238 int 239 procfs_open(v) 240 void *v; 241 { 242 struct vop_open_args /* { 243 struct vnode *a_vp; 244 int a_mode; 245 struct ucred *a_cred; 246 struct proc *a_p; 247 } */ *ap = v; 248 struct pfsnode *pfs = VTOPFS(ap->a_vp); 249 struct proc *p1, *p2; 250 int error; 251 252 p1 = ap->a_p; /* tracer */ 253 p2 = PFIND(pfs->pfs_pid); /* traced */ 254 255 if (p2 == NULL) 256 return (ENOENT); /* was ESRCH, jsp */ 257 258 switch (pfs->pfs_type) { 259 case Pmem: 260 if (((pfs->pfs_flags & FWRITE) && (ap->a_mode & O_EXCL)) || 261 ((pfs->pfs_flags & O_EXCL) && (ap->a_mode & FWRITE))) 262 return (EBUSY); 263 264 if ((error = process_checkioperm(p1, p2)) != 0) 265 return (error); 266 267 if (ap->a_mode & FWRITE) 268 pfs->pfs_flags = ap->a_mode & (FWRITE|O_EXCL); 269 270 return (0); 271 272 default: 273 break; 274 } 275 276 return (0); 277 } 278 279 /* 280 * close the pfsnode (vp) after doing i/o. 281 * (vp) is not locked on entry or exit. 282 * 283 * nothing to do for procfs other than undo 284 * any exclusive open flag (see _open above). 285 */ 286 int 287 procfs_close(v) 288 void *v; 289 { 290 struct vop_close_args /* { 291 struct vnode *a_vp; 292 int a_fflag; 293 struct ucred *a_cred; 294 struct proc *a_p; 295 } */ *ap = v; 296 struct pfsnode *pfs = VTOPFS(ap->a_vp); 297 298 switch (pfs->pfs_type) { 299 case Pmem: 300 if ((ap->a_fflag & FWRITE) && (pfs->pfs_flags & O_EXCL)) 301 pfs->pfs_flags &= ~(FWRITE|O_EXCL); 302 break; 303 304 default: 305 break; 306 } 307 308 return (0); 309 } 310 311 /* 312 * _inactive is called when the pfsnode 313 * is vrele'd and the reference count goes 314 * to zero. (vp) will be on the vnode free 315 * list, so to get it back vget() must be 316 * used. 317 * 318 * for procfs, check if the process is still 319 * alive and if it isn't then just throw away 320 * the vnode by calling vgone(). this may 321 * be overkill and a waste of time since the 322 * chances are that the process will still be 323 * there and PFIND is not free. 324 * 325 * (vp) is locked on entry, but must be unlocked on exit. 326 */ 327 int 328 procfs_inactive(v) 329 void *v; 330 { 331 struct vop_inactive_args /* { 332 struct vnode *a_vp; 333 struct proc *a_p; 334 } */ *ap = v; 335 struct pfsnode *pfs = VTOPFS(ap->a_vp); 336 337 VOP_UNLOCK(ap->a_vp, 0); 338 if (PFIND(pfs->pfs_pid) == NULL) 339 vgone(ap->a_vp); 340 341 return (0); 342 } 343 344 /* 345 * _reclaim is called when getnewvnode() 346 * wants to make use of an entry on the vnode 347 * free list. at this time the filesystem needs 348 * to free any private data and remove the node 349 * from any private lists. 350 */ 351 int 352 procfs_reclaim(v) 353 void *v; 354 { 355 struct vop_reclaim_args /* { 356 struct vnode *a_vp; 357 } */ *ap = v; 358 359 return (procfs_freevp(ap->a_vp)); 360 } 361 362 /* 363 * Return POSIX pathconf information applicable to special devices. 364 */ 365 int 366 procfs_pathconf(v) 367 void *v; 368 { 369 struct vop_pathconf_args /* { 370 struct vnode *a_vp; 371 int a_name; 372 register_t *a_retval; 373 } */ *ap = v; 374 375 switch (ap->a_name) { 376 case _PC_LINK_MAX: 377 *ap->a_retval = LINK_MAX; 378 return (0); 379 case _PC_MAX_CANON: 380 *ap->a_retval = MAX_CANON; 381 return (0); 382 case _PC_MAX_INPUT: 383 *ap->a_retval = MAX_INPUT; 384 return (0); 385 case _PC_PIPE_BUF: 386 *ap->a_retval = PIPE_BUF; 387 return (0); 388 case _PC_CHOWN_RESTRICTED: 389 *ap->a_retval = 1; 390 return (0); 391 case _PC_VDISABLE: 392 *ap->a_retval = _POSIX_VDISABLE; 393 return (0); 394 case _PC_SYNC_IO: 395 *ap->a_retval = 1; 396 return (0); 397 default: 398 return (EINVAL); 399 } 400 /* NOTREACHED */ 401 } 402 403 /* 404 * _print is used for debugging. 405 * just print a readable description 406 * of (vp). 407 */ 408 int 409 procfs_print(v) 410 void *v; 411 { 412 struct vop_print_args /* { 413 struct vnode *a_vp; 414 } */ *ap = v; 415 struct pfsnode *pfs = VTOPFS(ap->a_vp); 416 417 printf("tag VT_PROCFS, type %d, pid %d, mode %x, flags %lx\n", 418 pfs->pfs_type, pfs->pfs_pid, pfs->pfs_mode, pfs->pfs_flags); 419 return 0; 420 } 421 422 int 423 procfs_link(v) 424 void *v; 425 { 426 struct vop_link_args /* { 427 struct vnode *a_dvp; 428 struct vnode *a_vp; 429 struct componentname *a_cnp; 430 } */ *ap = v; 431 432 VOP_ABORTOP(ap->a_dvp, ap->a_cnp); 433 vput(ap->a_dvp); 434 return (EROFS); 435 } 436 437 int 438 procfs_symlink(v) 439 void *v; 440 { 441 struct vop_symlink_args /* { 442 struct vnode *a_dvp; 443 struct vnode **a_vpp; 444 struct componentname *a_cnp; 445 struct vattr *a_vap; 446 char *a_target; 447 } */ *ap = v; 448 449 VOP_ABORTOP(ap->a_dvp, ap->a_cnp); 450 vput(ap->a_dvp); 451 return (EROFS); 452 } 453 454 /* 455 * Invent attributes for pfsnode (vp) and store 456 * them in (vap). 457 * Directories lengths are returned as zero since 458 * any real length would require the genuine size 459 * to be computed, and nothing cares anyway. 460 * 461 * this is relatively minimal for procfs. 462 */ 463 int 464 procfs_getattr(v) 465 void *v; 466 { 467 struct vop_getattr_args /* { 468 struct vnode *a_vp; 469 struct vattr *a_vap; 470 struct ucred *a_cred; 471 struct proc *a_p; 472 } */ *ap = v; 473 struct pfsnode *pfs = VTOPFS(ap->a_vp); 474 struct vattr *vap = ap->a_vap; 475 struct proc *procp; 476 int error; 477 478 /* first check the process still exists */ 479 switch (pfs->pfs_type) { 480 case Proot: 481 case Pcurproc: 482 case Pself: 483 procp = 0; 484 break; 485 486 default: 487 procp = PFIND(pfs->pfs_pid); 488 if (procp == NULL) 489 return (ENOENT); 490 break; 491 } 492 493 error = 0; 494 495 /* start by zeroing out the attributes */ 496 VATTR_NULL(vap); 497 498 /* next do all the common fields */ 499 vap->va_type = ap->a_vp->v_type; 500 vap->va_mode = pfs->pfs_mode; 501 vap->va_fileid = pfs->pfs_fileno; 502 vap->va_flags = 0; 503 vap->va_blocksize = PAGE_SIZE; 504 505 /* 506 * Make all times be current TOD. Avoid microtime(9), it's slow. 507 * We don't guard the read from time(9) with splclock(9) since we 508 * don't actually need to be THAT sure the access is atomic. 509 * 510 * It would be possible to get the process start 511 * time from the p_stat structure, but there's 512 * no "file creation" time stamp anyway, and the 513 * p_stat structure is not addressible if u. gets 514 * swapped out for that process. 515 */ 516 TIMEVAL_TO_TIMESPEC(&time, &vap->va_ctime); 517 vap->va_atime = vap->va_mtime = vap->va_ctime; 518 519 switch (pfs->pfs_type) { 520 case Pmem: 521 case Pregs: 522 case Pfpregs: 523 #if defined(__HAVE_PROCFS_MACHDEP) && defined(PROCFS_MACHDEP_PROTECT_CASES) 524 PROCFS_MACHDEP_PROTECT_CASES 525 #endif 526 /* 527 * If the process has exercised some setuid or setgid 528 * privilege, then rip away read/write permission so 529 * that only root can gain access. 530 */ 531 if (procp->p_flag & P_SUGID) 532 vap->va_mode &= ~(S_IRUSR|S_IWUSR); 533 /* FALLTHROUGH */ 534 case Pctl: 535 case Pstatus: 536 case Pstat: 537 case Pnote: 538 case Pnotepg: 539 case Pmap: 540 case Pmaps: 541 case Pcmdline: 542 vap->va_nlink = 1; 543 vap->va_uid = procp->p_ucred->cr_uid; 544 vap->va_gid = procp->p_ucred->cr_gid; 545 break; 546 case Pmeminfo: 547 case Pcpuinfo: 548 case Puptime: 549 vap->va_nlink = 1; 550 vap->va_uid = vap->va_gid = 0; 551 break; 552 553 default: 554 break; 555 } 556 557 /* 558 * now do the object specific fields 559 * 560 * The size could be set from struct reg, but it's hardly 561 * worth the trouble, and it puts some (potentially) machine 562 * dependent data into this machine-independent code. If it 563 * becomes important then this function should break out into 564 * a per-file stat function in the corresponding .c file. 565 */ 566 567 switch (pfs->pfs_type) { 568 case Proot: 569 /* 570 * Set nlink to 1 to tell fts(3) we don't actually know. 571 */ 572 vap->va_nlink = 1; 573 vap->va_uid = 0; 574 vap->va_gid = 0; 575 vap->va_bytes = vap->va_size = DEV_BSIZE; 576 break; 577 578 case Pcurproc: { 579 char buf[16]; /* should be enough */ 580 vap->va_nlink = 1; 581 vap->va_uid = 0; 582 vap->va_gid = 0; 583 vap->va_bytes = vap->va_size = 584 sprintf(buf, "%ld", (long)curproc->p_pid); 585 break; 586 } 587 588 case Pself: 589 vap->va_nlink = 1; 590 vap->va_uid = 0; 591 vap->va_gid = 0; 592 vap->va_bytes = vap->va_size = sizeof("curproc"); 593 break; 594 595 case Pfd: 596 if (pfs->pfs_fd != -1) { 597 struct file *fp; 598 struct proc *pown; 599 600 if ((error = procfs_getfp(pfs, &pown, &fp)) != 0) 601 return error; 602 FILE_USE(fp); 603 vap->va_nlink = 1; 604 vap->va_uid = fp->f_cred->cr_uid; 605 vap->va_gid = fp->f_cred->cr_gid; 606 switch (fp->f_type) { 607 case DTYPE_VNODE: 608 vap->va_bytes = vap->va_size = 609 ((struct vnode *)fp->f_data)->v_size; 610 break; 611 default: 612 vap->va_bytes = vap->va_size = 0; 613 break; 614 } 615 FILE_UNUSE(fp, pown); 616 break; 617 } 618 /*FALLTHROUGH*/ 619 case Pproc: 620 vap->va_nlink = 2; 621 vap->va_uid = procp->p_ucred->cr_uid; 622 vap->va_gid = procp->p_ucred->cr_gid; 623 vap->va_bytes = vap->va_size = DEV_BSIZE; 624 break; 625 626 case Pfile: 627 error = EOPNOTSUPP; 628 break; 629 630 case Pmem: 631 vap->va_bytes = vap->va_size = 632 ctob(procp->p_vmspace->vm_tsize + 633 procp->p_vmspace->vm_dsize + 634 procp->p_vmspace->vm_ssize); 635 break; 636 637 #if defined(PT_GETREGS) || defined(PT_SETREGS) 638 case Pregs: 639 vap->va_bytes = vap->va_size = sizeof(struct reg); 640 break; 641 #endif 642 643 #if defined(PT_GETFPREGS) || defined(PT_SETFPREGS) 644 case Pfpregs: 645 vap->va_bytes = vap->va_size = sizeof(struct fpreg); 646 break; 647 #endif 648 649 case Pctl: 650 case Pstatus: 651 case Pstat: 652 case Pnote: 653 case Pnotepg: 654 case Pcmdline: 655 case Pmeminfo: 656 case Pcpuinfo: 657 case Puptime: 658 vap->va_bytes = vap->va_size = 0; 659 break; 660 case Pmap: 661 case Pmaps: 662 /* 663 * Advise a larger blocksize for the map files, so that 664 * they may be read in one pass. 665 */ 666 vap->va_blocksize = 4 * PAGE_SIZE; 667 vap->va_bytes = vap->va_size = 0; 668 break; 669 670 #ifdef __HAVE_PROCFS_MACHDEP 671 PROCFS_MACHDEP_NODETYPE_CASES 672 error = procfs_machdep_getattr(ap->a_vp, vap, procp); 673 break; 674 #endif 675 676 default: 677 panic("procfs_getattr"); 678 } 679 680 return (error); 681 } 682 683 /*ARGSUSED*/ 684 int 685 procfs_setattr(v) 686 void *v; 687 { 688 /* 689 * just fake out attribute setting 690 * it's not good to generate an error 691 * return, otherwise things like creat() 692 * will fail when they try to set the 693 * file length to 0. worse, this means 694 * that echo $note > /proc/$pid/note will fail. 695 */ 696 697 return (0); 698 } 699 700 /* 701 * implement access checking. 702 * 703 * actually, the check for super-user is slightly 704 * broken since it will allow read access to write-only 705 * objects. this doesn't cause any particular trouble 706 * but does mean that the i/o entry points need to check 707 * that the operation really does make sense. 708 */ 709 int 710 procfs_access(v) 711 void *v; 712 { 713 struct vop_access_args /* { 714 struct vnode *a_vp; 715 int a_mode; 716 struct ucred *a_cred; 717 struct proc *a_p; 718 } */ *ap = v; 719 struct vattr va; 720 int error; 721 722 if ((error = VOP_GETATTR(ap->a_vp, &va, ap->a_cred, ap->a_p)) != 0) 723 return (error); 724 725 return (vaccess(va.va_type, va.va_mode, 726 va.va_uid, va.va_gid, ap->a_mode, ap->a_cred)); 727 } 728 729 /* 730 * lookup. this is incredibly complicated in the 731 * general case, however for most pseudo-filesystems 732 * very little needs to be done. 733 * 734 * Locking isn't hard here, just poorly documented. 735 * 736 * If we're looking up ".", just vref the parent & return it. 737 * 738 * If we're looking up "..", unlock the parent, and lock "..". If everything 739 * went ok, and we're on the last component and the caller requested the 740 * parent locked, try to re-lock the parent. We do this to prevent lock 741 * races. 742 * 743 * For anything else, get the needed node. Then unlock the parent if not 744 * the last component or not LOCKPARENT (i.e. if we wouldn't re-lock the 745 * parent in the .. case). 746 * 747 * We try to exit with the parent locked in error cases. 748 */ 749 int 750 procfs_lookup(v) 751 void *v; 752 { 753 struct vop_lookup_args /* { 754 struct vnode * a_dvp; 755 struct vnode ** a_vpp; 756 struct componentname * a_cnp; 757 } */ *ap = v; 758 struct componentname *cnp = ap->a_cnp; 759 struct vnode **vpp = ap->a_vpp; 760 struct vnode *dvp = ap->a_dvp; 761 const char *pname = cnp->cn_nameptr; 762 const struct proc_target *pt = NULL; 763 struct vnode *fvp; 764 pid_t pid; 765 struct pfsnode *pfs; 766 struct proc *p = NULL; 767 int i, error, wantpunlock, iscurproc = 0, isself = 0; 768 769 *vpp = NULL; 770 cnp->cn_flags &= ~PDIRUNLOCK; 771 772 if (cnp->cn_nameiop == DELETE || cnp->cn_nameiop == RENAME) 773 return (EROFS); 774 775 if (cnp->cn_namelen == 1 && *pname == '.') { 776 *vpp = dvp; 777 VREF(dvp); 778 return (0); 779 } 780 781 wantpunlock = (~cnp->cn_flags & (LOCKPARENT | ISLASTCN)); 782 pfs = VTOPFS(dvp); 783 switch (pfs->pfs_type) { 784 case Proot: 785 /* 786 * Shouldn't get here with .. in the root node. 787 */ 788 if (cnp->cn_flags & ISDOTDOT) 789 return (EIO); 790 791 iscurproc = CNEQ(cnp, "curproc", 7); 792 isself = CNEQ(cnp, "self", 4); 793 794 if (iscurproc || isself) { 795 error = procfs_allocvp(dvp->v_mount, vpp, 0, 796 iscurproc ? Pcurproc : Pself, -1); 797 if ((error == 0) && (wantpunlock)) { 798 VOP_UNLOCK(dvp, 0); 799 cnp->cn_flags |= PDIRUNLOCK; 800 } 801 return (error); 802 } 803 804 for (i = 0; i < nproc_root_targets; i++) { 805 pt = &proc_root_targets[i]; 806 if (cnp->cn_namelen == pt->pt_namlen && 807 memcmp(pt->pt_name, pname, cnp->cn_namelen) == 0 && 808 (pt->pt_valid == NULL || 809 (*pt->pt_valid)(p, dvp->v_mount))) 810 break; 811 } 812 813 if (i != nproc_root_targets) { 814 error = procfs_allocvp(dvp->v_mount, vpp, 0, 815 pt->pt_pfstype, -1); 816 if ((error == 0) && (wantpunlock)) { 817 VOP_UNLOCK(dvp, 0); 818 cnp->cn_flags |= PDIRUNLOCK; 819 } 820 return (error); 821 } 822 823 pid = (pid_t)atoi(pname, cnp->cn_namelen); 824 825 p = PFIND(pid); 826 if (p == NULL) 827 break; 828 829 error = procfs_allocvp(dvp->v_mount, vpp, pid, Pproc, -1); 830 if ((error == 0) && (wantpunlock)) { 831 VOP_UNLOCK(dvp, 0); 832 cnp->cn_flags |= PDIRUNLOCK; 833 } 834 return (error); 835 836 case Pproc: 837 /* 838 * do the .. dance. We unlock the directory, and then 839 * get the root dir. That will automatically return .. 840 * locked. Then if the caller wanted dvp locked, we 841 * re-lock. 842 */ 843 if (cnp->cn_flags & ISDOTDOT) { 844 VOP_UNLOCK(dvp, 0); 845 cnp->cn_flags |= PDIRUNLOCK; 846 error = procfs_root(dvp->v_mount, vpp); 847 if ((error == 0) && (wantpunlock == 0) && 848 ((error = vn_lock(dvp, LK_EXCLUSIVE)) == 0)) 849 cnp->cn_flags &= ~PDIRUNLOCK; 850 return (error); 851 } 852 853 p = PFIND(pfs->pfs_pid); 854 if (p == NULL) 855 break; 856 857 for (pt = proc_targets, i = 0; i < nproc_targets; pt++, i++) { 858 if (cnp->cn_namelen == pt->pt_namlen && 859 memcmp(pt->pt_name, pname, cnp->cn_namelen) == 0 && 860 (pt->pt_valid == NULL || 861 (*pt->pt_valid)(p, dvp->v_mount))) 862 goto found; 863 } 864 break; 865 866 found: 867 if (pt->pt_pfstype == Pfile) { 868 fvp = p->p_textvp; 869 /* We already checked that it exists. */ 870 VREF(fvp); 871 vn_lock(fvp, LK_EXCLUSIVE | LK_RETRY); 872 if (wantpunlock) { 873 VOP_UNLOCK(dvp, 0); 874 cnp->cn_flags |= PDIRUNLOCK; 875 } 876 *vpp = fvp; 877 return (0); 878 } 879 880 error = procfs_allocvp(dvp->v_mount, vpp, pfs->pfs_pid, 881 pt->pt_pfstype, -1); 882 if ((error == 0) && (wantpunlock)) { 883 VOP_UNLOCK(dvp, 0); 884 cnp->cn_flags |= PDIRUNLOCK; 885 } 886 return (error); 887 888 case Pfd: { 889 int fd; 890 struct file *fp; 891 /* 892 * do the .. dance. We unlock the directory, and then 893 * get the proc dir. That will automatically return .. 894 * locked. Then if the caller wanted dvp locked, we 895 * re-lock. 896 */ 897 if (cnp->cn_flags & ISDOTDOT) { 898 VOP_UNLOCK(dvp, 0); 899 cnp->cn_flags |= PDIRUNLOCK; 900 error = procfs_allocvp(dvp->v_mount, vpp, pfs->pfs_pid, 901 Pproc, -1); 902 if ((error == 0) && (wantpunlock == 0) && 903 ((error = vn_lock(dvp, LK_EXCLUSIVE)) == 0)) 904 cnp->cn_flags &= ~PDIRUNLOCK; 905 return (error); 906 } 907 fd = atoi(pname, cnp->cn_namelen); 908 p = PFIND(pfs->pfs_pid); 909 if (p == NULL || (fp = fd_getfile(p->p_fd, fd)) == NULL) 910 return ENOENT; 911 FILE_USE(fp); 912 913 switch (fp->f_type) { 914 case DTYPE_VNODE: 915 fvp = (struct vnode *)fp->f_data; 916 917 /* Don't show directories */ 918 if (fvp->v_type == VDIR) 919 goto symlink; 920 921 VREF(fvp); 922 FILE_UNUSE(fp, p); 923 vn_lock(fvp, LK_EXCLUSIVE | LK_RETRY | 924 (p == curproc ? LK_CANRECURSE : 0)); 925 *vpp = fvp; 926 error = 0; 927 break; 928 default: 929 symlink: 930 FILE_UNUSE(fp, p); 931 error = procfs_allocvp(dvp->v_mount, vpp, pfs->pfs_pid, 932 Pfd, fd); 933 break; 934 } 935 if ((error == 0) && (wantpunlock)) { 936 VOP_UNLOCK(dvp, 0); 937 cnp->cn_flags |= PDIRUNLOCK; 938 } 939 return error; 940 } 941 default: 942 return (ENOTDIR); 943 } 944 945 return (cnp->cn_nameiop == LOOKUP ? ENOENT : EROFS); 946 } 947 948 int 949 procfs_validfile(p, mp) 950 struct proc *p; 951 struct mount *mp; 952 { 953 return (p->p_textvp != NULL); 954 } 955 956 static int 957 procfs_validfile_linux(p, mp) 958 struct proc *p; 959 struct mount *mp; 960 { 961 int flags; 962 963 flags = VFSTOPROC(mp)->pmnt_flags; 964 return ((flags & PROCFSMNT_LINUXCOMPAT) && 965 (p == NULL || procfs_validfile(p, mp))); 966 } 967 968 /* 969 * readdir returns directory entries from pfsnode (vp). 970 * 971 * the strategy here with procfs is to generate a single 972 * directory entry at a time (struct dirent) and then 973 * copy that out to userland using uiomove. a more efficent 974 * though more complex implementation, would try to minimize 975 * the number of calls to uiomove(). for procfs, this is 976 * hardly worth the added code complexity. 977 * 978 * this should just be done through read() 979 */ 980 int 981 procfs_readdir(v) 982 void *v; 983 { 984 struct vop_readdir_args /* { 985 struct vnode *a_vp; 986 struct uio *a_uio; 987 struct ucred *a_cred; 988 int *a_eofflag; 989 off_t **a_cookies; 990 int *a_ncookies; 991 } */ *ap = v; 992 struct uio *uio = ap->a_uio; 993 struct dirent d; 994 struct pfsnode *pfs; 995 off_t i; 996 int error; 997 off_t *cookies = NULL; 998 int ncookies, left, skip, j; 999 struct vnode *vp; 1000 const struct proc_target *pt; 1001 1002 vp = ap->a_vp; 1003 pfs = VTOPFS(vp); 1004 1005 if (uio->uio_resid < UIO_MX) 1006 return (EINVAL); 1007 if (uio->uio_offset < 0) 1008 return (EINVAL); 1009 1010 error = 0; 1011 i = uio->uio_offset; 1012 memset((caddr_t)&d, 0, UIO_MX); 1013 d.d_reclen = UIO_MX; 1014 ncookies = uio->uio_resid / UIO_MX; 1015 1016 switch (pfs->pfs_type) { 1017 /* 1018 * this is for the process-specific sub-directories. 1019 * all that is needed to is copy out all the entries 1020 * from the procent[] table (top of this file). 1021 */ 1022 case Pproc: { 1023 struct proc *p; 1024 1025 if (i >= nproc_targets) 1026 return 0; 1027 1028 p = PFIND(pfs->pfs_pid); 1029 if (p == NULL) 1030 break; 1031 1032 if (ap->a_ncookies) { 1033 ncookies = min(ncookies, (nproc_targets - i)); 1034 cookies = malloc(ncookies * sizeof (off_t), 1035 M_TEMP, M_WAITOK); 1036 *ap->a_cookies = cookies; 1037 } 1038 1039 for (pt = &proc_targets[i]; 1040 uio->uio_resid >= UIO_MX && i < nproc_targets; pt++, i++) { 1041 if (pt->pt_valid && 1042 (*pt->pt_valid)(p, vp->v_mount) == 0) 1043 continue; 1044 1045 d.d_fileno = PROCFS_FILENO(pfs->pfs_pid, 1046 pt->pt_pfstype, -1); 1047 d.d_namlen = pt->pt_namlen; 1048 memcpy(d.d_name, pt->pt_name, pt->pt_namlen + 1); 1049 d.d_type = pt->pt_type; 1050 1051 if ((error = uiomove((caddr_t)&d, UIO_MX, uio)) != 0) 1052 break; 1053 if (cookies) 1054 *cookies++ = i + 1; 1055 } 1056 1057 break; 1058 } 1059 case Pfd: { 1060 struct proc *p; 1061 struct filedesc *fdp; 1062 struct file *fp; 1063 int lim, last, nc = 0; 1064 1065 p = PFIND(pfs->pfs_pid); 1066 if (p == NULL) 1067 return ESRCH; 1068 1069 fdp = p->p_fd; 1070 1071 lim = min((int)p->p_rlimit[RLIMIT_NOFILE].rlim_cur, maxfiles); 1072 last = min(fdp->fd_nfiles, lim); 1073 if (i >= lim) 1074 return 0; 1075 1076 if (ap->a_ncookies) { 1077 ncookies = min(ncookies, (fdp->fd_nfiles + 2 - i)); 1078 cookies = malloc(ncookies * sizeof (off_t), 1079 M_TEMP, M_WAITOK); 1080 *ap->a_cookies = cookies; 1081 } 1082 1083 for (; i < 2 && uio->uio_resid >= UIO_MX; i++) { 1084 pt = &proc_targets[i]; 1085 d.d_fileno = (pfs->pfs_pid << 8) + i; 1086 d.d_namlen = pt->pt_namlen; 1087 d.d_fileno = PROCFS_FILENO(pfs->pfs_pid, 1088 pt->pt_pfstype, -1); 1089 (void)memcpy(d.d_name, pt->pt_name, pt->pt_namlen + 1); 1090 d.d_type = pt->pt_type; 1091 if ((error = uiomove((caddr_t)&d, UIO_MX, uio)) != 0) 1092 break; 1093 if (cookies) 1094 *cookies++ = i + 1; 1095 nc++; 1096 } 1097 if (error) { 1098 ncookies = nc; 1099 break; 1100 } 1101 for (; uio->uio_resid >= UIO_MX && i < fdp->fd_nfiles; i++) { 1102 if ((fp = fd_getfile(fdp, i - 2)) == NULL) 1103 continue; 1104 d.d_fileno = PROCFS_FILENO(pfs->pfs_pid, Pfd, i - 2); 1105 d.d_namlen = snprintf(d.d_name, sizeof(d.d_name), 1106 "%lld", (long long)(i - 2)); 1107 d.d_type = VREG; 1108 if ((error = uiomove((caddr_t)&d, UIO_MX, uio)) != 0) 1109 break; 1110 if (cookies) 1111 *cookies++ = i + 1; 1112 nc++; 1113 } 1114 ncookies = nc; 1115 break; 1116 } 1117 1118 /* 1119 * this is for the root of the procfs filesystem 1120 * what is needed are special entries for "curproc" 1121 * and "self" followed by an entry for each process 1122 * on allproc 1123 #ifdef PROCFS_ZOMBIE 1124 * and deadproc and zombproc. 1125 #endif 1126 */ 1127 1128 case Proot: { 1129 int pcnt = i, nc = 0; 1130 const struct proclist_desc *pd; 1131 volatile struct proc *p; 1132 1133 if (pcnt > 3) 1134 pcnt = 3; 1135 if (ap->a_ncookies) { 1136 /* 1137 * XXX Potentially allocating too much space here, 1138 * but I'm lazy. This loop needs some work. 1139 */ 1140 cookies = malloc(ncookies * sizeof (off_t), 1141 M_TEMP, M_WAITOK); 1142 *ap->a_cookies = cookies; 1143 } 1144 /* 1145 * XXX: THIS LOOP ASSUMES THAT allproc IS THE FIRST 1146 * PROCLIST IN THE proclists! 1147 */ 1148 proclist_lock_read(); 1149 pd = proclists; 1150 #ifdef PROCFS_ZOMBIE 1151 again: 1152 #endif 1153 for (p = LIST_FIRST(pd->pd_list); 1154 p != NULL && uio->uio_resid >= UIO_MX; i++, pcnt++) { 1155 switch (i) { 1156 case 0: /* `.' */ 1157 case 1: /* `..' */ 1158 d.d_fileno = PROCFS_FILENO(0, Proot, -1); 1159 d.d_namlen = i + 1; 1160 memcpy(d.d_name, "..", d.d_namlen); 1161 d.d_name[i + 1] = '\0'; 1162 d.d_type = DT_DIR; 1163 break; 1164 1165 case 2: 1166 d.d_fileno = PROCFS_FILENO(0, Pcurproc, -1); 1167 d.d_namlen = sizeof("curproc") - 1; 1168 memcpy(d.d_name, "curproc", sizeof("curproc")); 1169 d.d_type = DT_LNK; 1170 break; 1171 1172 case 3: 1173 d.d_fileno = PROCFS_FILENO(0, Pself, -1); 1174 d.d_namlen = sizeof("self") - 1; 1175 memcpy(d.d_name, "self", sizeof("self")); 1176 d.d_type = DT_LNK; 1177 break; 1178 1179 default: 1180 while (pcnt < i) { 1181 pcnt++; 1182 p = LIST_NEXT(p, p_list); 1183 if (!p) 1184 goto done; 1185 } 1186 d.d_fileno = PROCFS_FILENO(p->p_pid, Pproc, -1); 1187 d.d_namlen = sprintf(d.d_name, "%ld", 1188 (long)p->p_pid); 1189 d.d_type = DT_DIR; 1190 p = p->p_list.le_next; 1191 break; 1192 } 1193 1194 if ((error = uiomove((caddr_t)&d, UIO_MX, uio)) != 0) 1195 break; 1196 nc++; 1197 if (cookies) 1198 *cookies++ = i + 1; 1199 } 1200 done: 1201 1202 #ifdef PROCFS_ZOMBIE 1203 pd++; 1204 if (p == NULL && pd->pd_list != NULL) 1205 goto again; 1206 #endif 1207 proclist_unlock_read(); 1208 1209 skip = i - pcnt; 1210 if (skip >= nproc_root_targets) 1211 break; 1212 left = nproc_root_targets - skip; 1213 for (j = 0, pt = &proc_root_targets[0]; 1214 uio->uio_resid >= UIO_MX && j < left; 1215 pt++, j++, i++) { 1216 if (pt->pt_valid && 1217 (*pt->pt_valid)(NULL, vp->v_mount) == 0) 1218 continue; 1219 d.d_fileno = PROCFS_FILENO(0, pt->pt_pfstype, -1); 1220 d.d_namlen = pt->pt_namlen; 1221 memcpy(d.d_name, pt->pt_name, pt->pt_namlen + 1); 1222 d.d_type = pt->pt_type; 1223 1224 if ((error = uiomove((caddr_t)&d, UIO_MX, uio)) != 0) 1225 break; 1226 nc++; 1227 if (cookies) 1228 *cookies++ = i + 1; 1229 } 1230 1231 ncookies = nc; 1232 break; 1233 } 1234 1235 default: 1236 error = ENOTDIR; 1237 break; 1238 } 1239 1240 if (ap->a_ncookies) { 1241 if (error) { 1242 if (cookies) 1243 free(*ap->a_cookies, M_TEMP); 1244 *ap->a_ncookies = 0; 1245 *ap->a_cookies = NULL; 1246 } else 1247 *ap->a_ncookies = ncookies; 1248 } 1249 uio->uio_offset = i; 1250 return (error); 1251 } 1252 1253 /* 1254 * readlink reads the link of `curproc' 1255 */ 1256 int 1257 procfs_readlink(v) 1258 void *v; 1259 { 1260 struct vop_readlink_args *ap = v; 1261 char buf[16]; /* should be enough */ 1262 char *bp = buf; 1263 char *path = NULL; 1264 int len; 1265 int error = 0; 1266 struct pfsnode *pfs = VTOPFS(ap->a_vp); 1267 1268 if (pfs->pfs_fileno == PROCFS_FILENO(0, Pcurproc, -1)) 1269 len = sprintf(buf, "%ld", (long)curproc->p_pid); 1270 else if (pfs->pfs_fileno == PROCFS_FILENO(0, Pself, -1)) 1271 len = sprintf(buf, "%s", "curproc"); 1272 else { 1273 struct file *fp; 1274 struct proc *pown; 1275 struct vnode *vxp, *vp; 1276 1277 if ((error = procfs_getfp(pfs, &pown, &fp)) != 0) 1278 return error; 1279 FILE_USE(fp); 1280 switch (fp->f_type) { 1281 case DTYPE_VNODE: 1282 vxp = (struct vnode *)fp->f_data; 1283 if (vxp->v_type != VDIR) { 1284 FILE_UNUSE(fp, pown); 1285 return EINVAL; 1286 } 1287 if ((path = malloc(MAXPATHLEN, M_TEMP, M_WAITOK)) 1288 == NULL) { 1289 FILE_UNUSE(fp, pown); 1290 return ENOMEM; 1291 } 1292 bp = path + MAXPATHLEN; 1293 *--bp = '\0'; 1294 vp = curproc->p_cwdi->cwdi_rdir; 1295 if (vp == NULL) 1296 vp = rootvnode; 1297 error = getcwd_common(vxp, vp, &bp, path, 1298 MAXPATHLEN / 2, 0, curproc); 1299 FILE_UNUSE(fp, pown); 1300 if (error) { 1301 free(path, M_TEMP); 1302 return error; 1303 } 1304 len = strlen(bp); 1305 break; 1306 1307 case DTYPE_MISC: 1308 len = sprintf(buf, "%s", "[misc]"); 1309 break; 1310 1311 case DTYPE_KQUEUE: 1312 len = sprintf(buf, "%s", "[kqueue]"); 1313 break; 1314 1315 default: 1316 return EINVAL; 1317 } 1318 } 1319 1320 error = uiomove((caddr_t)bp, len, ap->a_uio); 1321 if (path) 1322 free(path, M_TEMP); 1323 return error; 1324 } 1325 1326 /* 1327 * convert decimal ascii to int 1328 */ 1329 static int 1330 atoi(b, len) 1331 const char *b; 1332 size_t len; 1333 { 1334 int p = 0; 1335 1336 while (len--) { 1337 char c = *b++; 1338 if (c < '0' || c > '9') 1339 return -1; 1340 p = 10 * p + (c - '0'); 1341 } 1342 1343 return p; 1344 } 1345