diff options
author | Claudio Jeker <claudio@cvs.openbsd.org> | 2014-07-13 16:41:23 +0000 |
---|---|---|
committer | Claudio Jeker <claudio@cvs.openbsd.org> | 2014-07-13 16:41:23 +0000 |
commit | 0a62e3699149faa5ecee87ff710c406eb40e9d64 (patch) | |
tree | de62b925dcff0be23d142e4d7a167b7d745e6886 /sys/kern/kern_sysctl.c | |
parent | ebff1c1914c0660343592efe09fb9ad4994a9316 (diff) |
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@
Diffstat (limited to 'sys/kern/kern_sysctl.c')
-rw-r--r-- | sys/kern/kern_sysctl.c | 49 |
1 files changed, 48 insertions, 1 deletions
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 /* |