linux_signal.c 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936
  1. /* $OpenBSD: linux_signal.c,v 1.18 2015/02/09 13:41:24 pelikan Exp $ */
  2. /* $NetBSD: linux_signal.c,v 1.10 1996/04/04 23:51:36 christos Exp $ */
  3. /*
  4. * Copyright (c) 1995 Frank van der Linden
  5. * All rights reserved.
  6. *
  7. * Redistribution and use in source and binary forms, with or without
  8. * modification, are permitted provided that the following conditions
  9. * are met:
  10. * 1. Redistributions of source code must retain the above copyright
  11. * notice, this list of conditions and the following disclaimer.
  12. * 2. Redistributions in binary form must reproduce the above copyright
  13. * notice, this list of conditions and the following disclaimer in the
  14. * documentation and/or other materials provided with the distribution.
  15. * 3. All advertising materials mentioning features or use of this software
  16. * must display the following acknowledgement:
  17. * This product includes software developed for the NetBSD Project
  18. * by Frank van der Linden
  19. * 4. The name of the author may not be used to endorse or promote products
  20. * derived from this software without specific prior written permission
  21. *
  22. * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
  23. * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
  24. * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
  25. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
  26. * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
  27. * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  28. * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
  29. * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  30. * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
  31. * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  32. *
  33. * heavily from: svr4_signal.c,v 1.7 1995/01/09 01:04:21 christos Exp
  34. */
  35. #include <sys/param.h>
  36. #include <sys/systm.h>
  37. #include <sys/namei.h>
  38. #include <sys/proc.h>
  39. #include <sys/filedesc.h>
  40. #include <sys/ioctl.h>
  41. #include <sys/mount.h>
  42. #include <sys/kernel.h>
  43. #include <sys/signal.h>
  44. #include <sys/signalvar.h>
  45. #include <sys/malloc.h>
  46. #include <sys/syscallargs.h>
  47. #include <compat/linux/linux_types.h>
  48. #include <compat/linux/linux_signal.h>
  49. #include <compat/linux/linux_syscallargs.h>
  50. #include <compat/linux/linux_util.h>
  51. #define sigemptyset(s) memset((s), 0, sizeof(*(s)))
  52. #define sigismember(s, n) (*(s) & sigmask(n))
  53. #define sigaddset(s, n) (*(s) |= sigmask(n))
  54. /* Locally used defines (in bsd<->linux conversion functions): */
  55. #define linux_sigmask(n) (1 << ((n) - 1))
  56. #define linux_sigemptyset(s) memset((s), 0, sizeof(*(s)))
  57. #define linux_sigismember(s, n) ((s)->sig[((n) - 1) / LINUX__NSIG_BPW] \
  58. & (1 << ((n) - 1) % LINUX__NSIG_BPW))
  59. #define linux_sigaddset(s, n) ((s)->sig[((n) - 1) / LINUX__NSIG_BPW] \
  60. |= (1 << ((n) - 1) % LINUX__NSIG_BPW))
  61. int bsd_to_linux_sig[NSIG] = {
  62. 0,
  63. LINUX_SIGHUP,
  64. LINUX_SIGINT,
  65. LINUX_SIGQUIT,
  66. LINUX_SIGILL,
  67. LINUX_SIGTRAP,
  68. LINUX_SIGABRT,
  69. LINUX_NSIG, /* XXX Kludge to get RT signal #32 to work */
  70. LINUX_SIGFPE,
  71. LINUX_SIGKILL,
  72. LINUX_SIGBUS,
  73. LINUX_SIGSEGV,
  74. LINUX_NSIG + 1, /* XXX Kludge to get RT signal #32 to work */
  75. LINUX_SIGPIPE,
  76. LINUX_SIGALRM,
  77. LINUX_SIGTERM,
  78. LINUX_SIGURG,
  79. LINUX_SIGSTOP,
  80. LINUX_SIGTSTP,
  81. LINUX_SIGCONT,
  82. LINUX_SIGCHLD,
  83. LINUX_SIGTTIN,
  84. LINUX_SIGTTOU,
  85. LINUX_SIGIO,
  86. LINUX_SIGXCPU,
  87. LINUX_SIGXFSZ,
  88. LINUX_SIGVTALRM,
  89. LINUX_SIGPROF,
  90. LINUX_SIGWINCH,
  91. 0, /* SIGINFO */
  92. LINUX_SIGUSR1,
  93. LINUX_SIGUSR2,
  94. 0, /* SIGTHR */
  95. };
  96. int linux_to_bsd_sig[LINUX__NSIG] = {
  97. 0,
  98. SIGHUP,
  99. SIGINT,
  100. SIGQUIT,
  101. SIGILL,
  102. SIGTRAP,
  103. SIGABRT,
  104. SIGBUS,
  105. SIGFPE,
  106. SIGKILL,
  107. SIGUSR1,
  108. SIGSEGV,
  109. SIGUSR2,
  110. SIGPIPE,
  111. SIGALRM,
  112. SIGTERM,
  113. 0, /* SIGSTKFLT */
  114. SIGCHLD,
  115. SIGCONT,
  116. SIGSTOP,
  117. SIGTSTP,
  118. SIGTTIN,
  119. SIGTTOU,
  120. SIGURG,
  121. SIGXCPU,
  122. SIGXFSZ,
  123. SIGVTALRM,
  124. SIGPROF,
  125. SIGWINCH,
  126. SIGIO,
  127. 0, /* SIGUNUSED */
  128. 0,
  129. SIGEMT, /* XXX Gruesome hack for linuxthreads: */
  130. SIGSYS, /* Map 1st 2 RT signals onto ones we handle. */
  131. 0,
  132. 0,
  133. 0,
  134. 0,
  135. 0,
  136. 0,
  137. 0,
  138. 0,
  139. 0,
  140. 0,
  141. 0,
  142. 0,
  143. 0,
  144. 0,
  145. 0,
  146. 0,
  147. 0,
  148. 0,
  149. 0,
  150. 0,
  151. 0,
  152. 0,
  153. 0,
  154. 0,
  155. 0,
  156. 0,
  157. 0,
  158. 0,
  159. 0,
  160. 0,
  161. };
  162. /*
  163. * Convert between Linux and BSD signal sets.
  164. */
  165. void
  166. linux_old_to_bsd_sigset(lss, bss)
  167. const linux_old_sigset_t *lss;
  168. sigset_t *bss;
  169. {
  170. linux_old_extra_to_bsd_sigset(lss, (const unsigned long *) 0, bss);
  171. }
  172. void
  173. bsd_to_linux_old_sigset(bss, lss)
  174. const sigset_t *bss;
  175. linux_old_sigset_t *lss;
  176. {
  177. bsd_to_linux_old_extra_sigset(bss, lss, (unsigned long *) 0);
  178. }
  179. void
  180. linux_old_extra_to_bsd_sigset(lss, extra, bss)
  181. const linux_old_sigset_t *lss;
  182. const unsigned long *extra;
  183. sigset_t *bss;
  184. {
  185. linux_sigset_t lsnew;
  186. /* convert old sigset to new sigset */
  187. linux_sigemptyset(&lsnew);
  188. lsnew.sig[0] = *lss;
  189. if (extra)
  190. bcopy(extra, &lsnew.sig[1],
  191. sizeof(linux_sigset_t) - sizeof(linux_old_sigset_t));
  192. linux_to_bsd_sigset(&lsnew, bss);
  193. }
  194. void
  195. bsd_to_linux_old_extra_sigset(bss, lss, extra)
  196. const sigset_t *bss;
  197. linux_old_sigset_t *lss;
  198. unsigned long *extra;
  199. {
  200. linux_sigset_t lsnew;
  201. bsd_to_linux_sigset(bss, &lsnew);
  202. /* convert new sigset to old sigset */
  203. *lss = lsnew.sig[0];
  204. if (extra)
  205. bcopy(&lsnew.sig[1], extra,
  206. sizeof(linux_sigset_t) - sizeof(linux_old_sigset_t));
  207. }
  208. void
  209. linux_to_bsd_sigset(lss, bss)
  210. const linux_sigset_t *lss;
  211. sigset_t *bss;
  212. {
  213. int i, newsig;
  214. sigemptyset(bss);
  215. for (i = 1; i < LINUX__NSIG; i++) {
  216. if (linux_sigismember(lss, i)) {
  217. newsig = linux_to_bsd_sig[i];
  218. if (newsig)
  219. sigaddset(bss, newsig);
  220. }
  221. }
  222. }
  223. void
  224. bsd_to_linux_sigset(bss, lss)
  225. const sigset_t *bss;
  226. linux_sigset_t *lss;
  227. {
  228. int i, newsig;
  229. linux_sigemptyset(lss);
  230. for (i = 1; i < NSIG; i++) {
  231. if (sigismember(bss, i)) {
  232. newsig = bsd_to_linux_sig[i];
  233. if (newsig)
  234. linux_sigaddset(lss, newsig);
  235. }
  236. }
  237. }
  238. /*
  239. * Convert between Linux and BSD sigaction structures. Linux has
  240. * one extra field (sa_restorer) which we don't support.
  241. */
  242. void
  243. linux_old_to_bsd_sigaction(lsa, bsa)
  244. struct linux_old_sigaction *lsa;
  245. struct sigaction *bsa;
  246. {
  247. bsa->sa_handler = lsa->sa__handler;
  248. linux_old_to_bsd_sigset(&lsa->sa_mask, &bsa->sa_mask);
  249. bsa->sa_flags = 0;
  250. if ((lsa->sa_flags & LINUX_SA_ONSTACK) != 0)
  251. bsa->sa_flags |= SA_ONSTACK;
  252. if ((lsa->sa_flags & LINUX_SA_RESTART) != 0)
  253. bsa->sa_flags |= SA_RESTART;
  254. if ((lsa->sa_flags & LINUX_SA_ONESHOT) != 0)
  255. bsa->sa_flags |= SA_RESETHAND;
  256. if ((lsa->sa_flags & LINUX_SA_NOCLDSTOP) != 0)
  257. bsa->sa_flags |= SA_NOCLDSTOP;
  258. if ((lsa->sa_flags & LINUX_SA_NOMASK) != 0)
  259. bsa->sa_flags |= SA_NODEFER;
  260. }
  261. void
  262. bsd_to_linux_old_sigaction(bsa, lsa)
  263. struct sigaction *bsa;
  264. struct linux_old_sigaction *lsa;
  265. {
  266. lsa->sa__handler = bsa->sa_handler;
  267. bsd_to_linux_old_sigset(&bsa->sa_mask, &lsa->sa_mask);
  268. lsa->sa_flags = 0;
  269. if ((bsa->sa_flags & SA_NOCLDSTOP) != 0)
  270. lsa->sa_flags |= LINUX_SA_NOCLDSTOP;
  271. if ((bsa->sa_flags & SA_ONSTACK) != 0)
  272. lsa->sa_flags |= LINUX_SA_ONSTACK;
  273. if ((bsa->sa_flags & SA_RESTART) != 0)
  274. lsa->sa_flags |= LINUX_SA_RESTART;
  275. if ((bsa->sa_flags & SA_NODEFER) != 0)
  276. lsa->sa_flags |= LINUX_SA_NOMASK;
  277. if ((bsa->sa_flags & SA_RESETHAND) != 0)
  278. lsa->sa_flags |= LINUX_SA_ONESHOT;
  279. lsa->sa_restorer = NULL;
  280. }
  281. void
  282. linux_to_bsd_sigaction(lsa, bsa)
  283. struct linux_sigaction *lsa;
  284. struct sigaction *bsa;
  285. {
  286. bsa->sa_handler = lsa->sa__handler;
  287. linux_to_bsd_sigset(&lsa->sa_mask, &bsa->sa_mask);
  288. bsa->sa_flags = 0;
  289. if ((lsa->sa_flags & LINUX_SA_NOCLDSTOP) != 0)
  290. bsa->sa_flags |= SA_NOCLDSTOP;
  291. if ((lsa->sa_flags & LINUX_SA_ONSTACK) != 0)
  292. bsa->sa_flags |= SA_ONSTACK;
  293. if ((lsa->sa_flags & LINUX_SA_RESTART) != 0)
  294. bsa->sa_flags |= SA_RESTART;
  295. if ((lsa->sa_flags & LINUX_SA_ONESHOT) != 0)
  296. bsa->sa_flags |= SA_RESETHAND;
  297. if ((lsa->sa_flags & LINUX_SA_NOMASK) != 0)
  298. bsa->sa_flags |= SA_NODEFER;
  299. if ((lsa->sa_flags & LINUX_SA_SIGINFO) != 0)
  300. bsa->sa_flags |= SA_SIGINFO;
  301. }
  302. void
  303. bsd_to_linux_sigaction(bsa, lsa)
  304. struct sigaction *bsa;
  305. struct linux_sigaction *lsa;
  306. {
  307. /* Clear sa_flags and sa_restorer (if it exists) */
  308. memset(lsa, 0, sizeof(struct linux_sigaction));
  309. /* ...and fill in the mask and flags */
  310. bsd_to_linux_sigset(&bsa->sa_mask, &lsa->sa_mask);
  311. if ((bsa->sa_flags & SA_NOCLDSTOP) != 0)
  312. lsa->sa_flags |= LINUX_SA_NOCLDSTOP;
  313. if ((bsa->sa_flags & SA_ONSTACK) != 0)
  314. lsa->sa_flags |= LINUX_SA_ONSTACK;
  315. if ((bsa->sa_flags & SA_RESTART) != 0)
  316. lsa->sa_flags |= LINUX_SA_RESTART;
  317. if ((bsa->sa_flags & SA_NODEFER) != 0)
  318. lsa->sa_flags |= LINUX_SA_NOMASK;
  319. if ((bsa->sa_flags & SA_RESETHAND) != 0)
  320. lsa->sa_flags |= LINUX_SA_ONESHOT;
  321. if ((bsa->sa_flags & SA_SIGINFO) != 0)
  322. lsa->sa_flags |= LINUX_SA_SIGINFO;
  323. lsa->sa__handler = bsa->sa_handler;
  324. }
  325. int
  326. linux_to_bsd_signal(int linuxsig, int *bsdsig)
  327. {
  328. if (linuxsig < 0 || linuxsig >= LINUX__NSIG)
  329. return (EINVAL);
  330. *bsdsig = linux_to_bsd_sig[linuxsig];
  331. return (0);
  332. }
  333. int
  334. bsd_to_linux_signal(int bsdsig, int *linuxsig)
  335. {
  336. if (bsdsig < 0 || bsdsig >= NSIG)
  337. return (EINVAL);
  338. *linuxsig = bsd_to_linux_sig[bsdsig];
  339. return (0);
  340. }
  341. /*
  342. * The Linux sigaction() system call. Do the usual conversions,
  343. * and just call sigaction(). Some flags and values are silently
  344. * ignored (see above).
  345. */
  346. int
  347. linux_sys_sigaction(p, v, retval)
  348. register struct proc *p;
  349. void *v;
  350. register_t *retval;
  351. {
  352. struct linux_sys_sigaction_args /* {
  353. syscallarg(int) signum;
  354. syscallarg(struct linux_old_sigaction *) nsa;
  355. syscallarg(struct linux_old_sigaction *) osa;
  356. } */ *uap = v;
  357. struct linux_old_sigaction *nlsa, *olsa, tmplsa;
  358. struct sigaction *nbsa, *obsa, tmpbsa;
  359. struct sys_sigaction_args sa;
  360. caddr_t sg;
  361. int error;
  362. if (SCARG(uap, signum) < 0 || SCARG(uap, signum) >= LINUX__NSIG)
  363. return (EINVAL);
  364. sg = stackgap_init(p);
  365. nlsa = SCARG(uap, nsa);
  366. olsa = SCARG(uap, osa);
  367. if (olsa != NULL)
  368. obsa = stackgap_alloc(&sg, sizeof(struct sigaction));
  369. else
  370. obsa = NULL;
  371. if (nlsa != NULL) {
  372. nbsa = stackgap_alloc(&sg, sizeof(struct sigaction));
  373. if ((error = copyin(nlsa, &tmplsa, sizeof(tmplsa))) != 0)
  374. return (error);
  375. linux_old_to_bsd_sigaction(&tmplsa, &tmpbsa);
  376. if ((error = copyout(&tmpbsa, nbsa, sizeof(tmpbsa))) != 0)
  377. return (error);
  378. } else
  379. nbsa = NULL;
  380. SCARG(&sa, signum) = linux_to_bsd_sig[SCARG(uap, signum)];
  381. SCARG(&sa, nsa) = nbsa;
  382. SCARG(&sa, osa) = obsa;
  383. /* Silently ignore unknown signals */
  384. if (SCARG(&sa, signum) == 0) {
  385. if (obsa != NULL) {
  386. obsa->sa_handler = SIG_IGN;
  387. sigemptyset(&obsa->sa_mask);
  388. obsa->sa_flags = 0;
  389. }
  390. }
  391. else {
  392. if ((error = sys_sigaction(p, &sa, retval)) != 0)
  393. return (error);
  394. }
  395. if (olsa != NULL) {
  396. if ((error = copyin(obsa, &tmpbsa, sizeof(tmpbsa))) != 0)
  397. return (error);
  398. bsd_to_linux_old_sigaction(&tmpbsa, &tmplsa);
  399. if ((error = copyout(&tmplsa, olsa, sizeof(tmplsa))) != 0)
  400. return (error);
  401. }
  402. return (0);
  403. }
  404. int
  405. linux_sys_rt_sigaction(p, v, retval)
  406. register struct proc *p;
  407. void *v;
  408. register_t *retval;
  409. {
  410. struct linux_sys_rt_sigaction_args /* {
  411. syscallarg(int) signum;
  412. syscallarg(struct linux_sigaction *) nsa;
  413. syscallarg(struct linux_sigaction *) osa;
  414. syscallarg(size_t) sigsetsize;
  415. } */ *uap = v;
  416. struct linux_sigaction *nlsa, *olsa, tmplsa;
  417. struct sigaction *nbsa, *obsa, tmpbsa;
  418. struct sys_sigaction_args sa;
  419. caddr_t sg;
  420. int error;
  421. if (SCARG(uap, sigsetsize) != sizeof(linux_sigset_t))
  422. return (EINVAL);
  423. if (SCARG(uap, signum) < 0 || SCARG(uap, signum) >= LINUX__NSIG)
  424. return (EINVAL);
  425. sg = stackgap_init(p);
  426. nlsa = SCARG(uap, nsa);
  427. olsa = SCARG(uap, osa);
  428. if (olsa != NULL)
  429. obsa = stackgap_alloc(&sg, sizeof(struct sigaction));
  430. else
  431. obsa = NULL;
  432. if (nlsa != NULL) {
  433. nbsa = stackgap_alloc(&sg, sizeof(struct sigaction));
  434. if ((error = copyin(nlsa, &tmplsa, sizeof(tmplsa))) != 0)
  435. return (error);
  436. linux_to_bsd_sigaction(&tmplsa, &tmpbsa);
  437. if ((error = copyout(&tmpbsa, nbsa, sizeof(tmpbsa))) != 0)
  438. return (error);
  439. }
  440. else
  441. nbsa = NULL;
  442. SCARG(&sa, signum) = linux_to_bsd_sig[SCARG(uap, signum)];
  443. SCARG(&sa, nsa) = nbsa;
  444. SCARG(&sa, osa) = obsa;
  445. /* Silently ignore unknown signals */
  446. if (SCARG(&sa, signum) == 0) {
  447. if (obsa != NULL) {
  448. obsa->sa_handler = SIG_IGN;
  449. sigemptyset(&obsa->sa_mask);
  450. obsa->sa_flags = 0;
  451. }
  452. }
  453. else {
  454. if ((error = sys_sigaction(p, &sa, retval)) != 0)
  455. return (error);
  456. }
  457. if (olsa != NULL) {
  458. if ((error = copyin(obsa, &tmpbsa, sizeof(tmpbsa))) != 0)
  459. return (error);
  460. bsd_to_linux_sigaction(&tmpbsa, &tmplsa);
  461. if ((error = copyout(&tmplsa, olsa, sizeof(tmplsa))) != 0)
  462. return (error);
  463. }
  464. return (0);
  465. }
  466. /*
  467. * The Linux signal() system call. I think that the signal() in the C
  468. * library actually calls sigaction, so I doubt this one is ever used.
  469. * But hey, it can't hurt having it here. The same restrictions as for
  470. * sigaction() apply.
  471. */
  472. int
  473. linux_sys_signal(p, v, retval)
  474. register struct proc *p;
  475. void *v;
  476. register_t *retval;
  477. {
  478. struct linux_sys_signal_args /* {
  479. syscallarg(int) sig;
  480. syscallarg(linux_handler_t) handler;
  481. } */ *uap = v;
  482. caddr_t sg;
  483. struct sys_sigaction_args sa_args;
  484. struct sigaction *osa, *nsa, tmpsa;
  485. int error;
  486. if (SCARG(uap, sig) < 0 || SCARG(uap, sig) >= LINUX__NSIG)
  487. return (EINVAL);
  488. sg = stackgap_init(p);
  489. nsa = stackgap_alloc(&sg, sizeof *nsa);
  490. osa = stackgap_alloc(&sg, sizeof *osa);
  491. tmpsa.sa_handler = SCARG(uap, handler);
  492. tmpsa.sa_mask = (sigset_t) 0;
  493. tmpsa.sa_flags = SA_RESETHAND | SA_NODEFER;
  494. if ((error = copyout(&tmpsa, nsa, sizeof tmpsa)))
  495. return (error);
  496. SCARG(&sa_args, signum) = linux_to_bsd_sig[SCARG(uap, sig)];
  497. SCARG(&sa_args, osa) = osa;
  498. SCARG(&sa_args, nsa) = nsa;
  499. /* Silently ignore unknown signals */
  500. if (SCARG(&sa_args, signum) != 0) {
  501. if ((error = sys_sigaction(p, &sa_args, retval)))
  502. return (error);
  503. }
  504. if ((error = copyin(osa, &tmpsa, sizeof *osa)))
  505. return (error);
  506. retval[0] = (register_t) tmpsa.sa_handler;
  507. return (0);
  508. }
  509. /*
  510. * This is just a copy of the svr4 compat one. I feel so creative now.
  511. */
  512. int
  513. linux_sys_sigprocmask(p, v, retval)
  514. register struct proc *p;
  515. void *v;
  516. register_t *retval;
  517. {
  518. struct linux_sys_sigprocmask_args /* {
  519. syscallarg(int) how;
  520. syscallarg(linux_old_sigset_t *) set;
  521. syscallarg(linux_old_sigset_t *) oset;
  522. } */ *uap = v;
  523. linux_old_sigset_t ss;
  524. sigset_t bs;
  525. int error = 0;
  526. *retval = 0;
  527. if (SCARG(uap, oset) != NULL) {
  528. /* Fix the return value first if needed */
  529. bsd_to_linux_old_sigset(&p->p_sigmask, &ss);
  530. if ((error = copyout(&ss, SCARG(uap, oset), sizeof(ss))) != 0)
  531. return (error);
  532. }
  533. if (SCARG(uap, set) == NULL)
  534. /* Just examine */
  535. return (0);
  536. if ((error = copyin(SCARG(uap, set), &ss, sizeof(ss))) != 0)
  537. return (error);
  538. linux_old_to_bsd_sigset(&ss, &bs);
  539. bs &= ~sigcantmask;
  540. switch (SCARG(uap, how)) {
  541. case LINUX_SIG_BLOCK:
  542. atomic_setbits_int(&p->p_sigmask, bs);
  543. break;
  544. case LINUX_SIG_UNBLOCK:
  545. atomic_clearbits_int(&p->p_sigmask, bs);
  546. break;
  547. case LINUX_SIG_SETMASK:
  548. p->p_sigmask = bs;
  549. break;
  550. default:
  551. error = EINVAL;
  552. break;
  553. }
  554. return (error);
  555. }
  556. int
  557. linux_sys_rt_sigprocmask(p, v, retval)
  558. register struct proc *p;
  559. void *v;
  560. register_t *retval;
  561. {
  562. struct linux_sys_rt_sigprocmask_args /* {
  563. syscallarg(int) how;
  564. syscallarg(const linux_sigset_t *) set;
  565. syscallarg(linux_sigset_t *) oset;
  566. syscallarg(size_t) sigsetsize;
  567. } */ *uap = v;
  568. linux_sigset_t ls;
  569. sigset_t bs;
  570. int error = 0;
  571. if (SCARG(uap, sigsetsize) != sizeof(linux_sigset_t))
  572. return (EINVAL);
  573. *retval = 0;
  574. if (SCARG(uap, oset) != NULL) {
  575. /* Fix the return value first if needed */
  576. bsd_to_linux_sigset(&p->p_sigmask, &ls);
  577. if ((error = copyout(&ls, SCARG(uap, oset), sizeof(ls))) != 0)
  578. return (error);
  579. }
  580. if (SCARG(uap, set) == NULL)
  581. /* Just examine */
  582. return (0);
  583. if ((error = copyin(SCARG(uap, set), &ls, sizeof(ls))) != 0)
  584. return (error);
  585. linux_to_bsd_sigset(&ls, &bs);
  586. bs &= ~sigcantmask;
  587. switch (SCARG(uap, how)) {
  588. case LINUX_SIG_BLOCK:
  589. atomic_setbits_int(&p->p_sigmask, bs);
  590. break;
  591. case LINUX_SIG_UNBLOCK:
  592. atomic_clearbits_int(&p->p_sigmask, bs);
  593. break;
  594. case LINUX_SIG_SETMASK:
  595. p->p_sigmask = bs;
  596. break;
  597. default:
  598. error = EINVAL;
  599. break;
  600. }
  601. return (error);
  602. }
  603. /*
  604. * The functions below really make no distinction between an int
  605. * and [linux_]sigset_t. This is ok for now, but it might break
  606. * sometime. Then again, sigset_t is trusted to be an int everywhere
  607. * else in the kernel too.
  608. */
  609. /* ARGSUSED */
  610. int
  611. linux_sys_siggetmask(p, v, retval)
  612. register struct proc *p;
  613. void *v;
  614. register_t *retval;
  615. {
  616. bsd_to_linux_old_sigset(&p->p_sigmask, (linux_old_sigset_t *)retval);
  617. return (0);
  618. }
  619. /*
  620. * The following three functions fiddle with a process' signal mask.
  621. * Convert the signal masks because of the different signal
  622. * values for Linux. The need for this is the reason why
  623. * they are here, and have not been mapped directly.
  624. */
  625. int
  626. linux_sys_sigsetmask(p, v, retval)
  627. register struct proc *p;
  628. void *v;
  629. register_t *retval;
  630. {
  631. struct linux_sys_sigsetmask_args /* {
  632. syscallarg(linux_old_sigset_t) mask;
  633. } */ *uap = v;
  634. linux_old_sigset_t mask;
  635. sigset_t bsdsig;
  636. bsd_to_linux_old_sigset(&p->p_sigmask, (linux_old_sigset_t *)retval);
  637. mask = SCARG(uap, mask);
  638. bsd_to_linux_old_sigset(&bsdsig, &mask);
  639. p->p_sigmask = bsdsig & ~sigcantmask;
  640. return (0);
  641. }
  642. int
  643. linux_sys_sigpending(p, v, retval)
  644. register struct proc *p;
  645. void *v;
  646. register_t *retval;
  647. {
  648. struct linux_sys_sigpending_args /* {
  649. syscallarg(linux_old_sigset_t *) mask;
  650. } */ *uap = v;
  651. sigset_t bs;
  652. linux_old_sigset_t ls;
  653. bs = p->p_siglist & p->p_sigmask;
  654. bsd_to_linux_old_sigset(&bs, &ls);
  655. return (copyout(&ls, SCARG(uap, mask), sizeof ls));
  656. }
  657. int
  658. linux_sys_rt_sigpending(p, v, retval)
  659. register struct proc *p;
  660. void *v;
  661. register_t *retval;
  662. {
  663. struct linux_sys_rt_sigpending_args /* {
  664. syscallarg(linux_sigset_t *) set;
  665. syscallarg(size_t) sigsetsize;
  666. } */ *uap = v;
  667. sigset_t bs;
  668. linux_sigset_t ls;
  669. if (SCARG(uap, sigsetsize) != sizeof(linux_sigset_t))
  670. return (EINVAL);
  671. bs = p->p_siglist & p->p_sigmask;
  672. bsd_to_linux_sigset(&bs, &ls);
  673. return (copyout(&ls, SCARG(uap, set), sizeof ls));
  674. }
  675. int
  676. linux_sys_sigsuspend(p, v, retval)
  677. register struct proc *p;
  678. void *v;
  679. register_t *retval;
  680. {
  681. struct linux_sys_sigsuspend_args /* {
  682. syscallarg(caddr_t) restart;
  683. syscallarg(int) oldmask;
  684. syscallarg(int) mask;
  685. } */ *uap = v;
  686. struct sys_sigsuspend_args sa;
  687. linux_old_sigset_t mask = SCARG(uap, mask);
  688. linux_old_to_bsd_sigset(&mask, &SCARG(&sa, mask));
  689. return (sys_sigsuspend(p, &sa, retval));
  690. }
  691. int
  692. linux_sys_rt_sigsuspend(p, v, retval)
  693. register struct proc *p;
  694. void *v;
  695. register_t *retval;
  696. {
  697. struct linux_sys_rt_sigsuspend_args /* {
  698. syscallarg(sigset_t *) unewset;
  699. syscallarg(size_t) sigsetsize;
  700. } */ *uap = v;
  701. struct sys_sigsuspend_args sa;
  702. linux_sigset_t mask;
  703. int error;
  704. if (SCARG(uap, sigsetsize) != sizeof(linux_sigset_t))
  705. return (EINVAL);
  706. error = copyin(SCARG(uap, unewset), &mask, sizeof mask);
  707. if (error)
  708. return (error);
  709. linux_to_bsd_sigset(&mask, &SCARG(&sa, mask));
  710. return (sys_sigsuspend(p, &sa, retval));
  711. }
  712. /*
  713. * Linux' sigaltstack structure is just of a different order than BSD's
  714. * so just shuffle the fields around and call our version.
  715. */
  716. int
  717. linux_sys_sigaltstack(p, v, retval)
  718. register struct proc *p;
  719. void *v;
  720. register_t *retval;
  721. {
  722. struct linux_sys_sigaltstack_args /* {
  723. syscallarg(const struct linux_sigaltstack *) nss;
  724. syscallarg(struct linux_sigaltstack *) oss;
  725. } */ *uap = v;
  726. struct linux_sigaltstack linux_ss;
  727. struct sigaltstack *bsd_nss, *bsd_oss;
  728. struct sys_sigaltstack_args sa;
  729. int error;
  730. caddr_t sg;
  731. sg = stackgap_init(p);
  732. if (SCARG(uap, nss) != NULL) {
  733. bsd_nss = stackgap_alloc(&sg, sizeof *bsd_nss);
  734. error = copyin(SCARG(uap, nss), &linux_ss, sizeof linux_ss);
  735. if (error)
  736. return (error);
  737. bsd_nss->ss_sp = linux_ss.ss_sp;
  738. bsd_nss->ss_size = linux_ss.ss_size;
  739. bsd_nss->ss_flags = (linux_ss.ss_flags & LINUX_SS_DISABLE) ?
  740. SS_DISABLE : 0;
  741. SCARG(&sa, nss) = bsd_nss;
  742. } else
  743. SCARG(&sa, nss) = NULL;
  744. if (SCARG(uap, oss) == NULL) {
  745. SCARG(&sa, oss) = NULL;
  746. return (sys_sigaltstack(p, &sa, retval));
  747. }
  748. SCARG(&sa, oss) = bsd_oss = stackgap_alloc(&sg, sizeof *bsd_oss);
  749. error = sys_sigaltstack(p, &sa, retval);
  750. if (error)
  751. return (error);
  752. linux_ss.ss_sp = bsd_oss->ss_sp;
  753. linux_ss.ss_size = bsd_oss->ss_size;
  754. linux_ss.ss_flags = 0;
  755. if (bsd_oss->ss_flags & SS_ONSTACK)
  756. linux_ss.ss_flags |= LINUX_SS_ONSTACK;
  757. if (bsd_oss->ss_flags & SS_DISABLE)
  758. linux_ss.ss_flags |= LINUX_SS_DISABLE;
  759. return (copyout(&linux_ss, SCARG(uap, oss), sizeof linux_ss));
  760. }
  761. /*
  762. * The deprecated pause(2), which is really just an instance
  763. * of sigsuspend(2).
  764. */
  765. int
  766. linux_sys_pause(p, v, retval)
  767. register struct proc *p;
  768. void *v;
  769. register_t *retval;
  770. {
  771. struct sys_sigsuspend_args bsa;
  772. SCARG(&bsa, mask) = p->p_sigmask;
  773. return (sys_sigsuspend(p, &bsa, retval));
  774. }
  775. /*
  776. * Once more: only a signal conversion is needed.
  777. */
  778. int
  779. linux_sys_kill(p, v, retval)
  780. register struct proc *p;
  781. void *v;
  782. register_t *retval;
  783. {
  784. struct linux_sys_kill_args /* {
  785. syscallarg(int) pid;
  786. syscallarg(int) signum;
  787. } */ *uap = v;
  788. struct sys_kill_args ka;
  789. SCARG(&ka, pid) = SCARG(uap, pid);
  790. if (SCARG(uap, signum) < 0 || SCARG(uap, signum) >= LINUX__NSIG)
  791. return (EINVAL);
  792. SCARG(&ka, signum) = linux_to_bsd_sig[SCARG(uap, signum)];
  793. return (sys_kill(p, &ka, retval));
  794. }
  795. int
  796. linux_sys_tgkill(struct proc *p, void *v, register_t *retval)
  797. {
  798. struct linux_sys_tgkill_args /* {
  799. syscallarg(int) tgid;
  800. syscallarg(int) tid;
  801. syscallarg(int) sig;
  802. }; */ *uap = v;
  803. int error;
  804. int sig;
  805. struct sys_kill_args ka;
  806. if (SCARG(uap, tgid) < 0 || SCARG(uap, tid) < 0)
  807. return (EINVAL);
  808. if ((error = linux_to_bsd_signal(SCARG(uap, sig), &sig)))
  809. return (error);
  810. /* XXX: Ignoring tgid, behaving like the obsolete linux_sys_tkill */
  811. SCARG(&ka, pid) = SCARG(uap, tid);
  812. SCARG(&ka, signum) = sig;
  813. return (sys_kill(p, &ka, retval));
  814. }