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) 2018, Joyent, Inc.
25 * Copyright (c) 2017 by Delphix. All rights reserved.
26 * Copyright 2020 OmniOS Community Edition (OmniOSce) Association.
27 * Copyright 2022 MNX Cloud, Inc.
28 * Copyright 2023 Oxide Computer Company
29 */
30
31 /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
32 /* All Rights Reserved */
33
34 #include <sys/types.h>
35 #include <sys/param.h>
36 #include <sys/time.h>
37 #include <sys/cred.h>
38 #include <sys/policy.h>
39 #include <sys/debug.h>
40 #include <sys/dirent.h>
41 #include <sys/errno.h>
42 #include <sys/file.h>
43 #include <sys/inline.h>
44 #include <sys/kmem.h>
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_FDINFODIR, 22 * sizeof (prdirent_t), sizeof (prdirent_t),
161 "fdinfo" },
162 { PR_OBJECTDIR, 23 * sizeof (prdirent_t), sizeof (prdirent_t),
163 "object" },
164 { PR_LWPDIR, 24 * sizeof (prdirent_t), sizeof (prdirent_t),
165 "lwp" },
166 { PR_PRIV, 25 * sizeof (prdirent_t), sizeof (prdirent_t),
167 "priv" },
168 { PR_PATHDIR, 26 * sizeof (prdirent_t), sizeof (prdirent_t),
169 "path" },
170 { PR_CTDIR, 27 * sizeof (prdirent_t), sizeof (prdirent_t),
171 "contracts" },
172 { PR_SECFLAGS, 28 * sizeof (prdirent_t), sizeof (prdirent_t),
173 "secflags" },
174 #if defined(__x86)
175 { PR_LDT, 29 * sizeof (prdirent_t), sizeof (prdirent_t),
176 "ldt" },
177 #endif
178 };
179
180 #define NPIDDIRFILES (sizeof (piddir) / sizeof (piddir[0]) - 2)
181
182 /*
183 * Contents of a /proc/<pid>/lwp/<lwpid> directory.
184 */
185 static prdirent_t lwpiddir[] = {
186 { PR_LWPIDDIR, 1 * sizeof (prdirent_t), sizeof (prdirent_t),
187 "." },
188 { PR_LWPDIR, 2 * sizeof (prdirent_t), sizeof (prdirent_t),
189 ".." },
190 { PR_LWPCTL, 3 * sizeof (prdirent_t), sizeof (prdirent_t),
191 "lwpctl" },
192 { PR_LWPNAME, 4 * sizeof (prdirent_t), sizeof (prdirent_t),
193 "lwpname" },
194 { PR_LWPSTATUS, 5 * sizeof (prdirent_t), sizeof (prdirent_t),
195 "lwpstatus" },
576 if (killproc)
577 sigtoproc(p, NULL, SIGKILL);
578 else
579 allsetrun(p);
580 }
581
582 prunlock(pnp);
583 return (0);
584 }
585
586 /*
587 * Array of read functions, indexed by /proc file type.
588 */
589 static int pr_read_inval(), pr_read_as(), pr_read_status(),
590 pr_read_lstatus(), pr_read_psinfo(), pr_read_lpsinfo(),
591 pr_read_map(), pr_read_rmap(), pr_read_xmap(),
592 pr_read_cred(), pr_read_sigact(), pr_read_auxv(),
593 #if defined(__x86)
594 pr_read_ldt(),
595 #endif
596 pr_read_usage(), pr_read_lusage(), pr_read_pagedata(),
597 pr_read_watch(), pr_read_lwpstatus(), pr_read_lwpsinfo(),
598 pr_read_lwpusage(), pr_read_lwpname(),
599 pr_read_xregs(), pr_read_priv(),
600 pr_read_spymaster(), pr_read_secflags(),
601 #if defined(__sparc)
602 pr_read_gwindows(), pr_read_asrs(),
603 #endif
604 pr_read_piddir(), pr_read_pidfile(), pr_read_opagedata(),
605 pr_read_fdinfo();
606
607 static int (*pr_read_function[PR_NFILES])() = {
608 pr_read_inval, /* /proc */
609 pr_read_inval, /* /proc/self */
610 pr_read_piddir, /* /proc/<pid> (old /proc read()) */
611 pr_read_as, /* /proc/<pid>/as */
612 pr_read_inval, /* /proc/<pid>/ctl */
613 pr_read_status, /* /proc/<pid>/status */
614 pr_read_lstatus, /* /proc/<pid>/lstatus */
615 pr_read_psinfo, /* /proc/<pid>/psinfo */
616 pr_read_lpsinfo, /* /proc/<pid>/lpsinfo */
617 pr_read_map, /* /proc/<pid>/map */
618 pr_read_rmap, /* /proc/<pid>/rmap */
619 pr_read_xmap, /* /proc/<pid>/xmap */
620 pr_read_cred, /* /proc/<pid>/cred */
621 pr_read_sigact, /* /proc/<pid>/sigact */
622 pr_read_auxv, /* /proc/<pid>/auxv */
623 #if defined(__x86)
624 pr_read_ldt, /* /proc/<pid>/ldt */
625 #endif
626 pr_read_usage, /* /proc/<pid>/usage */
627 pr_read_lusage, /* /proc/<pid>/lusage */
628 pr_read_pagedata, /* /proc/<pid>/pagedata */
629 pr_read_watch, /* /proc/<pid>/watch */
630 pr_read_inval, /* /proc/<pid>/cwd */
631 pr_read_inval, /* /proc/<pid>/root */
632 pr_read_inval, /* /proc/<pid>/fd */
633 pr_read_inval, /* /proc/<pid>/fd/nn */
634 pr_read_inval, /* /proc/<pid>/fdinfo */
635 pr_read_fdinfo, /* /proc/<pid>/fdinfo/nn */
636 pr_read_inval, /* /proc/<pid>/object */
637 pr_read_inval, /* /proc/<pid>/object/xxx */
638 pr_read_inval, /* /proc/<pid>/lwp */
639 pr_read_inval, /* /proc/<pid>/lwp/<lwpid> */
640 pr_read_inval, /* /proc/<pid>/lwp/<lwpid>/lwpctl */
641 pr_read_lwpname, /* /proc/<pid>/lwp/<lwpid>/lwpname */
642 pr_read_lwpstatus, /* /proc/<pid>/lwp/<lwpid>/lwpstatus */
643 pr_read_lwpsinfo, /* /proc/<pid>/lwp/<lwpid>/lwpsinfo */
644 pr_read_lwpusage, /* /proc/<pid>/lwp/<lwpid>/lwpusage */
645 pr_read_xregs, /* /proc/<pid>/lwp/<lwpid>/xregs */
672 */
673 return (EINVAL);
674 }
675
676 static int
677 pr_uioread(void *base, long count, uio_t *uiop)
678 {
679 int error = 0;
680
681 ASSERT(count >= 0);
682 count -= uiop->uio_offset;
683 if (count > 0 && uiop->uio_offset >= 0) {
684 error = uiomove((char *)base + uiop->uio_offset,
685 count, UIO_READ, uiop);
686 }
687
688 return (error);
689 }
690
691 static int
692 pr_read_as(prnode_t *pnp, uio_t *uiop)
693 {
694 int error;
695
696 ASSERT(pnp->pr_type == PR_AS);
697
698 if ((error = prlock(pnp, ZNO)) == 0) {
699 proc_t *p = pnp->pr_common->prc_proc;
700 struct as *as = p->p_as;
701
702 /*
703 * /proc I/O cannot be done to a system process.
704 * A 32-bit process cannot read a 64-bit process.
705 */
706 if ((p->p_flag & SSYS) || as == &kas) {
707 error = 0;
708 #ifdef _SYSCALL32_IMPL
709 } else if (curproc->p_model == DATAMODEL_ILP32 &&
710 PROCESS_NOT_32BIT(p)) {
711 error = EOVERFLOW;
1913
1914 static int (*pr_read_function_32[PR_NFILES])() = {
1915 pr_read_inval, /* /proc */
1916 pr_read_inval, /* /proc/self */
1917 pr_read_piddir, /* /proc/<pid> (old /proc read()) */
1918 pr_read_as, /* /proc/<pid>/as */
1919 pr_read_inval, /* /proc/<pid>/ctl */
1920 pr_read_status_32, /* /proc/<pid>/status */
1921 pr_read_lstatus_32, /* /proc/<pid>/lstatus */
1922 pr_read_psinfo_32, /* /proc/<pid>/psinfo */
1923 pr_read_lpsinfo_32, /* /proc/<pid>/lpsinfo */
1924 pr_read_map_32, /* /proc/<pid>/map */
1925 pr_read_rmap_32, /* /proc/<pid>/rmap */
1926 pr_read_xmap_32, /* /proc/<pid>/xmap */
1927 pr_read_cred, /* /proc/<pid>/cred */
1928 pr_read_sigact_32, /* /proc/<pid>/sigact */
1929 pr_read_auxv_32, /* /proc/<pid>/auxv */
1930 #if defined(__x86)
1931 pr_read_ldt, /* /proc/<pid>/ldt */
1932 #endif
1933 pr_read_usage_32, /* /proc/<pid>/usage */
1934 pr_read_lusage_32, /* /proc/<pid>/lusage */
1935 pr_read_pagedata_32, /* /proc/<pid>/pagedata */
1936 pr_read_watch_32, /* /proc/<pid>/watch */
1937 pr_read_inval, /* /proc/<pid>/cwd */
1938 pr_read_inval, /* /proc/<pid>/root */
1939 pr_read_inval, /* /proc/<pid>/fd */
1940 pr_read_inval, /* /proc/<pid>/fd/nn */
1941 pr_read_inval, /* /proc/<pid>/fdinfo */
1942 pr_read_fdinfo, /* /proc/<pid>/fdinfo/nn */
1943 pr_read_inval, /* /proc/<pid>/object */
1944 pr_read_inval, /* /proc/<pid>/object/xxx */
1945 pr_read_inval, /* /proc/<pid>/lwp */
1946 pr_read_inval, /* /proc/<pid>/lwp/<lwpid> */
1947 pr_read_inval, /* /proc/<pid>/lwp/<lwpid>/lwpctl */
1948 pr_read_lwpname, /* /proc/<pid>/lwp/<lwpid>/lwpname */
1949 pr_read_lwpstatus_32, /* /proc/<pid>/lwp/<lwpid>/lwpstatus */
1950 pr_read_lwpsinfo_32, /* /proc/<pid>/lwp/<lwpid>/lwpsinfo */
1951 pr_read_lwpusage_32, /* /proc/<pid>/lwp/<lwpid>/lwpusage */
1952 pr_read_xregs, /* /proc/<pid>/lwp/<lwpid>/xregs */
2841 {
2842 prnode_t *pnp = VTOP(vp);
2843
2844 ASSERT(pnp->pr_type < PR_NFILES);
2845
2846 #ifdef _SYSCALL32_IMPL
2847 /*
2848 * What is read from the /proc files depends on the data
2849 * model of the caller. An LP64 process will see LP64
2850 * data. An ILP32 process will see ILP32 data.
2851 */
2852 if (curproc->p_model == DATAMODEL_LP64)
2853 return (pr_read_function[pnp->pr_type](pnp, uiop, cr));
2854 else
2855 return (pr_read_function_32[pnp->pr_type](pnp, uiop, cr));
2856 #else
2857 return (pr_read_function[pnp->pr_type](pnp, uiop, cr));
2858 #endif
2859 }
2860
2861 /* Note we intentionally don't handle partial writes/updates. */
2862 static int
2863 pr_write_lwpname(prnode_t *pnp, uio_t *uiop)
2864 {
2865 kthread_t *t = NULL;
2866 char *lwpname;
2867 int error;
2868
2869 lwpname = kmem_zalloc(THREAD_NAME_MAX, KM_SLEEP);
2870
2871 if ((error = uiomove(lwpname, THREAD_NAME_MAX, UIO_WRITE, uiop)) != 0) {
2872 kmem_free(lwpname, THREAD_NAME_MAX);
2873 return (error);
2874 }
2875
2876 /* Somebody tried to write too long a thread name... */
2877 if (lwpname[THREAD_NAME_MAX - 1] != '\0' || uiop->uio_resid > 0) {
2878 kmem_free(lwpname, THREAD_NAME_MAX);
2879 return (EIO);
2880 }
2967 * Perform the action on the control file
2968 * by passing curthreads credentials
2969 * and not target process's credentials.
2970 */
2971 #ifdef _SYSCALL32_IMPL
2972 if (curproc->p_model == DATAMODEL_ILP32)
2973 error = prwritectl32(vp, uiop, CRED());
2974 else
2975 error = prwritectl(vp, uiop, CRED());
2976 #else
2977 error = prwritectl(vp, uiop, CRED());
2978 #endif
2979 /*
2980 * This hack makes sure that the EINTR is passed
2981 * all the way back to the caller's write() call.
2982 */
2983 if (error == EINTR)
2984 uiop->uio_resid = resid;
2985 return (error);
2986
2987 case PR_LWPNAME:
2988 return (pr_write_lwpname(pnp, uiop));
2989
2990 default:
2991 return ((vp->v_type == VDIR)? EISDIR : EBADF);
2992 }
2993 /* NOTREACHED */
2994 }
2995
2996 static int
2997 prgetattr(vnode_t *vp, vattr_t *vap, int flags, cred_t *cr,
2998 caller_context_t *ct)
2999 {
3000 prnode_t *pnp = VTOP(vp);
3001 prnodetype_t type = pnp->pr_type;
3002 prcommon_t *pcp;
3003 proc_t *p;
3004 struct as *as;
3005 int error;
3006 vnode_t *rvp;
3296 vap->va_size = sizeof (prcred_t);
3297 ngroups = crgetngroups(p->p_cred);
3298 if (ngroups > 1)
3299 vap->va_size += (ngroups - 1) * sizeof (gid_t);
3300 mutex_exit(&p->p_crlock);
3301 break;
3302 case PR_PRIV:
3303 vap->va_size = prgetprivsize();
3304 break;
3305 case PR_SECFLAGS:
3306 vap->va_size = sizeof (prsecflags_t);
3307 break;
3308 case PR_SIGACT:
3309 nsig = PROC_IS_BRANDED(curproc)? BROP(curproc)->b_nsig : NSIG;
3310 vap->va_size = (nsig-1) *
3311 PR_OBJSIZE(struct sigaction32, struct sigaction);
3312 break;
3313 case PR_AUXV:
3314 vap->va_size = __KERN_NAUXV_IMPL * PR_OBJSIZE(auxv32_t, auxv_t);
3315 break;
3316 #if defined(__x86)
3317 case PR_LDT:
3318 mutex_exit(&p->p_lock);
3319 mutex_enter(&p->p_ldtlock);
3320 vap->va_size = prnldt(p) * sizeof (struct ssd);
3321 mutex_exit(&p->p_ldtlock);
3322 mutex_enter(&p->p_lock);
3323 break;
3324 #endif
3325 case PR_USAGE:
3326 vap->va_size = PR_OBJSIZE(prusage32_t, prusage_t);
3327 break;
3328 case PR_LUSAGE:
3329 vap->va_size = PR_OBJSIZE(prheader32_t, prheader_t) +
3330 (p->p_lwpcnt + 1) * PR_OBJSPAN(prusage32_t, prusage_t);
3331 break;
3332 case PR_PAGEDATA:
3333 if ((p->p_flag & SSYS) || (as = p->p_as) == &kas)
3334 vap->va_size = 0;
3335 else {
3418 if ((n = prnwindows(ttolwp(t))) == 0)
3419 vap->va_size = 0;
3420 else
3421 vap->va_size = PR_OBJSIZE(gwindows32_t, gwindows_t) -
3422 (SPARC_MAXREGWINDOW - n) *
3423 PR_OBJSIZE(struct rwindow32, struct rwindow);
3424 mutex_enter(&p->p_lock);
3425 break;
3426 }
3427 case PR_ASRS:
3428 #ifdef _LP64
3429 if (p->p_model == DATAMODEL_LP64)
3430 vap->va_size = sizeof (asrset_t);
3431 else
3432 #endif
3433 vap->va_size = 0;
3434 break;
3435 #endif
3436 case PR_CTL:
3437 case PR_LWPCTL:
3438 default:
3439 vap->va_size = 0;
3440 break;
3441 }
3442
3443 prunlock(pnp);
3444 vap->va_nblocks = (fsblkcnt64_t)btod(vap->va_size);
3445 return (0);
3446 }
3447
3448 static int
3449 praccess(vnode_t *vp, int mode, int flags, cred_t *cr, caller_context_t *ct)
3450 {
3451 prnode_t *pnp = VTOP(vp);
3452 prnodetype_t type = pnp->pr_type;
3453 int vmode;
3454 vtype_t vtype;
3455 proc_t *p;
3456 int error = 0;
3457 vnode_t *rvp;
3472 * Disallow access to fds with other than existing open modes.
3473 */
3474 rvp = pnp->pr_realvp;
3475 vtype = rvp->v_type;
3476 vmode = pnp->pr_mode;
3477 if ((type == PR_OBJECT && (mode & VWRITE)) ||
3478 (type == PR_FD && vtype != VREG && vtype != VDIR) ||
3479 (type == PR_FD && (vmode & mode) != mode &&
3480 secpolicy_proc_access(cr) != 0))
3481 return (EACCES);
3482 return (VOP_ACCESS(rvp, mode, flags, cr, ct));
3483
3484 case PR_PSINFO: /* these files can be read by anyone */
3485 case PR_LPSINFO:
3486 case PR_LWPSINFO:
3487 case PR_LWPDIR:
3488 case PR_LWPIDDIR:
3489 case PR_USAGE:
3490 case PR_LUSAGE:
3491 case PR_LWPUSAGE:
3492 p = pr_p_lock(pnp);
3493 mutex_exit(&pr_pidlock);
3494 if (p == NULL)
3495 return (ENOENT);
3496 prunlock(pnp);
3497 break;
3498
3499 default:
3500 /*
3501 * Except for the world-readable files above,
3502 * only /proc/pid exists if the process is a zombie.
3503 */
3504 if ((error = prlock(pnp,
3505 (type == PR_PIDDIR)? ZYES : ZNO)) != 0)
3506 return (error);
3507 p = pnp->pr_common->prc_proc;
3508 if (p != curproc)
3509 error = priv_proc_cred_perm(cr, p, NULL, mode);
3510
3511 if (error != 0 || p == curproc || (p->p_flag & SSYS) ||
3557
3558 static vnode_t *(*pr_lookup_function[PR_NFILES])() = {
3559 pr_lookup_procdir, /* /proc */
3560 pr_lookup_notdir, /* /proc/self */
3561 pr_lookup_piddir, /* /proc/<pid> */
3562 pr_lookup_notdir, /* /proc/<pid>/as */
3563 pr_lookup_notdir, /* /proc/<pid>/ctl */
3564 pr_lookup_notdir, /* /proc/<pid>/status */
3565 pr_lookup_notdir, /* /proc/<pid>/lstatus */
3566 pr_lookup_notdir, /* /proc/<pid>/psinfo */
3567 pr_lookup_notdir, /* /proc/<pid>/lpsinfo */
3568 pr_lookup_notdir, /* /proc/<pid>/map */
3569 pr_lookup_notdir, /* /proc/<pid>/rmap */
3570 pr_lookup_notdir, /* /proc/<pid>/xmap */
3571 pr_lookup_notdir, /* /proc/<pid>/cred */
3572 pr_lookup_notdir, /* /proc/<pid>/sigact */
3573 pr_lookup_notdir, /* /proc/<pid>/auxv */
3574 #if defined(__x86)
3575 pr_lookup_notdir, /* /proc/<pid>/ldt */
3576 #endif
3577 pr_lookup_notdir, /* /proc/<pid>/usage */
3578 pr_lookup_notdir, /* /proc/<pid>/lusage */
3579 pr_lookup_notdir, /* /proc/<pid>/pagedata */
3580 pr_lookup_notdir, /* /proc/<pid>/watch */
3581 pr_lookup_notdir, /* /proc/<pid>/cwd */
3582 pr_lookup_notdir, /* /proc/<pid>/root */
3583 pr_lookup_fddir, /* /proc/<pid>/fd */
3584 pr_lookup_notdir, /* /proc/<pid>/fd/nn */
3585 pr_lookup_fdinfodir, /* /proc/<pid>/fdinfo */
3586 pr_lookup_notdir, /* /proc/<pid>/fdinfo/nn */
3587 pr_lookup_objectdir, /* /proc/<pid>/object */
3588 pr_lookup_notdir, /* /proc/<pid>/object/xxx */
3589 pr_lookup_lwpdir, /* /proc/<pid>/lwp */
3590 pr_lookup_lwpiddir, /* /proc/<pid>/lwp/<lwpid> */
3591 pr_lookup_notdir, /* /proc/<pid>/lwp/<lwpid>/lwpctl */
3592 pr_lookup_notdir, /* /proc/<pid>/lwp/<lwpid>/lwpname */
3593 pr_lookup_notdir, /* /proc/<pid>/lwp/<lwpid>/lwpstatus */
3594 pr_lookup_notdir, /* /proc/<pid>/lwp/<lwpid>/lwpsinfo */
3595 pr_lookup_notdir, /* /proc/<pid>/lwp/<lwpid>/lwpusage */
3596 pr_lookup_notdir, /* /proc/<pid>/lwp/<lwpid>/xregs */
4887 case PR_LWPDIR:
4888 vp->v_type = VDIR;
4889 pnp->pr_mode = 0555; /* read-search by all */
4890 break;
4891
4892 case PR_AS:
4893 case PR_TMPL:
4894 pnp->pr_mode = 0600; /* read-write by owner only */
4895 break;
4896
4897 case PR_CTL:
4898 case PR_LWPCTL:
4899 pnp->pr_mode = 0200; /* write-only by owner only */
4900 break;
4901
4902 case PR_PIDFILE:
4903 case PR_LWPIDFILE:
4904 pnp->pr_mode = 0600; /* read-write by owner only */
4905 break;
4906
4907 case PR_LWPNAME:
4908 pnp->pr_mode = 0644; /* readable by all + owner can write */
4909 break;
4910
4911 case PR_PSINFO:
4912 case PR_LPSINFO:
4913 case PR_LWPSINFO:
4914 case PR_USAGE:
4915 case PR_LUSAGE:
4916 case PR_LWPUSAGE:
4917 pnp->pr_mode = 0444; /* read-only by all */
4918 break;
4919
4920 default:
4921 pnp->pr_mode = 0400; /* read-only by owner only */
4922 break;
4923 }
4924 vn_exists(vp);
4925 return (pnp);
4926 }
4927
4928 /*
4929 * Free the storage obtained from prgetnode().
4930 */
4931 void
4932 prfreenode(prnode_t *pnp)
4933 {
4934 vnode_t *vp;
4935 ulong_t nfiles;
4936
5004
5005 static int (*pr_readdir_function[PR_NFILES])() = {
5006 pr_readdir_procdir, /* /proc */
5007 pr_readdir_notdir, /* /proc/self */
5008 pr_readdir_piddir, /* /proc/<pid> */
5009 pr_readdir_notdir, /* /proc/<pid>/as */
5010 pr_readdir_notdir, /* /proc/<pid>/ctl */
5011 pr_readdir_notdir, /* /proc/<pid>/status */
5012 pr_readdir_notdir, /* /proc/<pid>/lstatus */
5013 pr_readdir_notdir, /* /proc/<pid>/psinfo */
5014 pr_readdir_notdir, /* /proc/<pid>/lpsinfo */
5015 pr_readdir_notdir, /* /proc/<pid>/map */
5016 pr_readdir_notdir, /* /proc/<pid>/rmap */
5017 pr_readdir_notdir, /* /proc/<pid>/xmap */
5018 pr_readdir_notdir, /* /proc/<pid>/cred */
5019 pr_readdir_notdir, /* /proc/<pid>/sigact */
5020 pr_readdir_notdir, /* /proc/<pid>/auxv */
5021 #if defined(__x86)
5022 pr_readdir_notdir, /* /proc/<pid>/ldt */
5023 #endif
5024 pr_readdir_notdir, /* /proc/<pid>/usage */
5025 pr_readdir_notdir, /* /proc/<pid>/lusage */
5026 pr_readdir_notdir, /* /proc/<pid>/pagedata */
5027 pr_readdir_notdir, /* /proc/<pid>/watch */
5028 pr_readdir_notdir, /* /proc/<pid>/cwd */
5029 pr_readdir_notdir, /* /proc/<pid>/root */
5030 pr_readdir_fddir, /* /proc/<pid>/fd */
5031 pr_readdir_notdir, /* /proc/<pid>/fd/nn */
5032 pr_readdir_fdinfodir, /* /proc/<pid>/fdinfo */
5033 pr_readdir_notdir, /* /proc/<pid>/fdinfo/nn */
5034 pr_readdir_objectdir, /* /proc/<pid>/object */
5035 pr_readdir_notdir, /* /proc/<pid>/object/xxx */
5036 pr_readdir_lwpdir, /* /proc/<pid>/lwp */
5037 pr_readdir_lwpiddir, /* /proc/<pid>/lwp/<lwpid> */
5038 pr_readdir_notdir, /* /proc/<pid>/lwp/<lwpid>/lwpctl */
5039 pr_readdir_notdir, /* /proc/<pid>/lwp/<lwpid>/lwpname */
5040 pr_readdir_notdir, /* /proc/<pid>/lwp/<lwpid>/lwpstatus */
5041 pr_readdir_notdir, /* /proc/<pid>/lwp/<lwpid>/lwpsinfo */
5042 pr_readdir_notdir, /* /proc/<pid>/lwp/<lwpid>/lwpusage */
5043 pr_readdir_notdir, /* /proc/<pid>/lwp/<lwpid>/xregs */
5157 if (pnp->pr_pcommon->prc_proc == NULL)
5158 return (ENOENT);
5159 if (uiop->uio_offset >= sizeof (piddir))
5160 goto out;
5161
5162 /*
5163 * Loop until user's request is satisfied, omitting some
5164 * files along the way if the process is a zombie.
5165 */
5166 for (dirp = &piddir[uiop->uio_offset / sizeof (prdirent_t)];
5167 uiop->uio_resid >= sizeof (prdirent_t) &&
5168 dirp < &piddir[NPIDDIRFILES+2];
5169 uiop->uio_offset = off + sizeof (prdirent_t), dirp++) {
5170 off = uiop->uio_offset;
5171 if (zombie) {
5172 switch (dirp->d_ino) {
5173 case PR_PIDDIR:
5174 case PR_PROCDIR:
5175 case PR_PSINFO:
5176 case PR_USAGE:
5177 break;
5178 default:
5179 continue;
5180 }
5181 }
5182 bcopy(dirp, &dirent, sizeof (prdirent_t));
5183 if (dirent.d_ino == PR_PROCDIR)
5184 dirent.d_ino = PRROOTINO;
5185 else
5186 dirent.d_ino = pmkino(0, pnp->pr_pcommon->prc_slot,
5187 dirent.d_ino);
5188 if ((error = uiomove((caddr_t)&dirent, sizeof (prdirent_t),
5189 UIO_READ, uiop)) != 0)
5190 return (error);
5191 }
5192 out:
5193 if (eofp)
5194 *eofp = (uiop->uio_offset >= sizeof (piddir));
5195 return (0);
5196 }
|
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 2019 Joyent, Inc.
25 * Copyright (c) 2017 by Delphix. All rights reserved.
26 * Copyright 2020 OmniOS Community Edition (OmniOSce) Association.
27 * Copyright 2022 MNX Cloud, Inc.
28 * Copyright 2023 Oxide Computer Company
29 */
30
31 /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
32 /* All Rights Reserved */
33
34 #include <sys/types.h>
35 #include <sys/param.h>
36 #include <sys/time.h>
37 #include <sys/cred.h>
38 #include <sys/policy.h>
39 #include <sys/debug.h>
40 #include <sys/dirent.h>
41 #include <sys/errno.h>
42 #include <sys/file.h>
43 #include <sys/inline.h>
44 #include <sys/kmem.h>
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_FDINFODIR, 22 * sizeof (prdirent_t), sizeof (prdirent_t),
161 "fdinfo" },
162 { PR_OBJECTDIR, 23 * sizeof (prdirent_t), sizeof (prdirent_t),
163 "object" },
164 { PR_LWPDIR, 24 * sizeof (prdirent_t), sizeof (prdirent_t),
165 "lwp" },
166 { PR_PRIV, 25 * sizeof (prdirent_t), sizeof (prdirent_t),
167 "priv" },
168 { PR_PATHDIR, 26 * sizeof (prdirent_t), sizeof (prdirent_t),
169 "path" },
170 { PR_CTDIR, 27 * sizeof (prdirent_t), sizeof (prdirent_t),
171 "contracts" },
172 { PR_SECFLAGS, 28 * sizeof (prdirent_t), sizeof (prdirent_t),
173 "secflags" },
174 { PR_ARGV, 29 * sizeof (prdirent_t), sizeof (prdirent_t),
175 "argv" },
176 { PR_CMDLINE, 30 * sizeof (prdirent_t), sizeof (prdirent_t),
177 "cmdline" },
178 #if defined(__x86)
179 { PR_LDT, 31 * sizeof (prdirent_t), sizeof (prdirent_t),
180 "ldt" },
181 #endif
182 };
183
184 #define NPIDDIRFILES (sizeof (piddir) / sizeof (piddir[0]) - 2)
185
186 /*
187 * Contents of a /proc/<pid>/lwp/<lwpid> directory.
188 */
189 static prdirent_t lwpiddir[] = {
190 { PR_LWPIDDIR, 1 * sizeof (prdirent_t), sizeof (prdirent_t),
191 "." },
192 { PR_LWPDIR, 2 * sizeof (prdirent_t), sizeof (prdirent_t),
193 ".." },
194 { PR_LWPCTL, 3 * sizeof (prdirent_t), sizeof (prdirent_t),
195 "lwpctl" },
196 { PR_LWPNAME, 4 * sizeof (prdirent_t), sizeof (prdirent_t),
197 "lwpname" },
198 { PR_LWPSTATUS, 5 * sizeof (prdirent_t), sizeof (prdirent_t),
199 "lwpstatus" },
580 if (killproc)
581 sigtoproc(p, NULL, SIGKILL);
582 else
583 allsetrun(p);
584 }
585
586 prunlock(pnp);
587 return (0);
588 }
589
590 /*
591 * Array of read functions, indexed by /proc file type.
592 */
593 static int pr_read_inval(), pr_read_as(), pr_read_status(),
594 pr_read_lstatus(), pr_read_psinfo(), pr_read_lpsinfo(),
595 pr_read_map(), pr_read_rmap(), pr_read_xmap(),
596 pr_read_cred(), pr_read_sigact(), pr_read_auxv(),
597 #if defined(__x86)
598 pr_read_ldt(),
599 #endif
600 pr_read_argv(), pr_read_cmdline(),
601 pr_read_usage(), pr_read_lusage(), pr_read_pagedata(),
602 pr_read_watch(), pr_read_lwpstatus(), pr_read_lwpsinfo(),
603 pr_read_lwpusage(), pr_read_lwpname(),
604 pr_read_xregs(), pr_read_priv(),
605 pr_read_spymaster(), pr_read_secflags(),
606 #if defined(__sparc)
607 pr_read_gwindows(), pr_read_asrs(),
608 #endif
609 pr_read_piddir(), pr_read_pidfile(), pr_read_opagedata(),
610 pr_read_fdinfo();
611
612 static int (*pr_read_function[PR_NFILES])() = {
613 pr_read_inval, /* /proc */
614 pr_read_inval, /* /proc/self */
615 pr_read_piddir, /* /proc/<pid> (old /proc read()) */
616 pr_read_as, /* /proc/<pid>/as */
617 pr_read_inval, /* /proc/<pid>/ctl */
618 pr_read_status, /* /proc/<pid>/status */
619 pr_read_lstatus, /* /proc/<pid>/lstatus */
620 pr_read_psinfo, /* /proc/<pid>/psinfo */
621 pr_read_lpsinfo, /* /proc/<pid>/lpsinfo */
622 pr_read_map, /* /proc/<pid>/map */
623 pr_read_rmap, /* /proc/<pid>/rmap */
624 pr_read_xmap, /* /proc/<pid>/xmap */
625 pr_read_cred, /* /proc/<pid>/cred */
626 pr_read_sigact, /* /proc/<pid>/sigact */
627 pr_read_auxv, /* /proc/<pid>/auxv */
628 #if defined(__x86)
629 pr_read_ldt, /* /proc/<pid>/ldt */
630 #endif
631 pr_read_argv, /* /proc/<pid>/argv */
632 pr_read_cmdline, /* /proc/<pid>/cmdline */
633 pr_read_usage, /* /proc/<pid>/usage */
634 pr_read_lusage, /* /proc/<pid>/lusage */
635 pr_read_pagedata, /* /proc/<pid>/pagedata */
636 pr_read_watch, /* /proc/<pid>/watch */
637 pr_read_inval, /* /proc/<pid>/cwd */
638 pr_read_inval, /* /proc/<pid>/root */
639 pr_read_inval, /* /proc/<pid>/fd */
640 pr_read_inval, /* /proc/<pid>/fd/nn */
641 pr_read_inval, /* /proc/<pid>/fdinfo */
642 pr_read_fdinfo, /* /proc/<pid>/fdinfo/nn */
643 pr_read_inval, /* /proc/<pid>/object */
644 pr_read_inval, /* /proc/<pid>/object/xxx */
645 pr_read_inval, /* /proc/<pid>/lwp */
646 pr_read_inval, /* /proc/<pid>/lwp/<lwpid> */
647 pr_read_inval, /* /proc/<pid>/lwp/<lwpid>/lwpctl */
648 pr_read_lwpname, /* /proc/<pid>/lwp/<lwpid>/lwpname */
649 pr_read_lwpstatus, /* /proc/<pid>/lwp/<lwpid>/lwpstatus */
650 pr_read_lwpsinfo, /* /proc/<pid>/lwp/<lwpid>/lwpsinfo */
651 pr_read_lwpusage, /* /proc/<pid>/lwp/<lwpid>/lwpusage */
652 pr_read_xregs, /* /proc/<pid>/lwp/<lwpid>/xregs */
679 */
680 return (EINVAL);
681 }
682
683 static int
684 pr_uioread(void *base, long count, uio_t *uiop)
685 {
686 int error = 0;
687
688 ASSERT(count >= 0);
689 count -= uiop->uio_offset;
690 if (count > 0 && uiop->uio_offset >= 0) {
691 error = uiomove((char *)base + uiop->uio_offset,
692 count, UIO_READ, uiop);
693 }
694
695 return (error);
696 }
697
698 static int
699 pr_read_cmdline(prnode_t *pnp, uio_t *uiop)
700 {
701 char *args;
702 int error;
703 size_t asz = PRMAXARGVLEN, sz;
704
705 /*
706 * Allocate a scratch buffer for collection of the process arguments.
707 */
708 args = kmem_alloc(asz, KM_SLEEP);
709
710 ASSERT(pnp->pr_type == PR_CMDLINE);
711
712 if ((error = prlock(pnp, ZNO)) != 0) {
713 kmem_free(args, asz);
714 return (error);
715 }
716
717 if ((error = prreadcmdline(pnp->pr_common->prc_proc, args, asz,
718 &sz)) != 0) {
719 prunlock(pnp);
720 kmem_free(args, asz);
721 return (error);
722 }
723
724 prunlock(pnp);
725
726 error = pr_uioread(args, sz, uiop);
727
728 kmem_free(args, asz);
729
730 return (error);
731 }
732
733 static int
734 pr_read_argv(prnode_t *pnp, uio_t *uiop)
735 {
736 char *args;
737 int error;
738 size_t asz = PRMAXARGVLEN, sz;
739
740 /*
741 * Allocate a scratch buffer for collection of the process arguments.
742 */
743 args = kmem_alloc(asz, KM_SLEEP);
744
745 ASSERT(pnp->pr_type == PR_ARGV);
746
747 if ((error = prlock(pnp, ZNO)) != 0) {
748 kmem_free(args, asz);
749 return (error);
750 }
751
752 if ((error = prreadargv(pnp->pr_common->prc_proc, args, asz,
753 &sz)) != 0) {
754 prunlock(pnp);
755 kmem_free(args, asz);
756 return (error);
757 }
758
759 prunlock(pnp);
760
761 error = pr_uioread(args, sz, uiop);
762
763 kmem_free(args, asz);
764
765 return (error);
766 }
767
768 static int
769 pr_read_as(prnode_t *pnp, uio_t *uiop)
770 {
771 int error;
772
773 ASSERT(pnp->pr_type == PR_AS);
774
775 if ((error = prlock(pnp, ZNO)) == 0) {
776 proc_t *p = pnp->pr_common->prc_proc;
777 struct as *as = p->p_as;
778
779 /*
780 * /proc I/O cannot be done to a system process.
781 * A 32-bit process cannot read a 64-bit process.
782 */
783 if ((p->p_flag & SSYS) || as == &kas) {
784 error = 0;
785 #ifdef _SYSCALL32_IMPL
786 } else if (curproc->p_model == DATAMODEL_ILP32 &&
787 PROCESS_NOT_32BIT(p)) {
788 error = EOVERFLOW;
1990
1991 static int (*pr_read_function_32[PR_NFILES])() = {
1992 pr_read_inval, /* /proc */
1993 pr_read_inval, /* /proc/self */
1994 pr_read_piddir, /* /proc/<pid> (old /proc read()) */
1995 pr_read_as, /* /proc/<pid>/as */
1996 pr_read_inval, /* /proc/<pid>/ctl */
1997 pr_read_status_32, /* /proc/<pid>/status */
1998 pr_read_lstatus_32, /* /proc/<pid>/lstatus */
1999 pr_read_psinfo_32, /* /proc/<pid>/psinfo */
2000 pr_read_lpsinfo_32, /* /proc/<pid>/lpsinfo */
2001 pr_read_map_32, /* /proc/<pid>/map */
2002 pr_read_rmap_32, /* /proc/<pid>/rmap */
2003 pr_read_xmap_32, /* /proc/<pid>/xmap */
2004 pr_read_cred, /* /proc/<pid>/cred */
2005 pr_read_sigact_32, /* /proc/<pid>/sigact */
2006 pr_read_auxv_32, /* /proc/<pid>/auxv */
2007 #if defined(__x86)
2008 pr_read_ldt, /* /proc/<pid>/ldt */
2009 #endif
2010 pr_read_argv, /* /proc/<pid>/argv */
2011 pr_read_cmdline, /* /proc/<pid>/cmdline */
2012 pr_read_usage_32, /* /proc/<pid>/usage */
2013 pr_read_lusage_32, /* /proc/<pid>/lusage */
2014 pr_read_pagedata_32, /* /proc/<pid>/pagedata */
2015 pr_read_watch_32, /* /proc/<pid>/watch */
2016 pr_read_inval, /* /proc/<pid>/cwd */
2017 pr_read_inval, /* /proc/<pid>/root */
2018 pr_read_inval, /* /proc/<pid>/fd */
2019 pr_read_inval, /* /proc/<pid>/fd/nn */
2020 pr_read_inval, /* /proc/<pid>/fdinfo */
2021 pr_read_fdinfo, /* /proc/<pid>/fdinfo/nn */
2022 pr_read_inval, /* /proc/<pid>/object */
2023 pr_read_inval, /* /proc/<pid>/object/xxx */
2024 pr_read_inval, /* /proc/<pid>/lwp */
2025 pr_read_inval, /* /proc/<pid>/lwp/<lwpid> */
2026 pr_read_inval, /* /proc/<pid>/lwp/<lwpid>/lwpctl */
2027 pr_read_lwpname, /* /proc/<pid>/lwp/<lwpid>/lwpname */
2028 pr_read_lwpstatus_32, /* /proc/<pid>/lwp/<lwpid>/lwpstatus */
2029 pr_read_lwpsinfo_32, /* /proc/<pid>/lwp/<lwpid>/lwpsinfo */
2030 pr_read_lwpusage_32, /* /proc/<pid>/lwp/<lwpid>/lwpusage */
2031 pr_read_xregs, /* /proc/<pid>/lwp/<lwpid>/xregs */
2920 {
2921 prnode_t *pnp = VTOP(vp);
2922
2923 ASSERT(pnp->pr_type < PR_NFILES);
2924
2925 #ifdef _SYSCALL32_IMPL
2926 /*
2927 * What is read from the /proc files depends on the data
2928 * model of the caller. An LP64 process will see LP64
2929 * data. An ILP32 process will see ILP32 data.
2930 */
2931 if (curproc->p_model == DATAMODEL_LP64)
2932 return (pr_read_function[pnp->pr_type](pnp, uiop, cr));
2933 else
2934 return (pr_read_function_32[pnp->pr_type](pnp, uiop, cr));
2935 #else
2936 return (pr_read_function[pnp->pr_type](pnp, uiop, cr));
2937 #endif
2938 }
2939
2940 /*
2941 * We make pr_write_psinfo_fname() somewhat simpler by asserting at compile
2942 * time that PRFNSZ has the same definition as MAXCOMLEN.
2943 */
2944 #if PRFNSZ != MAXCOMLEN
2945 #error PRFNSZ/MAXCOMLEN mismatch
2946 #endif
2947
2948 static int
2949 pr_write_psinfo_fname(prnode_t *pnp, uio_t *uiop)
2950 {
2951 char fname[PRFNSZ];
2952 int offset = offsetof(psinfo_t, pr_fname), error;
2953
2954 #ifdef _SYSCALL32_IMPL
2955 if (curproc->p_model != DATAMODEL_LP64)
2956 offset = offsetof(psinfo32_t, pr_fname);
2957 #endif
2958
2959 /*
2960 * If this isn't a write to pr_fname (or if the size doesn't match
2961 * PRFNSZ) return.
2962 */
2963 if (uiop->uio_offset != offset || uiop->uio_resid != PRFNSZ)
2964 return (0);
2965
2966 if ((error = uiomove(fname, PRFNSZ, UIO_WRITE, uiop)) != 0)
2967 return (error);
2968
2969 fname[PRFNSZ - 1] = '\0';
2970
2971 if ((error = prlock(pnp, ZNO)) != 0)
2972 return (error);
2973
2974 bcopy(fname, pnp->pr_common->prc_proc->p_user.u_comm, PRFNSZ);
2975
2976 prunlock(pnp);
2977
2978 return (0);
2979 }
2980
2981 /*
2982 * We make pr_write_psinfo_psargs() somewhat simpler by asserting at compile
2983 * time that PRARGSZ has the same definition as PSARGSZ.
2984 */
2985 #if PRARGSZ != PSARGSZ
2986 #error PRARGSZ/PSARGSZ mismatch
2987 #endif
2988
2989 static int
2990 pr_write_psinfo_psargs(prnode_t *pnp, uio_t *uiop)
2991 {
2992 char psargs[PRARGSZ];
2993 int offset = offsetof(psinfo_t, pr_psargs), error;
2994
2995 #ifdef _SYSCALL32_IMPL
2996 if (curproc->p_model != DATAMODEL_LP64)
2997 offset = offsetof(psinfo32_t, pr_psargs);
2998 #endif
2999
3000 /*
3001 * If this isn't a write to pr_psargs (or if the size doesn't match
3002 * PRARGSZ) return.
3003 */
3004 if (uiop->uio_offset != offset || uiop->uio_resid != PRARGSZ)
3005 return (0);
3006
3007 if ((error = uiomove(psargs, PRARGSZ, UIO_WRITE, uiop)) != 0)
3008 return (error);
3009
3010 psargs[PRARGSZ - 1] = '\0';
3011
3012 if ((error = prlock(pnp, ZNO)) != 0)
3013 return (error);
3014
3015 bcopy(psargs, pnp->pr_common->prc_proc->p_user.u_psargs, PRARGSZ);
3016
3017 prunlock(pnp);
3018
3019 return (0);
3020 }
3021
3022 int
3023 pr_write_psinfo(prnode_t *pnp, uio_t *uiop)
3024 {
3025 int error;
3026
3027 if ((error = pr_write_psinfo_fname(pnp, uiop)) != 0)
3028 return (error);
3029
3030 if ((error = pr_write_psinfo_psargs(pnp, uiop)) != 0)
3031 return (error);
3032
3033 return (0);
3034 }
3035
3036
3037 /* Note we intentionally don't handle partial writes/updates. */
3038 static int
3039 pr_write_lwpname(prnode_t *pnp, uio_t *uiop)
3040 {
3041 kthread_t *t = NULL;
3042 char *lwpname;
3043 int error;
3044
3045 lwpname = kmem_zalloc(THREAD_NAME_MAX, KM_SLEEP);
3046
3047 if ((error = uiomove(lwpname, THREAD_NAME_MAX, UIO_WRITE, uiop)) != 0) {
3048 kmem_free(lwpname, THREAD_NAME_MAX);
3049 return (error);
3050 }
3051
3052 /* Somebody tried to write too long a thread name... */
3053 if (lwpname[THREAD_NAME_MAX - 1] != '\0' || uiop->uio_resid > 0) {
3054 kmem_free(lwpname, THREAD_NAME_MAX);
3055 return (EIO);
3056 }
3143 * Perform the action on the control file
3144 * by passing curthreads credentials
3145 * and not target process's credentials.
3146 */
3147 #ifdef _SYSCALL32_IMPL
3148 if (curproc->p_model == DATAMODEL_ILP32)
3149 error = prwritectl32(vp, uiop, CRED());
3150 else
3151 error = prwritectl(vp, uiop, CRED());
3152 #else
3153 error = prwritectl(vp, uiop, CRED());
3154 #endif
3155 /*
3156 * This hack makes sure that the EINTR is passed
3157 * all the way back to the caller's write() call.
3158 */
3159 if (error == EINTR)
3160 uiop->uio_resid = resid;
3161 return (error);
3162
3163 case PR_PSINFO:
3164 return (pr_write_psinfo(pnp, uiop));
3165
3166 case PR_LWPNAME:
3167 return (pr_write_lwpname(pnp, uiop));
3168
3169 default:
3170 return ((vp->v_type == VDIR)? EISDIR : EBADF);
3171 }
3172 /* NOTREACHED */
3173 }
3174
3175 static int
3176 prgetattr(vnode_t *vp, vattr_t *vap, int flags, cred_t *cr,
3177 caller_context_t *ct)
3178 {
3179 prnode_t *pnp = VTOP(vp);
3180 prnodetype_t type = pnp->pr_type;
3181 prcommon_t *pcp;
3182 proc_t *p;
3183 struct as *as;
3184 int error;
3185 vnode_t *rvp;
3475 vap->va_size = sizeof (prcred_t);
3476 ngroups = crgetngroups(p->p_cred);
3477 if (ngroups > 1)
3478 vap->va_size += (ngroups - 1) * sizeof (gid_t);
3479 mutex_exit(&p->p_crlock);
3480 break;
3481 case PR_PRIV:
3482 vap->va_size = prgetprivsize();
3483 break;
3484 case PR_SECFLAGS:
3485 vap->va_size = sizeof (prsecflags_t);
3486 break;
3487 case PR_SIGACT:
3488 nsig = PROC_IS_BRANDED(curproc)? BROP(curproc)->b_nsig : NSIG;
3489 vap->va_size = (nsig-1) *
3490 PR_OBJSIZE(struct sigaction32, struct sigaction);
3491 break;
3492 case PR_AUXV:
3493 vap->va_size = __KERN_NAUXV_IMPL * PR_OBJSIZE(auxv32_t, auxv_t);
3494 break;
3495 case PR_ARGV:
3496 if ((p->p_flag & SSYS) || p->p_as == &kas) {
3497 vap->va_size = PSARGSZ;
3498 } else {
3499 vap->va_size = PRMAXARGVLEN;
3500 }
3501 break;
3502 #if defined(__x86)
3503 case PR_LDT:
3504 mutex_exit(&p->p_lock);
3505 mutex_enter(&p->p_ldtlock);
3506 vap->va_size = prnldt(p) * sizeof (struct ssd);
3507 mutex_exit(&p->p_ldtlock);
3508 mutex_enter(&p->p_lock);
3509 break;
3510 #endif
3511 case PR_USAGE:
3512 vap->va_size = PR_OBJSIZE(prusage32_t, prusage_t);
3513 break;
3514 case PR_LUSAGE:
3515 vap->va_size = PR_OBJSIZE(prheader32_t, prheader_t) +
3516 (p->p_lwpcnt + 1) * PR_OBJSPAN(prusage32_t, prusage_t);
3517 break;
3518 case PR_PAGEDATA:
3519 if ((p->p_flag & SSYS) || (as = p->p_as) == &kas)
3520 vap->va_size = 0;
3521 else {
3604 if ((n = prnwindows(ttolwp(t))) == 0)
3605 vap->va_size = 0;
3606 else
3607 vap->va_size = PR_OBJSIZE(gwindows32_t, gwindows_t) -
3608 (SPARC_MAXREGWINDOW - n) *
3609 PR_OBJSIZE(struct rwindow32, struct rwindow);
3610 mutex_enter(&p->p_lock);
3611 break;
3612 }
3613 case PR_ASRS:
3614 #ifdef _LP64
3615 if (p->p_model == DATAMODEL_LP64)
3616 vap->va_size = sizeof (asrset_t);
3617 else
3618 #endif
3619 vap->va_size = 0;
3620 break;
3621 #endif
3622 case PR_CTL:
3623 case PR_LWPCTL:
3624 case PR_CMDLINE:
3625 default:
3626 vap->va_size = 0;
3627 break;
3628 }
3629
3630 prunlock(pnp);
3631 vap->va_nblocks = (fsblkcnt64_t)btod(vap->va_size);
3632 return (0);
3633 }
3634
3635 static int
3636 praccess(vnode_t *vp, int mode, int flags, cred_t *cr, caller_context_t *ct)
3637 {
3638 prnode_t *pnp = VTOP(vp);
3639 prnodetype_t type = pnp->pr_type;
3640 int vmode;
3641 vtype_t vtype;
3642 proc_t *p;
3643 int error = 0;
3644 vnode_t *rvp;
3659 * Disallow access to fds with other than existing open modes.
3660 */
3661 rvp = pnp->pr_realvp;
3662 vtype = rvp->v_type;
3663 vmode = pnp->pr_mode;
3664 if ((type == PR_OBJECT && (mode & VWRITE)) ||
3665 (type == PR_FD && vtype != VREG && vtype != VDIR) ||
3666 (type == PR_FD && (vmode & mode) != mode &&
3667 secpolicy_proc_access(cr) != 0))
3668 return (EACCES);
3669 return (VOP_ACCESS(rvp, mode, flags, cr, ct));
3670
3671 case PR_PSINFO: /* these files can be read by anyone */
3672 case PR_LPSINFO:
3673 case PR_LWPSINFO:
3674 case PR_LWPDIR:
3675 case PR_LWPIDDIR:
3676 case PR_USAGE:
3677 case PR_LUSAGE:
3678 case PR_LWPUSAGE:
3679 case PR_ARGV:
3680 case PR_CMDLINE:
3681 p = pr_p_lock(pnp);
3682 mutex_exit(&pr_pidlock);
3683 if (p == NULL)
3684 return (ENOENT);
3685 prunlock(pnp);
3686 break;
3687
3688 default:
3689 /*
3690 * Except for the world-readable files above,
3691 * only /proc/pid exists if the process is a zombie.
3692 */
3693 if ((error = prlock(pnp,
3694 (type == PR_PIDDIR)? ZYES : ZNO)) != 0)
3695 return (error);
3696 p = pnp->pr_common->prc_proc;
3697 if (p != curproc)
3698 error = priv_proc_cred_perm(cr, p, NULL, mode);
3699
3700 if (error != 0 || p == curproc || (p->p_flag & SSYS) ||
3746
3747 static vnode_t *(*pr_lookup_function[PR_NFILES])() = {
3748 pr_lookup_procdir, /* /proc */
3749 pr_lookup_notdir, /* /proc/self */
3750 pr_lookup_piddir, /* /proc/<pid> */
3751 pr_lookup_notdir, /* /proc/<pid>/as */
3752 pr_lookup_notdir, /* /proc/<pid>/ctl */
3753 pr_lookup_notdir, /* /proc/<pid>/status */
3754 pr_lookup_notdir, /* /proc/<pid>/lstatus */
3755 pr_lookup_notdir, /* /proc/<pid>/psinfo */
3756 pr_lookup_notdir, /* /proc/<pid>/lpsinfo */
3757 pr_lookup_notdir, /* /proc/<pid>/map */
3758 pr_lookup_notdir, /* /proc/<pid>/rmap */
3759 pr_lookup_notdir, /* /proc/<pid>/xmap */
3760 pr_lookup_notdir, /* /proc/<pid>/cred */
3761 pr_lookup_notdir, /* /proc/<pid>/sigact */
3762 pr_lookup_notdir, /* /proc/<pid>/auxv */
3763 #if defined(__x86)
3764 pr_lookup_notdir, /* /proc/<pid>/ldt */
3765 #endif
3766 pr_lookup_notdir, /* /proc/<pid>/argv */
3767 pr_lookup_notdir, /* /proc/<pid>/cmdline */
3768 pr_lookup_notdir, /* /proc/<pid>/usage */
3769 pr_lookup_notdir, /* /proc/<pid>/lusage */
3770 pr_lookup_notdir, /* /proc/<pid>/pagedata */
3771 pr_lookup_notdir, /* /proc/<pid>/watch */
3772 pr_lookup_notdir, /* /proc/<pid>/cwd */
3773 pr_lookup_notdir, /* /proc/<pid>/root */
3774 pr_lookup_fddir, /* /proc/<pid>/fd */
3775 pr_lookup_notdir, /* /proc/<pid>/fd/nn */
3776 pr_lookup_fdinfodir, /* /proc/<pid>/fdinfo */
3777 pr_lookup_notdir, /* /proc/<pid>/fdinfo/nn */
3778 pr_lookup_objectdir, /* /proc/<pid>/object */
3779 pr_lookup_notdir, /* /proc/<pid>/object/xxx */
3780 pr_lookup_lwpdir, /* /proc/<pid>/lwp */
3781 pr_lookup_lwpiddir, /* /proc/<pid>/lwp/<lwpid> */
3782 pr_lookup_notdir, /* /proc/<pid>/lwp/<lwpid>/lwpctl */
3783 pr_lookup_notdir, /* /proc/<pid>/lwp/<lwpid>/lwpname */
3784 pr_lookup_notdir, /* /proc/<pid>/lwp/<lwpid>/lwpstatus */
3785 pr_lookup_notdir, /* /proc/<pid>/lwp/<lwpid>/lwpsinfo */
3786 pr_lookup_notdir, /* /proc/<pid>/lwp/<lwpid>/lwpusage */
3787 pr_lookup_notdir, /* /proc/<pid>/lwp/<lwpid>/xregs */
5078 case PR_LWPDIR:
5079 vp->v_type = VDIR;
5080 pnp->pr_mode = 0555; /* read-search by all */
5081 break;
5082
5083 case PR_AS:
5084 case PR_TMPL:
5085 pnp->pr_mode = 0600; /* read-write by owner only */
5086 break;
5087
5088 case PR_CTL:
5089 case PR_LWPCTL:
5090 pnp->pr_mode = 0200; /* write-only by owner only */
5091 break;
5092
5093 case PR_PIDFILE:
5094 case PR_LWPIDFILE:
5095 pnp->pr_mode = 0600; /* read-write by owner only */
5096 break;
5097
5098 case PR_PSINFO:
5099 case PR_LWPNAME:
5100 pnp->pr_mode = 0644; /* readable by all + owner can write */
5101 break;
5102
5103 case PR_LPSINFO:
5104 case PR_LWPSINFO:
5105 case PR_USAGE:
5106 case PR_LUSAGE:
5107 case PR_LWPUSAGE:
5108 case PR_ARGV:
5109 case PR_CMDLINE:
5110 pnp->pr_mode = 0444; /* read-only by all */
5111 break;
5112
5113 default:
5114 pnp->pr_mode = 0400; /* read-only by owner only */
5115 break;
5116 }
5117 vn_exists(vp);
5118 return (pnp);
5119 }
5120
5121 /*
5122 * Free the storage obtained from prgetnode().
5123 */
5124 void
5125 prfreenode(prnode_t *pnp)
5126 {
5127 vnode_t *vp;
5128 ulong_t nfiles;
5129
5197
5198 static int (*pr_readdir_function[PR_NFILES])() = {
5199 pr_readdir_procdir, /* /proc */
5200 pr_readdir_notdir, /* /proc/self */
5201 pr_readdir_piddir, /* /proc/<pid> */
5202 pr_readdir_notdir, /* /proc/<pid>/as */
5203 pr_readdir_notdir, /* /proc/<pid>/ctl */
5204 pr_readdir_notdir, /* /proc/<pid>/status */
5205 pr_readdir_notdir, /* /proc/<pid>/lstatus */
5206 pr_readdir_notdir, /* /proc/<pid>/psinfo */
5207 pr_readdir_notdir, /* /proc/<pid>/lpsinfo */
5208 pr_readdir_notdir, /* /proc/<pid>/map */
5209 pr_readdir_notdir, /* /proc/<pid>/rmap */
5210 pr_readdir_notdir, /* /proc/<pid>/xmap */
5211 pr_readdir_notdir, /* /proc/<pid>/cred */
5212 pr_readdir_notdir, /* /proc/<pid>/sigact */
5213 pr_readdir_notdir, /* /proc/<pid>/auxv */
5214 #if defined(__x86)
5215 pr_readdir_notdir, /* /proc/<pid>/ldt */
5216 #endif
5217 pr_readdir_notdir, /* /proc/<pid>/argv */
5218 pr_readdir_notdir, /* /proc/<pid>/cmdline */
5219 pr_readdir_notdir, /* /proc/<pid>/usage */
5220 pr_readdir_notdir, /* /proc/<pid>/lusage */
5221 pr_readdir_notdir, /* /proc/<pid>/pagedata */
5222 pr_readdir_notdir, /* /proc/<pid>/watch */
5223 pr_readdir_notdir, /* /proc/<pid>/cwd */
5224 pr_readdir_notdir, /* /proc/<pid>/root */
5225 pr_readdir_fddir, /* /proc/<pid>/fd */
5226 pr_readdir_notdir, /* /proc/<pid>/fd/nn */
5227 pr_readdir_fdinfodir, /* /proc/<pid>/fdinfo */
5228 pr_readdir_notdir, /* /proc/<pid>/fdinfo/nn */
5229 pr_readdir_objectdir, /* /proc/<pid>/object */
5230 pr_readdir_notdir, /* /proc/<pid>/object/xxx */
5231 pr_readdir_lwpdir, /* /proc/<pid>/lwp */
5232 pr_readdir_lwpiddir, /* /proc/<pid>/lwp/<lwpid> */
5233 pr_readdir_notdir, /* /proc/<pid>/lwp/<lwpid>/lwpctl */
5234 pr_readdir_notdir, /* /proc/<pid>/lwp/<lwpid>/lwpname */
5235 pr_readdir_notdir, /* /proc/<pid>/lwp/<lwpid>/lwpstatus */
5236 pr_readdir_notdir, /* /proc/<pid>/lwp/<lwpid>/lwpsinfo */
5237 pr_readdir_notdir, /* /proc/<pid>/lwp/<lwpid>/lwpusage */
5238 pr_readdir_notdir, /* /proc/<pid>/lwp/<lwpid>/xregs */
5352 if (pnp->pr_pcommon->prc_proc == NULL)
5353 return (ENOENT);
5354 if (uiop->uio_offset >= sizeof (piddir))
5355 goto out;
5356
5357 /*
5358 * Loop until user's request is satisfied, omitting some
5359 * files along the way if the process is a zombie.
5360 */
5361 for (dirp = &piddir[uiop->uio_offset / sizeof (prdirent_t)];
5362 uiop->uio_resid >= sizeof (prdirent_t) &&
5363 dirp < &piddir[NPIDDIRFILES+2];
5364 uiop->uio_offset = off + sizeof (prdirent_t), dirp++) {
5365 off = uiop->uio_offset;
5366 if (zombie) {
5367 switch (dirp->d_ino) {
5368 case PR_PIDDIR:
5369 case PR_PROCDIR:
5370 case PR_PSINFO:
5371 case PR_USAGE:
5372 case PR_ARGV:
5373 case PR_CMDLINE:
5374 break;
5375 default:
5376 continue;
5377 }
5378 }
5379 bcopy(dirp, &dirent, sizeof (prdirent_t));
5380 if (dirent.d_ino == PR_PROCDIR)
5381 dirent.d_ino = PRROOTINO;
5382 else
5383 dirent.d_ino = pmkino(0, pnp->pr_pcommon->prc_slot,
5384 dirent.d_ino);
5385 if ((error = uiomove((caddr_t)&dirent, sizeof (prdirent_t),
5386 UIO_READ, uiop)) != 0)
5387 return (error);
5388 }
5389 out:
5390 if (eofp)
5391 *eofp = (uiop->uio_offset >= sizeof (piddir));
5392 return (0);
5393 }
|