The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/compat/linux/common/linux_signal.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /*      $NetBSD: linux_signal.c,v 1.66 2008/10/21 21:52:29 njoly Exp $  */
    2 
    3 /*-
    4  * Copyright (c) 1995, 1998 The NetBSD Foundation, Inc.
    5  * All rights reserved.
    6  *
    7  * This code is derived from software contributed to The NetBSD Foundation
    8  * by Frank van der Linden and Eric Haszlakiewicz.
    9  *
   10  * Redistribution and use in source and binary forms, with or without
   11  * modification, are permitted provided that the following conditions
   12  * are met:
   13  * 1. Redistributions of source code must retain the above copyright
   14  *    notice, this list of conditions and the following disclaimer.
   15  * 2. Redistributions in binary form must reproduce the above copyright
   16  *    notice, this list of conditions and the following disclaimer in the
   17  *    documentation and/or other materials provided with the distribution.
   18  *
   19  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
   20  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
   21  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
   22  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
   23  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
   24  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
   25  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
   26  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
   27  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
   28  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
   29  * POSSIBILITY OF SUCH DAMAGE.
   30  */
   31 /*
   32  * heavily from: svr4_signal.c,v 1.7 1995/01/09 01:04:21 christos Exp
   33  */
   34 
   35 /*
   36  *   Functions in multiarch:
   37  *      linux_sys_signal        : linux_sig_notalpha.c
   38  *      linux_sys_siggetmask    : linux_sig_notalpha.c
   39  *      linux_sys_sigsetmask    : linux_sig_notalpha.c
   40  *      linux_sys_pause         : linux_sig_notalpha.c
   41  *      linux_sys_sigaction     : linux_sigaction.c
   42  *
   43  */
   44 
   45 /*
   46  *   Unimplemented:
   47  *      linux_sys_rt_sigtimedwait       : sigsuspend w/timeout.
   48  */
   49 
   50 #include <sys/cdefs.h>
   51 __KERNEL_RCSID(0, "$NetBSD: linux_signal.c,v 1.66 2008/10/21 21:52:29 njoly Exp $");
   52 
   53 #define COMPAT_LINUX 1
   54 
   55 #include <sys/param.h>
   56 #include <sys/systm.h>
   57 #include <sys/namei.h>
   58 #include <sys/proc.h>
   59 #include <sys/filedesc.h>
   60 #include <sys/ioctl.h>
   61 #include <sys/mount.h>
   62 #include <sys/kernel.h>
   63 #include <sys/signal.h>
   64 #include <sys/signalvar.h>
   65 #include <sys/malloc.h>
   66 
   67 #include <sys/syscallargs.h>
   68 
   69 #include <compat/linux/common/linux_types.h>
   70 #include <compat/linux/common/linux_signal.h>
   71 #include <compat/linux/common/linux_exec.h> /* For emul_linux */
   72 #include <compat/linux/common/linux_machdep.h> /* For LINUX_NPTL */
   73 #include <compat/linux/common/linux_emuldata.h> /* for linux_emuldata */
   74 #include <compat/linux/common/linux_siginfo.h>
   75 #include <compat/linux/common/linux_sigevent.h>
   76 #include <compat/linux/common/linux_util.h>
   77 #include <compat/linux/common/linux_ipc.h>
   78 #include <compat/linux/common/linux_sem.h>
   79 
   80 #include <compat/linux/linux_syscallargs.h>
   81 
   82 /* Locally used defines (in bsd<->linux conversion functions): */
   83 #define linux_sigemptyset(s)    memset((s), 0, sizeof(*(s)))
   84 #define linux_sigismember(s, n) ((s)->sig[((n) - 1) / LINUX__NSIG_BPW]  \
   85                                         & (1L << ((n) - 1) % LINUX__NSIG_BPW))
   86 #define linux_sigaddset(s, n)   ((s)->sig[((n) - 1) / LINUX__NSIG_BPW]  \
   87                                         |= (1L << ((n) - 1) % LINUX__NSIG_BPW))
   88 
   89 #ifdef DEBUG_LINUX
   90 #define DPRINTF(a)      uprintf a
   91 #else
   92 #define DPRINTF(a)
   93 #endif
   94 
   95 extern const int native_to_linux_signo[];
   96 extern const int linux_to_native_signo[];
   97 
   98 /*
   99  * Convert between Linux and BSD signal sets.
  100  */
  101 #if LINUX__NSIG_WORDS > 1
  102 void
  103 linux_old_extra_to_native_sigset(sigset_t *bss, const linux_old_sigset_t *lss, const unsigned long *extra)
  104 {
  105         linux_sigset_t lsnew;
  106 
  107         /* convert old sigset to new sigset */
  108         linux_sigemptyset(&lsnew);
  109         lsnew.sig[0] = *lss;
  110         if (extra)
  111                 memcpy(&lsnew.sig[1], extra,
  112                     sizeof(linux_sigset_t) - sizeof(linux_old_sigset_t));
  113 
  114         linux_to_native_sigset(bss, &lsnew);
  115 }
  116 
  117 void
  118 native_to_linux_old_extra_sigset(linux_old_sigset_t *lss, unsigned long *extra, const sigset_t *bss)
  119 {
  120         linux_sigset_t lsnew;
  121 
  122         native_to_linux_sigset(&lsnew, bss);
  123 
  124         /* convert new sigset to old sigset */
  125         *lss = lsnew.sig[0];
  126         if (extra)
  127                 memcpy(extra, &lsnew.sig[1],
  128                     sizeof(linux_sigset_t) - sizeof(linux_old_sigset_t));
  129 }
  130 #endif /* LINUX__NSIG_WORDS > 1 */
  131 
  132 void
  133 linux_to_native_sigset(sigset_t *bss, const linux_sigset_t *lss)
  134 {
  135         int i, newsig;
  136 
  137         sigemptyset(bss);
  138         for (i = 1; i < LINUX__NSIG; i++) {
  139                 if (linux_sigismember(lss, i)) {
  140                         newsig = linux_to_native_signo[i];
  141                         if (newsig)
  142                                 sigaddset(bss, newsig);
  143                 }
  144         }
  145 }
  146 
  147 void
  148 native_to_linux_sigset(linux_sigset_t *lss, const sigset_t *bss)
  149 {
  150         int i, newsig;
  151 
  152         linux_sigemptyset(lss);
  153         for (i = 1; i < NSIG; i++) {
  154                 if (sigismember(bss, i)) {
  155                         newsig = native_to_linux_signo[i];
  156                         if (newsig)
  157                                 linux_sigaddset(lss, newsig);
  158                 }
  159         }
  160 }
  161 
  162 unsigned int
  163 native_to_linux_sigflags(const int bsf)
  164 {
  165         unsigned int lsf = 0;
  166         if ((bsf & SA_NOCLDSTOP) != 0)
  167                 lsf |= LINUX_SA_NOCLDSTOP;
  168         if ((bsf & SA_NOCLDWAIT) != 0)
  169                 lsf |= LINUX_SA_NOCLDWAIT;
  170         if ((bsf & SA_ONSTACK) != 0)
  171                 lsf |= LINUX_SA_ONSTACK;
  172         if ((bsf & SA_RESTART) != 0)
  173                 lsf |= LINUX_SA_RESTART;
  174         if ((bsf & SA_NODEFER) != 0)
  175                 lsf |= LINUX_SA_NOMASK;
  176         if ((bsf & SA_RESETHAND) != 0)
  177                 lsf |= LINUX_SA_ONESHOT;
  178         if ((bsf & SA_SIGINFO) != 0)
  179                 lsf |= LINUX_SA_SIGINFO;
  180         return lsf;
  181 }
  182 
  183 int
  184 linux_to_native_sigflags(const unsigned long lsf)
  185 {
  186         int bsf = 0;
  187         if ((lsf & LINUX_SA_NOCLDSTOP) != 0)
  188                 bsf |= SA_NOCLDSTOP;
  189         if ((lsf & LINUX_SA_NOCLDWAIT) != 0)
  190                 bsf |= SA_NOCLDWAIT;
  191         if ((lsf & LINUX_SA_ONSTACK) != 0)
  192                 bsf |= SA_ONSTACK;
  193         if ((lsf & LINUX_SA_RESTART) != 0)
  194                 bsf |= SA_RESTART;
  195         if ((lsf & LINUX_SA_ONESHOT) != 0)
  196                 bsf |= SA_RESETHAND;
  197         if ((lsf & LINUX_SA_NOMASK) != 0)
  198                 bsf |= SA_NODEFER;
  199         if ((lsf & LINUX_SA_SIGINFO) != 0)
  200                 bsf |= SA_SIGINFO;
  201         if ((lsf & ~LINUX_SA_ALLBITS) != 0) {
  202                 DPRINTF(("linux_old_to_native_sigflags: "
  203                     "%lx extra bits ignored\n", lsf));
  204         }
  205         return bsf;
  206 }
  207 
  208 /*
  209  * Convert between Linux and BSD sigaction structures.
  210  */
  211 void
  212 linux_old_to_native_sigaction(struct sigaction *bsa, const struct linux_old_sigaction *lsa)
  213 {
  214         bsa->sa_handler = lsa->linux_sa_handler;
  215         linux_old_to_native_sigset(&bsa->sa_mask, &lsa->linux_sa_mask);
  216         bsa->sa_flags = linux_to_native_sigflags(lsa->linux_sa_flags);
  217 }
  218 
  219 void
  220 native_to_linux_old_sigaction(struct linux_old_sigaction *lsa, const struct sigaction *bsa)
  221 {
  222         lsa->linux_sa_handler = bsa->sa_handler;
  223         native_to_linux_old_sigset(&lsa->linux_sa_mask, &bsa->sa_mask);
  224         lsa->linux_sa_flags = native_to_linux_sigflags(bsa->sa_flags);
  225 #ifndef __alpha__
  226         lsa->linux_sa_restorer = NULL;
  227 #endif
  228 }
  229 
  230 /* ...and the new sigaction conversion funcs. */
  231 void
  232 linux_to_native_sigaction(struct sigaction *bsa, const struct linux_sigaction *lsa)
  233 {
  234         bsa->sa_handler = lsa->linux_sa_handler;
  235         linux_to_native_sigset(&bsa->sa_mask, &lsa->linux_sa_mask);
  236         bsa->sa_flags = linux_to_native_sigflags(lsa->linux_sa_flags);
  237 }
  238 
  239 void
  240 native_to_linux_sigaction(struct linux_sigaction *lsa, const struct sigaction *bsa)
  241 {
  242         lsa->linux_sa_handler = bsa->sa_handler;
  243         native_to_linux_sigset(&lsa->linux_sa_mask, &bsa->sa_mask);
  244         lsa->linux_sa_flags = native_to_linux_sigflags(bsa->sa_flags);
  245 #ifndef __alpha__
  246         lsa->linux_sa_restorer = NULL;
  247 #endif
  248 }
  249 
  250 /* ----------------------------------------------------------------------- */
  251 
  252 /*
  253  * The Linux sigaction() system call. Do the usual conversions,
  254  * and just call sigaction(). Some flags and values are silently
  255  * ignored (see above).
  256  */
  257 int
  258 linux_sys_rt_sigaction(struct lwp *l, const struct linux_sys_rt_sigaction_args *uap, register_t *retval)
  259 {
  260         /* {
  261                 syscallarg(int) signum;
  262                 syscallarg(const struct linux_sigaction *) nsa;
  263                 syscallarg(struct linux_sigaction *) osa;
  264                 syscallarg(size_t) sigsetsize;
  265         } */
  266         struct linux_sigaction nlsa, olsa;
  267         struct sigaction nbsa, obsa;
  268         int error, sig;
  269         void *tramp = NULL;
  270         int vers = 0;
  271 #if defined __amd64__
  272         struct sigacts *ps = l->l_proc->p_sigacts;
  273 #endif
  274 
  275         if (SCARG(uap, sigsetsize) != sizeof(linux_sigset_t))
  276                 return (EINVAL);
  277 
  278         if (SCARG(uap, nsa)) {
  279                 error = copyin(SCARG(uap, nsa), &nlsa, sizeof(nlsa));
  280                 if (error)
  281                         return (error);
  282                 linux_to_native_sigaction(&nbsa, &nlsa);
  283         }
  284 
  285         sig = SCARG(uap, signum);
  286         if (sig < 0 || sig >= LINUX__NSIG)
  287                 return (EINVAL);
  288         if (sig > 0 && !linux_to_native_signo[sig]) {
  289                 /* Pretend that we did something useful for unknown signals. */
  290                 obsa.sa_handler = SIG_IGN;
  291                 sigemptyset(&obsa.sa_mask);
  292                 obsa.sa_flags = 0;
  293         } else {
  294 #if defined __amd64__
  295                 if (nlsa.linux_sa_flags & LINUX_SA_RESTORER) {
  296                         if ((tramp = nlsa.linux_sa_restorer) != NULL)
  297                                 vers = 2; /* XXX arch dependant */
  298                 }
  299 #endif
  300 
  301                 error = sigaction1(l, linux_to_native_signo[sig],
  302                     SCARG(uap, nsa) ? &nbsa : NULL,
  303                     SCARG(uap, osa) ? &obsa : NULL,
  304                     tramp, vers);
  305                 if (error)
  306                         return (error);
  307         }
  308         if (SCARG(uap, osa)) {
  309                 native_to_linux_sigaction(&olsa, &obsa);
  310 
  311 #if defined __amd64__
  312                 if (ps->sa_sigdesc[sig].sd_vers != 0) {
  313                         olsa.linux_sa_restorer = ps->sa_sigdesc[sig].sd_tramp;
  314                         olsa.linux_sa_flags |= LINUX_SA_RESTORER;
  315                 }
  316 #endif
  317 
  318                 error = copyout(&olsa, SCARG(uap, osa), sizeof(olsa));
  319                 if (error)
  320                         return (error);
  321         }
  322         return (0);
  323 }
  324 
  325 int
  326 linux_sigprocmask1(struct lwp *l, int how, const linux_old_sigset_t *set, linux_old_sigset_t *oset)
  327 {
  328         struct proc *p = l->l_proc;
  329         linux_old_sigset_t nlss, olss;
  330         sigset_t nbss, obss;
  331         int error;
  332 
  333         switch (how) {
  334         case LINUX_SIG_BLOCK:
  335                 how = SIG_BLOCK;
  336                 break;
  337         case LINUX_SIG_UNBLOCK:
  338                 how = SIG_UNBLOCK;
  339                 break;
  340         case LINUX_SIG_SETMASK:
  341                 how = SIG_SETMASK;
  342                 break;
  343         default:
  344                 return (EINVAL);
  345         }
  346 
  347         if (set) {
  348                 error = copyin(set, &nlss, sizeof(nlss));
  349                 if (error)
  350                         return (error);
  351                 linux_old_to_native_sigset(&nbss, &nlss);
  352         }
  353         mutex_enter(p->p_lock);
  354         error = sigprocmask1(l, how,
  355             set ? &nbss : NULL, oset ? &obss : NULL);
  356         mutex_exit(p->p_lock);
  357         if (error)
  358                 return (error);
  359         if (oset) {
  360                 native_to_linux_old_sigset(&olss, &obss);
  361                 error = copyout(&olss, oset, sizeof(olss));
  362                 if (error)
  363                         return (error);
  364         }
  365         return (error);
  366 }
  367 
  368 int
  369 linux_sys_rt_sigprocmask(struct lwp *l, const struct linux_sys_rt_sigprocmask_args *uap, register_t *retval)
  370 {
  371         /* {
  372                 syscallarg(int) how;
  373                 syscallarg(const linux_sigset_t *) set;
  374                 syscallarg(linux_sigset_t *) oset;
  375                 syscallarg(size_t) sigsetsize;
  376         } */
  377         linux_sigset_t nlss, olss, *oset;
  378         const linux_sigset_t *set;
  379         struct proc *p = l->l_proc;
  380         sigset_t nbss, obss;
  381         int error, how;
  382 
  383         if (SCARG(uap, sigsetsize) != sizeof(linux_sigset_t))
  384                 return (EINVAL);
  385 
  386         switch (SCARG(uap, how)) {
  387         case LINUX_SIG_BLOCK:
  388                 how = SIG_BLOCK;
  389                 break;
  390         case LINUX_SIG_UNBLOCK:
  391                 how = SIG_UNBLOCK;
  392                 break;
  393         case LINUX_SIG_SETMASK:
  394                 how = SIG_SETMASK;
  395                 break;
  396         default:
  397                 return (EINVAL);
  398         }
  399 
  400         set = SCARG(uap, set);
  401         oset = SCARG(uap, oset);
  402 
  403         if (set) {
  404                 error = copyin(set, &nlss, sizeof(nlss));
  405                 if (error)
  406                         return (error);
  407                 linux_to_native_sigset(&nbss, &nlss);
  408         }
  409         mutex_enter(p->p_lock);
  410         error = sigprocmask1(l, how,
  411             set ? &nbss : NULL, oset ? &obss : NULL);
  412         mutex_exit(p->p_lock);
  413         if (!error && oset) {
  414                 native_to_linux_sigset(&olss, &obss);
  415                 error = copyout(&olss, oset, sizeof(olss));
  416         }
  417         return (error);
  418 }
  419 
  420 int
  421 linux_sys_rt_sigpending(struct lwp *l, const struct linux_sys_rt_sigpending_args *uap, register_t *retval)
  422 {
  423         /* {
  424                 syscallarg(linux_sigset_t *) set;
  425                 syscallarg(size_t) sigsetsize;
  426         } */
  427         sigset_t bss;
  428         linux_sigset_t lss;
  429 
  430         if (SCARG(uap, sigsetsize) != sizeof(linux_sigset_t))
  431                 return (EINVAL);
  432 
  433         sigpending1(l, &bss);
  434         native_to_linux_sigset(&lss, &bss);
  435         return copyout(&lss, SCARG(uap, set), sizeof(lss));
  436 }
  437 
  438 #ifndef __amd64__
  439 int
  440 linux_sys_sigpending(struct lwp *l, const struct linux_sys_sigpending_args *uap, register_t *retval)
  441 {
  442         /* {
  443                 syscallarg(linux_old_sigset_t *) mask;
  444         } */
  445         sigset_t bss;
  446         linux_old_sigset_t lss;
  447 
  448         sigpending1(l, &bss);
  449         native_to_linux_old_sigset(&lss, &bss);
  450         return copyout(&lss, SCARG(uap, set), sizeof(lss));
  451 }
  452 
  453 int
  454 linux_sys_sigsuspend(struct lwp *l, const struct linux_sys_sigsuspend_args *uap, register_t *retval)
  455 {
  456         /* {
  457                 syscallarg(void *) restart;
  458                 syscallarg(int) oldmask;
  459                 syscallarg(int) mask;
  460         } */
  461         linux_old_sigset_t lss;
  462         sigset_t bss;
  463 
  464         lss = SCARG(uap, mask);
  465         linux_old_to_native_sigset(&bss, &lss);
  466         return (sigsuspend1(l, &bss));
  467 }
  468 #endif /* __amd64__ */
  469 
  470 int
  471 linux_sys_rt_sigsuspend(struct lwp *l, const struct linux_sys_rt_sigsuspend_args *uap, register_t *retval)
  472 {
  473         /* {
  474                 syscallarg(linux_sigset_t *) unewset;
  475                 syscallarg(size_t) sigsetsize;
  476         } */
  477         linux_sigset_t lss;
  478         sigset_t bss;
  479         int error;
  480 
  481         if (SCARG(uap, sigsetsize) != sizeof(linux_sigset_t))
  482                 return (EINVAL);
  483 
  484         error = copyin(SCARG(uap, unewset), &lss, sizeof(linux_sigset_t));
  485         if (error)
  486                 return (error);
  487 
  488         linux_to_native_sigset(&bss, &lss);
  489 
  490         return (sigsuspend1(l, &bss));
  491 }
  492 
  493 /*
  494  * Once more: only a signal conversion is needed.
  495  * Note: also used as sys_rt_queueinfo.  The info field is ignored.
  496  */
  497 int
  498 linux_sys_rt_queueinfo(struct lwp *l, const struct linux_sys_rt_queueinfo_args *uap, register_t *retval)
  499 {
  500         /* XXX XAX This isn't this really int, int, siginfo_t *, is it? */
  501 #if 0
  502         struct linux_sys_rt_queueinfo_args /* {
  503                 syscallarg(int) pid;
  504                 syscallarg(int) signum;
  505                 syscallarg(siginfo_t *) uinfo;
  506         } */ *uap = v;
  507 #endif
  508 
  509         /* XXX To really implement this we need to      */
  510         /* XXX keep a list of queued signals somewhere. */
  511         return (linux_sys_kill(l, (const void *)uap, retval));
  512 }
  513 
  514 int
  515 linux_sys_kill(struct lwp *l, const struct linux_sys_kill_args *uap, register_t *retval)
  516 {
  517         /* {
  518                 syscallarg(int) pid;
  519                 syscallarg(int) signum;
  520         } */
  521 
  522         struct sys_kill_args ka;
  523         int sig;
  524 
  525         SCARG(&ka, pid) = SCARG(uap, pid);
  526         sig = SCARG(uap, signum);
  527         if (sig < 0 || sig >= LINUX__NSIG)
  528                 return (EINVAL);
  529         SCARG(&ka, signum) = linux_to_native_signo[sig];
  530         return sys_kill(l, &ka, retval);
  531 }
  532 
  533 #ifdef LINUX_SS_ONSTACK
  534 static void linux_to_native_sigaltstack(struct sigaltstack *,
  535     const struct linux_sigaltstack *);
  536 
  537 static void
  538 linux_to_native_sigaltstack(struct sigaltstack *bss, const struct linux_sigaltstack *lss)
  539 {
  540         bss->ss_sp = lss->ss_sp;
  541         bss->ss_size = lss->ss_size;
  542         if (lss->ss_flags & LINUX_SS_ONSTACK)
  543             bss->ss_flags = SS_ONSTACK;
  544         else if (lss->ss_flags & LINUX_SS_DISABLE)
  545             bss->ss_flags = SS_DISABLE;
  546         else
  547             bss->ss_flags = 0;
  548 }
  549 
  550 void
  551 native_to_linux_sigaltstack(struct linux_sigaltstack *lss, const struct sigaltstack *bss)
  552 {
  553         lss->ss_sp = bss->ss_sp;
  554         lss->ss_size = bss->ss_size;
  555         if (bss->ss_flags & SS_ONSTACK)
  556             lss->ss_flags = LINUX_SS_ONSTACK;
  557         else if (bss->ss_flags & SS_DISABLE)
  558             lss->ss_flags = LINUX_SS_DISABLE;
  559         else
  560             lss->ss_flags = 0;
  561 }
  562 
  563 int
  564 linux_sys_sigaltstack(struct lwp *l, const struct linux_sys_sigaltstack_args *uap, register_t *retval)
  565 {
  566         /* {
  567                 syscallarg(const struct linux_sigaltstack *) ss;
  568                 syscallarg(struct linux_sigaltstack *) oss;
  569         } */
  570         struct linux_sigaltstack ss;
  571         struct sigaltstack nss;
  572         struct proc *p = l->l_proc;
  573         int error = 0;
  574 
  575         if (SCARG(uap, oss)) {
  576                 native_to_linux_sigaltstack(&ss, &l->l_sigstk);
  577                 if ((error = copyout(&ss, SCARG(uap, oss), sizeof(ss))) != 0)
  578                         return error;
  579         }
  580 
  581         if (SCARG(uap, ss) != NULL) {
  582                 if ((error = copyin(SCARG(uap, ss), &ss, sizeof(ss))) != 0)
  583                         return error;
  584                 linux_to_native_sigaltstack(&nss, &ss);
  585 
  586                 mutex_enter(p->p_lock);
  587 
  588                 if (nss.ss_flags & ~SS_ALLBITS)
  589                         error = EINVAL;
  590                 else if (nss.ss_flags & SS_DISABLE) {
  591                         if (l->l_sigstk.ss_flags & SS_ONSTACK)
  592                                 error = EINVAL;
  593                 } else if (nss.ss_size < LINUX_MINSIGSTKSZ)
  594                         error = ENOMEM;
  595 
  596                 if (error == 0)
  597                         l->l_sigstk = nss;
  598 
  599                 mutex_exit(p->p_lock);
  600         }
  601 
  602         return error;
  603 }
  604 #endif /* LINUX_SS_ONSTACK */
  605 
  606 #ifdef LINUX_NPTL
  607 static int
  608 linux_do_tkill(struct lwp *l, int tgid, int tid, int signum)
  609 {
  610         struct proc *p;
  611         int error;
  612         ksiginfo_t ksi;
  613         struct linux_emuldata *led;
  614 
  615         if (signum < 0 || signum >= LINUX__NSIG)
  616                 return EINVAL;
  617         signum = linux_to_native_signo[signum];
  618 
  619         KSI_INIT(&ksi);
  620         ksi.ksi_signo = signum;
  621         ksi.ksi_code = SI_LWP;
  622         ksi.ksi_pid = l->l_proc->p_pid;
  623         ksi.ksi_uid = kauth_cred_geteuid(l->l_cred);
  624 
  625         mutex_enter(proc_lock);
  626         if ((p = p_find(tid, PFIND_LOCKED)) == NULL) {
  627                 mutex_exit(proc_lock);
  628                 return ESRCH;
  629         }
  630         led = p->p_emuldata;
  631         if (tgid > 0 && led->s->group_pid != tgid) {
  632                 mutex_exit(proc_lock);
  633                 return ESRCH;
  634         }
  635         mutex_enter(p->p_lock);
  636         error = kauth_authorize_process(l->l_cred,
  637             KAUTH_PROCESS_SIGNAL, p, KAUTH_ARG(signum), NULL, NULL);
  638         if (!error && signum)
  639                 kpsignal2(p, &ksi);
  640         mutex_exit(p->p_lock);
  641         mutex_exit(proc_lock);
  642 
  643         return error;
  644 }
  645 
  646 int
  647 linux_sys_tkill(struct lwp *l, const struct linux_sys_tkill_args *uap, register_t *retval)
  648 {
  649         /* {
  650                 syscallarg(int) tid;
  651                 syscallarg(int) sig;
  652         } */
  653 
  654         if (SCARG(uap, tid) <= 0)
  655                 return EINVAL;
  656 
  657         return linux_do_tkill(l, 0, SCARG(uap, tid), SCARG(uap, sig));
  658 }
  659 
  660 int
  661 linux_sys_tgkill(struct lwp *l, const struct linux_sys_tgkill_args *uap, register_t *retval)
  662 {
  663         /* {
  664                 syscallarg(int) tgid;
  665                 syscallarg(int) tid;
  666                 syscallarg(int) sig;
  667         } */
  668 
  669         if (SCARG(uap, tid) <= 0 || SCARG(uap, tgid) <= 0)
  670                 return EINVAL;
  671 
  672         return linux_do_tkill(l, SCARG(uap, tgid), SCARG(uap, tid), SCARG(uap, sig));
  673 }
  674 
  675 int
  676 native_to_linux_si_code(int code)
  677 {
  678         int si_codes[] = {
  679             LINUX_SI_USER, LINUX_SI_QUEUE, LINUX_SI_TIMER, LINUX_SI_ASYNCIO,
  680             LINUX_SI_MESGQ, LINUX_SI_TKILL /* SI_LWP */
  681         };
  682 
  683         if (code <= 0 && -code < __arraycount(si_codes))
  684                 return si_codes[-code];
  685 
  686         return code;
  687 }
  688 #endif /* LINUX_NPTL */

Cache object: e1589d58c5826237f8060d46d3e37d79


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.