4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21
22 /*
23 * Copyright (c) 1989, 2010, Oracle and/or its affiliates. All rights reserved.
24 * Copyright (c) 2014, Joyent, Inc. All rights reserved.
25 */
26
27 /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
28 /* All Rights Reserved */
29
30 #include <sys/types.h>
31 #include <sys/param.h>
32 #include <sys/time.h>
33 #include <sys/cred.h>
34 #include <sys/policy.h>
35 #include <sys/debug.h>
36 #include <sys/dirent.h>
37 #include <sys/errno.h>
38 #include <sys/file.h>
39 #include <sys/inline.h>
40 #include <sys/kmem.h>
41 #include <sys/pathname.h>
42 #include <sys/proc.h>
43 #include <sys/brand.h>
44 #include <sys/signal.h>
79
80 /*
81 * Created by prinit.
82 */
83 vnodeops_t *prvnodeops;
84
85 /*
86 * Directory characteristics (patterned after the s5 file system).
87 */
88 #define PRROOTINO 2
89
90 #define PRDIRSIZE 14
91 struct prdirect {
92 ushort_t d_ino;
93 char d_name[PRDIRSIZE];
94 };
95
96 #define PRSDSIZE (sizeof (struct prdirect))
97
98 /*
99 * Directory characteristics.
100 */
101 typedef struct prdirent {
102 ino64_t d_ino; /* "inode number" of entry */
103 off64_t d_off; /* offset of disk directory entry */
104 unsigned short d_reclen; /* length of this record */
105 char d_name[14]; /* name of file */
106 } prdirent_t;
107
108 /*
109 * Contents of a /proc/<pid> directory.
110 * Reuse d_ino field for the /proc file type.
111 */
112 static prdirent_t piddir[] = {
113 { PR_PIDDIR, 1 * sizeof (prdirent_t), sizeof (prdirent_t),
114 "." },
115 { PR_PROCDIR, 2 * sizeof (prdirent_t), sizeof (prdirent_t),
116 ".." },
117 { PR_AS, 3 * sizeof (prdirent_t), sizeof (prdirent_t),
118 "as" },
149 { PR_CURDIR, 19 * sizeof (prdirent_t), sizeof (prdirent_t),
150 "cwd" },
151 { PR_ROOTDIR, 20 * sizeof (prdirent_t), sizeof (prdirent_t),
152 "root" },
153 { PR_FDDIR, 21 * sizeof (prdirent_t), sizeof (prdirent_t),
154 "fd" },
155 { PR_OBJECTDIR, 22 * sizeof (prdirent_t), sizeof (prdirent_t),
156 "object" },
157 { PR_LWPDIR, 23 * sizeof (prdirent_t), sizeof (prdirent_t),
158 "lwp" },
159 { PR_PRIV, 24 * sizeof (prdirent_t), sizeof (prdirent_t),
160 "priv" },
161 { PR_PATHDIR, 25 * sizeof (prdirent_t), sizeof (prdirent_t),
162 "path" },
163 { PR_CTDIR, 26 * sizeof (prdirent_t), sizeof (prdirent_t),
164 "contracts" },
165 #if defined(__x86)
166 { PR_LDT, 27 * sizeof (prdirent_t), sizeof (prdirent_t),
167 "ldt" },
168 #endif
169 };
170
171 #define NPIDDIRFILES (sizeof (piddir) / sizeof (piddir[0]) - 2)
172
173 /*
174 * Contents of a /proc/<pid>/lwp/<lwpid> directory.
175 */
176 static prdirent_t lwpiddir[] = {
177 { PR_LWPIDDIR, 1 * sizeof (prdirent_t), sizeof (prdirent_t),
178 "." },
179 { PR_LWPDIR, 2 * sizeof (prdirent_t), sizeof (prdirent_t),
180 ".." },
181 { PR_LWPCTL, 3 * sizeof (prdirent_t), sizeof (prdirent_t),
182 "lwpctl" },
183 { PR_LWPSTATUS, 4 * sizeof (prdirent_t), sizeof (prdirent_t),
184 "lwpstatus" },
185 { PR_LWPSINFO, 5 * sizeof (prdirent_t), sizeof (prdirent_t),
186 "lwpsinfo" },
187 { PR_LWPUSAGE, 6 * sizeof (prdirent_t), sizeof (prdirent_t),
188 "lwpusage" },
565 if (killproc)
566 sigtoproc(p, NULL, SIGKILL);
567 else
568 allsetrun(p);
569 }
570
571 prunlock(pnp);
572 return (0);
573 }
574
575 /*
576 * Array of read functions, indexed by /proc file type.
577 */
578 static int pr_read_inval(), pr_read_as(), pr_read_status(),
579 pr_read_lstatus(), pr_read_psinfo(), pr_read_lpsinfo(),
580 pr_read_map(), pr_read_rmap(), pr_read_xmap(),
581 pr_read_cred(), pr_read_sigact(), pr_read_auxv(),
582 #if defined(__x86)
583 pr_read_ldt(),
584 #endif
585 pr_read_usage(), pr_read_lusage(), pr_read_pagedata(),
586 pr_read_watch(), pr_read_lwpstatus(), pr_read_lwpsinfo(),
587 pr_read_lwpusage(), pr_read_xregs(), pr_read_priv(),
588 pr_read_spymaster(),
589 #if defined(__sparc)
590 pr_read_gwindows(), pr_read_asrs(),
591 #endif
592 pr_read_piddir(), pr_read_pidfile(), pr_read_opagedata();
593
594 static int (*pr_read_function[PR_NFILES])() = {
595 pr_read_inval, /* /proc */
596 pr_read_inval, /* /proc/self */
597 pr_read_piddir, /* /proc/<pid> (old /proc read()) */
598 pr_read_as, /* /proc/<pid>/as */
599 pr_read_inval, /* /proc/<pid>/ctl */
600 pr_read_status, /* /proc/<pid>/status */
601 pr_read_lstatus, /* /proc/<pid>/lstatus */
602 pr_read_psinfo, /* /proc/<pid>/psinfo */
603 pr_read_lpsinfo, /* /proc/<pid>/lpsinfo */
604 pr_read_map, /* /proc/<pid>/map */
605 pr_read_rmap, /* /proc/<pid>/rmap */
606 pr_read_xmap, /* /proc/<pid>/xmap */
607 pr_read_cred, /* /proc/<pid>/cred */
608 pr_read_sigact, /* /proc/<pid>/sigact */
609 pr_read_auxv, /* /proc/<pid>/auxv */
610 #if defined(__x86)
611 pr_read_ldt, /* /proc/<pid>/ldt */
612 #endif
613 pr_read_usage, /* /proc/<pid>/usage */
614 pr_read_lusage, /* /proc/<pid>/lusage */
615 pr_read_pagedata, /* /proc/<pid>/pagedata */
616 pr_read_watch, /* /proc/<pid>/watch */
617 pr_read_inval, /* /proc/<pid>/cwd */
618 pr_read_inval, /* /proc/<pid>/root */
619 pr_read_inval, /* /proc/<pid>/fd */
620 pr_read_inval, /* /proc/<pid>/fd/nn */
621 pr_read_inval, /* /proc/<pid>/object */
622 pr_read_inval, /* /proc/<pid>/object/xxx */
623 pr_read_inval, /* /proc/<pid>/lwp */
624 pr_read_inval, /* /proc/<pid>/lwp/<lwpid> */
625 pr_read_inval, /* /proc/<pid>/lwp/<lwpid>/lwpctl */
626 pr_read_lwpstatus, /* /proc/<pid>/lwp/<lwpid>/lwpstatus */
627 pr_read_lwpsinfo, /* /proc/<pid>/lwp/<lwpid>/lwpsinfo */
628 pr_read_lwpusage, /* /proc/<pid>/lwp/<lwpid>/lwpusage */
629 pr_read_xregs, /* /proc/<pid>/lwp/<lwpid>/xregs */
630 pr_read_inval, /* /proc/<pid>/lwp/<lwpid>/templates */
631 pr_read_inval, /* /proc/<pid>/lwp/<lwpid>/templates/<id> */
632 pr_read_spymaster, /* /proc/<pid>/lwp/<lwpid>/spymaster */
655 */
656 return (EINVAL);
657 }
658
659 static int
660 pr_uioread(void *base, long count, uio_t *uiop)
661 {
662 int error = 0;
663
664 ASSERT(count >= 0);
665 count -= uiop->uio_offset;
666 if (count > 0 && uiop->uio_offset >= 0) {
667 error = uiomove((char *)base + uiop->uio_offset,
668 count, UIO_READ, uiop);
669 }
670
671 return (error);
672 }
673
674 static int
675 pr_read_as(prnode_t *pnp, uio_t *uiop)
676 {
677 int error;
678
679 ASSERT(pnp->pr_type == PR_AS);
680
681 if ((error = prlock(pnp, ZNO)) == 0) {
682 proc_t *p = pnp->pr_common->prc_proc;
683 struct as *as = p->p_as;
684
685 /*
686 * /proc I/O cannot be done to a system process.
687 * A 32-bit process cannot read a 64-bit process.
688 */
689 if ((p->p_flag & SSYS) || as == &kas) {
690 error = 0;
691 #ifdef _SYSCALL32_IMPL
692 } else if (curproc->p_model == DATAMODEL_ILP32 &&
693 PROCESS_NOT_32BIT(p)) {
694 error = EOVERFLOW;
1750
1751 static int (*pr_read_function_32[PR_NFILES])() = {
1752 pr_read_inval, /* /proc */
1753 pr_read_inval, /* /proc/self */
1754 pr_read_piddir, /* /proc/<pid> (old /proc read()) */
1755 pr_read_as, /* /proc/<pid>/as */
1756 pr_read_inval, /* /proc/<pid>/ctl */
1757 pr_read_status_32, /* /proc/<pid>/status */
1758 pr_read_lstatus_32, /* /proc/<pid>/lstatus */
1759 pr_read_psinfo_32, /* /proc/<pid>/psinfo */
1760 pr_read_lpsinfo_32, /* /proc/<pid>/lpsinfo */
1761 pr_read_map_32, /* /proc/<pid>/map */
1762 pr_read_rmap_32, /* /proc/<pid>/rmap */
1763 pr_read_xmap_32, /* /proc/<pid>/xmap */
1764 pr_read_cred, /* /proc/<pid>/cred */
1765 pr_read_sigact_32, /* /proc/<pid>/sigact */
1766 pr_read_auxv_32, /* /proc/<pid>/auxv */
1767 #if defined(__x86)
1768 pr_read_ldt, /* /proc/<pid>/ldt */
1769 #endif
1770 pr_read_usage_32, /* /proc/<pid>/usage */
1771 pr_read_lusage_32, /* /proc/<pid>/lusage */
1772 pr_read_pagedata_32, /* /proc/<pid>/pagedata */
1773 pr_read_watch_32, /* /proc/<pid>/watch */
1774 pr_read_inval, /* /proc/<pid>/cwd */
1775 pr_read_inval, /* /proc/<pid>/root */
1776 pr_read_inval, /* /proc/<pid>/fd */
1777 pr_read_inval, /* /proc/<pid>/fd/nn */
1778 pr_read_inval, /* /proc/<pid>/object */
1779 pr_read_inval, /* /proc/<pid>/object/xxx */
1780 pr_read_inval, /* /proc/<pid>/lwp */
1781 pr_read_inval, /* /proc/<pid>/lwp/<lwpid> */
1782 pr_read_inval, /* /proc/<pid>/lwp/<lwpid>/lwpctl */
1783 pr_read_lwpstatus_32, /* /proc/<pid>/lwp/<lwpid>/lwpstatus */
1784 pr_read_lwpsinfo_32, /* /proc/<pid>/lwp/<lwpid>/lwpsinfo */
1785 pr_read_lwpusage_32, /* /proc/<pid>/lwp/<lwpid>/lwpusage */
1786 pr_read_xregs, /* /proc/<pid>/lwp/<lwpid>/xregs */
1787 pr_read_inval, /* /proc/<pid>/lwp/<lwpid>/templates */
1788 pr_read_inval, /* /proc/<pid>/lwp/<lwpid>/templates/<id> */
1789 pr_read_spymaster_32, /* /proc/<pid>/lwp/<lwpid>/spymaster */
2669 {
2670 prnode_t *pnp = VTOP(vp);
2671
2672 ASSERT(pnp->pr_type < PR_NFILES);
2673
2674 #ifdef _SYSCALL32_IMPL
2675 /*
2676 * What is read from the /proc files depends on the data
2677 * model of the caller. An LP64 process will see LP64
2678 * data. An ILP32 process will see ILP32 data.
2679 */
2680 if (curproc->p_model == DATAMODEL_LP64)
2681 return (pr_read_function[pnp->pr_type](pnp, uiop));
2682 else
2683 return (pr_read_function_32[pnp->pr_type](pnp, uiop));
2684 #else
2685 return (pr_read_function[pnp->pr_type](pnp, uiop));
2686 #endif
2687 }
2688
2689 /* ARGSUSED */
2690 static int
2691 prwrite(vnode_t *vp, uio_t *uiop, int ioflag, cred_t *cr, caller_context_t *ct)
2692 {
2693 prnode_t *pnp = VTOP(vp);
2694 int old = 0;
2695 int error;
2696 ssize_t resid;
2697
2698 ASSERT(pnp->pr_type < PR_NFILES);
2699
2700 /*
2701 * Only a handful of /proc files are writable, enumerate them here.
2702 */
2703 switch (pnp->pr_type) {
2704 case PR_PIDDIR: /* directory write()s: visceral revulsion. */
2705 ASSERT(pnp->pr_pidfile != NULL);
2706 /* use the underlying PR_PIDFILE to write the process */
2707 vp = pnp->pr_pidfile;
2708 pnp = VTOP(vp);
2747 * Perform the action on the control file
2748 * by passing curthreads credentials
2749 * and not target process's credentials.
2750 */
2751 #ifdef _SYSCALL32_IMPL
2752 if (curproc->p_model == DATAMODEL_ILP32)
2753 error = prwritectl32(vp, uiop, CRED());
2754 else
2755 error = prwritectl(vp, uiop, CRED());
2756 #else
2757 error = prwritectl(vp, uiop, CRED());
2758 #endif
2759 /*
2760 * This hack makes sure that the EINTR is passed
2761 * all the way back to the caller's write() call.
2762 */
2763 if (error == EINTR)
2764 uiop->uio_resid = resid;
2765 return (error);
2766
2767 default:
2768 return ((vp->v_type == VDIR)? EISDIR : EBADF);
2769 }
2770 /* NOTREACHED */
2771 }
2772
2773 static int
2774 prgetattr(vnode_t *vp, vattr_t *vap, int flags, cred_t *cr,
2775 caller_context_t *ct)
2776 {
2777 prnode_t *pnp = VTOP(vp);
2778 prnodetype_t type = pnp->pr_type;
2779 prcommon_t *pcp;
2780 proc_t *p;
2781 struct as *as;
2782 int error;
2783 vnode_t *rvp;
2784 timestruc_t now;
2785 extern uint_t nproc;
2786 int ngroups;
3030 break;
3031 case PR_CRED:
3032 mutex_enter(&p->p_crlock);
3033 vap->va_size = sizeof (prcred_t);
3034 ngroups = crgetngroups(p->p_cred);
3035 if (ngroups > 1)
3036 vap->va_size += (ngroups - 1) * sizeof (gid_t);
3037 mutex_exit(&p->p_crlock);
3038 break;
3039 case PR_PRIV:
3040 vap->va_size = prgetprivsize();
3041 break;
3042 case PR_SIGACT:
3043 nsig = PROC_IS_BRANDED(curproc)? BROP(curproc)->b_nsig : NSIG;
3044 vap->va_size = (nsig-1) *
3045 PR_OBJSIZE(struct sigaction32, struct sigaction);
3046 break;
3047 case PR_AUXV:
3048 vap->va_size = __KERN_NAUXV_IMPL * PR_OBJSIZE(auxv32_t, auxv_t);
3049 break;
3050 #if defined(__x86)
3051 case PR_LDT:
3052 mutex_exit(&p->p_lock);
3053 mutex_enter(&p->p_ldtlock);
3054 vap->va_size = prnldt(p) * sizeof (struct ssd);
3055 mutex_exit(&p->p_ldtlock);
3056 mutex_enter(&p->p_lock);
3057 break;
3058 #endif
3059 case PR_USAGE:
3060 vap->va_size = PR_OBJSIZE(prusage32_t, prusage_t);
3061 break;
3062 case PR_LUSAGE:
3063 vap->va_size = PR_OBJSIZE(prheader32_t, prheader_t) +
3064 (p->p_lwpcnt + 1) * PR_OBJSPAN(prusage32_t, prusage_t);
3065 break;
3066 case PR_PAGEDATA:
3067 if ((p->p_flag & SSYS) || (as = p->p_as) == &kas)
3068 vap->va_size = 0;
3069 else {
3205 * Disallow access to fds with other than existing open modes.
3206 */
3207 rvp = pnp->pr_realvp;
3208 vtype = rvp->v_type;
3209 vmode = pnp->pr_mode;
3210 if ((type == PR_OBJECT && (mode & VWRITE)) ||
3211 (type == PR_FD && vtype != VREG && vtype != VDIR) ||
3212 (type == PR_FD && (vmode & mode) != mode &&
3213 secpolicy_proc_access(cr) != 0))
3214 return (EACCES);
3215 return (VOP_ACCESS(rvp, mode, flags, cr, ct));
3216
3217 case PR_PSINFO: /* these files can be read by anyone */
3218 case PR_LPSINFO:
3219 case PR_LWPSINFO:
3220 case PR_LWPDIR:
3221 case PR_LWPIDDIR:
3222 case PR_USAGE:
3223 case PR_LUSAGE:
3224 case PR_LWPUSAGE:
3225 p = pr_p_lock(pnp);
3226 mutex_exit(&pr_pidlock);
3227 if (p == NULL)
3228 return (ENOENT);
3229 prunlock(pnp);
3230 break;
3231
3232 default:
3233 /*
3234 * Except for the world-readable files above,
3235 * only /proc/pid exists if the process is a zombie.
3236 */
3237 if ((error = prlock(pnp,
3238 (type == PR_PIDDIR)? ZYES : ZNO)) != 0)
3239 return (error);
3240 p = pnp->pr_common->prc_proc;
3241 if (p != curproc)
3242 error = priv_proc_cred_perm(cr, p, NULL, mode);
3243
3244 if (error != 0 || p == curproc || (p->p_flag & SSYS) ||
3290
3291 static vnode_t *(*pr_lookup_function[PR_NFILES])() = {
3292 pr_lookup_procdir, /* /proc */
3293 pr_lookup_notdir, /* /proc/self */
3294 pr_lookup_piddir, /* /proc/<pid> */
3295 pr_lookup_notdir, /* /proc/<pid>/as */
3296 pr_lookup_notdir, /* /proc/<pid>/ctl */
3297 pr_lookup_notdir, /* /proc/<pid>/status */
3298 pr_lookup_notdir, /* /proc/<pid>/lstatus */
3299 pr_lookup_notdir, /* /proc/<pid>/psinfo */
3300 pr_lookup_notdir, /* /proc/<pid>/lpsinfo */
3301 pr_lookup_notdir, /* /proc/<pid>/map */
3302 pr_lookup_notdir, /* /proc/<pid>/rmap */
3303 pr_lookup_notdir, /* /proc/<pid>/xmap */
3304 pr_lookup_notdir, /* /proc/<pid>/cred */
3305 pr_lookup_notdir, /* /proc/<pid>/sigact */
3306 pr_lookup_notdir, /* /proc/<pid>/auxv */
3307 #if defined(__x86)
3308 pr_lookup_notdir, /* /proc/<pid>/ldt */
3309 #endif
3310 pr_lookup_notdir, /* /proc/<pid>/usage */
3311 pr_lookup_notdir, /* /proc/<pid>/lusage */
3312 pr_lookup_notdir, /* /proc/<pid>/pagedata */
3313 pr_lookup_notdir, /* /proc/<pid>/watch */
3314 pr_lookup_notdir, /* /proc/<pid>/cwd */
3315 pr_lookup_notdir, /* /proc/<pid>/root */
3316 pr_lookup_fddir, /* /proc/<pid>/fd */
3317 pr_lookup_notdir, /* /proc/<pid>/fd/nn */
3318 pr_lookup_objectdir, /* /proc/<pid>/object */
3319 pr_lookup_notdir, /* /proc/<pid>/object/xxx */
3320 pr_lookup_lwpdir, /* /proc/<pid>/lwp */
3321 pr_lookup_lwpiddir, /* /proc/<pid>/lwp/<lwpid> */
3322 pr_lookup_notdir, /* /proc/<pid>/lwp/<lwpid>/lwpctl */
3323 pr_lookup_notdir, /* /proc/<pid>/lwp/<lwpid>/lwpstatus */
3324 pr_lookup_notdir, /* /proc/<pid>/lwp/<lwpid>/lwpsinfo */
3325 pr_lookup_notdir, /* /proc/<pid>/lwp/<lwpid>/lwpusage */
3326 pr_lookup_notdir, /* /proc/<pid>/lwp/<lwpid>/xregs */
3327 pr_lookup_tmpldir, /* /proc/<pid>/lwp/<lwpid>/templates */
3328 pr_lookup_notdir, /* /proc/<pid>/lwp/<lwpid>/templates/<id> */
3329 pr_lookup_notdir, /* /proc/<pid>/lwp/<lwpid>/spymaster */
4529 vp->v_type = VDIR;
4530 pnp->pr_mode = 0555; /* read-search by all */
4531 break;
4532
4533 case PR_AS:
4534 case PR_TMPL:
4535 pnp->pr_mode = 0600; /* read-write by owner only */
4536 break;
4537
4538 case PR_CTL:
4539 case PR_LWPCTL:
4540 pnp->pr_mode = 0200; /* write-only by owner only */
4541 break;
4542
4543 case PR_PIDFILE:
4544 case PR_LWPIDFILE:
4545 pnp->pr_mode = 0600; /* read-write by owner only */
4546 break;
4547
4548 case PR_PSINFO:
4549 case PR_LPSINFO:
4550 case PR_LWPSINFO:
4551 case PR_USAGE:
4552 case PR_LUSAGE:
4553 case PR_LWPUSAGE:
4554 pnp->pr_mode = 0444; /* read-only by all */
4555 break;
4556
4557 default:
4558 pnp->pr_mode = 0400; /* read-only by owner only */
4559 break;
4560 }
4561 vn_exists(vp);
4562 return (pnp);
4563 }
4564
4565 /*
4566 * Free the storage obtained from prgetnode().
4567 */
4568 void
4569 prfreenode(prnode_t *pnp)
4570 {
4571 vnode_t *vp;
4572 ulong_t nfiles;
4573
4639
4640 static int (*pr_readdir_function[PR_NFILES])() = {
4641 pr_readdir_procdir, /* /proc */
4642 pr_readdir_notdir, /* /proc/self */
4643 pr_readdir_piddir, /* /proc/<pid> */
4644 pr_readdir_notdir, /* /proc/<pid>/as */
4645 pr_readdir_notdir, /* /proc/<pid>/ctl */
4646 pr_readdir_notdir, /* /proc/<pid>/status */
4647 pr_readdir_notdir, /* /proc/<pid>/lstatus */
4648 pr_readdir_notdir, /* /proc/<pid>/psinfo */
4649 pr_readdir_notdir, /* /proc/<pid>/lpsinfo */
4650 pr_readdir_notdir, /* /proc/<pid>/map */
4651 pr_readdir_notdir, /* /proc/<pid>/rmap */
4652 pr_readdir_notdir, /* /proc/<pid>/xmap */
4653 pr_readdir_notdir, /* /proc/<pid>/cred */
4654 pr_readdir_notdir, /* /proc/<pid>/sigact */
4655 pr_readdir_notdir, /* /proc/<pid>/auxv */
4656 #if defined(__x86)
4657 pr_readdir_notdir, /* /proc/<pid>/ldt */
4658 #endif
4659 pr_readdir_notdir, /* /proc/<pid>/usage */
4660 pr_readdir_notdir, /* /proc/<pid>/lusage */
4661 pr_readdir_notdir, /* /proc/<pid>/pagedata */
4662 pr_readdir_notdir, /* /proc/<pid>/watch */
4663 pr_readdir_notdir, /* /proc/<pid>/cwd */
4664 pr_readdir_notdir, /* /proc/<pid>/root */
4665 pr_readdir_fddir, /* /proc/<pid>/fd */
4666 pr_readdir_notdir, /* /proc/<pid>/fd/nn */
4667 pr_readdir_objectdir, /* /proc/<pid>/object */
4668 pr_readdir_notdir, /* /proc/<pid>/object/xxx */
4669 pr_readdir_lwpdir, /* /proc/<pid>/lwp */
4670 pr_readdir_lwpiddir, /* /proc/<pid>/lwp/<lwpid> */
4671 pr_readdir_notdir, /* /proc/<pid>/lwp/<lwpid>/lwpctl */
4672 pr_readdir_notdir, /* /proc/<pid>/lwp/<lwpid>/lwpstatus */
4673 pr_readdir_notdir, /* /proc/<pid>/lwp/<lwpid>/lwpsinfo */
4674 pr_readdir_notdir, /* /proc/<pid>/lwp/<lwpid>/lwpusage */
4675 pr_readdir_notdir, /* /proc/<pid>/lwp/<lwpid>/xregs */
4676 pr_readdir_tmpldir, /* /proc/<pid>/lwp/<lwpid>/templates */
4677 pr_readdir_notdir, /* /proc/<pid>/lwp/<lwpid>/templates/<id> */
4678 pr_readdir_notdir, /* /proc/<pid>/lwp/<lwpid>/spymaster */
4788 if (pnp->pr_pcommon->prc_proc == NULL)
4789 return (ENOENT);
4790 if (uiop->uio_offset >= sizeof (piddir))
4791 goto out;
4792
4793 /*
4794 * Loop until user's request is satisfied, omitting some
4795 * files along the way if the process is a zombie.
4796 */
4797 for (dirp = &piddir[uiop->uio_offset / sizeof (prdirent_t)];
4798 uiop->uio_resid >= sizeof (prdirent_t) &&
4799 dirp < &piddir[NPIDDIRFILES+2];
4800 uiop->uio_offset = off + sizeof (prdirent_t), dirp++) {
4801 off = uiop->uio_offset;
4802 if (zombie) {
4803 switch (dirp->d_ino) {
4804 case PR_PIDDIR:
4805 case PR_PROCDIR:
4806 case PR_PSINFO:
4807 case PR_USAGE:
4808 break;
4809 default:
4810 continue;
4811 }
4812 }
4813 bcopy(dirp, &dirent, sizeof (prdirent_t));
4814 if (dirent.d_ino == PR_PROCDIR)
4815 dirent.d_ino = PRROOTINO;
4816 else
4817 dirent.d_ino = pmkino(0, pnp->pr_pcommon->prc_slot,
4818 dirent.d_ino);
4819 if ((error = uiomove((caddr_t)&dirent, sizeof (prdirent_t),
4820 UIO_READ, uiop)) != 0)
4821 return (error);
4822 }
4823 out:
4824 if (eofp)
4825 *eofp = (uiop->uio_offset >= sizeof (piddir));
4826 return (0);
4827 }
|
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21
22 /*
23 * Copyright (c) 1989, 2010, Oracle and/or its affiliates. All rights reserved.
24 * Copyright 2015, Joyent, Inc.
25 */
26
27 /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
28 /* All Rights Reserved */
29
30 #include <sys/types.h>
31 #include <sys/param.h>
32 #include <sys/time.h>
33 #include <sys/cred.h>
34 #include <sys/policy.h>
35 #include <sys/debug.h>
36 #include <sys/dirent.h>
37 #include <sys/errno.h>
38 #include <sys/file.h>
39 #include <sys/inline.h>
40 #include <sys/kmem.h>
41 #include <sys/pathname.h>
42 #include <sys/proc.h>
43 #include <sys/brand.h>
44 #include <sys/signal.h>
79
80 /*
81 * Created by prinit.
82 */
83 vnodeops_t *prvnodeops;
84
85 /*
86 * Directory characteristics (patterned after the s5 file system).
87 */
88 #define PRROOTINO 2
89
90 #define PRDIRSIZE 14
91 struct prdirect {
92 ushort_t d_ino;
93 char d_name[PRDIRSIZE];
94 };
95
96 #define PRSDSIZE (sizeof (struct prdirect))
97
98 /*
99 * Maximum length of the /proc/$$/argv file:
100 */
101 int prmaxargvlen = 4096;
102
103 /*
104 * Directory characteristics.
105 */
106 typedef struct prdirent {
107 ino64_t d_ino; /* "inode number" of entry */
108 off64_t d_off; /* offset of disk directory entry */
109 unsigned short d_reclen; /* length of this record */
110 char d_name[14]; /* name of file */
111 } prdirent_t;
112
113 /*
114 * Contents of a /proc/<pid> directory.
115 * Reuse d_ino field for the /proc file type.
116 */
117 static prdirent_t piddir[] = {
118 { PR_PIDDIR, 1 * sizeof (prdirent_t), sizeof (prdirent_t),
119 "." },
120 { PR_PROCDIR, 2 * sizeof (prdirent_t), sizeof (prdirent_t),
121 ".." },
122 { PR_AS, 3 * sizeof (prdirent_t), sizeof (prdirent_t),
123 "as" },
154 { PR_CURDIR, 19 * sizeof (prdirent_t), sizeof (prdirent_t),
155 "cwd" },
156 { PR_ROOTDIR, 20 * sizeof (prdirent_t), sizeof (prdirent_t),
157 "root" },
158 { PR_FDDIR, 21 * sizeof (prdirent_t), sizeof (prdirent_t),
159 "fd" },
160 { PR_OBJECTDIR, 22 * sizeof (prdirent_t), sizeof (prdirent_t),
161 "object" },
162 { PR_LWPDIR, 23 * sizeof (prdirent_t), sizeof (prdirent_t),
163 "lwp" },
164 { PR_PRIV, 24 * sizeof (prdirent_t), sizeof (prdirent_t),
165 "priv" },
166 { PR_PATHDIR, 25 * sizeof (prdirent_t), sizeof (prdirent_t),
167 "path" },
168 { PR_CTDIR, 26 * sizeof (prdirent_t), sizeof (prdirent_t),
169 "contracts" },
170 #if defined(__x86)
171 { PR_LDT, 27 * sizeof (prdirent_t), sizeof (prdirent_t),
172 "ldt" },
173 #endif
174 { PR_ARGV, 28 * sizeof (prdirent_t), sizeof (prdirent_t),
175 "argv" },
176 };
177
178 #define NPIDDIRFILES (sizeof (piddir) / sizeof (piddir[0]) - 2)
179
180 /*
181 * Contents of a /proc/<pid>/lwp/<lwpid> directory.
182 */
183 static prdirent_t lwpiddir[] = {
184 { PR_LWPIDDIR, 1 * sizeof (prdirent_t), sizeof (prdirent_t),
185 "." },
186 { PR_LWPDIR, 2 * sizeof (prdirent_t), sizeof (prdirent_t),
187 ".." },
188 { PR_LWPCTL, 3 * sizeof (prdirent_t), sizeof (prdirent_t),
189 "lwpctl" },
190 { PR_LWPSTATUS, 4 * sizeof (prdirent_t), sizeof (prdirent_t),
191 "lwpstatus" },
192 { PR_LWPSINFO, 5 * sizeof (prdirent_t), sizeof (prdirent_t),
193 "lwpsinfo" },
194 { PR_LWPUSAGE, 6 * sizeof (prdirent_t), sizeof (prdirent_t),
195 "lwpusage" },
572 if (killproc)
573 sigtoproc(p, NULL, SIGKILL);
574 else
575 allsetrun(p);
576 }
577
578 prunlock(pnp);
579 return (0);
580 }
581
582 /*
583 * Array of read functions, indexed by /proc file type.
584 */
585 static int pr_read_inval(), pr_read_as(), pr_read_status(),
586 pr_read_lstatus(), pr_read_psinfo(), pr_read_lpsinfo(),
587 pr_read_map(), pr_read_rmap(), pr_read_xmap(),
588 pr_read_cred(), pr_read_sigact(), pr_read_auxv(),
589 #if defined(__x86)
590 pr_read_ldt(),
591 #endif
592 pr_read_argv(),
593 pr_read_usage(), pr_read_lusage(), pr_read_pagedata(),
594 pr_read_watch(), pr_read_lwpstatus(), pr_read_lwpsinfo(),
595 pr_read_lwpusage(), pr_read_xregs(), pr_read_priv(),
596 pr_read_spymaster(),
597 #if defined(__sparc)
598 pr_read_gwindows(), pr_read_asrs(),
599 #endif
600 pr_read_piddir(), pr_read_pidfile(), pr_read_opagedata();
601
602 static int (*pr_read_function[PR_NFILES])() = {
603 pr_read_inval, /* /proc */
604 pr_read_inval, /* /proc/self */
605 pr_read_piddir, /* /proc/<pid> (old /proc read()) */
606 pr_read_as, /* /proc/<pid>/as */
607 pr_read_inval, /* /proc/<pid>/ctl */
608 pr_read_status, /* /proc/<pid>/status */
609 pr_read_lstatus, /* /proc/<pid>/lstatus */
610 pr_read_psinfo, /* /proc/<pid>/psinfo */
611 pr_read_lpsinfo, /* /proc/<pid>/lpsinfo */
612 pr_read_map, /* /proc/<pid>/map */
613 pr_read_rmap, /* /proc/<pid>/rmap */
614 pr_read_xmap, /* /proc/<pid>/xmap */
615 pr_read_cred, /* /proc/<pid>/cred */
616 pr_read_sigact, /* /proc/<pid>/sigact */
617 pr_read_auxv, /* /proc/<pid>/auxv */
618 #if defined(__x86)
619 pr_read_ldt, /* /proc/<pid>/ldt */
620 #endif
621 pr_read_argv, /* /proc/<pid>/argv */
622 pr_read_usage, /* /proc/<pid>/usage */
623 pr_read_lusage, /* /proc/<pid>/lusage */
624 pr_read_pagedata, /* /proc/<pid>/pagedata */
625 pr_read_watch, /* /proc/<pid>/watch */
626 pr_read_inval, /* /proc/<pid>/cwd */
627 pr_read_inval, /* /proc/<pid>/root */
628 pr_read_inval, /* /proc/<pid>/fd */
629 pr_read_inval, /* /proc/<pid>/fd/nn */
630 pr_read_inval, /* /proc/<pid>/object */
631 pr_read_inval, /* /proc/<pid>/object/xxx */
632 pr_read_inval, /* /proc/<pid>/lwp */
633 pr_read_inval, /* /proc/<pid>/lwp/<lwpid> */
634 pr_read_inval, /* /proc/<pid>/lwp/<lwpid>/lwpctl */
635 pr_read_lwpstatus, /* /proc/<pid>/lwp/<lwpid>/lwpstatus */
636 pr_read_lwpsinfo, /* /proc/<pid>/lwp/<lwpid>/lwpsinfo */
637 pr_read_lwpusage, /* /proc/<pid>/lwp/<lwpid>/lwpusage */
638 pr_read_xregs, /* /proc/<pid>/lwp/<lwpid>/xregs */
639 pr_read_inval, /* /proc/<pid>/lwp/<lwpid>/templates */
640 pr_read_inval, /* /proc/<pid>/lwp/<lwpid>/templates/<id> */
641 pr_read_spymaster, /* /proc/<pid>/lwp/<lwpid>/spymaster */
664 */
665 return (EINVAL);
666 }
667
668 static int
669 pr_uioread(void *base, long count, uio_t *uiop)
670 {
671 int error = 0;
672
673 ASSERT(count >= 0);
674 count -= uiop->uio_offset;
675 if (count > 0 && uiop->uio_offset >= 0) {
676 error = uiomove((char *)base + uiop->uio_offset,
677 count, UIO_READ, uiop);
678 }
679
680 return (error);
681 }
682
683 static int
684 pr_read_argv(prnode_t *pnp, uio_t *uiop)
685 {
686 char *args;
687 int error;
688 size_t asz = prmaxargvlen, sz;
689
690 /*
691 * Allocate a scratch buffer for collection of the process arguments.
692 */
693 args = kmem_alloc(asz, KM_SLEEP);
694
695 ASSERT(pnp->pr_type == PR_ARGV);
696
697 if ((error = prlock(pnp, ZNO)) != 0) {
698 kmem_free(args, asz);
699 return (error);
700 }
701
702 if ((error = prreadargv(pnp->pr_common->prc_proc, args, asz,
703 &sz)) != 0) {
704 prunlock(pnp);
705 kmem_free(args, asz);
706 return (error);
707 }
708
709 prunlock(pnp);
710
711 error = pr_uioread(args, sz, uiop);
712
713 kmem_free(args, asz);
714
715 return (error);
716 }
717
718 static int
719 pr_read_as(prnode_t *pnp, uio_t *uiop)
720 {
721 int error;
722
723 ASSERT(pnp->pr_type == PR_AS);
724
725 if ((error = prlock(pnp, ZNO)) == 0) {
726 proc_t *p = pnp->pr_common->prc_proc;
727 struct as *as = p->p_as;
728
729 /*
730 * /proc I/O cannot be done to a system process.
731 * A 32-bit process cannot read a 64-bit process.
732 */
733 if ((p->p_flag & SSYS) || as == &kas) {
734 error = 0;
735 #ifdef _SYSCALL32_IMPL
736 } else if (curproc->p_model == DATAMODEL_ILP32 &&
737 PROCESS_NOT_32BIT(p)) {
738 error = EOVERFLOW;
1794
1795 static int (*pr_read_function_32[PR_NFILES])() = {
1796 pr_read_inval, /* /proc */
1797 pr_read_inval, /* /proc/self */
1798 pr_read_piddir, /* /proc/<pid> (old /proc read()) */
1799 pr_read_as, /* /proc/<pid>/as */
1800 pr_read_inval, /* /proc/<pid>/ctl */
1801 pr_read_status_32, /* /proc/<pid>/status */
1802 pr_read_lstatus_32, /* /proc/<pid>/lstatus */
1803 pr_read_psinfo_32, /* /proc/<pid>/psinfo */
1804 pr_read_lpsinfo_32, /* /proc/<pid>/lpsinfo */
1805 pr_read_map_32, /* /proc/<pid>/map */
1806 pr_read_rmap_32, /* /proc/<pid>/rmap */
1807 pr_read_xmap_32, /* /proc/<pid>/xmap */
1808 pr_read_cred, /* /proc/<pid>/cred */
1809 pr_read_sigact_32, /* /proc/<pid>/sigact */
1810 pr_read_auxv_32, /* /proc/<pid>/auxv */
1811 #if defined(__x86)
1812 pr_read_ldt, /* /proc/<pid>/ldt */
1813 #endif
1814 pr_read_argv, /* /proc/<pid>/argv */
1815 pr_read_usage_32, /* /proc/<pid>/usage */
1816 pr_read_lusage_32, /* /proc/<pid>/lusage */
1817 pr_read_pagedata_32, /* /proc/<pid>/pagedata */
1818 pr_read_watch_32, /* /proc/<pid>/watch */
1819 pr_read_inval, /* /proc/<pid>/cwd */
1820 pr_read_inval, /* /proc/<pid>/root */
1821 pr_read_inval, /* /proc/<pid>/fd */
1822 pr_read_inval, /* /proc/<pid>/fd/nn */
1823 pr_read_inval, /* /proc/<pid>/object */
1824 pr_read_inval, /* /proc/<pid>/object/xxx */
1825 pr_read_inval, /* /proc/<pid>/lwp */
1826 pr_read_inval, /* /proc/<pid>/lwp/<lwpid> */
1827 pr_read_inval, /* /proc/<pid>/lwp/<lwpid>/lwpctl */
1828 pr_read_lwpstatus_32, /* /proc/<pid>/lwp/<lwpid>/lwpstatus */
1829 pr_read_lwpsinfo_32, /* /proc/<pid>/lwp/<lwpid>/lwpsinfo */
1830 pr_read_lwpusage_32, /* /proc/<pid>/lwp/<lwpid>/lwpusage */
1831 pr_read_xregs, /* /proc/<pid>/lwp/<lwpid>/xregs */
1832 pr_read_inval, /* /proc/<pid>/lwp/<lwpid>/templates */
1833 pr_read_inval, /* /proc/<pid>/lwp/<lwpid>/templates/<id> */
1834 pr_read_spymaster_32, /* /proc/<pid>/lwp/<lwpid>/spymaster */
2714 {
2715 prnode_t *pnp = VTOP(vp);
2716
2717 ASSERT(pnp->pr_type < PR_NFILES);
2718
2719 #ifdef _SYSCALL32_IMPL
2720 /*
2721 * What is read from the /proc files depends on the data
2722 * model of the caller. An LP64 process will see LP64
2723 * data. An ILP32 process will see ILP32 data.
2724 */
2725 if (curproc->p_model == DATAMODEL_LP64)
2726 return (pr_read_function[pnp->pr_type](pnp, uiop));
2727 else
2728 return (pr_read_function_32[pnp->pr_type](pnp, uiop));
2729 #else
2730 return (pr_read_function[pnp->pr_type](pnp, uiop));
2731 #endif
2732 }
2733
2734 /*
2735 * We make pr_write_psinfo_fname() somewhat simpler by asserting at compile
2736 * time that PRFNSZ has the same definition as MAXCOMLEN.
2737 */
2738 #if PRFNSZ != MAXCOMLEN
2739 #error PRFNSZ/MAXCOMLEN mismatch
2740 #endif
2741
2742 static int
2743 pr_write_psinfo_fname(prnode_t *pnp, uio_t *uiop)
2744 {
2745 char fname[PRFNSZ];
2746 int offset = offsetof(psinfo_t, pr_fname), error;
2747
2748 #ifdef _SYSCALL32_IMPL
2749 if (curproc->p_model != DATAMODEL_LP64)
2750 offset = offsetof(psinfo32_t, pr_fname);
2751 #endif
2752
2753 /*
2754 * If this isn't a write to pr_fname (or if the size doesn't match
2755 * PRFNSZ) return.
2756 */
2757 if (uiop->uio_offset != offset || uiop->uio_resid != PRFNSZ)
2758 return (0);
2759
2760 if ((error = uiomove(fname, PRFNSZ, UIO_WRITE, uiop)) != 0)
2761 return (error);
2762
2763 fname[PRFNSZ - 1] = '\0';
2764
2765 if ((error = prlock(pnp, ZNO)) != 0)
2766 return (error);
2767
2768 bcopy(fname, pnp->pr_common->prc_proc->p_user.u_comm, PRFNSZ);
2769
2770 prunlock(pnp);
2771
2772 return (0);
2773 }
2774
2775 /*
2776 * We make pr_write_psinfo_psargs() somewhat simpler by asserting at compile
2777 * time that PRARGSZ has the same definition as PSARGSZ.
2778 */
2779 #if PRARGSZ != PSARGSZ
2780 #error PRARGSZ/PSARGSZ mismatch
2781 #endif
2782
2783 static int
2784 pr_write_psinfo_psargs(prnode_t *pnp, uio_t *uiop)
2785 {
2786 char psargs[PRARGSZ];
2787 int offset = offsetof(psinfo_t, pr_psargs), error;
2788
2789 #ifdef _SYSCALL32_IMPL
2790 if (curproc->p_model != DATAMODEL_LP64)
2791 offset = offsetof(psinfo32_t, pr_psargs);
2792 #endif
2793
2794 /*
2795 * If this isn't a write to pr_psargs (or if the size doesn't match
2796 * PRARGSZ) return.
2797 */
2798 if (uiop->uio_offset != offset || uiop->uio_resid != PRARGSZ)
2799 return (0);
2800
2801 if ((error = uiomove(psargs, PRARGSZ, UIO_WRITE, uiop)) != 0)
2802 return (error);
2803
2804 psargs[PRARGSZ - 1] = '\0';
2805
2806 if ((error = prlock(pnp, ZNO)) != 0)
2807 return (error);
2808
2809 bcopy(psargs, pnp->pr_common->prc_proc->p_user.u_psargs, PRARGSZ);
2810
2811 prunlock(pnp);
2812
2813 return (0);
2814 }
2815
2816 int
2817 pr_write_psinfo(prnode_t *pnp, uio_t *uiop)
2818 {
2819 int error;
2820
2821 if ((error = pr_write_psinfo_fname(pnp, uiop)) != 0)
2822 return (error);
2823
2824 if ((error = pr_write_psinfo_psargs(pnp, uiop)) != 0)
2825 return (error);
2826
2827 return (0);
2828 }
2829
2830
2831 /* ARGSUSED */
2832 static int
2833 prwrite(vnode_t *vp, uio_t *uiop, int ioflag, cred_t *cr, caller_context_t *ct)
2834 {
2835 prnode_t *pnp = VTOP(vp);
2836 int old = 0;
2837 int error;
2838 ssize_t resid;
2839
2840 ASSERT(pnp->pr_type < PR_NFILES);
2841
2842 /*
2843 * Only a handful of /proc files are writable, enumerate them here.
2844 */
2845 switch (pnp->pr_type) {
2846 case PR_PIDDIR: /* directory write()s: visceral revulsion. */
2847 ASSERT(pnp->pr_pidfile != NULL);
2848 /* use the underlying PR_PIDFILE to write the process */
2849 vp = pnp->pr_pidfile;
2850 pnp = VTOP(vp);
2889 * Perform the action on the control file
2890 * by passing curthreads credentials
2891 * and not target process's credentials.
2892 */
2893 #ifdef _SYSCALL32_IMPL
2894 if (curproc->p_model == DATAMODEL_ILP32)
2895 error = prwritectl32(vp, uiop, CRED());
2896 else
2897 error = prwritectl(vp, uiop, CRED());
2898 #else
2899 error = prwritectl(vp, uiop, CRED());
2900 #endif
2901 /*
2902 * This hack makes sure that the EINTR is passed
2903 * all the way back to the caller's write() call.
2904 */
2905 if (error == EINTR)
2906 uiop->uio_resid = resid;
2907 return (error);
2908
2909 case PR_PSINFO:
2910 return (pr_write_psinfo(pnp, uiop));
2911
2912 default:
2913 return ((vp->v_type == VDIR)? EISDIR : EBADF);
2914 }
2915 /* NOTREACHED */
2916 }
2917
2918 static int
2919 prgetattr(vnode_t *vp, vattr_t *vap, int flags, cred_t *cr,
2920 caller_context_t *ct)
2921 {
2922 prnode_t *pnp = VTOP(vp);
2923 prnodetype_t type = pnp->pr_type;
2924 prcommon_t *pcp;
2925 proc_t *p;
2926 struct as *as;
2927 int error;
2928 vnode_t *rvp;
2929 timestruc_t now;
2930 extern uint_t nproc;
2931 int ngroups;
3175 break;
3176 case PR_CRED:
3177 mutex_enter(&p->p_crlock);
3178 vap->va_size = sizeof (prcred_t);
3179 ngroups = crgetngroups(p->p_cred);
3180 if (ngroups > 1)
3181 vap->va_size += (ngroups - 1) * sizeof (gid_t);
3182 mutex_exit(&p->p_crlock);
3183 break;
3184 case PR_PRIV:
3185 vap->va_size = prgetprivsize();
3186 break;
3187 case PR_SIGACT:
3188 nsig = PROC_IS_BRANDED(curproc)? BROP(curproc)->b_nsig : NSIG;
3189 vap->va_size = (nsig-1) *
3190 PR_OBJSIZE(struct sigaction32, struct sigaction);
3191 break;
3192 case PR_AUXV:
3193 vap->va_size = __KERN_NAUXV_IMPL * PR_OBJSIZE(auxv32_t, auxv_t);
3194 break;
3195 case PR_ARGV:
3196 if ((p->p_flag & SSYS) || p->p_as == &kas) {
3197 vap->va_size = PSARGSZ;
3198 } else {
3199 vap->va_size = prmaxargvlen;
3200 }
3201 break;
3202 #if defined(__x86)
3203 case PR_LDT:
3204 mutex_exit(&p->p_lock);
3205 mutex_enter(&p->p_ldtlock);
3206 vap->va_size = prnldt(p) * sizeof (struct ssd);
3207 mutex_exit(&p->p_ldtlock);
3208 mutex_enter(&p->p_lock);
3209 break;
3210 #endif
3211 case PR_USAGE:
3212 vap->va_size = PR_OBJSIZE(prusage32_t, prusage_t);
3213 break;
3214 case PR_LUSAGE:
3215 vap->va_size = PR_OBJSIZE(prheader32_t, prheader_t) +
3216 (p->p_lwpcnt + 1) * PR_OBJSPAN(prusage32_t, prusage_t);
3217 break;
3218 case PR_PAGEDATA:
3219 if ((p->p_flag & SSYS) || (as = p->p_as) == &kas)
3220 vap->va_size = 0;
3221 else {
3357 * Disallow access to fds with other than existing open modes.
3358 */
3359 rvp = pnp->pr_realvp;
3360 vtype = rvp->v_type;
3361 vmode = pnp->pr_mode;
3362 if ((type == PR_OBJECT && (mode & VWRITE)) ||
3363 (type == PR_FD && vtype != VREG && vtype != VDIR) ||
3364 (type == PR_FD && (vmode & mode) != mode &&
3365 secpolicy_proc_access(cr) != 0))
3366 return (EACCES);
3367 return (VOP_ACCESS(rvp, mode, flags, cr, ct));
3368
3369 case PR_PSINFO: /* these files can be read by anyone */
3370 case PR_LPSINFO:
3371 case PR_LWPSINFO:
3372 case PR_LWPDIR:
3373 case PR_LWPIDDIR:
3374 case PR_USAGE:
3375 case PR_LUSAGE:
3376 case PR_LWPUSAGE:
3377 case PR_ARGV:
3378 p = pr_p_lock(pnp);
3379 mutex_exit(&pr_pidlock);
3380 if (p == NULL)
3381 return (ENOENT);
3382 prunlock(pnp);
3383 break;
3384
3385 default:
3386 /*
3387 * Except for the world-readable files above,
3388 * only /proc/pid exists if the process is a zombie.
3389 */
3390 if ((error = prlock(pnp,
3391 (type == PR_PIDDIR)? ZYES : ZNO)) != 0)
3392 return (error);
3393 p = pnp->pr_common->prc_proc;
3394 if (p != curproc)
3395 error = priv_proc_cred_perm(cr, p, NULL, mode);
3396
3397 if (error != 0 || p == curproc || (p->p_flag & SSYS) ||
3443
3444 static vnode_t *(*pr_lookup_function[PR_NFILES])() = {
3445 pr_lookup_procdir, /* /proc */
3446 pr_lookup_notdir, /* /proc/self */
3447 pr_lookup_piddir, /* /proc/<pid> */
3448 pr_lookup_notdir, /* /proc/<pid>/as */
3449 pr_lookup_notdir, /* /proc/<pid>/ctl */
3450 pr_lookup_notdir, /* /proc/<pid>/status */
3451 pr_lookup_notdir, /* /proc/<pid>/lstatus */
3452 pr_lookup_notdir, /* /proc/<pid>/psinfo */
3453 pr_lookup_notdir, /* /proc/<pid>/lpsinfo */
3454 pr_lookup_notdir, /* /proc/<pid>/map */
3455 pr_lookup_notdir, /* /proc/<pid>/rmap */
3456 pr_lookup_notdir, /* /proc/<pid>/xmap */
3457 pr_lookup_notdir, /* /proc/<pid>/cred */
3458 pr_lookup_notdir, /* /proc/<pid>/sigact */
3459 pr_lookup_notdir, /* /proc/<pid>/auxv */
3460 #if defined(__x86)
3461 pr_lookup_notdir, /* /proc/<pid>/ldt */
3462 #endif
3463 pr_lookup_notdir, /* /proc/<pid>/argv */
3464 pr_lookup_notdir, /* /proc/<pid>/usage */
3465 pr_lookup_notdir, /* /proc/<pid>/lusage */
3466 pr_lookup_notdir, /* /proc/<pid>/pagedata */
3467 pr_lookup_notdir, /* /proc/<pid>/watch */
3468 pr_lookup_notdir, /* /proc/<pid>/cwd */
3469 pr_lookup_notdir, /* /proc/<pid>/root */
3470 pr_lookup_fddir, /* /proc/<pid>/fd */
3471 pr_lookup_notdir, /* /proc/<pid>/fd/nn */
3472 pr_lookup_objectdir, /* /proc/<pid>/object */
3473 pr_lookup_notdir, /* /proc/<pid>/object/xxx */
3474 pr_lookup_lwpdir, /* /proc/<pid>/lwp */
3475 pr_lookup_lwpiddir, /* /proc/<pid>/lwp/<lwpid> */
3476 pr_lookup_notdir, /* /proc/<pid>/lwp/<lwpid>/lwpctl */
3477 pr_lookup_notdir, /* /proc/<pid>/lwp/<lwpid>/lwpstatus */
3478 pr_lookup_notdir, /* /proc/<pid>/lwp/<lwpid>/lwpsinfo */
3479 pr_lookup_notdir, /* /proc/<pid>/lwp/<lwpid>/lwpusage */
3480 pr_lookup_notdir, /* /proc/<pid>/lwp/<lwpid>/xregs */
3481 pr_lookup_tmpldir, /* /proc/<pid>/lwp/<lwpid>/templates */
3482 pr_lookup_notdir, /* /proc/<pid>/lwp/<lwpid>/templates/<id> */
3483 pr_lookup_notdir, /* /proc/<pid>/lwp/<lwpid>/spymaster */
4683 vp->v_type = VDIR;
4684 pnp->pr_mode = 0555; /* read-search by all */
4685 break;
4686
4687 case PR_AS:
4688 case PR_TMPL:
4689 pnp->pr_mode = 0600; /* read-write by owner only */
4690 break;
4691
4692 case PR_CTL:
4693 case PR_LWPCTL:
4694 pnp->pr_mode = 0200; /* write-only by owner only */
4695 break;
4696
4697 case PR_PIDFILE:
4698 case PR_LWPIDFILE:
4699 pnp->pr_mode = 0600; /* read-write by owner only */
4700 break;
4701
4702 case PR_PSINFO:
4703 pnp->pr_mode = 0644; /* readable by all + owner can write */
4704 break;
4705
4706 case PR_LPSINFO:
4707 case PR_LWPSINFO:
4708 case PR_USAGE:
4709 case PR_LUSAGE:
4710 case PR_LWPUSAGE:
4711 case PR_ARGV:
4712 pnp->pr_mode = 0444; /* read-only by all */
4713 break;
4714
4715 default:
4716 pnp->pr_mode = 0400; /* read-only by owner only */
4717 break;
4718 }
4719 vn_exists(vp);
4720 return (pnp);
4721 }
4722
4723 /*
4724 * Free the storage obtained from prgetnode().
4725 */
4726 void
4727 prfreenode(prnode_t *pnp)
4728 {
4729 vnode_t *vp;
4730 ulong_t nfiles;
4731
4797
4798 static int (*pr_readdir_function[PR_NFILES])() = {
4799 pr_readdir_procdir, /* /proc */
4800 pr_readdir_notdir, /* /proc/self */
4801 pr_readdir_piddir, /* /proc/<pid> */
4802 pr_readdir_notdir, /* /proc/<pid>/as */
4803 pr_readdir_notdir, /* /proc/<pid>/ctl */
4804 pr_readdir_notdir, /* /proc/<pid>/status */
4805 pr_readdir_notdir, /* /proc/<pid>/lstatus */
4806 pr_readdir_notdir, /* /proc/<pid>/psinfo */
4807 pr_readdir_notdir, /* /proc/<pid>/lpsinfo */
4808 pr_readdir_notdir, /* /proc/<pid>/map */
4809 pr_readdir_notdir, /* /proc/<pid>/rmap */
4810 pr_readdir_notdir, /* /proc/<pid>/xmap */
4811 pr_readdir_notdir, /* /proc/<pid>/cred */
4812 pr_readdir_notdir, /* /proc/<pid>/sigact */
4813 pr_readdir_notdir, /* /proc/<pid>/auxv */
4814 #if defined(__x86)
4815 pr_readdir_notdir, /* /proc/<pid>/ldt */
4816 #endif
4817 pr_readdir_notdir, /* /proc/<pid>/argv */
4818 pr_readdir_notdir, /* /proc/<pid>/usage */
4819 pr_readdir_notdir, /* /proc/<pid>/lusage */
4820 pr_readdir_notdir, /* /proc/<pid>/pagedata */
4821 pr_readdir_notdir, /* /proc/<pid>/watch */
4822 pr_readdir_notdir, /* /proc/<pid>/cwd */
4823 pr_readdir_notdir, /* /proc/<pid>/root */
4824 pr_readdir_fddir, /* /proc/<pid>/fd */
4825 pr_readdir_notdir, /* /proc/<pid>/fd/nn */
4826 pr_readdir_objectdir, /* /proc/<pid>/object */
4827 pr_readdir_notdir, /* /proc/<pid>/object/xxx */
4828 pr_readdir_lwpdir, /* /proc/<pid>/lwp */
4829 pr_readdir_lwpiddir, /* /proc/<pid>/lwp/<lwpid> */
4830 pr_readdir_notdir, /* /proc/<pid>/lwp/<lwpid>/lwpctl */
4831 pr_readdir_notdir, /* /proc/<pid>/lwp/<lwpid>/lwpstatus */
4832 pr_readdir_notdir, /* /proc/<pid>/lwp/<lwpid>/lwpsinfo */
4833 pr_readdir_notdir, /* /proc/<pid>/lwp/<lwpid>/lwpusage */
4834 pr_readdir_notdir, /* /proc/<pid>/lwp/<lwpid>/xregs */
4835 pr_readdir_tmpldir, /* /proc/<pid>/lwp/<lwpid>/templates */
4836 pr_readdir_notdir, /* /proc/<pid>/lwp/<lwpid>/templates/<id> */
4837 pr_readdir_notdir, /* /proc/<pid>/lwp/<lwpid>/spymaster */
4947 if (pnp->pr_pcommon->prc_proc == NULL)
4948 return (ENOENT);
4949 if (uiop->uio_offset >= sizeof (piddir))
4950 goto out;
4951
4952 /*
4953 * Loop until user's request is satisfied, omitting some
4954 * files along the way if the process is a zombie.
4955 */
4956 for (dirp = &piddir[uiop->uio_offset / sizeof (prdirent_t)];
4957 uiop->uio_resid >= sizeof (prdirent_t) &&
4958 dirp < &piddir[NPIDDIRFILES+2];
4959 uiop->uio_offset = off + sizeof (prdirent_t), dirp++) {
4960 off = uiop->uio_offset;
4961 if (zombie) {
4962 switch (dirp->d_ino) {
4963 case PR_PIDDIR:
4964 case PR_PROCDIR:
4965 case PR_PSINFO:
4966 case PR_USAGE:
4967 case PR_ARGV:
4968 break;
4969 default:
4970 continue;
4971 }
4972 }
4973 bcopy(dirp, &dirent, sizeof (prdirent_t));
4974 if (dirent.d_ino == PR_PROCDIR)
4975 dirent.d_ino = PRROOTINO;
4976 else
4977 dirent.d_ino = pmkino(0, pnp->pr_pcommon->prc_slot,
4978 dirent.d_ino);
4979 if ((error = uiomove((caddr_t)&dirent, sizeof (prdirent_t),
4980 UIO_READ, uiop)) != 0)
4981 return (error);
4982 }
4983 out:
4984 if (eofp)
4985 *eofp = (uiop->uio_offset >= sizeof (piddir));
4986 return (0);
4987 }
|