Print this page




   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 }