summaryrefslogtreecommitdiff
path: root/sys/kern/kern_sysctl.c
diff options
context:
space:
mode:
authorClaudio Jeker <claudio@cvs.openbsd.org>2014-07-13 16:41:23 +0000
committerClaudio Jeker <claudio@cvs.openbsd.org>2014-07-13 16:41:23 +0000
commit0a62e3699149faa5ecee87ff710c406eb40e9d64 (patch)
treede62b925dcff0be23d142e4d7a167b7d745e6886 /sys/kern/kern_sysctl.c
parentebff1c1914c0660343592efe09fb9ad4994a9316 (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.c49
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
/*