1 /* $NetBSD: signals.c,v 1.12 2013/11/22 21:56:24 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.12 2013/11/22 21:56:24 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 43 const struct filterops sig_filtops = { 44 .f_attach = (void *)eopnotsupp, 45 }; 46 47 sigset_t sigcantmask; 48 49 static void 50 pgrp_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 65 static void 66 rumpsig_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 80 static void 81 rumpsig_ignore(struct proc *p, int signo) 82 { 83 84 return; 85 } 86 87 /* RUMP_SIGMODEL_HOST */ 88 89 static void 90 rumpsig_host(struct proc *p, int signo) 91 { 92 93 rumpuser_kill(p->p_pid, signo); 94 } 95 96 /* RUMP_SIGMODEL_RAISE */ 97 98 static void 99 rumpsig_raise(struct proc *p, int signo) 100 { 101 102 if (RUMP_LOCALPROC_P(p)) { 103 rumpuser_kill(RUMPUSER_PID_SELF, signo); 104 } else { 105 rumpuser_sp_raise(p->p_vmspace->vm_map.pmap, signo); 106 } 107 } 108 109 static void 110 rumpsig_record(struct proc *p, int signo) 111 { 112 113 if (!sigismember(&p->p_sigctx.ps_sigignore, signo)) { 114 sigaddset(&p->p_sigpend.sp_set, signo); 115 } 116 } 117 118 typedef void (*rumpsig_fn)(struct proc *, int); 119 120 static rumpsig_fn rumpsig = rumpsig_raise; 121 122 /* 123 * Set signal delivery model. It would be nice if we could 124 * take a functional argument. But then we'd need some 125 * OS independent way to represent a signal number and also 126 * a method for easy processing (parsing is boring). 127 * 128 * Plus, upcalls from the rump kernel into process space except 129 * via rumpuser is a somewhat gray area now. 130 */ 131 void 132 rump_boot_setsigmodel(enum rump_sigmodel model) 133 { 134 135 switch (model) { 136 case RUMP_SIGMODEL_PANIC: 137 rumpsig = rumpsig_panic; 138 break; 139 case RUMP_SIGMODEL_IGNORE: 140 rumpsig = rumpsig_ignore; 141 break; 142 case RUMP_SIGMODEL_HOST: 143 rumpsig = rumpsig_host; 144 break; 145 case RUMP_SIGMODEL_RAISE: 146 rumpsig = rumpsig_raise; 147 break; 148 case RUMP_SIGMODEL_RECORD: 149 rumpsig = rumpsig_record; 150 break; 151 } 152 } 153 154 void 155 psignal(struct proc *p, int sig) 156 { 157 158 rumpsig(p, sig); 159 } 160 161 void 162 pgsignal(struct pgrp *pgrp, int sig, int checktty) 163 { 164 165 pgrp_apply(pgrp, sig, rumpsig); 166 } 167 168 void 169 kpsignal(struct proc *p, ksiginfo_t *ksi, void *data) 170 { 171 172 rumpsig(p, ksi->ksi_signo); 173 } 174 175 void 176 kpgsignal(struct pgrp *pgrp, ksiginfo_t *ksi, void *data, int checkctty) 177 { 178 179 pgrp_apply(pgrp, ksi->ksi_signo, rumpsig); 180 } 181 182 int 183 sigispending(struct lwp *l, int signo) 184 { 185 struct proc *p = l->l_proc; 186 sigset_t tset; 187 188 tset = p->p_sigpend.sp_set; 189 190 if (signo == 0) { 191 if (firstsig(&tset) != 0) 192 return EINTR; 193 } else if (sigismember(&tset, signo)) 194 return EINTR; 195 return 0; 196 } 197 198 void 199 sigpending1(struct lwp *l, sigset_t *ss) 200 { 201 struct proc *p = l->l_proc; 202 203 mutex_enter(p->p_lock); 204 *ss = l->l_proc->p_sigpend.sp_set; 205 mutex_exit(p->p_lock); 206 } 207 208 int 209 sigismasked(struct lwp *l, int sig) 210 { 211 212 return sigismember(&l->l_proc->p_sigctx.ps_sigignore, sig); 213 } 214 215 void 216 sigclear(sigpend_t *sp, const sigset_t *mask, ksiginfoq_t *kq) 217 { 218 219 if (mask == NULL) 220 sigemptyset(&sp->sp_set); 221 else 222 sigminusset(mask, &sp->sp_set); 223 } 224 225 void 226 sigclearall(struct proc *p, const sigset_t *mask, ksiginfoq_t *kq) 227 { 228 229 /* don't assert proc lock, hence callable from user context */ 230 sigclear(&p->p_sigpend, mask, kq); 231 } 232 233 void 234 ksiginfo_queue_drain0(ksiginfoq_t *kq) 235 { 236 237 if (!(TAILQ_EMPTY(kq))) 238 panic("how did that get there?"); 239 } 240 241 int 242 sigprocmask1(struct lwp *l, int how, const sigset_t *nss, sigset_t *oss) 243 { 244 sigset_t *mask = &l->l_proc->p_sigctx.ps_sigignore; 245 246 KASSERT(mutex_owned(l->l_proc->p_lock)); 247 248 if (oss) 249 *oss = *mask; 250 251 if (nss) { 252 switch (how) { 253 case SIG_BLOCK: 254 sigplusset(nss, mask); 255 break; 256 case SIG_UNBLOCK: 257 sigminusset(nss, mask); 258 break; 259 case SIG_SETMASK: 260 *mask = *nss; 261 break; 262 default: 263 return EINVAL; 264 } 265 } 266 267 return 0; 268 } 269 270 void 271 siginit(struct proc *p) 272 { 273 274 sigemptyset(&p->p_sigctx.ps_sigignore); 275 sigemptyset(&p->p_sigpend.sp_set); 276 } 277 278 void 279 sigsuspendsetup(struct lwp *l, const sigset_t *ss) 280 { 281 /* XXX: Partial copy of kernel code, remove and use the kernel code. */ 282 struct proc *p = l->l_proc; 283 284 mutex_enter(p->p_lock); 285 l->l_sigrestore = 1; 286 l->l_sigoldmask = l->l_sigmask; 287 l->l_sigmask = *ss; 288 sigminusset(&sigcantmask, &l->l_sigmask); 289 mutex_exit(p->p_lock); 290 } 291 292 void 293 sigsuspendteardown(struct lwp *l) 294 { 295 /* XXX: Copy of kernel code, remove and use the kernel code. */ 296 struct proc *p = l->l_proc; 297 298 mutex_enter(p->p_lock); 299 if (l->l_sigrestore) { 300 l->l_sigrestore = 0; 301 l->l_sigmask = l->l_sigoldmask; 302 } 303 mutex_exit(p->p_lock); 304 } 305