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