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