Restore the sys_o58_kill system call.
authorjsing <jsing@openbsd.org>
Mon, 27 Jun 2016 16:49:45 +0000 (16:49 +0000)
committerjsing <jsing@openbsd.org>
Mon, 27 Jun 2016 16:49:45 +0000 (16:49 +0000)
By keeping both the new (sys_kill/sys_thrkill) and old (sys_o58_kill)
system calls for the OpenBSD 6.0 release, code that uses either of these
mechanisms will work on both of the supported OpenBSD releases. This
provides a clean transition for runtimes that make direct system calls
(namely the Go programming language).

This requires a minimal amount of non-intrusive code and does not block
development progress within OpenBSD.

ok deraadt@ guenther@

sys/kern/kern_pledge.c
sys/kern/kern_sig.c

index 1a3a9e5..047225c 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: kern_pledge.c,v 1.171 2016/06/27 16:33:48 jca Exp $   */
+/*     $OpenBSD: kern_pledge.c,v 1.172 2016/06/27 16:49:45 jsing Exp $ */
 
 /*
  * Copyright (c) 2015 Nicholas Marriott <nicm@openbsd.org>
@@ -230,6 +230,7 @@ const uint64_t pledge_syscalls[SYS_MAXSYSCALL] = {
         * Can kill self with "stdio".  Killing another pid
         * requires "proc"
         */
+       [SYS_o58_kill] = PLEDGE_STDIO,
        [SYS_kill] = PLEDGE_STDIO,
 
        /*
index 7b9cba2..db92fb2 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: kern_sig.c,v 1.198 2016/06/11 21:41:50 tedu Exp $     */
+/*     $OpenBSD: kern_sig.c,v 1.199 2016/06/27 16:49:45 jsing Exp $    */
 /*     $NetBSD: kern_sig.c,v 1.54 1996/04/22 01:38:32 christos Exp $   */
 
 /*
@@ -559,6 +559,63 @@ sys_sigaltstack(struct proc *p, void *v, register_t *retval)
        return (0);
 }
 
+int
+sys_o58_kill(struct proc *cp, void *v, register_t *retval)
+{
+       struct sys_o58_kill_args /* {
+               syscallarg(int) pid;
+               syscallarg(int) signum;
+       } */ *uap = v;
+       struct proc *p;
+       int pid = SCARG(uap, pid);
+       int signum = SCARG(uap, signum);
+       int error;
+
+       if (pid <= THREAD_PID_OFFSET && (error = pledge_kill(cp, pid)) != 0)
+               return (error);
+       if (((u_int)signum) >= NSIG)
+               return (EINVAL);
+       if (pid > 0) {
+               enum signal_type type = SPROCESS;
+
+               /*
+                * If the target pid is > THREAD_PID_OFFSET then this
+                * must be a kill of another thread in the same process.
+                * Otherwise, this is a process kill and the target must
+                * be a main thread.
+                */
+               if (pid > THREAD_PID_OFFSET) {
+                       if ((p = pfind(pid - THREAD_PID_OFFSET)) == NULL)
+                               return (ESRCH);
+                       if (p->p_p != cp->p_p)
+                               return (ESRCH);
+                       type = STHREAD;
+               } else {
+                       /* XXX use prfind() */
+                       if ((p = pfind(pid)) == NULL)
+                               return (ESRCH);
+                       if (p->p_flag & P_THREAD)
+                               return (ESRCH);
+                       if (!cansignal(cp, p->p_p, signum))
+                               return (EPERM);
+               }
+
+               /* kill single process or thread */
+               if (signum)
+                       ptsignal(p, signum, type);
+               return (0);
+       }
+       switch (pid) {
+       case -1:                /* broadcast signal */
+               return (killpg1(cp, signum, 0, 1));
+       case 0:                 /* signal own process group */
+               return (killpg1(cp, signum, 0, 0));
+       default:                /* negative explicit process group */
+               return (killpg1(cp, signum, -pid, 0));
+       }
+       /* NOTREACHED */
+}
+
 int
 sys_kill(struct proc *cp, void *v, register_t *retval)
 {