On Thu, Dec 01, 2022 at 11:28:59AM -0800, Philip Guenther wrote:
> On Thu, Dec 1, 2022 at 10:31 AM Vitaliy Makkoveev <m...@openbsd.org> wrote:
> ...
> 
> > --- sys/sys/sysctl.h    7 Nov 2022 14:25:44 -0000       1.231
> > +++ sys/sys/sysctl.h    1 Dec 2022 18:15:06 -0000
> > @@ -587,7 +587,7 @@ struct kinfo_vmentry {
> >
> >  #define        _FILL_KPROC_MIN(a,b) (((a)<(b))?(a):(b))
> >
> > -#define FILL_KPROC(kp, copy_str, p, pr, uc, pg, paddr, \
> > +#define FILL_KPROC(kp, copy_str, p, pr, pg, paddr, \
> >      praddr, sess, vm, lim, sa, isthread, show_addresses) \
> >
> ...
> 
> > -       (kp)->p_svgid = (uc)->cr_svgid;                                 \
> > +       PR_LOCK(pr);                                                    \
> > +       (kp)->p_uid = (pr)->ps_ucred->cr_uid;                           \
> >
> 
> Nope.  As the block comment about this notes, FILL_KPROC() is shared
> between the kernel and libkvm and takes each structure pointer separately
> as, for example, pr->ps_ucred has the kva address, not the address of the
> ucred struct that libkvm has separately read into user memory.
> 
> Now, you _could_ have libkvm update pr->ps_ucred to point to its user-space
> copy.  However, that would make ucred handling different from the other
> sub-structures of struct proc and MOST of those we need the real kva for
> the show_address functionality.
> 
> Not sure if this is the yak-shave you want right now...
> 
> (libkvm will obviously also need no-op #defines for PR_LOCK() etc)
> 

I missed this.

Since `ps_ucred' is immutable, we could bump it's reference and use it
without holding `ps_mtx':

        mtx_enter(&pr->ps_mtx);
        prucred = crhold(pr->ps_ucred);
        mtx_leave(&pr->ps_mtx);

        FILL_KPROC(ki, strlcpy, p, pr, prucred, pr->ps_pgrp, ...);
        crfree(prucred);

Otherwise, we could grab `ps_mtx' mutex outside FILL_KPROC(), so dummy
PR_LOCK() define will be not required in userland.

The diff below follows the first way.

Index: sys/kern/kern_acct.c
===================================================================
RCS file: /cvs/src/sys/kern/kern_acct.c,v
retrieving revision 1.47
diff -u -p -r1.47 kern_acct.c
--- sys/kern/kern_acct.c        14 Aug 2022 01:58:27 -0000      1.47
+++ sys/kern/kern_acct.c        1 Dec 2022 19:49:15 -0000
@@ -221,8 +221,10 @@ acct_process(struct proc *p)
        acct.ac_io = encode_comp_t(r->ru_inblock + r->ru_oublock, 0);
 
        /* (6) The UID and GID of the process */
+       mtx_enter(&pr->ps_mtx);
        acct.ac_uid = pr->ps_ucred->cr_ruid;
        acct.ac_gid = pr->ps_ucred->cr_rgid;
+       mtx_leave(&pr->ps_mtx);
 
        /* (7) The terminal from which the process was started */
        if ((pr->ps_flags & PS_CONTROLT) &&
Index: sys/kern/kern_exec.c
===================================================================
RCS file: /cvs/src/sys/kern/kern_exec.c,v
retrieving revision 1.240
diff -u -p -r1.240 kern_exec.c
--- sys/kern/kern_exec.c        23 Nov 2022 11:00:27 -0000      1.240
+++ sys/kern/kern_exec.c        1 Dec 2022 19:49:15 -0000
@@ -649,9 +649,11 @@ sys_execve(struct proc *p, void *v, regi
        if (pr->ps_ucred != cred) {
                struct ucred *ocred;
 
-               ocred = pr->ps_ucred;
                crhold(cred);
+               mtx_enter(&pr->ps_mtx);
+               ocred = pr->ps_ucred;
                pr->ps_ucred = cred;
+               mtx_leave(&pr->ps_mtx);
                crfree(ocred);
        }
 
Index: sys/kern/kern_exit.c
===================================================================
RCS file: /cvs/src/sys/kern/kern_exit.c,v
retrieving revision 1.207
diff -u -p -r1.207 kern_exit.c
--- sys/kern/kern_exit.c        3 Nov 2022 04:56:47 -0000       1.207
+++ sys/kern/kern_exit.c        1 Dec 2022 19:49:15 -0000
@@ -494,7 +494,9 @@ loop:
                        *retval = pr->ps_pid;
                        if (info != NULL) {
                                info->si_pid = pr->ps_pid;
+                               mtx_enter(&pr->ps_mtx);
                                info->si_uid = pr->ps_ucred->cr_uid;
+                               mtx_leave(&pr->ps_mtx);
                                info->si_signo = SIGCHLD;
                                if (pr->ps_xsig == 0) {
                                        info->si_code = CLD_EXITED;
@@ -530,7 +532,9 @@ loop:
                        *retval = pr->ps_pid;
                        if (info != NULL) {
                                info->si_pid = pr->ps_pid;
+                               mtx_enter(&pr->ps_mtx);
                                info->si_uid = pr->ps_ucred->cr_uid;
+                               mtx_leave(&pr->ps_mtx);
                                info->si_signo = SIGCHLD;
                                info->si_code = CLD_TRAPPED;
                                info->si_status = pr->ps_xsig;
@@ -553,7 +557,9 @@ loop:
                        *retval = pr->ps_pid;
                        if (info != 0) {
                                info->si_pid = pr->ps_pid;
+                               mtx_enter(&pr->ps_mtx);
                                info->si_uid = pr->ps_ucred->cr_uid;
+                               mtx_leave(&pr->ps_mtx);
                                info->si_signo = SIGCHLD;
                                info->si_code = CLD_STOPPED;
                                info->si_status = pr->ps_xsig;
@@ -572,7 +578,9 @@ loop:
                        *retval = pr->ps_pid;
                        if (info != NULL) {
                                info->si_pid = pr->ps_pid;
+                               mtx_enter(&pr->ps_mtx);
                                info->si_uid = pr->ps_ucred->cr_uid;
+                               mtx_leave(&pr->ps_mtx);
                                info->si_signo = SIGCHLD;
                                info->si_code = CLD_CONTINUED;
                                info->si_status = SIGCONT;
Index: sys/kern/kern_ktrace.c
===================================================================
RCS file: /cvs/src/sys/kern/kern_ktrace.c,v
retrieving revision 1.108
diff -u -p -r1.108 kern_ktrace.c
--- sys/kern/kern_ktrace.c      14 Aug 2022 01:58:27 -0000      1.108
+++ sys/kern/kern_ktrace.c      1 Dec 2022 19:49:15 -0000
@@ -693,7 +693,12 @@ int
 ktrcanset(struct proc *callp, struct process *targetpr)
 {
        struct ucred *caller = callp->p_ucred;
-       struct ucred *target = targetpr->ps_ucred;
+       struct ucred *target;
+       int ret = 0;
+
+       mtx_enter(&targetpr->ps_mtx);
+
+       target = targetpr->ps_ucred;
 
        if ((caller->cr_uid == target->cr_ruid &&
            target->cr_ruid == target->cr_svuid &&
@@ -702,7 +707,9 @@ ktrcanset(struct proc *callp, struct pro
            (targetpr->ps_traceflag & KTRFAC_ROOT) == 0 &&
            !ISSET(targetpr->ps_flags, PS_SUGID)) ||
            caller->cr_uid == 0)
-               return (1);
+               ret = 1;
+
+       mtx_leave(&targetpr->ps_mtx);
 
-       return (0);
+       return (ret);
 }
Index: sys/kern/kern_proc.c
===================================================================
RCS file: /cvs/src/sys/kern/kern_proc.c,v
retrieving revision 1.92
diff -u -p -r1.92 kern_proc.c
--- sys/kern/kern_proc.c        14 Aug 2022 01:58:27 -0000      1.92
+++ sys/kern/kern_proc.c        1 Dec 2022 19:49:15 -0000
@@ -583,6 +583,7 @@ db_show_all_procs(db_expr_t addr, int ha
                                        break;
 
                                case 'n':
+                                       mtx_enter(&pr->ps_mtx);
                                        db_printf("%6d  %5d  %5d  %d  %#10x  "
                                            "%-12.12s  %-15s\n",
                                            p->p_tid, ppr ? ppr->ps_pid : -1,
@@ -590,6 +591,7 @@ db_show_all_procs(db_expr_t addr, int ha
                                            p->p_flag | pr->ps_flags,
                                            (p->p_wchan && p->p_wmesg) ?
                                                p->p_wmesg : "", pr->ps_comm);
+                                       mtx_leave(&pr->ps_mtx);
                                        break;
 
                                case 'w':
@@ -602,6 +604,7 @@ db_show_all_procs(db_expr_t addr, int ha
                                        break;
 
                                case 'o':
+                                       mtx_enter(&pr->ps_mtx);
                                        db_printf("%5d  %5d  %#10x %#10x  %3d"
                                            "%c %-31s\n",
                                            pr->ps_pid, pr->ps_ucred->cr_ruid,
@@ -609,6 +612,7 @@ db_show_all_procs(db_expr_t addr, int ha
                                            CPU_INFO_UNIT(p->p_cpu),
                                            has_kernel_lock ? 'K' : ' ',
                                            pr->ps_comm);
+                                       mtx_leave(&pr->ps_mtx);
                                        break;
 
                                }
Index: sys/kern/kern_prot.c
===================================================================
RCS file: /cvs/src/sys/kern/kern_prot.c,v
retrieving revision 1.80
diff -u -p -r1.80 kern_prot.c
--- sys/kern/kern_prot.c        14 Aug 2022 01:58:27 -0000      1.80
+++ sys/kern/kern_prot.c        1 Dec 2022 19:49:15 -0000
@@ -351,12 +351,16 @@ sys_setresuid(struct proc *p, void *v, r
        struct process *pr = p->p_p;
        struct ucred *pruc, *newcred, *uc = p->p_ucred;
        uid_t ruid, euid, suid;
-       int error;
+       int error = 0;
 
        ruid = SCARG(uap, ruid);
        euid = SCARG(uap, euid);
        suid = SCARG(uap, suid);
 
+       newcred = crget();
+
+       mtx_enter(&pr->ps_mtx);
+
        /*
         * make permission checks against the thread's ucred,
         * but the actual changes will be to the process's ucred
@@ -365,7 +369,7 @@ sys_setresuid(struct proc *p, void *v, r
        if ((ruid == (uid_t)-1 || ruid == pruc->cr_ruid) &&
            (euid == (uid_t)-1 || euid == pruc->cr_uid) &&
            (suid == (uid_t)-1 || suid == pruc->cr_svuid))
-               return (0);                     /* no change */
+               goto error;                     /* no change */
 
        /*
         * Any of the real, effective, and saved uids may be changed
@@ -376,28 +380,25 @@ sys_setresuid(struct proc *p, void *v, r
            ruid != uc->cr_uid &&
            ruid != uc->cr_svuid &&
            (error = suser(p)))
-               return (error);
+               goto error;
 
        if (euid != (uid_t)-1 &&
            euid != uc->cr_ruid &&
            euid != uc->cr_uid &&
            euid != uc->cr_svuid &&
            (error = suser(p)))
-               return (error);
+               goto error;
 
        if (suid != (uid_t)-1 &&
            suid != uc->cr_ruid &&
            suid != uc->cr_uid &&
            suid != uc->cr_svuid &&
            (error = suser(p)))
-               return (error);
+               goto error;
 
        /*
         * Copy credentials so other references do not see our changes.
-        * ps_ucred may change during the crget().
         */
-       newcred = crget();
-       pruc = pr->ps_ucred;
        crset(newcred, pruc);
 
        /*
@@ -411,6 +412,9 @@ sys_setresuid(struct proc *p, void *v, r
        if (suid != (uid_t)-1)
                newcred->cr_svuid = suid;
        pr->ps_ucred = newcred;
+
+       mtx_leave(&pr->ps_mtx);
+
        atomic_setbits_int(&p->p_p->ps_flags, PS_SUGID);
 
        /* now that we can sleep, transfer proc count to new user */
@@ -421,6 +425,12 @@ sys_setresuid(struct proc *p, void *v, r
        crfree(pruc);
 
        return (0);
+
+error:
+       mtx_leave(&pr->ps_mtx);
+       crfree(newcred);
+
+       return (error);
 }
 
 int
@@ -460,12 +470,16 @@ sys_setresgid(struct proc *p, void *v, r
        struct process *pr = p->p_p;
        struct ucred *pruc, *newcred, *uc = p->p_ucred;
        gid_t rgid, egid, sgid;
-       int error;
+       int error = 0;
 
        rgid = SCARG(uap, rgid);
        egid = SCARG(uap, egid);
        sgid = SCARG(uap, sgid);
 
+       newcred = crget();
+
+       mtx_enter(&pr->ps_mtx);
+
        /*
         * make permission checks against the thread's ucred,
         * but the actual changes will be to the process's ucred
@@ -474,7 +488,7 @@ sys_setresgid(struct proc *p, void *v, r
        if ((rgid == (gid_t)-1 || rgid == pruc->cr_rgid) &&
            (egid == (gid_t)-1 || egid == pruc->cr_gid) &&
            (sgid == (gid_t)-1 || sgid == pruc->cr_svgid))
-               return (0);                     /* no change */
+               goto error;                     /* no change */
 
        /*
         * Any of the real, effective, and saved gids may be changed
@@ -485,28 +499,25 @@ sys_setresgid(struct proc *p, void *v, r
            rgid != uc->cr_gid &&
            rgid != uc->cr_svgid &&
            (error = suser(p)))
-               return (error);
+               goto error;
 
        if (egid != (gid_t)-1 &&
            egid != uc->cr_rgid &&
            egid != uc->cr_gid &&
            egid != uc->cr_svgid &&
            (error = suser(p)))
-               return (error);
+               goto error;
 
        if (sgid != (gid_t)-1 &&
            sgid != uc->cr_rgid &&
            sgid != uc->cr_gid &&
            sgid != uc->cr_svgid &&
            (error = suser(p)))
-               return (error);
+               goto error;
 
        /*
         * Copy credentials so other references do not see our changes.
-        * ps_ucred may change during the crget().
         */
-       newcred = crget();
-       pruc = pr->ps_ucred;
        crset(newcred, pruc);
 
        /*
@@ -520,9 +531,18 @@ sys_setresgid(struct proc *p, void *v, r
        if (sgid != (gid_t)-1)
                newcred->cr_svgid = sgid;
        pr->ps_ucred = newcred;
+
+       mtx_leave(&pr->ps_mtx);
+
        atomic_setbits_int(&p->p_p->ps_flags, PS_SUGID);
        crfree(pruc);
        return (0);
+
+error:
+       mtx_leave(&pr->ps_mtx);
+       crfree(newcred);
+
+       return (error);
 }
 
 int
@@ -535,11 +555,15 @@ sys_setregid(struct proc *p, void *v, re
        struct process *pr = p->p_p;
        struct ucred *pruc, *newcred, *uc = p->p_ucred;
        gid_t rgid, egid;
-       int error;
+       int error = 0;
 
        rgid = SCARG(uap, rgid);
        egid = SCARG(uap, egid);
 
+       newcred = crget();
+
+       mtx_enter(&pr->ps_mtx);
+
        /*
         * make permission checks against the thread's ucred,
         * but the actual changes will be to the process's ucred
@@ -556,7 +580,7 @@ sys_setregid(struct proc *p, void *v, re
            (egid == (gid_t)-1 || egid == pruc->cr_gid) &&
            (rgid == (gid_t)-1 || (rgid == pruc->cr_rgid &&
            pruc->cr_svgid == (egid != (gid_t)-1 ? egid : pruc->cr_gid))))
-               return (0);                     /* no change */
+               goto error;                     /* no change */
 
        /*
         * Any of the real, effective, and saved gids may be changed
@@ -567,21 +591,18 @@ sys_setregid(struct proc *p, void *v, re
            rgid != uc->cr_gid &&
            rgid != uc->cr_svgid &&
            (error = suser(p)))
-               return (error);
+               goto error;
 
        if (egid != (gid_t)-1 &&
            egid != uc->cr_rgid &&
            egid != uc->cr_gid &&
            egid != uc->cr_svgid &&
            (error = suser(p)))
-               return (error);
+               goto error;
 
        /*
         * Copy credentials so other references do not see our changes.
-        * ps_ucred may change during the crget().
         */
-       newcred = crget();
-       pruc = pr->ps_ucred;
        crset(newcred, pruc);
 
        if (rgid != (gid_t)-1)
@@ -599,9 +620,18 @@ sys_setregid(struct proc *p, void *v, re
            pruc->cr_svgid != (egid != (gid_t)-1 ? egid : pruc->cr_gid)))
                newcred->cr_svgid = rgid;
        pr->ps_ucred = newcred;
+
+       mtx_leave(&pr->ps_mtx);
+
        atomic_setbits_int(&p->p_p->ps_flags, PS_SUGID);
        crfree(pruc);
        return (0);
+
+error:
+       mtx_leave(&pr->ps_mtx);
+       crfree(newcred);
+
+       return (error);
 }
 
 int
@@ -614,11 +644,15 @@ sys_setreuid(struct proc *p, void *v, re
        struct process *pr = p->p_p;
        struct ucred *pruc, *newcred, *uc = p->p_ucred;
        uid_t ruid, euid;
-       int error;
+       int error = 0;
 
        ruid = SCARG(uap, ruid);
        euid = SCARG(uap, euid);
 
+       newcred = crget();
+
+       mtx_enter(&pr->ps_mtx);
+
        /*
         * make permission checks against the thread's ucred,
         * but the actual changes will be to the process's ucred
@@ -635,7 +669,7 @@ sys_setreuid(struct proc *p, void *v, re
            (euid == (uid_t)-1 || euid == pruc->cr_uid) &&
            (ruid == (uid_t)-1 || (ruid == pruc->cr_ruid &&
            pruc->cr_svuid == (euid != (uid_t)-1 ? euid : pruc->cr_uid))))
-               return (0);                     /* no change */
+               goto error;                     /* no change */
 
        /*
         * Any of the real, effective, and saved uids may be changed
@@ -646,21 +680,18 @@ sys_setreuid(struct proc *p, void *v, re
            ruid != uc->cr_uid &&
            ruid != uc->cr_svuid &&
            (error = suser(p)))
-               return (error);
+               goto error;
 
        if (euid != (uid_t)-1 &&
            euid != uc->cr_ruid &&
            euid != uc->cr_uid &&
            euid != uc->cr_svuid &&
            (error = suser(p)))
-               return (error);
+               goto error;
 
        /*
         * Copy credentials so other references do not see our changes.
-        * ps_ucred may change during the crget().
         */
-       newcred = crget();
-       pruc = pr->ps_ucred;
        crset(newcred, pruc);
 
        if (ruid != (uid_t)-1)
@@ -678,6 +709,9 @@ sys_setreuid(struct proc *p, void *v, re
            pruc->cr_svuid != (euid != (uid_t)-1 ? euid : pruc->cr_uid)))
                newcred->cr_svuid = ruid;
        pr->ps_ucred = newcred;
+
+       mtx_leave(&pr->ps_mtx);
+
        atomic_setbits_int(&p->p_p->ps_flags, PS_SUGID);
 
        /* now that we can sleep, transfer proc count to new user */
@@ -688,6 +722,12 @@ sys_setreuid(struct proc *p, void *v, re
        crfree(pruc);
 
        return (0);
+
+error:
+       mtx_leave(&pr->ps_mtx);
+       crfree(newcred);
+
+       return (error);
 }
 
 int
@@ -699,28 +739,29 @@ sys_setuid(struct proc *p, void *v, regi
        struct process *pr = p->p_p;
        struct ucred *pruc, *newcred, *uc = p->p_ucred;
        uid_t uid;
-       int did_real, error;
+       int did_real, error = 0;
 
        uid = SCARG(uap, uid);
 
+       newcred = crget();
+
+       mtx_enter(&pr->ps_mtx);
+
        pruc = pr->ps_ucred;
        if (pruc->cr_uid == uid &&
            pruc->cr_ruid == uid &&
            pruc->cr_svuid == uid)
-               return (0);
+               goto error;
 
        if (uid != uc->cr_ruid &&
            uid != uc->cr_svuid &&
            uid != uc->cr_uid &&
            (error = suser(p)))
-               return (error);
+               goto error;
 
        /*
         * Copy credentials so other references do not see our changes.
-        * ps_ucred may change during the crget().
         */
-       newcred = crget();
-       pruc = pr->ps_ucred;
        crset(newcred, pruc);
 
        /*
@@ -734,6 +775,9 @@ sys_setuid(struct proc *p, void *v, regi
                did_real = 0;
        newcred->cr_uid = uid;
        pr->ps_ucred = newcred;
+
+       mtx_leave(&pr->ps_mtx);
+
        atomic_setbits_int(&p->p_p->ps_flags, PS_SUGID);
 
        /*
@@ -746,6 +790,12 @@ sys_setuid(struct proc *p, void *v, regi
        crfree(pruc);
 
        return (0);
+
+error: 
+       mtx_leave(&pr->ps_mtx);
+       crfree(newcred);
+
+       return (error);
 }
 
 int
@@ -757,29 +807,40 @@ sys_seteuid(struct proc *p, void *v, reg
        struct process *pr = p->p_p;
        struct ucred *pruc, *newcred, *uc = p->p_ucred;
        uid_t euid;
-       int error;
+       int error = 0;
 
        euid = SCARG(uap, euid);
 
+       newcred = crget();
+
+       mtx_enter(&pr->ps_mtx);
+
        if (pr->ps_ucred->cr_uid == euid)
-               return (0);
+               goto error;
 
        if (euid != uc->cr_ruid && euid != uc->cr_svuid &&
            (error = suser(p)))
-               return (error);
+               goto error;
 
        /*
         * Copy credentials so other references do not see our changes.
-        * ps_ucred may change during the crget().
         */
-       newcred = crget();
        pruc = pr->ps_ucred;
        crset(newcred, pruc);
        newcred->cr_uid = euid;
        pr->ps_ucred = newcred;
+
+       mtx_leave(&pr->ps_mtx);
+
        atomic_setbits_int(&p->p_p->ps_flags, PS_SUGID);
        crfree(pruc);
        return (0);
+
+error:
+       mtx_leave(&pr->ps_mtx);
+       crfree(newcred);
+
+       return (error);
 }
 
 int
@@ -791,28 +852,29 @@ sys_setgid(struct proc *p, void *v, regi
        struct process *pr = p->p_p;
        struct ucred *pruc, *newcred, *uc = p->p_ucred;
        gid_t gid;
-       int error;
+       int error = 0;
 
        gid = SCARG(uap, gid);
 
+       newcred = crget();
+
+       mtx_enter(&pr->ps_mtx);
+
        pruc = pr->ps_ucred;
        if (pruc->cr_gid == gid &&
            pruc->cr_rgid == gid &&
            pruc->cr_svgid == gid)
-               return (0);
+               goto error;
 
        if (gid != uc->cr_rgid &&
            gid != uc->cr_svgid &&
            gid != uc->cr_gid &&
            (error = suser(p)))
-               return (error);
+               goto error;
 
        /*
         * Copy credentials so other references do not see our changes.
-        * ps_ucred may change during the crget().
         */
-       newcred = crget();
-       pruc = pr->ps_ucred;
        crset(newcred, pruc);
 
        if (gid == pruc->cr_gid || suser(p) == 0) {
@@ -821,9 +883,18 @@ sys_setgid(struct proc *p, void *v, regi
        }
        newcred->cr_gid = gid;
        pr->ps_ucred = newcred;
+
+       mtx_leave(&pr->ps_mtx);
+
        atomic_setbits_int(&p->p_p->ps_flags, PS_SUGID);
        crfree(pruc);
        return (0);
+
+error:
+       mtx_leave(&pr->ps_mtx);
+       crfree(newcred);
+
+       return (error);
 }
 
 int
@@ -835,29 +906,40 @@ sys_setegid(struct proc *p, void *v, reg
        struct process *pr = p->p_p;
        struct ucred *pruc, *newcred, *uc = p->p_ucred;
        gid_t egid;
-       int error;
+       int error = 0;
 
        egid = SCARG(uap, egid);
 
+       newcred = crget();
+
+       mtx_enter(&pr->ps_mtx);
+
        if (pr->ps_ucred->cr_gid == egid)
-               return (0);
+               goto error;
 
        if (egid != uc->cr_rgid && egid != uc->cr_svgid &&
            (error = suser(p)))
-               return (error);
+               goto error;
 
        /*
         * Copy credentials so other references do not see our changes.
-        * ps_ucred may change during the crget().
         */
-       newcred = crget();
        pruc = pr->ps_ucred;
        crset(newcred, pruc);
        newcred->cr_gid = egid;
        pr->ps_ucred = newcred;
+
+       mtx_leave(&pr->ps_mtx);
+
        atomic_setbits_int(&p->p_p->ps_flags, PS_SUGID);
        crfree(pruc);
        return (0);
+       
+error:
+       mtx_leave(&pr->ps_mtx);
+       crfree(newcred);
+
+       return (error);
 }
 
 int
@@ -881,11 +963,13 @@ sys_setgroups(struct proc *p, void *v, r
        error = copyin(SCARG(uap, gidset), groups, ngrp * sizeof(gid_t));
        if (error == 0) {
                newcred = crget();
+               mtx_enter(&pr->ps_mtx);
                pruc = pr->ps_ucred;
                crset(newcred, pruc);
                memcpy(newcred->cr_groups, groups, ngrp * sizeof(gid_t));
                newcred->cr_ngroups = ngrp;
                pr->ps_ucred = newcred;
+               mtx_leave(&pr->ps_mtx);
                atomic_setbits_int(&p->p_p->ps_flags, PS_SUGID);
                crfree(pruc);
        }
@@ -1120,10 +1204,12 @@ dorefreshcreds(struct process *pr, struc
        struct ucred *uc = p->p_ucred;
 
        KERNEL_LOCK();          /* XXX should be PROCESS_RLOCK(pr) */
+       mtx_enter(&pr->ps_mtx);
        if (uc != pr->ps_ucred) {
                p->p_ucred = pr->ps_ucred;
                crhold(p->p_ucred);
                crfree(uc);
        }
+       mtx_leave(&pr->ps_mtx);
        KERNEL_UNLOCK();
 }
Index: sys/kern/kern_resource.c
===================================================================
RCS file: /cvs/src/sys/kern/kern_resource.c,v
retrieving revision 1.76
diff -u -p -r1.76 kern_resource.c
--- sys/kern/kern_resource.c    17 Nov 2022 18:53:13 -0000      1.76
+++ sys/kern/kern_resource.c    1 Dec 2022 19:49:15 -0000
@@ -122,10 +122,13 @@ sys_getpriority(struct proc *curp, void 
        case PRIO_USER:
                if (SCARG(uap, who) == 0)
                        SCARG(uap, who) = curp->p_ucred->cr_uid;
-               LIST_FOREACH(pr, &allprocess, ps_list)
+               LIST_FOREACH(pr, &allprocess, ps_list) {
+                       mtx_enter(&pr->ps_mtx);
                        if (pr->ps_ucred->cr_uid == SCARG(uap, who) &&
                            pr->ps_nice < low)
                                low = pr->ps_nice;
+                       mtx_leave(&pr->ps_mtx);
+               }
                break;
 
        default:
@@ -178,11 +181,14 @@ sys_setpriority(struct proc *curp, void 
        case PRIO_USER:
                if (SCARG(uap, who) == 0)
                        SCARG(uap, who) = curp->p_ucred->cr_uid;
-               LIST_FOREACH(pr, &allprocess, ps_list)
+               LIST_FOREACH(pr, &allprocess, ps_list) {
+                       mtx_enter(&pr->ps_mtx);
                        if (pr->ps_ucred->cr_uid == SCARG(uap, who)) {
                                error = donice(curp, pr, SCARG(uap, prio));
                                found = 1;
                        }
+                       mtx_leave(&pr->ps_mtx);
+               }
                break;
 
        default:
@@ -200,10 +206,15 @@ donice(struct proc *curp, struct process
        struct proc *p;
        int s;
 
+       mtx_enter(&chgpr->ps_mtx);
        if (ucred->cr_uid != 0 && ucred->cr_ruid != 0 &&
            ucred->cr_uid != chgpr->ps_ucred->cr_uid &&
-           ucred->cr_ruid != chgpr->ps_ucred->cr_uid)
+           ucred->cr_ruid != chgpr->ps_ucred->cr_uid) {
+               mtx_leave(&chgpr->ps_mtx);
                return (EPERM);
+       }
+       mtx_leave(&chgpr->ps_mtx);
+
        if (n > PRIO_MAX)
                n = PRIO_MAX;
        if (n < PRIO_MIN)
Index: sys/kern/kern_sig.c
===================================================================
RCS file: /cvs/src/sys/kern/kern_sig.c,v
retrieving revision 1.301
diff -u -p -r1.301 kern_sig.c
--- sys/kern/kern_sig.c 16 Oct 2022 16:27:02 -0000      1.301
+++ sys/kern/kern_sig.c 1 Dec 2022 19:49:15 -0000
@@ -149,7 +149,8 @@ cansignal(struct proc *p, struct process
 {
        struct process *pr = p->p_p;
        struct ucred *uc = p->p_ucred;
-       struct ucred *quc = qr->ps_ucred;
+       struct ucred *quc;
+       int ret = 0;
 
        if (uc->cr_uid == 0)
                return (1);             /* root can always signal */
@@ -157,12 +158,20 @@ cansignal(struct proc *p, struct process
        if (pr == qr)
                return (1);             /* process can always signal itself */
 
+       mtx_enter(&qr->ps_mtx);
+
+       quc = qr->ps_ucred;
+
        /* optimization: if the same creds then the tests below will pass */
-       if (uc == quc)
-               return (1);
+       if (uc == quc) {
+               ret = 1;
+               goto out;
+       }
 
-       if (signum == SIGCONT && qr->ps_session == pr->ps_session)
-               return (1);             /* SIGCONT in session */
+       if (signum == SIGCONT && qr->ps_session == pr->ps_session) {
+               ret = 1;                /* SIGCONT in session */
+               goto out;
+       }
 
        /*
         * Using kill(), only certain signals can be sent to setugid
@@ -184,17 +193,20 @@ cansignal(struct proc *p, struct process
                case SIGUSR2:
                        if (uc->cr_ruid == quc->cr_ruid ||
                            uc->cr_uid == quc->cr_ruid)
-                               return (1);
+                               ret = 1;
                }
-               return (0);
+               goto out;
        }
 
        if (uc->cr_ruid == quc->cr_ruid ||
            uc->cr_ruid == quc->cr_svuid ||
            uc->cr_uid == quc->cr_ruid ||
            uc->cr_uid == quc->cr_svuid)
-               return (1);
-       return (0);
+               ret = 1;
+
+out:
+       mtx_leave(&qr->ps_mtx);
+       return (ret);
 }
 
 /*
@@ -755,13 +767,17 @@ pgsigio(struct sigio_ref *sir, int sig, 
        if (sigio == NULL)
                goto out;
        if (sigio->sio_pgid > 0) {
+               mtx_enter(&sigio->sio_proc->ps_mtx);
                if (CANSIGIO(sigio->sio_ucred, sigio->sio_proc))
                        prsignal(sigio->sio_proc, sig);
+               mtx_leave(&sigio->sio_proc->ps_mtx);
        } else if (sigio->sio_pgid < 0) {
                LIST_FOREACH(pr, &sigio->sio_pgrp->pg_members, ps_pglist) {
+                       mtx_enter(&pr->ps_mtx);
                        if (CANSIGIO(sigio->sio_ucred, pr) &&
                            (checkctty == 0 || (pr->ps_flags & PS_CONTROLT)))
                                prsignal(pr, sig);
+                       mtx_leave(&pr->ps_mtx);
                }
        }
 out:
Index: sys/kern/kern_sysctl.c
===================================================================
RCS file: /cvs/src/sys/kern/kern_sysctl.c,v
retrieving revision 1.408
diff -u -p -r1.408 kern_sysctl.c
--- sys/kern/kern_sysctl.c      7 Nov 2022 14:25:44 -0000       1.408
+++ sys/kern/kern_sysctl.c      1 Dec 2022 19:49:15 -0000
@@ -1303,8 +1303,10 @@ fill_file(struct kinfo_file *kf, struct 
        /* per-process information for KERN_FILE_BY[PU]ID */
        if (pr != NULL) {
                kf->p_pid = pr->ps_pid;
+               mtx_enter(&pr->ps_mtx);
                kf->p_uid = pr->ps_ucred->cr_uid;
                kf->p_gid = pr->ps_ucred->cr_gid;
+               mtx_leave(&pr->ps_mtx);
                kf->p_tid = -1;
                strlcpy(kf->p_comm, pr->ps_comm, sizeof(kf->p_comm));
        }
@@ -1457,10 +1459,13 @@ sysctl_file(int *name, u_int namelen, ch
                         */
                        if (pr->ps_flags & (PS_SYSTEM | PS_EMBRYO | PS_EXITING))
                                continue;
+                       mtx_enter(&pr->ps_mtx);
                        if (arg >= 0 && pr->ps_ucred->cr_uid != (uid_t)arg) {
+                               mtx_leave(&pr->ps_mtx);
                                /* not the uid we are looking for */
                                continue;
                        }
+                       mtx_leave(&pr->ps_mtx);
                        fdp = pr->ps_fd;
                        if (fdp->fd_cdir)
                                FILLIT(NULL, NULL, KERN_FILE_CDIR, 
fdp->fd_cdir, pr);
@@ -1575,13 +1580,21 @@ again:
                        break;
 
                case KERN_PROC_UID:
-                       if (pr->ps_ucred->cr_uid != (uid_t)arg)
+                       mtx_enter(&pr->ps_mtx);
+                       if (pr->ps_ucred->cr_uid != (uid_t)arg) {
+                               mtx_leave(&pr->ps_mtx);
                                continue;
+                       }
+                       mtx_leave(&pr->ps_mtx);
                        break;
 
                case KERN_PROC_RUID:
-                       if (pr->ps_ucred->cr_ruid != (uid_t)arg)
+                       mtx_enter(&pr->ps_mtx);
+                       if (pr->ps_ucred->cr_ruid != (uid_t)arg) {
+                               mtx_leave(&pr->ps_mtx);
                                continue;
+                       }
+                       mtx_leave(&pr->ps_mtx);
                        break;
 
                case KERN_PROC_ALL:
@@ -1658,15 +1671,21 @@ fill_kproc(struct process *pr, struct ki
        struct tty *tp;
        struct vmspace *vm = pr->ps_vmspace;
        struct timespec booted, st, ut, utc;
+       struct ucred *prucred;
        int isthread;
 
        isthread = p != NULL;
        if (!isthread)
                p = pr->ps_mainproc;            /* XXX */
 
-       FILL_KPROC(ki, strlcpy, p, pr, pr->ps_ucred, pr->ps_pgrp,
+       mtx_enter(&pr->ps_mtx);
+       prucred = crhold(pr->ps_ucred);
+       mtx_leave(&pr->ps_mtx);
+
+       FILL_KPROC(ki, strlcpy, p, pr, prucred, pr->ps_pgrp,
            p, pr, s, vm, pr->ps_limit, pr->ps_sigacts, isthread,
            show_pointers);
+       crfree(prucred);
 
        /* stuff that's too painful to generalize into the macros */
        if (pr->ps_pptr)
@@ -1781,11 +1800,15 @@ sysctl_proc_args(int *name, u_int namele
        if ((vpr->ps_flags & PS_INEXEC))
                return (EBUSY);
 
+       mtx_enter(&vpr->ps_mtx);
        /* Only owner or root can get env */
        if ((op == KERN_PROC_NENV || op == KERN_PROC_ENV) &&
            (vpr->ps_ucred->cr_uid != cp->p_ucred->cr_uid &&
-           (error = suser(cp)) != 0))
+           (error = suser(cp)) != 0)) {
+               mtx_leave(&vpr->ps_mtx);
                return (error);
+       }
+       mtx_leave(&vpr->ps_mtx);
 
        ps_strings = vpr->ps_strings;
        vm = vpr->ps_vmspace;
@@ -1966,9 +1989,13 @@ sysctl_proc_cwd(int *name, u_int namelen
                return (EINVAL);
 
        /* Only owner or root can get cwd */
+       mtx_enter(&findpr->ps_mtx);
        if (findpr->ps_ucred->cr_uid != cp->p_ucred->cr_uid &&
-           (error = suser(cp)) != 0)
+           (error = suser(cp)) != 0) {
+               mtx_leave(&findpr->ps_mtx);
                return (error);
+       }
+       mtx_leave(&findpr->ps_mtx);
 
        len = *oldlenp;
        if (len > MAXPATHLEN * 4)
Index: sys/kern/sys_process.c
===================================================================
RCS file: /cvs/src/sys/kern/sys_process.c,v
retrieving revision 1.89
diff -u -p -r1.89 sys_process.c
--- sys/kern/sys_process.c      7 Dec 2021 04:19:24 -0000       1.89
+++ sys/kern/sys_process.c      1 Dec 2022 19:49:15 -0000
@@ -376,10 +376,14 @@ ptrace_ctrl(struct proc *p, int req, pid
                 *      process which revokes its special privileges using
                 *      setuid() from being traced.  This is good security.]
                 */
+               mtx_enter(&tr->ps_mtx);
                if ((tr->ps_ucred->cr_ruid != p->p_ucred->cr_ruid ||
                    ISSET(tr->ps_flags, PS_SUGIDEXEC | PS_SUGID)) &&
-                   (error = suser(p)) != 0)
+                   (error = suser(p)) != 0) {
+                       mtx_leave(&tr->ps_mtx);
                        goto fail;
+               }
+               mtx_leave(&tr->ps_mtx);
 
                /*
                 *      (5.5) it's not a child of the tracing process.
@@ -822,10 +826,14 @@ process_checkioperm(struct proc *p, stru
 {
        int error;
 
+       mtx_enter(&tr->ps_mtx);
        if ((tr->ps_ucred->cr_ruid != p->p_ucred->cr_ruid ||
            ISSET(tr->ps_flags, PS_SUGIDEXEC | PS_SUGID)) &&
-           (error = suser(p)) != 0)
+           (error = suser(p)) != 0) {
+               mtx_leave(&tr->ps_mtx);
                return (error);
+       }
+       mtx_leave(&tr->ps_mtx);
 
        if ((tr->ps_pid == 1) && (securelevel > -1))
                return (EPERM);
Index: sys/kern/syscalls.c
===================================================================
RCS file: /cvs/src/sys/kern/syscalls.c,v
retrieving revision 1.252
diff -u -p -r1.252 syscalls.c
--- sys/kern/syscalls.c 30 Nov 2022 10:21:29 -0000      1.252
+++ sys/kern/syscalls.c 1 Dec 2022 19:49:15 -0000
@@ -1,4 +1,4 @@
-/*     $OpenBSD: syscalls.c,v 1.252 2022/11/30 10:21:29 mvs Exp $      */
+/*     $OpenBSD$       */
 
 /*
  * System call names.
Index: sys/kern/syscalls.master
===================================================================
RCS file: /cvs/src/sys/kern/syscalls.master,v
retrieving revision 1.237
diff -u -p -r1.237 syscalls.master
--- sys/kern/syscalls.master    30 Nov 2022 10:20:37 -0000      1.237
+++ sys/kern/syscalls.master    1 Dec 2022 19:49:15 -0000
@@ -79,7 +79,7 @@
 21     STD             { int sys_mount(const char *type, const char *path, \
                            int flags, void *data); }
 22     STD             { int sys_unmount(const char *path, int flags); }
-23     STD             { int sys_setuid(uid_t uid); }
+23     STD NOLOCK      { int sys_setuid(uid_t uid); }
 24     STD NOLOCK      { uid_t sys_getuid(void); }
 25     STD NOLOCK      { uid_t sys_geteuid(void); }
 #ifdef PTRACE
@@ -184,7 +184,7 @@
                            int flags, int fd, off_t pos); }
 79     STD NOLOCK      { int sys_getgroups(int gidsetsize, \
                            gid_t *gidset); }
-80     STD             { int sys_setgroups(int gidsetsize, \
+80     STD NOLOCK      { int sys_setgroups(int gidsetsize, \
                            const gid_t *gidset); }
 81     STD             { int sys_getpgrp(void); }
 82     STD             { int sys_setpgid(pid_t pid, pid_t pgid); }
@@ -260,8 +260,8 @@
 123    STD             { int sys_fchown(int fd, uid_t uid, gid_t gid); }
 124    STD             { int sys_fchmod(int fd, mode_t mode); }
 125    OBSOL           orecvfrom
-126    STD             { int sys_setreuid(uid_t ruid, uid_t euid); }
-127    STD             { int sys_setregid(gid_t rgid, gid_t egid); }
+126    STD NOLOCK      { int sys_setreuid(uid_t ruid, uid_t euid); }
+127    STD NOLOCK      { int sys_setregid(gid_t rgid, gid_t egid); }
 128    STD             { int sys_rename(const char *from, const char *to); }
 129    OBSOL           otruncate
 130    OBSOL           oftruncate
@@ -340,9 +340,9 @@
 180    UNIMPL
 
 ; Syscalls 181-199 are used by/reserved for BSD
-181    STD             { int sys_setgid(gid_t gid); }
-182    STD             { int sys_setegid(gid_t egid); }
-183    STD             { int sys_seteuid(uid_t euid); }
+181    STD NOLOCK      { int sys_setgid(gid_t gid); }
+182    STD NOLOCK      { int sys_setegid(gid_t egid); }
+183    STD NOLOCK      { int sys_seteuid(uid_t euid); }
 184    OBSOL           lfs_bmapv
 185    OBSOL           lfs_markv
 186    OBSOL           lfs_segclean
@@ -484,11 +484,11 @@
 280    UNIMPL          sys_extattr_delete_fd
 281    STD NOLOCK      { int sys_getresuid(uid_t *ruid, uid_t *euid, \
                            uid_t *suid); }
-282    STD             { int sys_setresuid(uid_t ruid, uid_t euid, \
+282    STD NOLOCK      { int sys_setresuid(uid_t ruid, uid_t euid, \
                            uid_t suid); }
 283    STD NOLOCK      { int sys_getresgid(gid_t *rgid, gid_t *egid, \
                            gid_t *sgid); }
-284    STD             { int sys_setresgid(gid_t rgid, gid_t egid, \
+284    STD NOLOCK      { int sys_setresgid(gid_t rgid, gid_t egid, \
                            gid_t sgid); }
 285    OBSOL           sys_omquery
 286    STD             { void *sys_pad_mquery(void *addr, size_t len, \
Index: sys/sys/proc.h
===================================================================
RCS file: /cvs/src/sys/sys/proc.h,v
retrieving revision 1.335
diff -u -p -r1.335 proc.h
--- sys/sys/proc.h      23 Nov 2022 11:00:27 -0000      1.335
+++ sys/sys/proc.h      1 Dec 2022 19:49:15 -0000
@@ -135,7 +135,7 @@ struct process {
         * some signal and ptrace behaviors that need to be fixed.
         */
        struct  proc *ps_mainproc;
-       struct  ucred *ps_ucred;        /* Process owner's identity. */
+       struct  ucred *ps_ucred;        /* [m] Process owner's identity. */
 
        LIST_ENTRY(process) ps_list;    /* List of all processes. */
        TAILQ_HEAD(,proc) ps_threads;   /* [K|S] Threads in this process. */
Index: sys/sys/syscall.h
===================================================================
RCS file: /cvs/src/sys/sys/syscall.h,v
retrieving revision 1.251
diff -u -p -r1.251 syscall.h
--- sys/sys/syscall.h   30 Nov 2022 10:21:29 -0000      1.251
+++ sys/sys/syscall.h   1 Dec 2022 19:49:15 -0000
@@ -1,4 +1,4 @@
-/*     $OpenBSD: syscall.h,v 1.251 2022/11/30 10:21:29 mvs Exp $       */
+/*     $OpenBSD$       */
 
 /*
  * System call numbers.
Index: sys/sys/syscallargs.h
===================================================================
RCS file: /cvs/src/sys/sys/syscallargs.h,v
retrieving revision 1.254
diff -u -p -r1.254 syscallargs.h
--- sys/sys/syscallargs.h       30 Nov 2022 10:21:29 -0000      1.254
+++ sys/sys/syscallargs.h       1 Dec 2022 19:49:15 -0000
@@ -1,4 +1,4 @@
-/*     $OpenBSD: syscallargs.h,v 1.254 2022/11/30 10:21:29 mvs Exp $   */
+/*     $OpenBSD$       */
 
 /*
  * System call argument lists.

Reply via email to