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