1
2 /*--------------------------------------------------------------------*/
3 /*--- Signal-related libc stuff. m_libcsignal.c ---*/
4 /*--------------------------------------------------------------------*/
5
6 /*
7 This file is part of Valgrind, a dynamic binary instrumentation
8 framework.
9
10 Copyright (C) 2000-2017 Julian Seward
11 jseward@acm.org
12
13 This program is free software; you can redistribute it and/or
14 modify it under the terms of the GNU General Public License as
15 published by the Free Software Foundation; either version 2 of the
16 License, or (at your option) any later version.
17
18 This program is distributed in the hope that it will be useful, but
19 WITHOUT ANY WARRANTY; without even the implied warranty of
20 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
21 General Public License for more details.
22
23 You should have received a copy of the GNU General Public License
24 along with this program; if not, write to the Free Software
25 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
26 02111-1307, USA.
27
28 The GNU General Public License is contained in the file COPYING.
29 */
30
31 #include "pub_core_basics.h"
32 #include "pub_core_debuglog.h"
33 #include "pub_core_vki.h"
34 #include "pub_core_vkiscnums.h"
35 #include "pub_core_libcbase.h"
36 #include "pub_core_libcassert.h"
37 #include "pub_core_syscall.h"
38 #include "pub_core_libcsignal.h" /* self */
39
40 #if !defined(VGO_solaris)
41 # define _VKI_MAXSIG (_VKI_NSIG - 1)
42 #endif
43 STATIC_ASSERT((_VKI_MAXSIG % _VKI_NSIG_BPW) != 0);
44
45 /* IMPORTANT: on Darwin it is essential to use the _nocancel versions
46 of syscalls rather than the vanilla version, if a _nocancel version
47 is available. See docs/internals/Darwin-notes.txt for the reason
48 why. */
49
50 /* sigemptyset, sigfullset, sigaddset and sigdelset return 0 on
51 success and -1 on error. */
52 /* In the sigset routines below, be aware that _VKI_NSIG_BPW can be
53 either 32 or 64, and hence the sig[] words can either be 32- or
54 64-bits. And which they are it doesn't necessarily follow from the
55 host word size. */
56
57 /* Functions VG_(isemptysigset) and VG_(isfullsigset) check only bits that
58 represent valid signals (i.e. signals <= _VKI_MAXSIG). The same applies
59 for the comparison in VG_(iseqsigset). This is important because when
60 a signal set is received from an operating system then bits which represent
61 signals > _VKI_MAXSIG can have unexpected values for Valgrind. This is
62 mainly specific to the Solaris kernel which clears these bits. */
63
VG_(sigfillset)64 Int VG_(sigfillset)( vki_sigset_t* set )
65 {
66 Int i;
67 if (set == NULL)
68 return -1;
69 for (i = 0; i < _VKI_NSIG_WORDS; i++)
70 set->sig[i] = ~0;
71 return 0;
72 }
73
VG_(sigemptyset)74 Int VG_(sigemptyset)( vki_sigset_t* set )
75 {
76 Int i;
77 if (set == NULL)
78 return -1;
79 for (i = 0; i < _VKI_NSIG_WORDS; i++)
80 set->sig[i] = 0;
81 return 0;
82 }
83
VG_(isemptysigset)84 Bool VG_(isemptysigset)( const vki_sigset_t* set )
85 {
86 Int i;
87 vg_assert(set != NULL);
88 for (i = 0; i < _VKI_NSIG_WORDS; i++) {
89 if (_VKI_NSIG_BPW * (i + 1) <= (_VKI_MAXSIG + 1)) {
90 /* Full word check. */
91 if (set->sig[i] != 0) return False;
92 }
93 else {
94 /* Partial word check. */
95 ULong mask = ((ULong)1UL << (_VKI_MAXSIG % _VKI_NSIG_BPW)) - 1;
96 if ((set->sig[i] & mask) != 0) return False;
97 break;
98 }
99 }
100 return True;
101 }
102
VG_(isfullsigset)103 Bool VG_(isfullsigset)( const vki_sigset_t* set )
104 {
105 Int i;
106 vg_assert(set != NULL);
107 for (i = 0; i < _VKI_NSIG_WORDS; i++) {
108 if (_VKI_NSIG_BPW * (i + 1) <= (_VKI_MAXSIG + 1)) {
109 /* Full word check. */
110 if (set->sig[i] != ~0) return False;
111 }
112 else {
113 /* Partial word check. */
114 ULong mask = ((ULong)1UL << (_VKI_MAXSIG % _VKI_NSIG_BPW)) - 1;
115 if ((set->sig[i] & mask) != mask) return False;
116 break;
117 }
118 }
119 return True;
120 }
121
VG_(iseqsigset)122 Bool VG_(iseqsigset)( const vki_sigset_t* set1, const vki_sigset_t* set2 )
123 {
124 Int i;
125 vg_assert(set1 != NULL && set2 != NULL);
126 for (i = 0; i < _VKI_NSIG_WORDS; i++) {
127 if (_VKI_NSIG_BPW * (i + 1) <= (_VKI_MAXSIG + 1)) {
128 /* Full word comparison. */
129 if (set1->sig[i] != set2->sig[i]) return False;
130 }
131 else {
132 /* Partial word comparison. */
133 ULong mask = ((ULong)1UL << (_VKI_MAXSIG % _VKI_NSIG_BPW)) - 1;
134 if ((set1->sig[i] & mask) != (set2->sig[i] & mask)) return False;
135 break;
136 }
137 }
138 return True;
139 }
140
141
VG_(sigaddset)142 Int VG_(sigaddset)( vki_sigset_t* set, Int signum )
143 {
144 if (set == NULL)
145 return -1;
146 if (signum < 1 || signum > _VKI_NSIG)
147 return -1;
148 signum--;
149 set->sig[signum / _VKI_NSIG_BPW] |= (1ULL << (signum % _VKI_NSIG_BPW));
150 return 0;
151 }
152
VG_(sigdelset)153 Int VG_(sigdelset)( vki_sigset_t* set, Int signum )
154 {
155 if (set == NULL)
156 return -1;
157 if (signum < 1 || signum > _VKI_NSIG)
158 return -1;
159 signum--;
160 set->sig[signum / _VKI_NSIG_BPW] &= ~(1ULL << (signum % _VKI_NSIG_BPW));
161 return 0;
162 }
163
VG_(sigismember)164 Int VG_(sigismember) ( const vki_sigset_t* set, Int signum )
165 {
166 if (set == NULL)
167 return 0;
168 if (signum < 1 || signum > _VKI_NSIG)
169 return 0;
170 signum--;
171 if (1 & ((set->sig[signum / _VKI_NSIG_BPW]) >> (signum % _VKI_NSIG_BPW)))
172 return 1;
173 else
174 return 0;
175 }
176
177 /* Add all signals in src to dst. */
VG_(sigaddset_from_set)178 void VG_(sigaddset_from_set)( vki_sigset_t* dst, const vki_sigset_t* src )
179 {
180 Int i;
181 vg_assert(dst != NULL && src != NULL);
182 for (i = 0; i < _VKI_NSIG_WORDS; i++)
183 dst->sig[i] |= src->sig[i];
184 }
185
186 /* Remove all signals in src from dst. */
VG_(sigdelset_from_set)187 void VG_(sigdelset_from_set)( vki_sigset_t* dst, const vki_sigset_t* src )
188 {
189 Int i;
190 vg_assert(dst != NULL && src != NULL);
191 for (i = 0; i < _VKI_NSIG_WORDS; i++)
192 dst->sig[i] &= ~(src->sig[i]);
193 }
194
195 /* dst = dst `intersect` src. */
VG_(sigintersectset)196 void VG_(sigintersectset)( vki_sigset_t* dst, const vki_sigset_t* src )
197 {
198 Int i;
199 vg_assert(dst != NULL && src != NULL);
200 for (i = 0; i < _VKI_NSIG_WORDS; i++)
201 dst->sig[i] &= src->sig[i];
202 }
203
204 /* dst = ~src */
VG_(sigcomplementset)205 void VG_(sigcomplementset)( vki_sigset_t* dst, const vki_sigset_t* src )
206 {
207 Int i;
208 vg_assert(dst != NULL && src != NULL);
209 for (i = 0; i < _VKI_NSIG_WORDS; i++)
210 dst->sig[i] = ~ src->sig[i];
211 }
212
213
214 /* The functions sigaction, sigprocmask, sigpending and sigsuspend
215 return 0 on success and -1 on error.
216 */
VG_(sigprocmask)217 Int VG_(sigprocmask)( Int how, const vki_sigset_t* set, vki_sigset_t* oldset)
218 {
219 # if defined(VGO_linux) || defined(VGO_solaris) || defined(VGO_dragonfly)
220 # if defined(__NR_rt_sigprocmask)
221 SysRes res = VG_(do_syscall4)(__NR_rt_sigprocmask,
222 how, (UWord)set, (UWord)oldset,
223 _VKI_NSIG_WORDS * sizeof(UWord));
224 # else
225 SysRes res = VG_(do_syscall3)(__NR_sigprocmask,
226 how, (UWord)set, (UWord)oldset);
227 # endif
228
229 # elif defined(VGO_darwin)
230 /* On Darwin, __NR_sigprocmask appears to affect the entire
231 process, not just this thread. Hence need to use
232 __NR___pthread_sigmask instead. */
233 SysRes res = VG_(do_syscall3)(__NR___pthread_sigmask,
234 how, (UWord)set, (UWord)oldset);
235 # else
236 # error "Unknown OS"
237 # endif
238 return sr_isError(res) ? -1 : 0;
239 }
240
241
242 #if defined(VGO_darwin)
243 /* A helper function for sigaction on Darwin. */
244 static
darwin_signal_demux(void * a1,UWord a2,UWord a3,void * a4,void * a5)245 void darwin_signal_demux(void* a1, UWord a2, UWord a3, void* a4, void* a5) {
246 VG_(debugLog)(2, "libcsignal",
247 "PRE demux sig, a2 = %lu, signo = %lu\n", a2, a3);
248 if (a2 == 1)
249 ((void(*)(int))a1) (a3);
250 else
251 ((void(*)(int,void*,void*))a1) (a3,a4,a5);
252 VG_(debugLog)(2, "libcsignal",
253 "POST demux sig, a2 = %lu, signo = %lu\n", a2, a3);
254 VG_(do_syscall2)(__NR_sigreturn, (UWord)a5, 0x1E);
255 /* NOTREACHED */
256 __asm__ __volatile__("ud2");
257 }
258 #endif
259
VG_(sigaction)260 Int VG_(sigaction) ( Int signum,
261 const vki_sigaction_toK_t* act,
262 vki_sigaction_fromK_t* oldact)
263 {
264 # if defined(VGO_linux)
265 /* Normal case: vki_sigaction_toK_t and vki_sigaction_fromK_t are
266 identical types. */
267 SysRes res = VG_(do_syscall4)(__NR_rt_sigaction,
268 signum, (UWord)act, (UWord)oldact,
269 _VKI_NSIG_WORDS * sizeof(UWord));
270 return sr_isError(res) ? -1 : 0;
271
272 # elif defined(VGO_darwin)
273 /* If we're passing a new action to the kernel, make a copy of the
274 new action, install our own sa_tramp field in it, and ignore
275 whatever we were provided with. This is OK because all the
276 sigaction requests come from m_signals, and are not directly
277 what the client program requested, so there is no chance that we
278 will inadvertently ignore the sa_tramp field requested by the
279 client. (In fact m_signals does ignore it when building signal
280 frames for the client, but that's a completely different
281 matter).
282
283 If we're receiving an old action from the kernel, be very
284 paranoid and make sure the kernel doesn't trash bits of memory
285 that we don't expect it to. */
286 SysRes res;
287
288 vki_sigaction_toK_t actCopy;
289 struct {
290 ULong before[2];
291 vki_sigaction_fromK_t oa;
292 ULong after[2];
293 }
294 oldactCopy;
295
296 vki_sigaction_toK_t* real_act;
297 vki_sigaction_fromK_t* real_oldact;
298
299 real_act = act ? &actCopy : NULL;
300 real_oldact = oldact ? &oldactCopy.oa : NULL;
301 VG_(memset)(&oldactCopy, 0x55, sizeof(oldactCopy));
302 if (real_act) {
303 *real_act = *act;
304 real_act->sa_tramp = (void*)&darwin_signal_demux;
305 }
306 res = VG_(do_syscall3)(__NR_sigaction,
307 signum, (UWord)real_act, (UWord)real_oldact);
308 if (real_oldact) {
309 vg_assert(oldactCopy.before[0] == 0x5555555555555555ULL);
310 vg_assert(oldactCopy.before[1] == 0x5555555555555555ULL);
311 vg_assert(oldactCopy.after[0] == 0x5555555555555555ULL);
312 vg_assert(oldactCopy.after[1] == 0x5555555555555555ULL);
313 *oldact = *real_oldact;
314 }
315 return sr_isError(res) ? -1 : 0;
316
317 # elif defined(VGO_solaris)
318 /* vki_sigaction_toK_t and vki_sigaction_fromK_t are identical types. */
319 SysRes res = VG_(do_syscall3)(__NR_sigaction,
320 signum, (UWord)act, (UWord)oldact);
321 return sr_isError(res) ? -1 : 0;
322
323 # elif defined(VGO_dragonfly)
324 SysRes res = VG_(do_syscall3)(__NR_sigaction,
325 signum, (UWord)act, (UWord)oldact);
326 return sr_isError(res) ? -1 : 0;
327
328
329 # else
330 # error "Unsupported OS"
331 # endif
332 }
333
334
335 /* See explanation in pub_core_libcsignal.h. */
336 void
VG_(convert_sigaction_fromK_to_toK)337 VG_(convert_sigaction_fromK_to_toK)( const vki_sigaction_fromK_t* fromK,
338 /*OUT*/vki_sigaction_toK_t* toK )
339 {
340 # if defined(VGO_linux) || defined(VGO_solaris) || defined(VGO_dragonfly)
341 *toK = *fromK;
342 # elif defined(VGO_darwin)
343 toK->ksa_handler = fromK->ksa_handler;
344 toK->sa_tramp = NULL; /* the cause of all the difficulty */
345 toK->sa_mask = fromK->sa_mask;
346 toK->sa_flags = fromK->sa_flags;
347 # else
348 # error "Unsupported OS"
349 # endif
350 }
351
352
VG_(kill)353 Int VG_(kill)( Int pid, Int signo )
354 {
355 # if defined(VGO_linux) || defined(VGO_solaris)
356 SysRes res = VG_(do_syscall2)(__NR_kill, pid, signo);
357 # elif defined(VGO_darwin) || defined(VGO_dragonfly)
358 SysRes res = VG_(do_syscall3)(__NR_kill,
359 pid, signo, 1/*posix-compliant*/);
360 # else
361 # error "Unsupported OS"
362 # endif
363 return sr_isError(res) ? -1 : 0;
364 }
365
VG_(tkill)366 Int VG_(tkill)( Int lwpid, Int signo )
367 {
368 # if defined(__NR_tkill)
369 SysRes res = VG_(mk_SysRes_Error)(VKI_ENOSYS);
370 res = VG_(do_syscall2)(__NR_tkill, lwpid, signo);
371 if (sr_isError(res) && sr_Err(res) == VKI_ENOSYS)
372 res = VG_(do_syscall2)(__NR_kill, lwpid, signo);
373 return sr_isError(res) ? -1 : 0;
374
375 # elif defined(VGO_darwin)
376 // Note that the __pthread_kill syscall takes a Mach thread, not a pthread.
377 SysRes res;
378 res = VG_(do_syscall2)(__NR___pthread_kill, lwpid, signo);
379 return sr_isError(res) ? -1 : 0;
380
381 # elif defined(VGO_solaris)
382 SysRes res;
383 # if defined(SOLARIS_LWP_SIGQUEUE_SYSCALL)
384 # if defined(SOLARIS_LWP_SIGQUEUE_SYSCALL_TAKES_PID)
385 res = VG_(do_syscall6)(__NR_lwp_sigqueue, 0, lwpid, signo,
386 0, VKI_SI_LWP, 0);
387 # else
388 res = VG_(do_syscall5)(__NR_lwp_sigqueue, lwpid, signo,
389 0, VKI_SI_LWP, 0);
390 # endif
391 # else
392 res = VG_(do_syscall2)(__NR_lwp_kill, lwpid, signo);
393 # endif
394 return sr_isError(res) ? -1 : 0;
395
396
397 # elif defined(VGO_dragonfly)
398 SysRes res;
399 res = VG_(do_syscall3)(__NR_lwp_kill, -1, lwpid, signo);
400 return sr_isError(res) ? -1 : 0;
401
402 # else
403 # error "Unsupported plat"
404 # endif
405 }
406
407 /* ---------------------- sigtimedwait_zero ----------------------- */
408
409 /* A cut-down version of POSIX sigtimedwait: poll for pending signals
410 mentioned in the sigset_t, and if any are present, select one
411 arbitrarily, return its number (which must be > 0), and put
412 auxiliary info about it in the siginfo_t, and make it
413 not-pending-any-more. If none are pending, return zero. The _zero
414 refers to the fact that there is zero timeout, so if no signals are
415 pending it returns immediately. Perhaps a better name would be
416 'sigpoll'. Returns -1 on error, 0 if no signals pending, and n > 0
417 if signal n was selected.
418
419 The Linux implementation is trivial: do the corresponding syscall.
420
421 The Darwin implementation is horrible and probably broken in a dozen
422 obscure ways. I suspect it's only thread-safe because V forces
423 single-threadedness. */
424
425 /* ---------- sigtimedwait_zero: Linux ----------- */
426
427 #if defined(VGO_linux)
VG_(sigtimedwait_zero)428 Int VG_(sigtimedwait_zero)( const vki_sigset_t *set,
429 vki_siginfo_t *info )
430 {
431 static const struct vki_timespec zero = { 0, 0 };
432 SysRes res = VG_(do_syscall4)(__NR_rt_sigtimedwait, (UWord)set, (UWord)info,
433 (UWord)&zero, sizeof(*set));
434 return sr_isError(res) ? -1 : sr_Res(res);
435 }
436
437 /* ---------- sigtimedwait_zero: Darwin ----------- */
438
439 #elif defined(VGO_darwin)
440
441 //static void show_set ( HChar* str, const vki_sigset_t* set ) {
442 // Int i;
443 // VG_(printf)("%s { ", str);
444 // for (i = 1; i <= _VKI_NSIG; i++) {
445 // if (VG_(sigismember)(set, i))
446 // VG_(printf)("%u ", i);
447 // }
448 // VG_(printf)("}\n");
449 //}
450
451 /* The general idea is:
452 - use sigpending to find out which signals are pending
453 - choose one
454 - temporarily set its handler to sigtimedwait_zero_handler
455 - use sigsuspend atomically unblock it and wait for the signal.
456 Upon return, sigsuspend restores the signal mask to what it
457 was to start with.
458 - Restore the handler for the signal to whatever it was before.
459 */
460
461 /* A signal handler which does nothing (it doesn't need to). It does
462 however check that it's not handing a sync signal for which
463 returning is meaningless. */
sigtimedwait_zero_handler(Int sig)464 static void sigtimedwait_zero_handler ( Int sig )
465 {
466 /* XXX this is wrong -- get rid of these. We could
467 get _any_ signal here */
468 vg_assert(sig != VKI_SIGILL);
469 vg_assert(sig != VKI_SIGSEGV);
470 vg_assert(sig != VKI_SIGBUS);
471 vg_assert(sig != VKI_SIGTRAP);
472 /* do nothing */
473 }
474
VG_(sigtimedwait_zero)475 Int VG_(sigtimedwait_zero)( const vki_sigset_t *set,
476 vki_siginfo_t *info )
477 {
478 const Bool debug = False;
479 Int i, ir;
480 SysRes sr;
481 vki_sigset_t pending, blocked, allbutone;
482 vki_sigaction_toK_t sa, saved_sa2;
483 vki_sigaction_fromK_t saved_sa;
484
485 //show_set("STWZ: looking for", set);
486
487 /* Find out what's pending: Darwin sigpending */
488 sr = VG_(do_syscall1)(__NR_sigpending, (UWord)&pending);
489 vg_assert(!sr_isError(sr));
490
491 /* don't try for signals not in 'set' */
492 /* pending = pending `intersect` set */
493 VG_(sigintersectset)(&pending, (const vki_sigset_t*)set);
494
495 /* don't try for signals not blocked at the moment */
496 ir = VG_(sigprocmask)(VKI_SIG_SETMASK, NULL, &blocked);
497 vg_assert(ir == 0);
498
499 /* pending = pending `intersect` blocked */
500 VG_(sigintersectset)(&pending, &blocked);
501
502 /* decide which signal we're going to snarf */
503 for (i = 1; i < _VKI_NSIG; i++)
504 if (VG_(sigismember)(&pending,i))
505 break;
506
507 if (i == _VKI_NSIG)
508 return 0;
509
510 if (debug)
511 VG_(debugLog)(0, "libcsignal",
512 "sigtimedwait_zero: snarfing signal %d\n", i );
513
514 /* fetch signal i.
515 pre: i is blocked and pending
516 pre: we are the only thread running
517 */
518 /* Set up alternative signal handler */
519 VG_(sigfillset)(&sa.sa_mask);
520 sa.ksa_handler = &sigtimedwait_zero_handler;
521 sa.sa_flags = 0;
522 ir = VG_(sigaction)(i, &sa, &saved_sa);
523 vg_assert(ir == 0);
524
525 /* Switch signal masks and wait for the signal. This should happen
526 immediately, since we've already established it is pending and
527 blocked. */
528 VG_(sigfillset)(&allbutone);
529 VG_(sigdelset)(&allbutone, i);
530 /* Note: pass the sig mask by value here, not reference (!) */
531 vg_assert(_VKI_NSIG_WORDS == 1);
532 sr = VG_(do_syscall3)(__NR_sigsuspend_nocancel,
533 (UWord)allbutone.sig[0], 0,0);
534 if (debug)
535 VG_(debugLog)(0, "libcsignal",
536 "sigtimedwait_zero: sigsuspend got "
537 "res: %s %#lx\n",
538 sr_isError(sr) ? "FAIL" : "SUCCESS",
539 sr_isError(sr) ? sr_Err(sr) : sr_Res(sr));
540 vg_assert(sr_isError(sr));
541 vg_assert(sr_Err(sr) == VKI_EINTR);
542
543 /* Restore signal's handler to whatever it was before */
544 VG_(convert_sigaction_fromK_to_toK)( &saved_sa, &saved_sa2 );
545 ir = VG_(sigaction)(i, &saved_sa2, NULL);
546 vg_assert(ir == 0);
547
548 /* This is bogus - we could get more info from the sighandler. */
549 VG_(memset)( info, 0, sizeof(*info) );
550 info->si_signo = i;
551
552 return i;
553 }
554
555 #elif defined(VGO_solaris)
VG_(sigtimedwait_zero)556 Int VG_(sigtimedwait_zero)( const vki_sigset_t *set, vki_siginfo_t *info )
557 {
558 /* Trivial as on Linux. */
559 static const struct vki_timespec zero = { 0, 0 };
560 SysRes res = VG_(do_syscall3)(__NR_sigtimedwait, (UWord)set, (UWord)info,
561 (UWord)&zero);
562 return sr_isError(res) ? -1 : sr_Res(res);
563 }
564
565 #elif defined(VGO_dragonfly)
566
VG_(sigtimedwait_zero)567 Int VG_(sigtimedwait_zero)( const vki_sigset_t *set,
568 vki_siginfo_t *info )
569 {
570 static const struct vki_timespec zero = { 0, 0 };
571
572 SysRes res = VG_(do_syscall3)(__NR_sigtimedwait, (UWord)set, (UWord)info,
573 (UWord)&zero);
574
575 return sr_isError(res) ? -1 : sr_Res(res);
576 }
577
578 #else
579 # error "Unknown OS"
580 #endif
581
582 /*--------------------------------------------------------------------*/
583 /*--- end ---*/
584 /*--------------------------------------------------------------------*/
585