On Sat, Dec 03, 2022 at 08:45:52PM +0300, Vitaliy Makkoveev wrote: > On Thu, Dec 01, 2022 at 10:50:03PM +0300, Vitaliy Makkoveev wrote: > > 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. > > > > A little update. Kernel lock is not required within dorefreshcreds() > because `ps_mtx' mutex(9) is taken. Also forgotten makesyscalls.sh > generated chunks removed. > >
Anyone? The `pr' locking for FILL_KPROC() usage is discussible. We already use PR_LOCK() for `sa' copying, which is used within FILL_KPROC() as `sa', but not pr->ps_sigacts. So the same could be done for `uc' copying too: #define FILL_KPROC(kp, copy_str, p, pr, uc, pg, paddr, \ praddr, sess, vm, lim, sa, isthread, show_addresses) \ do { \ PR_LOCK(pr); \ (kp)->p_uid = (uc)->cr_uid; \ (kp)->p_ruid = (uc)->cr_ruid; \ /* ... */ \ PR_UNLOCK(pr); \ PR_LOCK(pr); \ (kp)->p_sigignore = (sa) ? (sa)->ps_sigignore : 0; \ /* ... */ \ PR_UNLOCK(pr); \ > 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 3 Dec 2022 17:39:00 -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 3 Dec 2022 17:39:00 -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 3 Dec 2022 17:39:00 -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 3 Dec 2022 17:39:00 -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 3 Dec 2022 17:39:00 -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 3 Dec 2022 17:39:00 -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); > } > @@ -1119,11 +1203,11 @@ 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); > } > - KERNEL_UNLOCK(); > + mtx_leave(&pr->ps_mtx); > } > 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 3 Dec 2022 17:39:00 -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 3 Dec 2022 17:39:00 -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 3 Dec 2022 17:39:00 -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 3 Dec 2022 17:39:00 -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.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 3 Dec 2022 17:39:00 -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 3 Dec 2022 17:39:00 -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. */