diff options
-rw-r--r-- | sys/dev/systrace.c | 23 | ||||
-rw-r--r-- | sys/dev/systrace.h | 2 |
2 files changed, 20 insertions, 5 deletions
diff --git a/sys/dev/systrace.c b/sys/dev/systrace.c index f407e2d8da7..22d4959fbb7 100644 --- a/sys/dev/systrace.c +++ b/sys/dev/systrace.c @@ -523,6 +523,8 @@ systraceioctl(dev, cmd, data, flag, p) if (suser(p->p_ucred, &p->p_acflag) == 0) fst->issuser = 1; + fst->p_ruid = p->p_cred->p_ruid; + fst->p_rgid = p->p_cred->p_rgid; error = falloc(p, &f, &fd); if (error) { @@ -638,7 +640,7 @@ systrace_redirect(int code, struct proc *p, void *v, register_t *retval) struct str_process *strp; struct str_policy *strpolicy; struct fsystrace *fst = NULL; - int policy, error = 0, report = 0; + int policy, error = 0, report = 0, maycontrol = 0; systrace_lock(); strp = p->p_systrace; @@ -654,10 +656,21 @@ systrace_redirect(int code, struct proc *p, void *v, register_t *retval) lockmgr(&fst->lock, LK_EXCLUSIVE, NULL, p); systrace_unlock(); - if ((p->p_flag & P_SUGID) && !fst->issuser) { - /* We can not monitor a SUID process unless we are root, - * but we wait until it executes something unprivileged. - */ + /* + * We can not monitor a SUID process unless we are root, + * but we wait until it executes something unprivileged. + * A non-root user may only monitor if the real uid and + * real gid match the monitored process. Changing the + * uid or gid causes P_SUGID to be set. + */ + if (fst->issuser) + maycontrol = 1; + else if (!(p->p_flag & P_SUGID)) { + maycontrol = fst->p_ruid == p->p_cred->p_ruid && + fst->p_rgid == p->p_cred->p_rgid; + } + + if (!maycontrol) { policy = SYSTR_POLICY_PERMIT; } else { /* Find out current policy */ diff --git a/sys/dev/systrace.h b/sys/dev/systrace.h index d4bd99b6e83..bd5fe3086ec 100644 --- a/sys/dev/systrace.h +++ b/sys/dev/systrace.h @@ -163,6 +163,8 @@ struct fsystrace { int npolicies; int issuser; + uid_t p_ruid; + gid_t p_rgid; /* cwd magic */ pid_t fd_pid; |