1/* $NetBSD: signals.c,v 1.9 2011/05/18 15:57:14 christos Exp $ */ 2 3/*- 4 * Copyright (c) 2010, 2011 Antti Kantee. All Rights Reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: 9 * 1. Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 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 * 15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS 16 * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 17 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 18 * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 19 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 20 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 21 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 22 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 23 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 24 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 25 * SUCH DAMAGE. 26 */ 27 28#include <sys/cdefs.h> 29__KERNEL_RCSID(0, "$NetBSD: signals.c,v 1.9 2011/05/18 15:57:14 christos Exp $"); 30 31#include <sys/param.h> 32#include <sys/atomic.h> 33#include <sys/event.h> 34#include <sys/proc.h> 35#include <sys/signal.h> 36 37#include <rump/rump.h> 38#include <rump/rumpuser.h> 39 40#include "rump_private.h" 41#include "rumpkern_if_priv.h" 42 43const struct filterops sig_filtops = { 44 .f_attach = (void *)eopnotsupp, 45}; 46 47sigset_t sigcantmask; 48 49static void 50pgrp_apply(struct pgrp *pgrp, int signo, void (*apply)(struct proc *p, int)) 51{ 52 struct proc *p; 53 54 KASSERT(mutex_owned(proc_lock)); 55 56 LIST_FOREACH(p, &pgrp->pg_members, p_pglist) { 57 mutex_enter(p->p_lock); 58 apply(p, signo); 59 mutex_exit(p->p_lock); 60 } 61} 62 63/* RUMP_SIGMODEL_PANIC */ 64 65static void 66rumpsig_panic(struct proc *p, int signo) 67{ 68 69 switch (signo) { 70 case SIGSYS: 71 case SIGPIPE: 72 break; 73 default: 74 panic("unhandled signal %d", signo); 75 } 76} 77 78/* RUMP_SIGMODEL_IGNORE */ 79 80static void 81rumpsig_ignore(struct proc *p, int signo) 82{ 83 84 return; 85} 86 87/* RUMP_SIGMODEL_HOST */ 88 89static void 90rumpsig_host(struct proc *p, int signo) 91{ 92 int error; 93 94 rumpuser_kill(p->p_pid, signo, &error); 95} 96 97/* RUMP_SIGMODEL_RAISE */ 98 99static void 100rumpsig_raise(struct proc *p, int signo) 101{ 102 int error = 0; 103 104 if (RUMP_LOCALPROC_P(p)) { 105 rumpuser_kill(RUMPUSER_PID_SELF, signo, &error); 106 } else { 107 rumpuser_sp_raise(p->p_vmspace->vm_map.pmap, signo); 108 } 109} 110 111static void 112rumpsig_record(struct proc *p, int signo) 113{ 114 115 if (!sigismember(&p->p_sigctx.ps_sigignore, signo)) { 116 sigaddset(&p->p_sigpend.sp_set, signo); 117 } 118} 119 120typedef void (*rumpsig_fn)(struct proc *, int); 121 122static rumpsig_fn rumpsig = rumpsig_raise; 123 124/* 125 * Set signal delivery model. It would be nice if we could 126 * take a functional argument. But then we'd need some 127 * OS independent way to represent a signal number and also 128 * a method for easy processing (parsing is boring). 129 * 130 * Plus, upcalls from the rump kernel into process space except 131 * via rumpuser is a somewhat gray area now. 132 */ 133void 134rump_boot_setsigmodel(enum rump_sigmodel model) 135{ 136 137 switch (model) { 138 case RUMP_SIGMODEL_PANIC: 139 rumpsig = rumpsig_panic; 140 break; 141 case RUMP_SIGMODEL_IGNORE: 142 rumpsig = rumpsig_ignore; 143 break; 144 case RUMP_SIGMODEL_HOST: 145 rumpsig = rumpsig_host; 146 break; 147 case RUMP_SIGMODEL_RAISE: 148 rumpsig = rumpsig_raise; 149 break; 150 case RUMP_SIGMODEL_RECORD: 151 rumpsig = rumpsig_record; 152 break; 153 } 154} 155 156void 157psignal(struct proc *p, int sig) 158{ 159 160 rumpsig(p, sig); 161} 162 163void 164pgsignal(struct pgrp *pgrp, int sig, int checktty) 165{ 166 167 pgrp_apply(pgrp, sig, rumpsig); 168} 169 170void 171kpsignal(struct proc *p, ksiginfo_t *ksi, void *data) 172{ 173 174 rumpsig(p, ksi->ksi_signo); 175} 176 177void 178kpgsignal(struct pgrp *pgrp, ksiginfo_t *ksi, void *data, int checkctty) 179{ 180 181 pgrp_apply(pgrp, ksi->ksi_signo, rumpsig); 182} 183 184int 185sigispending(struct lwp *l, int signo) 186{ 187 struct proc *p = l->l_proc; 188 sigset_t tset; 189 190 tset = p->p_sigpend.sp_set; 191 192 if (signo == 0) { 193 if (firstsig(&tset) != 0) 194 return EINTR; 195 } else if (sigismember(&tset, signo)) 196 return EINTR; 197 return 0; 198} 199 200void 201sigpending1(struct lwp *l, sigset_t *ss) 202{ 203 struct proc *p = l->l_proc; 204 205 mutex_enter(p->p_lock); 206 *ss = l->l_proc->p_sigpend.sp_set; 207 mutex_exit(p->p_lock); 208} 209 210int 211sigismasked(struct lwp *l, int sig) 212{ 213 214 return sigismember(&l->l_proc->p_sigctx.ps_sigignore, sig); 215} 216 217void 218sigclear(sigpend_t *sp, const sigset_t *mask, ksiginfoq_t *kq) 219{ 220 221 if (mask == NULL) 222 sigemptyset(&sp->sp_set); 223 else 224 sigminusset(mask, &sp->sp_set); 225} 226 227void 228sigclearall(struct proc *p, const sigset_t *mask, ksiginfoq_t *kq) 229{ 230 231 /* don't assert proc lock, hence callable from user context */ 232 sigclear(&p->p_sigpend, mask, kq); 233} 234 235void 236ksiginfo_queue_drain0(ksiginfoq_t *kq) 237{ 238 239 if (!(CIRCLEQ_EMPTY(kq))) 240 panic("how did that get there?"); 241} 242 243int 244sigprocmask1(struct lwp *l, int how, const sigset_t *nss, sigset_t *oss) 245{ 246 sigset_t *mask = &l->l_proc->p_sigctx.ps_sigignore; 247 248 KASSERT(mutex_owned(l->l_proc->p_lock)); 249 250 if (oss) 251 *oss = *mask; 252 253 if (nss) { 254 switch (how) { 255 case SIG_BLOCK: 256 sigplusset(nss, mask); 257 break; 258 case SIG_UNBLOCK: 259 sigminusset(nss, mask); 260 break; 261 case SIG_SETMASK: 262 *mask = *nss; 263 break; 264 default: 265 return EINVAL; 266 } 267 } 268 269 return 0; 270} 271 272void 273siginit(struct proc *p) 274{ 275 276 sigemptyset(&p->p_sigctx.ps_sigignore); 277 sigemptyset(&p->p_sigpend.sp_set); 278} 279 280void 281sigsuspendsetup(struct lwp *l, const sigset_t *ss) 282{ 283 /* XXX: Partial copy of kernel code, remove and use the kernel code. */ 284 struct proc *p = l->l_proc; 285 286 mutex_enter(p->p_lock); 287 l->l_sigrestore = 1; 288 l->l_sigoldmask = l->l_sigmask; 289 l->l_sigmask = *ss; 290 sigminusset(&sigcantmask, &l->l_sigmask); 291 mutex_exit(p->p_lock); 292} 293 294void 295sigsuspendteardown(struct lwp *l) 296{ 297 /* XXX: Copy of kernel code, remove and use the kernel code. */ 298 struct proc *p = l->l_proc; 299 300 mutex_enter(p->p_lock); 301 if (l->l_sigrestore) { 302 l->l_sigrestore = 0; 303 l->l_sigmask = l->l_sigoldmask; 304 } 305 mutex_exit(p->p_lock); 306} 307