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