1 /* $NetBSD: procfs_vnops.c,v 1.69 1999/09/02 23:33:45 thorpej 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/param.h> 47 #include <sys/systm.h> 48 #include <sys/time.h> 49 #include <sys/kernel.h> 50 #include <sys/file.h> 51 #include <sys/proc.h> 52 #include <sys/vnode.h> 53 #include <sys/namei.h> 54 #include <sys/malloc.h> 55 #include <sys/dirent.h> 56 #include <sys/resourcevar.h> 57 #include <sys/ptrace.h> 58 #include <sys/stat.h> 59 60 #include <vm/vm.h> /* for PAGE_SIZE */ 61 62 #include <machine/reg.h> 63 64 #include <miscfs/genfs/genfs.h> 65 #include <miscfs/procfs/procfs.h> 66 67 /* 68 * Vnode Operations. 69 * 70 */ 71 72 /* 73 * This is a list of the valid names in the 74 * process-specific sub-directories. It is 75 * used in procfs_lookup and procfs_readdir 76 */ 77 struct proc_target { 78 u_char pt_type; 79 u_char pt_namlen; 80 char *pt_name; 81 pfstype pt_pfstype; 82 int (*pt_valid) __P((struct proc *p)); 83 } proc_targets[] = { 84 #define N(s) sizeof(s)-1, s 85 /* name type validp */ 86 { DT_DIR, N("."), Pproc, NULL }, 87 { DT_DIR, N(".."), Proot, NULL }, 88 { DT_REG, N("file"), Pfile, procfs_validfile }, 89 { DT_REG, N("mem"), Pmem, NULL }, 90 { DT_REG, N("regs"), Pregs, procfs_validregs }, 91 { DT_REG, N("fpregs"), Pfpregs, procfs_validfpregs }, 92 { DT_REG, N("ctl"), Pctl, NULL }, 93 { DT_REG, N("status"), Pstatus, NULL }, 94 { DT_REG, N("note"), Pnote, NULL }, 95 { DT_REG, N("notepg"), Pnotepg, NULL }, 96 { DT_REG, N("map"), Pmap, procfs_validmap }, 97 { DT_REG, N("cmdline"), Pcmdline, NULL }, 98 #undef N 99 }; 100 static int nproc_targets = sizeof(proc_targets) / sizeof(proc_targets[0]); 101 102 static pid_t atopid __P((const char *, u_int)); 103 104 int procfs_lookup __P((void *)); 105 #define procfs_create genfs_eopnotsupp_rele 106 #define procfs_mknod genfs_eopnotsupp_rele 107 int procfs_open __P((void *)); 108 int procfs_close __P((void *)); 109 int procfs_access __P((void *)); 110 int procfs_getattr __P((void *)); 111 int procfs_setattr __P((void *)); 112 #define procfs_read procfs_rw 113 #define procfs_write procfs_rw 114 #define procfs_fcntl genfs_fcntl 115 #define procfs_ioctl genfs_enoioctl 116 #define procfs_poll genfs_poll 117 #define procfs_revoke genfs_revoke 118 #define procfs_mmap genfs_eopnotsupp 119 #define procfs_fsync genfs_nullop 120 #define procfs_seek genfs_nullop 121 #define procfs_remove genfs_eopnotsupp_rele 122 int procfs_link __P((void *)); 123 #define procfs_rename genfs_eopnotsupp_rele 124 #define procfs_mkdir genfs_eopnotsupp_rele 125 #define procfs_rmdir genfs_eopnotsupp_rele 126 int procfs_symlink __P((void *)); 127 int procfs_readdir __P((void *)); 128 int procfs_readlink __P((void *)); 129 #define procfs_abortop genfs_abortop 130 int procfs_inactive __P((void *)); 131 int procfs_reclaim __P((void *)); 132 #define procfs_lock genfs_lock 133 #define procfs_unlock genfs_unlock 134 int procfs_bmap __P((void *)); 135 #define procfs_strategy genfs_badop 136 int procfs_print __P((void *)); 137 int procfs_pathconf __P((void *)); 138 #define procfs_islocked genfs_islocked 139 #define procfs_advlock genfs_einval 140 #define procfs_blkatoff genfs_eopnotsupp 141 #define procfs_valloc genfs_eopnotsupp 142 #define procfs_vfree genfs_nullop 143 #define procfs_truncate genfs_eopnotsupp 144 #define procfs_update genfs_nullop 145 #define procfs_bwrite genfs_eopnotsupp 146 147 static pid_t atopid __P((const char *, u_int)); 148 149 /* 150 * procfs vnode operations. 151 */ 152 int (**procfs_vnodeop_p) __P((void *)); 153 struct vnodeopv_entry_desc procfs_vnodeop_entries[] = { 154 { &vop_default_desc, vn_default_error }, 155 { &vop_lookup_desc, procfs_lookup }, /* lookup */ 156 { &vop_create_desc, procfs_create }, /* create */ 157 { &vop_mknod_desc, procfs_mknod }, /* mknod */ 158 { &vop_open_desc, procfs_open }, /* open */ 159 { &vop_close_desc, procfs_close }, /* close */ 160 { &vop_access_desc, procfs_access }, /* access */ 161 { &vop_getattr_desc, procfs_getattr }, /* getattr */ 162 { &vop_setattr_desc, procfs_setattr }, /* setattr */ 163 { &vop_read_desc, procfs_read }, /* read */ 164 { &vop_write_desc, procfs_write }, /* write */ 165 { &vop_fcntl_desc, procfs_fcntl }, /* fcntl */ 166 { &vop_ioctl_desc, procfs_ioctl }, /* ioctl */ 167 { &vop_poll_desc, procfs_poll }, /* poll */ 168 { &vop_revoke_desc, procfs_revoke }, /* revoke */ 169 { &vop_mmap_desc, procfs_mmap }, /* mmap */ 170 { &vop_fsync_desc, procfs_fsync }, /* fsync */ 171 { &vop_seek_desc, procfs_seek }, /* seek */ 172 { &vop_remove_desc, procfs_remove }, /* remove */ 173 { &vop_link_desc, procfs_link }, /* link */ 174 { &vop_rename_desc, procfs_rename }, /* rename */ 175 { &vop_mkdir_desc, procfs_mkdir }, /* mkdir */ 176 { &vop_rmdir_desc, procfs_rmdir }, /* rmdir */ 177 { &vop_symlink_desc, procfs_symlink }, /* symlink */ 178 { &vop_readdir_desc, procfs_readdir }, /* readdir */ 179 { &vop_readlink_desc, procfs_readlink }, /* readlink */ 180 { &vop_abortop_desc, procfs_abortop }, /* abortop */ 181 { &vop_inactive_desc, procfs_inactive }, /* inactive */ 182 { &vop_reclaim_desc, procfs_reclaim }, /* reclaim */ 183 { &vop_lock_desc, procfs_lock }, /* lock */ 184 { &vop_unlock_desc, procfs_unlock }, /* unlock */ 185 { &vop_bmap_desc, procfs_bmap }, /* bmap */ 186 { &vop_strategy_desc, procfs_strategy }, /* strategy */ 187 { &vop_print_desc, procfs_print }, /* print */ 188 { &vop_islocked_desc, procfs_islocked }, /* islocked */ 189 { &vop_pathconf_desc, procfs_pathconf }, /* pathconf */ 190 { &vop_advlock_desc, procfs_advlock }, /* advlock */ 191 { &vop_blkatoff_desc, procfs_blkatoff }, /* blkatoff */ 192 { &vop_valloc_desc, procfs_valloc }, /* valloc */ 193 { &vop_vfree_desc, procfs_vfree }, /* vfree */ 194 { &vop_truncate_desc, procfs_truncate }, /* truncate */ 195 { &vop_update_desc, procfs_update }, /* update */ 196 { (struct vnodeop_desc*)NULL, (int(*) __P((void *)))NULL } 197 }; 198 struct vnodeopv_desc procfs_vnodeop_opv_desc = 199 { &procfs_vnodeop_p, procfs_vnodeop_entries }; 200 /* 201 * set things up for doing i/o on 202 * the pfsnode (vp). (vp) is locked 203 * on entry, and should be left locked 204 * on exit. 205 * 206 * for procfs we don't need to do anything 207 * in particular for i/o. all that is done 208 * is to support exclusive open on process 209 * memory images. 210 */ 211 int 212 procfs_open(v) 213 void *v; 214 { 215 struct vop_open_args /* { 216 struct vnode *a_vp; 217 int a_mode; 218 struct ucred *a_cred; 219 struct proc *a_p; 220 } */ *ap = v; 221 struct pfsnode *pfs = VTOPFS(ap->a_vp); 222 struct proc *p1, *p2; 223 int error; 224 225 p1 = ap->a_p; /* tracer */ 226 p2 = PFIND(pfs->pfs_pid); /* traced */ 227 228 if (p2 == NULL) 229 return (ENOENT); /* was ESRCH, jsp */ 230 231 switch (pfs->pfs_type) { 232 case Pmem: 233 if (((pfs->pfs_flags & FWRITE) && (ap->a_mode & O_EXCL)) || 234 ((pfs->pfs_flags & O_EXCL) && (ap->a_mode & FWRITE))) 235 return (EBUSY); 236 237 if ((error = procfs_checkioperm(p1, p2)) != 0) 238 return (EPERM); 239 240 if (ap->a_mode & FWRITE) 241 pfs->pfs_flags = ap->a_mode & (FWRITE|O_EXCL); 242 243 return (0); 244 245 default: 246 break; 247 } 248 249 return (0); 250 } 251 252 /* 253 * close the pfsnode (vp) after doing i/o. 254 * (vp) is not locked on entry or exit. 255 * 256 * nothing to do for procfs other than undo 257 * any exclusive open flag (see _open above). 258 */ 259 int 260 procfs_close(v) 261 void *v; 262 { 263 struct vop_close_args /* { 264 struct vnode *a_vp; 265 int a_fflag; 266 struct ucred *a_cred; 267 struct proc *a_p; 268 } */ *ap = v; 269 struct pfsnode *pfs = VTOPFS(ap->a_vp); 270 271 switch (pfs->pfs_type) { 272 case Pmem: 273 if ((ap->a_fflag & FWRITE) && (pfs->pfs_flags & O_EXCL)) 274 pfs->pfs_flags &= ~(FWRITE|O_EXCL); 275 break; 276 277 default: 278 break; 279 } 280 281 return (0); 282 } 283 284 /* 285 * do block mapping for pfsnode (vp). 286 * since we don't use the buffer cache 287 * for procfs this function should never 288 * be called. in any case, it's not clear 289 * what part of the kernel ever makes use 290 * of this function. for sanity, this is the 291 * usual no-op bmap, although returning 292 * (EIO) would be a reasonable alternative. 293 */ 294 int 295 procfs_bmap(v) 296 void *v; 297 { 298 struct vop_bmap_args /* { 299 struct vnode *a_vp; 300 daddr_t a_bn; 301 struct vnode **a_vpp; 302 daddr_t *a_bnp; 303 int * a_runp; 304 } */ *ap = v; 305 306 if (ap->a_vpp != NULL) 307 *ap->a_vpp = ap->a_vp; 308 if (ap->a_bnp != NULL) 309 *ap->a_bnp = ap->a_bn; 310 if (ap->a_runp != NULL) 311 *ap->a_runp = 0; 312 return (0); 313 } 314 315 /* 316 * _inactive is called when the pfsnode 317 * is vrele'd and the reference count goes 318 * to zero. (vp) will be on the vnode free 319 * list, so to get it back vget() must be 320 * used. 321 * 322 * for procfs, check if the process is still 323 * alive and if it isn't then just throw away 324 * the vnode by calling vgone(). this may 325 * be overkill and a waste of time since the 326 * chances are that the process will still be 327 * there and PFIND is not free. 328 * 329 * (vp) is locked on entry, but must be unlocked on exit. 330 */ 331 int 332 procfs_inactive(v) 333 void *v; 334 { 335 struct vop_inactive_args /* { 336 struct vnode *a_vp; 337 struct proc *a_p; 338 } */ *ap = v; 339 struct pfsnode *pfs = VTOPFS(ap->a_vp); 340 341 VOP_UNLOCK(ap->a_vp, 0); 342 if (PFIND(pfs->pfs_pid) == 0) 343 vgone(ap->a_vp); 344 345 return (0); 346 } 347 348 /* 349 * _reclaim is called when getnewvnode() 350 * wants to make use of an entry on the vnode 351 * free list. at this time the filesystem needs 352 * to free any private data and remove the node 353 * from any private lists. 354 */ 355 int 356 procfs_reclaim(v) 357 void *v; 358 { 359 struct vop_reclaim_args /* { 360 struct vnode *a_vp; 361 } */ *ap = v; 362 363 return (procfs_freevp(ap->a_vp)); 364 } 365 366 /* 367 * Return POSIX pathconf information applicable to special devices. 368 */ 369 int 370 procfs_pathconf(v) 371 void *v; 372 { 373 struct vop_pathconf_args /* { 374 struct vnode *a_vp; 375 int a_name; 376 register_t *a_retval; 377 } */ *ap = v; 378 379 switch (ap->a_name) { 380 case _PC_LINK_MAX: 381 *ap->a_retval = LINK_MAX; 382 return (0); 383 case _PC_MAX_CANON: 384 *ap->a_retval = MAX_CANON; 385 return (0); 386 case _PC_MAX_INPUT: 387 *ap->a_retval = MAX_INPUT; 388 return (0); 389 case _PC_PIPE_BUF: 390 *ap->a_retval = PIPE_BUF; 391 return (0); 392 case _PC_CHOWN_RESTRICTED: 393 *ap->a_retval = 1; 394 return (0); 395 case _PC_VDISABLE: 396 *ap->a_retval = _POSIX_VDISABLE; 397 return (0); 398 case _PC_SYNC_IO: 399 *ap->a_retval = 1; 400 return (0); 401 default: 402 return (EINVAL); 403 } 404 /* NOTREACHED */ 405 } 406 407 /* 408 * _print is used for debugging. 409 * just print a readable description 410 * of (vp). 411 */ 412 int 413 procfs_print(v) 414 void *v; 415 { 416 struct vop_print_args /* { 417 struct vnode *a_vp; 418 } */ *ap = v; 419 struct pfsnode *pfs = VTOPFS(ap->a_vp); 420 421 printf("tag VT_PROCFS, type %d, pid %d, mode %x, flags %lx\n", 422 pfs->pfs_type, pfs->pfs_pid, pfs->pfs_mode, pfs->pfs_flags); 423 return 0; 424 } 425 426 int 427 procfs_link(v) 428 void *v; 429 { 430 struct vop_link_args /* { 431 struct vnode *a_dvp; 432 struct vnode *a_vp; 433 struct componentname *a_cnp; 434 } */ *ap = v; 435 436 VOP_ABORTOP(ap->a_dvp, ap->a_cnp); 437 vput(ap->a_dvp); 438 return (EROFS); 439 } 440 441 int 442 procfs_symlink(v) 443 void *v; 444 { 445 struct vop_symlink_args /* { 446 struct vnode *a_dvp; 447 struct vnode **a_vpp; 448 struct componentname *a_cnp; 449 struct vattr *a_vap; 450 char *a_target; 451 } */ *ap = v; 452 453 VOP_ABORTOP(ap->a_dvp, ap->a_cnp); 454 vput(ap->a_dvp); 455 return (EROFS); 456 } 457 458 /* 459 * Invent attributes for pfsnode (vp) and store 460 * them in (vap). 461 * Directories lengths are returned as zero since 462 * any real length would require the genuine size 463 * to be computed, and nothing cares anyway. 464 * 465 * this is relatively minimal for procfs. 466 */ 467 int 468 procfs_getattr(v) 469 void *v; 470 { 471 struct vop_getattr_args /* { 472 struct vnode *a_vp; 473 struct vattr *a_vap; 474 struct ucred *a_cred; 475 struct proc *a_p; 476 } */ *ap = v; 477 struct pfsnode *pfs = VTOPFS(ap->a_vp); 478 struct vattr *vap = ap->a_vap; 479 struct proc *procp; 480 struct timeval tv; 481 int error; 482 483 /* first check the process still exists */ 484 switch (pfs->pfs_type) { 485 case Proot: 486 case Pcurproc: 487 case Pself: 488 procp = 0; 489 break; 490 491 default: 492 procp = PFIND(pfs->pfs_pid); 493 if (procp == 0) 494 return (ENOENT); 495 break; 496 } 497 498 error = 0; 499 500 /* start by zeroing out the attributes */ 501 VATTR_NULL(vap); 502 503 /* next do all the common fields */ 504 vap->va_type = ap->a_vp->v_type; 505 vap->va_mode = pfs->pfs_mode; 506 vap->va_fileid = pfs->pfs_fileno; 507 vap->va_flags = 0; 508 vap->va_blocksize = PAGE_SIZE; 509 510 /* 511 * Make all times be current TOD. 512 * It would be possible to get the process start 513 * time from the p_stat structure, but there's 514 * no "file creation" time stamp anyway, and the 515 * p_stat structure is not addressible if u. gets 516 * swapped out for that process. 517 */ 518 microtime(&tv); 519 TIMEVAL_TO_TIMESPEC(&tv, &vap->va_ctime); 520 vap->va_atime = vap->va_mtime = vap->va_ctime; 521 522 switch (pfs->pfs_type) { 523 case Pmem: 524 case Pregs: 525 case Pfpregs: 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 Pnote: 537 case Pnotepg: 538 case Pmap: 539 case Pcmdline: 540 vap->va_nlink = 1; 541 vap->va_uid = procp->p_ucred->cr_uid; 542 vap->va_gid = procp->p_ucred->cr_gid; 543 break; 544 545 default: 546 break; 547 } 548 549 /* 550 * now do the object specific fields 551 * 552 * The size could be set from struct reg, but it's hardly 553 * worth the trouble, and it puts some (potentially) machine 554 * dependent data into this machine-independent code. If it 555 * becomes important then this function should break out into 556 * a per-file stat function in the corresponding .c file. 557 */ 558 559 switch (pfs->pfs_type) { 560 case Proot: 561 /* 562 * Set nlink to 1 to tell fts(3) we don't actually know. 563 */ 564 vap->va_nlink = 1; 565 vap->va_uid = 0; 566 vap->va_gid = 0; 567 vap->va_bytes = vap->va_size = DEV_BSIZE; 568 break; 569 570 case Pcurproc: { 571 char buf[16]; /* should be enough */ 572 vap->va_nlink = 1; 573 vap->va_uid = 0; 574 vap->va_gid = 0; 575 vap->va_bytes = vap->va_size = 576 sprintf(buf, "%ld", (long)curproc->p_pid); 577 break; 578 } 579 580 case Pself: 581 vap->va_nlink = 1; 582 vap->va_uid = 0; 583 vap->va_gid = 0; 584 vap->va_bytes = vap->va_size = sizeof("curproc"); 585 break; 586 587 case Pproc: 588 vap->va_nlink = 2; 589 vap->va_uid = procp->p_ucred->cr_uid; 590 vap->va_gid = procp->p_ucred->cr_gid; 591 vap->va_bytes = vap->va_size = DEV_BSIZE; 592 break; 593 594 case Pfile: 595 error = EOPNOTSUPP; 596 break; 597 598 case Pmem: 599 vap->va_bytes = vap->va_size = 600 ctob(procp->p_vmspace->vm_tsize + 601 procp->p_vmspace->vm_dsize + 602 procp->p_vmspace->vm_ssize); 603 break; 604 605 #if defined(PT_GETREGS) || defined(PT_SETREGS) 606 case Pregs: 607 vap->va_bytes = vap->va_size = sizeof(struct reg); 608 break; 609 #endif 610 611 #if defined(PT_GETFPREGS) || defined(PT_SETFPREGS) 612 case Pfpregs: 613 vap->va_bytes = vap->va_size = sizeof(struct fpreg); 614 break; 615 #endif 616 617 case Pctl: 618 case Pstatus: 619 case Pnote: 620 case Pnotepg: 621 case Pmap: 622 case Pcmdline: 623 vap->va_bytes = vap->va_size = 0; 624 break; 625 626 default: 627 panic("procfs_getattr"); 628 } 629 630 return (error); 631 } 632 633 /*ARGSUSED*/ 634 int 635 procfs_setattr(v) 636 void *v; 637 { 638 /* 639 * just fake out attribute setting 640 * it's not good to generate an error 641 * return, otherwise things like creat() 642 * will fail when they try to set the 643 * file length to 0. worse, this means 644 * that echo $note > /proc/$pid/note will fail. 645 */ 646 647 return (0); 648 } 649 650 /* 651 * implement access checking. 652 * 653 * actually, the check for super-user is slightly 654 * broken since it will allow read access to write-only 655 * objects. this doesn't cause any particular trouble 656 * but does mean that the i/o entry points need to check 657 * that the operation really does make sense. 658 */ 659 int 660 procfs_access(v) 661 void *v; 662 { 663 struct vop_access_args /* { 664 struct vnode *a_vp; 665 int a_mode; 666 struct ucred *a_cred; 667 struct proc *a_p; 668 } */ *ap = v; 669 struct vattr va; 670 int error; 671 672 if ((error = VOP_GETATTR(ap->a_vp, &va, ap->a_cred, ap->a_p)) != 0) 673 return (error); 674 675 return (vaccess(va.va_type, va.va_mode, 676 va.va_uid, va.va_gid, ap->a_mode, ap->a_cred)); 677 } 678 679 /* 680 * lookup. this is incredibly complicated in the 681 * general case, however for most pseudo-filesystems 682 * very little needs to be done. 683 * 684 * Locking isn't hard here, just poorly documented. 685 * 686 * If we're looking up ".", just vref the parent & return it. 687 * 688 * If we're looking up "..", unlock the parent, and lock "..". If everything 689 * went ok, and we're on the last component and the caller requested the 690 * parent locked, try to re-lock the parent. We do this to prevent lock 691 * races. 692 * 693 * For anything else, get the needed node. Then unlock the parent if not 694 * the last component or not LOCKPARENT (i.e. if we wouldn't re-lock the 695 * parent in the .. case). 696 * 697 * We try to exit with the parent locked in error cases. 698 */ 699 int 700 procfs_lookup(v) 701 void *v; 702 { 703 struct vop_lookup_args /* { 704 struct vnode * a_dvp; 705 struct vnode ** a_vpp; 706 struct componentname * a_cnp; 707 } */ *ap = v; 708 struct componentname *cnp = ap->a_cnp; 709 struct vnode **vpp = ap->a_vpp; 710 struct vnode *dvp = ap->a_dvp; 711 const char *pname = cnp->cn_nameptr; 712 struct proc_target *pt; 713 struct vnode *fvp; 714 pid_t pid; 715 struct pfsnode *pfs; 716 struct proc *p; 717 int i, error, wantpunlock, iscurproc = 0, isself = 0; 718 719 *vpp = NULL; 720 cnp->cn_flags &= ~PDIRUNLOCK; 721 722 if (cnp->cn_nameiop == DELETE || cnp->cn_nameiop == RENAME) 723 return (EROFS); 724 725 if (cnp->cn_namelen == 1 && *pname == '.') { 726 *vpp = dvp; 727 VREF(dvp); 728 return (0); 729 } 730 731 wantpunlock = (~cnp->cn_flags & (LOCKPARENT | ISLASTCN)); 732 pfs = VTOPFS(dvp); 733 switch (pfs->pfs_type) { 734 case Proot: 735 /* 736 * Shouldn't get here with .. in the root node. 737 */ 738 if (cnp->cn_flags & ISDOTDOT) 739 return (EIO); 740 741 iscurproc = CNEQ(cnp, "curproc", 7); 742 isself = CNEQ(cnp, "self", 4); 743 744 if (iscurproc || isself) { 745 error = procfs_allocvp(dvp->v_mount, vpp, 0, 746 iscurproc ? Pcurproc : Pself); 747 if ((error == 0) && (wantpunlock)) { 748 VOP_UNLOCK(dvp, 0); 749 cnp->cn_flags |= PDIRUNLOCK; 750 } 751 return (error); 752 } 753 754 pid = atopid(pname, cnp->cn_namelen); 755 if (pid == NO_PID) 756 break; 757 758 p = PFIND(pid); 759 if (p == 0) 760 break; 761 762 error = procfs_allocvp(dvp->v_mount, vpp, pid, Pproc); 763 if ((error == 0) && (wantpunlock)) { 764 VOP_UNLOCK(dvp, 0); 765 cnp->cn_flags |= PDIRUNLOCK; 766 } 767 return (error); 768 769 case Pproc: 770 /* 771 * do the .. dance. We unlock the directory, and then 772 * get the root dir. That will automatically return .. 773 * locked. Then if the caller wanted dvp locked, we 774 * re-lock. 775 */ 776 if (cnp->cn_flags & ISDOTDOT) { 777 VOP_UNLOCK(dvp, 0); 778 cnp->cn_flags |= PDIRUNLOCK; 779 error = procfs_root(dvp->v_mount, vpp); 780 if ((error == 0) && (wantpunlock == 0) && 781 ((error = vn_lock(dvp, LK_EXCLUSIVE)) == 0)) 782 cnp->cn_flags &= ~PDIRUNLOCK; 783 return (error); 784 } 785 786 p = PFIND(pfs->pfs_pid); 787 if (p == 0) 788 break; 789 790 for (pt = proc_targets, i = 0; i < nproc_targets; pt++, i++) { 791 if (cnp->cn_namelen == pt->pt_namlen && 792 memcmp(pt->pt_name, pname, cnp->cn_namelen) == 0 && 793 (pt->pt_valid == NULL || (*pt->pt_valid)(p))) 794 goto found; 795 } 796 break; 797 798 found: 799 if (pt->pt_pfstype == Pfile) { 800 fvp = procfs_findtextvp(p); 801 /* We already checked that it exists. */ 802 VREF(fvp); 803 vn_lock(fvp, LK_EXCLUSIVE | LK_RETRY); 804 if (wantpunlock) { 805 VOP_UNLOCK(dvp, 0); 806 cnp->cn_flags |= PDIRUNLOCK; 807 } 808 *vpp = fvp; 809 return (0); 810 } 811 812 error = procfs_allocvp(dvp->v_mount, vpp, pfs->pfs_pid, 813 pt->pt_pfstype); 814 if ((error == 0) && (wantpunlock)) { 815 VOP_UNLOCK(dvp, 0); 816 cnp->cn_flags |= PDIRUNLOCK; 817 } 818 return (error); 819 820 default: 821 return (ENOTDIR); 822 } 823 824 return (cnp->cn_nameiop == LOOKUP ? ENOENT : EROFS); 825 } 826 827 int 828 procfs_validfile(p) 829 struct proc *p; 830 { 831 832 return (procfs_findtextvp(p) != NULLVP); 833 } 834 835 /* 836 * readdir returns directory entries from pfsnode (vp). 837 * 838 * the strategy here with procfs is to generate a single 839 * directory entry at a time (struct dirent) and then 840 * copy that out to userland using uiomove. a more efficent 841 * though more complex implementation, would try to minimize 842 * the number of calls to uiomove(). for procfs, this is 843 * hardly worth the added code complexity. 844 * 845 * this should just be done through read() 846 */ 847 int 848 procfs_readdir(v) 849 void *v; 850 { 851 struct vop_readdir_args /* { 852 struct vnode *a_vp; 853 struct uio *a_uio; 854 struct ucred *a_cred; 855 int *a_eofflag; 856 off_t **a_cookies; 857 int *a_ncookies; 858 } */ *ap = v; 859 struct uio *uio = ap->a_uio; 860 struct dirent d; 861 struct pfsnode *pfs; 862 off_t i; 863 int error; 864 off_t *cookies = NULL; 865 int ncookies; 866 867 pfs = VTOPFS(ap->a_vp); 868 869 if (uio->uio_resid < UIO_MX) 870 return (EINVAL); 871 if (uio->uio_offset < 0) 872 return (EINVAL); 873 874 error = 0; 875 i = uio->uio_offset; 876 memset((caddr_t)&d, 0, UIO_MX); 877 d.d_reclen = UIO_MX; 878 ncookies = uio->uio_resid / UIO_MX; 879 880 switch (pfs->pfs_type) { 881 /* 882 * this is for the process-specific sub-directories. 883 * all that is needed to is copy out all the entries 884 * from the procent[] table (top of this file). 885 */ 886 case Pproc: { 887 struct proc *p; 888 struct proc_target *pt; 889 890 if (i >= nproc_targets) 891 return 0; 892 893 p = PFIND(pfs->pfs_pid); 894 if (p == NULL) 895 break; 896 897 if (ap->a_ncookies) { 898 ncookies = min(ncookies, (nproc_targets - i)); 899 MALLOC(cookies, off_t *, ncookies * sizeof (off_t), 900 M_TEMP, M_WAITOK); 901 *ap->a_cookies = cookies; 902 } 903 904 for (pt = &proc_targets[i]; 905 uio->uio_resid >= UIO_MX && i < nproc_targets; pt++, i++) { 906 if (pt->pt_valid && (*pt->pt_valid)(p) == 0) 907 continue; 908 909 d.d_fileno = PROCFS_FILENO(pfs->pfs_pid, pt->pt_pfstype); 910 d.d_namlen = pt->pt_namlen; 911 memcpy(d.d_name, pt->pt_name, pt->pt_namlen + 1); 912 d.d_type = pt->pt_type; 913 914 if ((error = uiomove((caddr_t)&d, UIO_MX, uio)) != 0) 915 break; 916 if (cookies) 917 *cookies++ = i + 1; 918 } 919 920 break; 921 } 922 923 /* 924 * this is for the root of the procfs filesystem 925 * what is needed are special entries for "curproc" 926 * and "self" followed by an entry for each process 927 * on allproc 928 #ifdef PROCFS_ZOMBIE 929 * and deadproc and zombproc. 930 #endif 931 */ 932 933 case Proot: { 934 int pcnt = i, nc = 0; 935 const struct proclist_desc *pd; 936 volatile struct proc *p; 937 938 if (pcnt > 3) 939 pcnt = 3; 940 if (ap->a_ncookies) { 941 /* 942 * XXX Potentially allocating too much space here, 943 * but I'm lazy. This loop needs some work. 944 */ 945 MALLOC(cookies, off_t *, ncookies * sizeof (off_t), 946 M_TEMP, M_WAITOK); 947 *ap->a_cookies = cookies; 948 } 949 /* 950 * XXX: THIS LOOP ASSUMES THAT allproc IS THE FIRST 951 * PROCLIST IN THE proclists! 952 */ 953 proclist_lock_read(); 954 pd = proclists; 955 #ifdef PROCFS_ZOMBIE 956 again: 957 #endif 958 for (p = LIST_FIRST(pd->pd_list); 959 p != NULL && uio->uio_resid >= UIO_MX; i++, pcnt++) { 960 switch (i) { 961 case 0: /* `.' */ 962 case 1: /* `..' */ 963 d.d_fileno = PROCFS_FILENO(0, Proot); 964 d.d_namlen = i + 1; 965 memcpy(d.d_name, "..", d.d_namlen); 966 d.d_name[i + 1] = '\0'; 967 d.d_type = DT_DIR; 968 break; 969 970 case 2: 971 d.d_fileno = PROCFS_FILENO(0, Pcurproc); 972 d.d_namlen = sizeof("curproc") - 1; 973 memcpy(d.d_name, "curproc", sizeof("curproc")); 974 d.d_type = DT_LNK; 975 break; 976 977 case 3: 978 d.d_fileno = PROCFS_FILENO(0, Pself); 979 d.d_namlen = sizeof("self") - 1; 980 memcpy(d.d_name, "self", sizeof("self")); 981 d.d_type = DT_LNK; 982 break; 983 984 default: 985 while (pcnt < i) { 986 pcnt++; 987 p = LIST_NEXT(p, p_list); 988 if (!p) 989 goto done; 990 } 991 d.d_fileno = PROCFS_FILENO(p->p_pid, Pproc); 992 d.d_namlen = sprintf(d.d_name, "%ld", 993 (long)p->p_pid); 994 d.d_type = DT_REG; 995 p = p->p_list.le_next; 996 break; 997 } 998 999 if ((error = uiomove((caddr_t)&d, UIO_MX, uio)) != 0) 1000 break; 1001 nc++; 1002 if (cookies) 1003 *cookies++ = i + 1; 1004 } 1005 done: 1006 1007 #ifdef PROCFS_ZOMBIE 1008 pd++; 1009 if (p == NULL && pd->pd_list != NULL) 1010 goto again; 1011 #endif 1012 proclist_unlock_read(); 1013 ncookies = nc; 1014 1015 break; 1016 1017 } 1018 1019 default: 1020 error = ENOTDIR; 1021 break; 1022 } 1023 1024 if (ap->a_ncookies) { 1025 if (error) { 1026 if (cookies) 1027 FREE(*ap->a_cookies, M_TEMP); 1028 *ap->a_ncookies = 0; 1029 *ap->a_cookies = NULL; 1030 } else 1031 *ap->a_ncookies = ncookies; 1032 } 1033 uio->uio_offset = i; 1034 return (error); 1035 } 1036 1037 /* 1038 * readlink reads the link of `curproc' 1039 */ 1040 int 1041 procfs_readlink(v) 1042 void *v; 1043 { 1044 struct vop_readlink_args *ap = v; 1045 char buf[16]; /* should be enough */ 1046 int len; 1047 1048 if (VTOPFS(ap->a_vp)->pfs_fileno == PROCFS_FILENO(0, Pcurproc)) 1049 len = sprintf(buf, "%ld", (long)curproc->p_pid); 1050 else if (VTOPFS(ap->a_vp)->pfs_fileno == PROCFS_FILENO(0, Pself)) 1051 len = sprintf(buf, "%s", "curproc"); 1052 else 1053 return (EINVAL); 1054 1055 return (uiomove((caddr_t)buf, len, ap->a_uio)); 1056 } 1057 1058 /* 1059 * convert decimal ascii to pid_t 1060 */ 1061 static pid_t 1062 atopid(b, len) 1063 const char *b; 1064 u_int len; 1065 { 1066 pid_t p = 0; 1067 1068 while (len--) { 1069 char c = *b++; 1070 if (c < '0' || c > '9') 1071 return (NO_PID); 1072 p = 10 * p + (c - '0'); 1073 if (p > PID_MAX) 1074 return (NO_PID); 1075 } 1076 1077 return (p); 1078 } 1079