From 45c2dfd412dd459e0cd48afefede63b618ec8658 Mon Sep 17 00:00:00 2001 From: mpi Date: Tue, 20 Feb 2018 12:38:58 +0000 Subject: [PATCH] Introduce enternewpgrp() & enterthispgrp(), from FreeBSD via guenther@. This code shuffling will ease the introduction of the proctree lock in sys_setsid() and sys_setpgid(). Extracted from a larger diff from guenther@, ok visa@ --- sys/kern/kern_proc.c | 99 ++++++++++++++++++++------------------------ sys/kern/kern_prot.c | 32 +++++++++----- sys/sys/proc.h | 7 ++-- 3 files changed, 68 insertions(+), 70 deletions(-) diff --git a/sys/kern/kern_proc.c b/sys/kern/kern_proc.c index 7ca14325220..8ba12226f0d 100644 --- a/sys/kern/kern_proc.c +++ b/sys/kern/kern_proc.c @@ -1,4 +1,4 @@ -/* $OpenBSD: kern_proc.c,v 1.80 2018/02/10 10:32:51 mpi Exp $ */ +/* $OpenBSD: kern_proc.c,v 1.81 2018/02/20 12:38:58 mpi Exp $ */ /* $NetBSD: kern_proc.c,v 1.14 1996/02/09 18:59:41 christos Exp $ */ /* @@ -73,6 +73,9 @@ struct pool ucred_pool; struct pool pgrp_pool; struct pool session_pool; +void pgdelete(struct pgrp *); +void fixjobc(struct process *, struct pgrp *, int); + static void orphanpg(struct pgrp *); #ifdef DEBUG void pgrpdump(void); @@ -222,67 +225,54 @@ zombiefind(pid_t pid) } /* - * Move p to a new or existing process group (and session) - * Caller provides a pre-allocated pgrp and session that should - * be freed if they are not used. - * XXX need proctree lock + * Move process to a new process group. If a session is provided + * then it's a new session to contain this process group; otherwise + * the process is staying within its existing session. */ -int -enterpgrp(struct process *pr, pid_t pgid, struct pgrp *newpgrp, - struct session *newsess) +void +enternewpgrp(struct process *pr, struct pgrp *pgrp, struct session *newsess) { - struct pgrp *pgrp = pgfind(pgid); - #ifdef DIAGNOSTIC - if (pgrp != NULL && newsess) /* firewalls */ - panic("enterpgrp: setsid into non-empty pgrp"); if (SESS_LEADER(pr)) - panic("enterpgrp: session leader attempted setpgrp"); + panic("%s: session leader attempted setpgrp", __func__); #endif - if (pgrp == NULL) { + + if (newsess != NULL) { /* - * new process group + * New session. Initialize it completely */ + timeout_set(&newsess->s_verauthto, zapverauth, newsess); + newsess->s_leader = pr; + newsess->s_count = 1; + newsess->s_ttyvp = NULL; + newsess->s_ttyp = NULL; + memcpy(newsess->s_login, pr->ps_session->s_login, + sizeof(newsess->s_login)); + atomic_clearbits_int(&pr->ps_flags, PS_CONTROLT); + pgrp->pg_session = newsess; #ifdef DIAGNOSTIC - if (pr->ps_pid != pgid) - panic("enterpgrp: new pgrp and pid != pgid"); -#endif - - pgrp = newpgrp; - if (newsess) { - /* - * new session - */ - newsess->s_leader = pr; - newsess->s_count = 1; - newsess->s_ttyvp = NULL; - newsess->s_ttyp = NULL; - memcpy(newsess->s_login, pr->ps_session->s_login, - sizeof(newsess->s_login)); - atomic_clearbits_int(&pr->ps_flags, PS_CONTROLT); - pgrp->pg_session = newsess; -#ifdef DIAGNOSTIC - if (pr != curproc->p_p) - panic("enterpgrp: mksession but not curproc"); + if (pr != curproc->p_p) + panic("%s: mksession but not curproc", __func__); #endif - } else { - pgrp->pg_session = pr->ps_session; - pgrp->pg_session->s_count++; - } - pgrp->pg_id = pgid; - LIST_INIT(&pgrp->pg_members); - LIST_INSERT_HEAD(PGRPHASH(pgid), pgrp, pg_hash); - pgrp->pg_jobc = 0; - } else if (pgrp == pr->ps_pgrp) { - if (newsess) - pool_put(&session_pool, newsess); - pool_put(&pgrp_pool, newpgrp); - return (0); } else { - if (newsess) - pool_put(&session_pool, newsess); - pool_put(&pgrp_pool, newpgrp); + pgrp->pg_session = pr->ps_session; + pgrp->pg_session->s_count++; } + pgrp->pg_id = pr->ps_pid; + LIST_INIT(&pgrp->pg_members); + LIST_INSERT_HEAD(PGRPHASH(pr->ps_pid), pgrp, pg_hash); + pgrp->pg_jobc = 0; + + enterthispgrp(pr, pgrp); +} + +/* + * move process to an existing process group + */ +void +enterthispgrp(struct process *pr, struct pgrp *pgrp) +{ + struct pgrp *savepgrp = pr->ps_pgrp; /* * Adjust eligibility of affected pgrps to participate in job control. @@ -290,14 +280,13 @@ enterpgrp(struct process *pr, pid_t pgid, struct pgrp *newpgrp, * could reach 0 spuriously during the first call. */ fixjobc(pr, pgrp, 1); - fixjobc(pr, pr->ps_pgrp, 0); + fixjobc(pr, savepgrp, 0); LIST_REMOVE(pr, ps_pglist); - if (LIST_EMPTY(&pr->ps_pgrp->pg_members)) - pgdelete(pr->ps_pgrp); pr->ps_pgrp = pgrp; LIST_INSERT_HEAD(&pgrp->pg_members, pr, ps_pglist); - return (0); + if (LIST_EMPTY(&savepgrp->pg_members)) + pgdelete(savepgrp); } /* diff --git a/sys/kern/kern_prot.c b/sys/kern/kern_prot.c index c5d1a9f8082..ec7ac4d4f32 100644 --- a/sys/kern/kern_prot.c +++ b/sys/kern/kern_prot.c @@ -1,4 +1,4 @@ -/* $OpenBSD: kern_prot.c,v 1.72 2018/02/19 08:59:52 mpi Exp $ */ +/* $OpenBSD: kern_prot.c,v 1.73 2018/02/20 12:38:58 mpi Exp $ */ /* $NetBSD: kern_prot.c,v 1.33 1996/02/09 18:59:42 christos Exp $ */ /* @@ -222,15 +222,14 @@ sys_setsid(struct proc *p, void *v, register_t *retval) pid_t pid = pr->ps_pid; newsess = pool_get(&session_pool, PR_WAITOK); - timeout_set(&newsess->s_verauthto, zapverauth, newsess); newpgrp = pool_get(&pgrp_pool, PR_WAITOK); - if (pr->ps_pgid == pid || pgfind(pid)) { + if (pr->ps_pgid == pid || pgfind(pid) != NULL) { pool_put(&pgrp_pool, newpgrp); pool_put(&session_pool, newsess); return (EPERM); } else { - (void) enterpgrp(pr, pid, newpgrp, newsess); + enternewpgrp(pr, newpgrp, newsess); *retval = pid; return (0); } @@ -291,15 +290,26 @@ sys_setpgid(struct proc *curp, void *v, register_t *retval) } if (pgid == 0) pgid = targpr->ps_pid; - else if (pgid != targpr->ps_pid) - if ((pgrp = pgfind(pgid)) == 0 || - pgrp->pg_session != curpr->ps_session) { + + error = 0; + if ((pgrp = pgfind(pgid)) == NULL) { + /* can only create a new process group with pgid == pid */ + if (pgid != targpr->ps_pid) error = EPERM; - goto out; + else { + enternewpgrp(targpr, newpgrp, NULL); + newpgrp = NULL; } - return (enterpgrp(targpr, pgid, newpgrp, NULL)); -out: - pool_put(&pgrp_pool, newpgrp); + } else if (pgrp != targpr->ps_pgrp) { /* anything to do? */ + if (pgid != targpr->ps_pid && + pgrp->pg_session != curpr->ps_session) + error = EPERM; + else + enterthispgrp(targpr, pgrp); + } + out: + if (newpgrp != NULL) + pool_put(&pgrp_pool, newpgrp); return (error); } diff --git a/sys/sys/proc.h b/sys/sys/proc.h index e79adb5972e..fd0e46e5984 100644 --- a/sys/sys/proc.h +++ b/sys/sys/proc.h @@ -1,4 +1,4 @@ -/* $OpenBSD: proc.h,v 1.245 2018/02/10 10:32:51 mpi Exp $ */ +/* $OpenBSD: proc.h,v 1.246 2018/02/20 12:38:58 mpi Exp $ */ /* $NetBSD: proc.h,v 1.44 1996/04/22 01:23:21 christos Exp $ */ /*- @@ -496,13 +496,12 @@ void proc_printit(struct proc *p, const char *modif, int (*pr)(const char *, ...)); int chgproccnt(uid_t uid, int diff); -int enterpgrp(struct process *, pid_t, struct pgrp *, struct session *); -void fixjobc(struct process *, struct pgrp *, int); +void enternewpgrp(struct process *, struct pgrp *, struct session *); +void enterthispgrp(struct process *, struct pgrp *); int inferior(struct process *, struct process *); void leavepgrp(struct process *); void killjobc(struct process *); void preempt(void); -void pgdelete(struct pgrp *); void procinit(void); void resetpriority(struct proc *); void setrunnable(struct proc *); -- 2.20.1