1 /*
   2  * CDDL HEADER START
   3  *
   4  * The contents of this file are subject to the terms of the
   5  * Common Development and Distribution License (the "License").
   6  * You may not use this file except in compliance with the License.
   7  *
   8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
   9  * or http://www.opensolaris.org/os/licensing.
  10  * See the License for the specific language governing permissions
  11  * and limitations under the License.
  12  *
  13  * When distributing Covered Code, include this CDDL HEADER in each
  14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  15  * If applicable, add the following below this CDDL HEADER, with the
  16  * fields enclosed by brackets "[]" replaced with your own identifying
  17  * information: Portions Copyright [yyyy] [name of copyright owner]
  18  *
  19  * CDDL HEADER END
  20  */
  21 /*
  22  * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
  23  * Use is subject to license terms.
  24  */
  25 
  26 
  27 #pragma ident   "%Z%%M% %I%     %E% SMI"
  28 
  29 
  30 #include <sys/types.h>
  31 #include <sys/systm.h>
  32 #include <sys/errno.h>
  33 #include <sys/proc.h>
  34 #include <sys/zone.h>
  35 #include <sys/thread.h>
  36 #include <sys/signal.h>
  37 #include <sys/brand.h>
  38 #include <sys/lx_brand.h>
  39 #include <sys/lx_pid.h>
  40 #include <lx_signum.h>
  41 
  42 extern int kill(pid_t, int);
  43 
  44 /*
  45  * Check if it is legal to send this signal to the init process.  Linux
  46  * kill(2) semantics dictate that no _unhandled_ signal may be sent to pid
  47  * 1.
  48  */
  49 static int
  50 init_sig_check(int sig, pid_t pid)
  51 {
  52         proc_t *p;
  53         int rv = 0;
  54 
  55         mutex_enter(&pidlock);
  56 
  57         if (((p = prfind(pid)) == NULL) || (p->p_stat == SIDL))
  58                 rv = ESRCH;
  59         else if (sig && (sigismember(&cantmask, sig) ||
  60             (PTOU(p)->u_signal[sig-1] == SIG_DFL) ||
  61             (PTOU(p)->u_signal[sig-1] == SIG_IGN)))
  62                 rv = EPERM;
  63 
  64         mutex_exit(&pidlock);
  65 
  66         return (rv);
  67 }
  68 
  69 long
  70 lx_tkill(pid_t pid, int lx_sig)
  71 {
  72         kthread_t *t;
  73         proc_t *pp;
  74         pid_t initpid;
  75         sigqueue_t *sqp;
  76         struct lx_lwp_data *br = ttolxlwp(curthread);
  77         int tid = 1;    /* default tid */
  78         int sig, rv;
  79 
  80         /*
  81          * Unlike kill(2), Linux tkill(2) doesn't allow signals to
  82          * be sent to process IDs <= 0 as it doesn't overlay any special
  83          * semantics on the pid.
  84          */
  85         if ((pid <= 0) || ((lx_sig < 0) || (lx_sig >= LX_NSIG)) ||
  86             ((sig = ltos_signo[lx_sig]) < 0))
  87                 return (set_errno(EINVAL));
  88 
  89         /*
  90          * If the Linux pid is 1, translate the pid to the actual init
  91          * pid for the zone.  Note that Linux dictates that no unhandled
  92          * signals may be sent to init, so check for that, too.
  93          *
  94          * Otherwise, extract the tid and real pid from the Linux pid.
  95          */
  96         initpid = curproc->p_zone->zone_proc_initpid;
  97         if (pid == 1)
  98                 pid = initpid;
  99         if ((pid == initpid) && ((rv = init_sig_check(sig, pid)) != 0))
 100                 return (set_errno(rv));
 101         else if (lx_lpid_to_spair(pid, &pid, &tid) < 0)
 102                 return (set_errno(ESRCH));
 103 
 104         sqp = kmem_zalloc(sizeof (sigqueue_t), KM_SLEEP);
 105 
 106         /*
 107          * Find the process for the passed pid...
 108          */
 109         mutex_enter(&pidlock);
 110         if (((pp = prfind(pid)) == NULL) || (pp->p_stat == SIDL)) {
 111                 mutex_exit(&pidlock);
 112                 rv = set_errno(ESRCH);
 113                 goto free_and_exit;
 114         }
 115         mutex_enter(&pp->p_lock);
 116         mutex_exit(&pidlock);
 117 
 118         /*
 119          * Deny permission to send the signal if either of the following
 120          * is true:
 121          *
 122          *      + The signal is SIGCONT and the target pid is not in the same
 123          *        session as the sender
 124          *
 125          *      + prochasprocperm() shows the user lacks sufficient permission
 126          *        to send the signal to the target pid
 127          */
 128         if (((sig == SIGCONT) && (pp->p_sessp != curproc->p_sessp)) ||
 129             (!prochasprocperm(pp, curproc, CRED()))) {
 130                 mutex_exit(&pp->p_lock);
 131                 rv = set_errno(EPERM);
 132                 goto free_and_exit;
 133         }
 134 
 135         /* check for the tid */
 136         if ((t = idtot(pp, tid)) == NULL) {
 137                 mutex_exit(&pp->p_lock);
 138                 rv = set_errno(ESRCH);
 139                 goto free_and_exit;
 140         }
 141 
 142         /* a signal of 0 means just check for the existence of the thread */
 143         if (lx_sig == 0) {
 144                 mutex_exit(&pp->p_lock);
 145                 rv = 0;
 146                 goto free_and_exit;
 147         }
 148 
 149         sqp->sq_info.si_signo = sig;
 150         sqp->sq_info.si_code = SI_LWP;
 151         sqp->sq_info.si_pid = br->br_pid;
 152         sqp->sq_info.si_uid = crgetruid(CRED());
 153         sigaddqa(pp, t, sqp);
 154 
 155         mutex_exit(&pp->p_lock);
 156 
 157         return (0);
 158 
 159 free_and_exit:
 160         kmem_free(sqp, sizeof (sigqueue_t));
 161         return (rv);
 162 }
 163 
 164 long
 165 lx_kill(pid_t lx_pid, int lx_sig)
 166 {
 167         pid_t s_pid, initpid;
 168         sigsend_t v;
 169         zone_t *zone = curproc->p_zone;
 170         struct proc *p;
 171         int err, sig, nfound;
 172 
 173         if ((lx_sig < 0) || (lx_sig >= LX_NSIG) ||
 174             ((sig = ltos_signo[lx_sig]) < 0))
 175                 return (set_errno(EINVAL));
 176 
 177         /*
 178          * Since some linux apps rely on init(1M) having PID 1, we
 179          * transparently translate 1 to the real init(1M)'s pid.  We then
 180          * check to be sure that it is legal for this process to send this
 181          * signal to init(1M).
 182          */
 183         initpid = zone->zone_proc_initpid;
 184         if (lx_pid == 1 || lx_pid == -1) {
 185                 s_pid = initpid;
 186         } else if (lx_pid == 0) {
 187                 s_pid = 0;
 188         } else if (lx_pid > 0) {
 189                 if (lx_lpid_to_spair(lx_pid, &s_pid, NULL) != 0) {
 190                         /*
 191                          * If we didn't find this pid that means it doesn't
 192                          * exist in this zone.
 193                          */
 194                         return (set_errno(ESRCH));
 195                 }
 196         } else {
 197                 ASSERT(lx_pid < 0);
 198                 if (lx_lpid_to_spair(-lx_pid, &s_pid, NULL) != 0) {
 199                         /*
 200                          * If we didn't find this pid it means that the
 201                          * process group leader doesn't exist in this zone.
 202                          * In this case assuming that the Linux pid is
 203                          * the same as the Solaris pid will get us the
 204                          * correct behavior.
 205                          */
 206                         s_pid = -lx_pid;
 207                 }
 208         }
 209 
 210         if ((s_pid == initpid) && ((err = init_sig_check(sig, s_pid)) != 0))
 211                 return (set_errno(err));
 212 
 213         /*
 214          * For individual processes, kill() semantics are the same between
 215          * Solaris and Linux.
 216          */
 217         if (lx_pid >= 0)
 218                 return (kill(s_pid, sig));
 219 
 220         /*
 221          * In Solaris, sending a signal to -pid means "send a signal to
 222          * everyone in process group pid."  In Linux it means "send a
 223          * signal to everyone in the group other than init."  Sending a
 224          * signal to -1 means "send a signal to every process except init
 225          * and myself."
 226          */
 227 
 228         bzero(&v, sizeof (v));
 229         v.sig = sig;
 230         v.checkperm = 1;
 231         v.sicode = SI_USER;
 232         err = 0;
 233 
 234         mutex_enter(&pidlock);
 235 
 236         p = (lx_pid == -1) ? practive : pgfind(s_pid);
 237         nfound = 0;
 238         while (err == 0 && p != NULL) {
 239                 if ((p->p_zone == zone) && (p->p_stat != SIDL) &&
 240                     (p->p_pid != initpid) && (lx_pid < -1 || p != curproc)) {
 241                         nfound++;
 242                         err = sigsendproc(p, &v);
 243                 }
 244 
 245                 p = (lx_pid == -1) ? p->p_next : p->p_pglink;
 246         }
 247         mutex_exit(&pidlock);
 248         if (nfound == 0)
 249                 err = ESRCH;
 250         else if (err == 0 && v.perm == 0)
 251                 err = EPERM;
 252         return (err ? set_errno(err) : 0);
 253 }