From 557a2e77887aad35a0a6d434142c294424f1505d Mon Sep 17 00:00:00 2001 From: claudio Date: Sun, 13 Jul 2014 16:41:21 +0000 Subject: [PATCH] Introduce PS_NOBROADCASTKILL a process flag that excludes processes from receiving broadcast signals (kill -1). The flag can be set via a new sysctl KERN_PROC_NOBROADCASTKILL. This will be used by iscsid to survive the mass killing by init(8) when terminating multi-user operations. With and OK guenther@ --- sys/kern/kern_sig.c | 5 +++-- sys/kern/kern_sysctl.c | 49 +++++++++++++++++++++++++++++++++++++++++- sys/sys/proc.h | 5 +++-- sys/sys/sysctl.h | 6 ++++-- 4 files changed, 58 insertions(+), 7 deletions(-) diff --git a/sys/kern/kern_sig.c b/sys/kern/kern_sig.c index 970507f28b6..88a8865d1a9 100644 --- a/sys/kern/kern_sig.c +++ b/sys/kern/kern_sig.c @@ -1,4 +1,4 @@ -/* $OpenBSD: kern_sig.c,v 1.172 2014/07/13 15:46:21 uebayasi Exp $ */ +/* $OpenBSD: kern_sig.c,v 1.173 2014/07/13 16:41:21 claudio Exp $ */ /* $NetBSD: kern_sig.c,v 1.54 1996/04/22 01:38:32 christos Exp $ */ /* @@ -629,7 +629,8 @@ killpg1(struct proc *cp, int signum, int pgid, int all) * broadcast */ LIST_FOREACH(pr, &allprocess, ps_list) { - if (pr->ps_pid <= 1 || pr->ps_flags & PS_SYSTEM || + if (pr->ps_pid <= 1 || + pr->ps_flags & (PS_SYSTEM | PS_NOBROADCASTKILL) || pr == cp->p_p || !cansignal(cp, pr, signum)) continue; nfound++; diff --git a/sys/kern/kern_sysctl.c b/sys/kern/kern_sysctl.c index c0a9d02cc43..d89199df16a 100644 --- a/sys/kern/kern_sysctl.c +++ b/sys/kern/kern_sysctl.c @@ -1,4 +1,4 @@ -/* $OpenBSD: kern_sysctl.c,v 1.257 2014/07/13 15:29:04 tedu Exp $ */ +/* $OpenBSD: kern_sysctl.c,v 1.258 2014/07/13 16:41:21 claudio Exp $ */ /* $NetBSD: kern_sysctl.c,v 1.17 1996/05/20 17:49:05 mrg Exp $ */ /*- @@ -116,6 +116,8 @@ extern void nmbclust_update(void); int sysctl_diskinit(int, struct proc *); int sysctl_proc_args(int *, u_int, void *, size_t *, struct proc *); int sysctl_proc_cwd(int *, u_int, void *, size_t *, struct proc *); +int sysctl_proc_nobroadcastkill(int *, u_int, void *, size_t, void *, size_t *, + struct proc *); int sysctl_intrcnt(int *, u_int, void *, size_t *); int sysctl_sensors(int *, u_int, void *, size_t *, void *, size_t); int sysctl_emul(int *, u_int, void *, size_t *, void *, size_t); @@ -284,6 +286,7 @@ kern_sysctl(int *name, u_int namelen, void *oldp, size_t *oldlenp, void *newp, case KERN_POOL: case KERN_PROC_ARGS: case KERN_PROC_CWD: + case KERN_PROC_NOBROADCASTKILL: case KERN_SYSVIPC_INFO: case KERN_SEMINFO: case KERN_SHMINFO: @@ -372,6 +375,9 @@ kern_sysctl(int *name, u_int namelen, void *oldp, size_t *oldlenp, void *newp, case KERN_PROC_CWD: return (sysctl_proc_cwd(name + 1, namelen - 1, oldp, oldlenp, p)); + case KERN_PROC_NOBROADCASTKILL: + return (sysctl_proc_nobroadcastkill(name + 1, namelen - 1, + newp, newlen, oldp, oldlenp, p)); case KERN_FILE: return (sysctl_file(name + 1, namelen - 1, oldp, oldlenp, p)); #endif @@ -1820,6 +1826,47 @@ sysctl_proc_cwd(int *name, u_int namelen, void *oldp, size_t *oldlenp, return (error); } + +int +sysctl_proc_nobroadcastkill(int *name, u_int namelen, void *newp, size_t newlen, + void *oldp, size_t *oldlenp, struct proc *cp) +{ + struct process *findpr; + pid_t pid; + int error, flag; + + if (namelen > 1) + return (ENOTDIR); + if (namelen < 1) + return (EINVAL); + + pid = name[0]; + if ((findpr = prfind(pid)) == NULL) + return (ESRCH); + + /* Either system process or exiting/zombie */ + if (findpr->ps_flags & (PS_SYSTEM | PS_EXITING)) + return (EINVAL); + + /* Only root can change PS_NOBROADCASTKILL */ + if (newp != 0 && (error = suser(cp, 0)) != 0) + return (error); + + /* get the PS_NOBROADCASTKILL flag */ + flag = findpr->ps_flags & PS_NOBROADCASTKILL ? 1 : 0; + + error = sysctl_int(oldp, oldlenp, newp, newlen, &flag); + if (error == 0 && newp) { + if (flag) + atomic_setbits_int(&findpr->ps_flags, + PS_NOBROADCASTKILL); + else + atomic_clearbits_int(&findpr->ps_flags, + PS_NOBROADCASTKILL); + } + + return (error); +} #endif /* diff --git a/sys/sys/proc.h b/sys/sys/proc.h index d7c3224701e..6f25f2c0e52 100644 --- a/sys/sys/proc.h +++ b/sys/sys/proc.h @@ -1,4 +1,4 @@ -/* $OpenBSD: proc.h,v 1.189 2014/07/12 21:21:19 matthew Exp $ */ +/* $OpenBSD: proc.h,v 1.190 2014/07/13 16:41:21 claudio Exp $ */ /* $NetBSD: proc.h,v 1.44 1996/04/22 01:23:21 christos Exp $ */ /*- @@ -247,12 +247,13 @@ struct process { #define PS_SYSTEM 0x00010000 /* No sigs, stats or swapping. */ #define PS_EMBRYO 0x00020000 /* New process, not yet fledged */ #define PS_ZOMBIE 0x00040000 /* Dead and ready to be waited for */ +#define PS_NOBROADCASTKILL 0x00080000 /* Process excluded from kill -1. */ #define PS_BITS \ ("\20\01CONTROLT\02EXEC\03INEXEC\04EXITING\05SUGID" \ "\06SUGIDEXEC\07PPWAIT\010ISPWAIT\011PROFIL\012TRACED" \ "\013WAITED\014COREDUMP\015SINGLEEXIT\016SINGLEUNWIND" \ - "\017NOZOMBIE\020STOPPED\021SYSTEM\022EMBRYO\023ZOMBIE") + "\017NOZOMBIE\020STOPPED\021SYSTEM\022EMBRYO\023ZOMBIE\024NOBROADCASTKILL") struct proc { diff --git a/sys/sys/sysctl.h b/sys/sys/sysctl.h index b9e38a95369..889e997e0f3 100644 --- a/sys/sys/sysctl.h +++ b/sys/sys/sysctl.h @@ -1,4 +1,4 @@ -/* $OpenBSD: sysctl.h,v 1.147 2014/07/08 17:19:26 deraadt Exp $ */ +/* $OpenBSD: sysctl.h,v 1.148 2014/07/13 16:41:22 claudio Exp $ */ /* $NetBSD: sysctl.h,v 1.16 1996/04/09 20:55:36 cgd Exp $ */ /* @@ -179,7 +179,8 @@ struct ctlname { #define KERN_NETLIVELOCKS 76 /* int: number of network livelocks */ #define KERN_POOL_DEBUG 77 /* int: enable pool_debug */ #define KERN_PROC_CWD 78 /* node: proc cwd */ -#define KERN_MAXID 79 /* number of valid kern ids */ +#define KERN_PROC_NOBROADCASTKILL 79 /* node: proc no broadcast kill */ +#define KERN_MAXID 80 /* number of valid kern ids */ #define CTL_KERN_NAMES { \ { 0, 0 }, \ @@ -261,6 +262,7 @@ struct ctlname { { "netlivelocks", CTLTYPE_INT }, \ { "pool_debug", CTLTYPE_INT }, \ { "proc_cwd", CTLTYPE_NODE }, \ + { "proc_nobroadcastkill", CTLTYPE_NODE }, \ } /* -- 2.20.1