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/i386/linux/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 /*-
    2  * Copyright (c) 1994-1995 Søren Schmidt
    3  * All rights reserved.
    4  *
    5  * Redistribution and use in source and binary forms, with or without
    6  * modification, are permitted provided that the following conditions
    7  * are met:
    8  * 1. Redistributions of source code must retain the above copyright
    9  *    notice, this list of conditions and the following disclaimer 
   10  *    in this position and unchanged.
   11  * 2. Redistributions in binary form must reproduce the above copyright
   12  *    notice, this list of conditions and the following disclaimer in the
   13  *    documentation and/or other materials provided with the distribution.
   14  * 3. The name of the author may not be used to endorse or promote products
   15  *    derived from this software withough specific prior written permission
   16  *
   17  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
   18  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   19  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
   20  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
   21  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
   22  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
   23  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
   24  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
   25  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
   26  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
   27  *
   28  * $FreeBSD$
   29  */
   30 
   31 #include <sys/param.h>
   32 #include <sys/systm.h>
   33 #include <sys/sysproto.h>
   34 #include <sys/proc.h>
   35 #include <sys/signalvar.h>
   36 
   37 #include <i386/linux/linux.h>
   38 #include <i386/linux/linux_proto.h>
   39 #include <i386/linux/linux_util.h>
   40 
   41 static sigset_t
   42 linux_to_bsd_sigset(linux_sigset_t mask) {
   43     int b, l;
   44     sigset_t new = 0;
   45 
   46     for (l = 1; l < LINUX_NSIG; l++) {
   47         if (mask & (1 << (l - 1))) {
   48             if ((b = linux_to_bsd_signal[l]))
   49                 new |= (1 << (b - 1));
   50         }
   51     }
   52     return new;
   53 }
   54 
   55 static linux_sigset_t
   56 bsd_to_linux_sigset(sigset_t mask) {
   57     int b, l;
   58     sigset_t new = 0;
   59 
   60     for (b = 1; b < NSIG; b++) {
   61         if (mask & (1 << (b - 1))) {
   62             if ((l = bsd_to_linux_signal[b]))
   63                 new |= (1 << (l - 1));
   64         }
   65     }
   66     return new;
   67 }
   68 
   69 static void
   70 linux_to_bsd_sigaction(linux_sigaction_t *lsa, struct sigaction *bsa)
   71 {
   72     bsa->sa_mask = linux_to_bsd_sigset(lsa->sa_mask);
   73     bsa->sa_handler = lsa->sa_handler;
   74     bsa->sa_flags = 0;
   75     if (lsa->sa_flags & LINUX_SA_NOCLDSTOP)
   76         bsa->sa_flags |= SA_NOCLDSTOP;
   77     if (lsa->sa_flags & LINUX_SA_NOCLDWAIT)
   78         bsa->sa_flags |= SA_NOCLDWAIT;
   79     if (lsa->sa_flags & LINUX_SA_ONSTACK)
   80         bsa->sa_flags |= SA_ONSTACK;
   81     if (lsa->sa_flags & LINUX_SA_RESTART)
   82         bsa->sa_flags |= SA_RESTART;
   83     if (lsa->sa_flags & LINUX_SA_ONESHOT)
   84         bsa->sa_flags |= SA_RESETHAND;
   85     if (lsa->sa_flags & LINUX_SA_NOMASK)
   86         bsa->sa_flags |= SA_NODEFER;
   87 }
   88 
   89 static void
   90 bsd_to_linux_sigaction(struct sigaction *bsa, linux_sigaction_t *lsa)
   91 {
   92     lsa->sa_handler = bsa->sa_handler;
   93     lsa->sa_restorer = NULL;    /* unsupported */
   94     lsa->sa_mask = bsd_to_linux_sigset(bsa->sa_mask);
   95     lsa->sa_flags = 0;
   96     if (bsa->sa_flags & SA_NOCLDSTOP)
   97         lsa->sa_flags |= LINUX_SA_NOCLDSTOP;
   98     if (bsa->sa_flags & SA_NOCLDWAIT)
   99         lsa->sa_flags |= LINUX_SA_NOCLDWAIT;
  100     if (bsa->sa_flags & SA_ONSTACK)
  101         lsa->sa_flags |= LINUX_SA_ONSTACK;
  102     if (bsa->sa_flags & SA_RESTART)
  103         lsa->sa_flags |= LINUX_SA_RESTART;
  104     if (bsa->sa_flags & SA_RESETHAND)
  105         lsa->sa_flags |= LINUX_SA_ONESHOT;
  106     if (bsa->sa_flags & SA_NODEFER)
  107         lsa->sa_flags |= LINUX_SA_NOMASK;
  108 }
  109 
  110 static int
  111 linux_do_sigaction(struct proc *p, int linux_sig, linux_sigaction_t *linux_nsa,
  112                    linux_sigaction_t *linux_osa)
  113 {
  114         struct sigaction *nsa, *osa, sa;
  115         struct sigaction_args sa_args;
  116         int error;
  117         caddr_t sg = stackgap_init();
  118 
  119         if (linux_sig <= 0 || linux_sig >= LINUX_NSIG)
  120                 return EINVAL;
  121 
  122         if (linux_osa)
  123                 osa = stackgap_alloc(&sg, sizeof(struct sigaction));
  124         else
  125                 osa = NULL;
  126 
  127         if (linux_nsa) {
  128                 nsa = stackgap_alloc(&sg, sizeof(struct sigaction));
  129                 linux_to_bsd_sigaction(linux_nsa, &sa);
  130                 error = copyout(&sa, nsa, sizeof(struct sigaction));
  131                 if (error)
  132                         return error;
  133         }
  134         else
  135                 nsa = NULL;
  136 
  137         sa_args.signum = linux_to_bsd_signal[linux_sig];
  138         sa_args.nsa = nsa;
  139         sa_args.osa = osa;
  140         error = sigaction(p, &sa_args);
  141         if (error)
  142                 return error;
  143 
  144         if (linux_osa) {
  145                 error = copyin(osa, &sa, sizeof(struct sigaction));
  146                 if (error)
  147                         return error;
  148                 bsd_to_linux_sigaction(&sa, linux_osa);
  149         }
  150 
  151         return 0;
  152 }
  153 
  154 int
  155 linux_sigaction(struct proc *p, struct linux_sigaction_args *args)
  156 {
  157         linux_sigaction_t nsa, osa;
  158         int error;
  159 
  160 #ifdef DEBUG
  161         printf("Linux-emul(%ld): sigaction(%d, %p, %p)\n", (long)p->p_pid,
  162                args->sig, (void *)args->nsa, (void *)args->osa);
  163 #endif
  164 
  165         if (args->nsa) {
  166                 error = copyin(args->nsa, &nsa, sizeof(linux_sigaction_t));
  167                 if (error)
  168                         return error;
  169         }
  170 
  171         error = linux_do_sigaction(p, args->sig,
  172                                    args->nsa ? &nsa : NULL,
  173                                    args->osa ? &osa : NULL);
  174         if (error)
  175                 return error;
  176 
  177         if (args->osa) {
  178                 error = copyout(&osa, args->osa, sizeof(linux_sigaction_t));
  179                 if (error)
  180                         return error;
  181         }
  182 
  183         return 0;
  184 }
  185 
  186 int
  187 linux_signal(struct proc *p, struct linux_signal_args *args)
  188 {
  189         linux_sigaction_t nsa, osa;
  190         int error;
  191 
  192 #ifdef DEBUG
  193         printf("Linux-emul(%ld): signal(%d, %p)\n", (long)p->p_pid,
  194                args->sig, (void *)args->handler);
  195 #endif
  196 
  197         nsa.sa_handler = args->handler;
  198         nsa.sa_flags = LINUX_SA_ONESHOT | LINUX_SA_NOMASK;
  199         nsa.sa_mask = NULL;
  200 
  201         error = linux_do_sigaction(p, args->sig, &nsa, &osa);
  202 
  203         p->p_retval[0] = (int)osa.sa_handler;
  204 
  205         return 0;
  206 }
  207 
  208 int
  209 linux_rt_sigaction(struct proc *p, struct linux_rt_sigaction_args *args)
  210 {
  211         linux_sigaction_t nsa, osa;
  212         linux_new_sigaction_t new_sa;
  213         int error;
  214 
  215 #ifdef DEBUG
  216         printf("Linux-emul(%ld): rt_sigaction(%d, %p, %p, %d)\n",
  217                (long)p->p_pid, args->sig, (void *)args->act,
  218                (void *)args->oact, args->sigsetsize);
  219 #endif
  220 
  221         if (args->sigsetsize != sizeof(linux_new_sigset_t))
  222                 return EINVAL;
  223 
  224 #ifdef DEBUG
  225         if (args->sig >= LINUX_NSIG) {
  226                 printf("LINUX(%ld): rt_sigaction: 64-bit signal (%d)\n",
  227                        (long)p->p_pid, args->sig);
  228         }
  229 #endif
  230 
  231         if (args->act) {
  232                 error = copyin(args->act, &new_sa, sizeof(linux_new_sigaction_t));
  233                 if (error)
  234                         return error;
  235 
  236                 nsa.sa_handler = new_sa.lsa_handler;
  237                 nsa.sa_mask = new_sa.lsa_mask.sig[0];
  238                 nsa.sa_flags = new_sa.lsa_flags;
  239                 nsa.sa_restorer = new_sa.lsa_restorer;
  240 
  241 #ifdef DEBUG
  242                 if (new_sa.lsa_mask.sig[1] != 0)
  243                         printf("LINUX(%ld): rt_sigaction: sig[1] = 0x%08lx\n",
  244                                (long)p->p_pid, new_sa.lsa_mask.sig[1]);
  245 #endif
  246         }
  247 
  248         error = linux_do_sigaction(p, args->sig,
  249                                    args->act ? &nsa : NULL,
  250                                    args->oact ? &osa : NULL);
  251         if (error)
  252                 return error;
  253 
  254         if (args->oact) {
  255                 new_sa.lsa_handler = osa.sa_handler;
  256                 new_sa.lsa_flags = osa.sa_flags;
  257                 new_sa.lsa_restorer = osa.sa_restorer;
  258                 new_sa.lsa_mask.sig[0] = osa.sa_mask;
  259                 new_sa.lsa_mask.sig[1] = 0;
  260                 error = copyout(&osa, args->oact, sizeof(linux_new_sigaction_t));
  261                 if (error)
  262                         return error;
  263         }
  264 
  265         return 0;
  266 }
  267 
  268 static int
  269 linux_do_sigprocmask(struct proc *p, int how, linux_sigset_t *new,
  270                      linux_sigset_t *old)
  271 {
  272         int error = 0, s;
  273         sigset_t mask;
  274 
  275         p->p_retval[0] = 0;
  276 
  277         if (old != NULL)
  278                 *old = bsd_to_linux_sigset(p->p_sigmask);
  279 
  280         if (new != NULL) {
  281                 mask = linux_to_bsd_sigset(*new);
  282 
  283                 s = splhigh();
  284 
  285                 switch (how) {
  286                 case LINUX_SIG_BLOCK:
  287                         p->p_sigmask |= (mask & ~sigcantmask);
  288                         break;
  289                 case LINUX_SIG_UNBLOCK:
  290                         p->p_sigmask &= ~mask;
  291                         break;
  292                 case LINUX_SIG_SETMASK:
  293                         p->p_sigmask = (mask & ~sigcantmask);
  294                         break;
  295                 default:
  296                         error = EINVAL;
  297                         break;
  298                 }
  299 
  300                 splx(s);
  301         }
  302 
  303         return error;
  304 }
  305 
  306 int
  307 linux_sigprocmask(struct proc *p, struct linux_sigprocmask_args *args)
  308 {
  309         linux_sigset_t mask;
  310         linux_sigset_t omask;
  311         int error;
  312 
  313 #ifdef DEBUG
  314         printf("Linux-emul(%ld): sigprocmask(%d, *, *)\n", (long)p->p_pid,
  315                args->how);
  316 #endif
  317 
  318         if (args->mask != NULL) {
  319                 error = copyin(args->mask, &mask, sizeof(linux_sigset_t));
  320                 if (error)
  321                         return error;
  322         }
  323 
  324         error = linux_do_sigprocmask(p, args->how,
  325                                      args->mask ? &mask : NULL,
  326                                      args->omask ? &omask : NULL);
  327 
  328         if (!error && args->omask != NULL) {
  329                 error = copyout(&omask, args->omask, sizeof(linux_sigset_t));
  330         }
  331 
  332         return error;
  333 }
  334 
  335 int
  336 linux_rt_sigprocmask(struct proc *p, struct linux_rt_sigprocmask_args *args)
  337 {
  338         linux_new_sigset_t new_mask;
  339         linux_sigset_t old_mask;
  340         int error;
  341 
  342 #ifdef DEBUG
  343         printf("Linux-emul(%ld): rt_sigprocmask(%d, %p, %p, %d)\n",
  344                (long)p->p_pid, args->how, (void *)args->mask,
  345                (void *)args->omask, args->sigsetsize);
  346 #endif
  347 
  348         if (args->sigsetsize != sizeof(linux_new_sigset_t))
  349                 return EINVAL;
  350 
  351         if (args->mask != NULL) {
  352                 error = copyin(args->mask, &new_mask, sizeof(linux_new_sigset_t));
  353                 if (error)
  354                         return error;
  355 
  356 #ifdef DEBUG
  357                 if (new_mask.sig[1] != 0)
  358                         printf("LINUX(%ld): rt_sigprocmask: sig[1] = 0x%08lx\n",
  359                                (long)p->p_pid, new_mask.sig[1]);
  360 #endif
  361         }
  362 
  363         error = linux_do_sigprocmask(p, args->how,
  364                                      args->mask ? new_mask.sig : NULL,
  365                                      args->omask ? &old_mask : NULL);
  366 
  367         if (!error && args->omask != NULL) {
  368                 new_mask.sig[0] = old_mask;
  369                 error = copyout(&new_mask, args->omask, sizeof(linux_new_sigset_t));
  370         }
  371 
  372         return error;
  373 }
  374 
  375 int
  376 linux_siggetmask(struct proc *p, struct linux_siggetmask_args *args)
  377 {
  378 #ifdef DEBUG
  379     printf("Linux-emul(%d): siggetmask()\n", p->p_pid);
  380 #endif
  381     p->p_retval[0] = bsd_to_linux_sigset(p->p_sigmask);
  382     return 0;
  383 }
  384 
  385 int
  386 linux_sigsetmask(struct proc *p, struct linux_sigsetmask_args *args)
  387 {
  388     int s;
  389     sigset_t mask;
  390 
  391 #ifdef DEBUG
  392     printf("Linux-emul(%ld): sigsetmask(%08lx)\n",
  393         (long)p->p_pid, (unsigned long)args->mask);
  394 #endif
  395     p->p_retval[0] = bsd_to_linux_sigset(p->p_sigmask);
  396 
  397     mask = linux_to_bsd_sigset(args->mask);
  398     s = splhigh();
  399     p->p_sigmask = mask & ~sigcantmask;
  400     splx(s);
  401     return 0;
  402 }
  403 
  404 int
  405 linux_sigpending(struct proc *p, struct linux_sigpending_args *args)
  406 {
  407     linux_sigset_t linux_sig;
  408 
  409 #ifdef DEBUG
  410     printf("Linux-emul(%d): sigpending(*)\n", p->p_pid);
  411 #endif
  412     linux_sig = bsd_to_linux_sigset(p->p_siglist & p->p_sigmask);
  413     return copyout(&linux_sig, args->mask, sizeof(linux_sig));
  414 }
  415 
  416 /*
  417  * Linux has two extra args, restart and oldmask.  We dont use these,
  418  * but it seems that "restart" is actually a context pointer that
  419  * enables the signal to happen with a different register set.
  420  */
  421 int
  422 linux_sigsuspend(struct proc *p, struct linux_sigsuspend_args *args)
  423 {
  424     struct sigsuspend_args tmp;
  425 
  426 #ifdef DEBUG
  427     printf("Linux-emul(%ld): sigsuspend(%08lx)\n",
  428         (long)p->p_pid, (unsigned long)args->mask);
  429 #endif
  430     tmp.mask = linux_to_bsd_sigset(args->mask);
  431     return sigsuspend(p, &tmp);
  432 }
  433 
  434 int
  435 linux_rt_sigsuspend(p, uap)
  436         struct proc *p;
  437         struct linux_rt_sigsuspend_args *uap;
  438 {
  439         linux_new_sigset_t lmask;
  440         struct sigsuspend_args bsd;
  441         int error;
  442 
  443 #ifdef DEBUG
  444         printf("Linux-emul(%ld): rt_sigsuspend(%p, %d)\n", (long)p->p_pid,
  445             (void *)uap->newset, uap->sigsetsize);
  446 #endif
  447 
  448         if (uap->sigsetsize != sizeof(linux_new_sigset_t))
  449                 return (EINVAL);
  450 
  451         error = copyin(uap->newset, &lmask, sizeof(linux_new_sigset_t));
  452         if (error)
  453                 return (error);
  454 
  455         bsd.mask = linux_to_bsd_sigset(lmask.sig[0]);
  456         return (sigsuspend(p, &bsd));
  457 }
  458 
  459 int
  460 linux_pause(struct proc *p, struct linux_pause_args *args)
  461 {
  462     struct sigsuspend_args tmp;
  463 
  464 #ifdef DEBUG
  465     printf("Linux-emul(%d): pause()\n", p->p_pid);
  466 #endif
  467     tmp.mask = p->p_sigmask;
  468     return sigsuspend(p, &tmp);
  469 }
  470 
  471 int
  472 linux_kill(struct proc *p, struct linux_kill_args *args)
  473 {
  474     struct kill_args /* {
  475         int pid;
  476         int signum;
  477     } */ tmp;
  478 
  479 #ifdef DEBUG
  480     printf("Linux-emul(%d): kill(%d, %d)\n", 
  481            p->p_pid, args->pid, args->signum);
  482 #endif
  483     if (args->signum < 0 || args->signum >= LINUX_NSIG)
  484         return EINVAL;
  485     tmp.pid = args->pid;
  486     tmp.signum = linux_to_bsd_signal[args->signum];
  487     return kill(p, &tmp);
  488 }
  489 
  490 int
  491 linux_sigaltstack(p, uap)
  492         struct proc *p;
  493         struct linux_sigaltstack_args *uap;
  494 {
  495         struct sigaltstack_args bsd;
  496         struct sigaltstack *ss, *oss;
  497         linux_stack_t lss;
  498         int error;
  499         caddr_t sg = stackgap_init();
  500 
  501 #ifdef DEBUG
  502         printf("Linux-emul(%ld): sigaltstack(%p, %p)\n",
  503             (long)p->p_pid, uap->uss, uap->uoss);
  504 #endif
  505 
  506         error = copyin(uap->uss, &lss, sizeof(linux_stack_t));
  507         if (error)
  508                 return (error);
  509 
  510         ss = stackgap_alloc(&sg, sizeof(struct sigaltstack));
  511         ss->ss_sp = lss.ss_sp;
  512         ss->ss_size = lss.ss_size;
  513         ss->ss_flags = lss.ss_flags;
  514 
  515         oss = (uap->uoss != NULL)
  516             ? stackgap_alloc(&sg, sizeof(struct sigaltstack))
  517             : NULL;
  518 
  519         bsd.nss = ss;
  520         bsd.oss = oss;
  521         error = sigaltstack(p, &bsd);
  522 
  523         if (!error && oss != NULL) {
  524                 lss.ss_sp = oss->ss_sp;
  525                 lss.ss_size = oss->ss_size;
  526                 lss.ss_flags = oss->ss_flags;
  527                 error = copyout(&lss, uap->uoss, sizeof(linux_stack_t));
  528         }
  529 
  530         return (error);
  531 }

Cache object: 8bddf9d3cfe0c50da15d9d5c5dd4007a


[ 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.