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 = (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 = (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 = (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)
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 # else
324 # error "Unsupported OS"
325 # endif
326 }
327
328
329 /* See explanation in pub_core_libcsignal.h. */
330 void
VG_(convert_sigaction_fromK_to_toK)331 VG_(convert_sigaction_fromK_to_toK)( const vki_sigaction_fromK_t* fromK,
332 /*OUT*/vki_sigaction_toK_t* toK )
333 {
334 # if defined(VGO_linux) || defined(VGO_solaris)
335 *toK = *fromK;
336 # elif defined(VGO_darwin)
337 toK->ksa_handler = fromK->ksa_handler;
338 toK->sa_tramp = NULL; /* the cause of all the difficulty */
339 toK->sa_mask = fromK->sa_mask;
340 toK->sa_flags = fromK->sa_flags;
341 # else
342 # error "Unsupported OS"
343 # endif
344 }
345
346
VG_(kill)347 Int VG_(kill)( Int pid, Int signo )
348 {
349 # if defined(VGO_linux) || defined(VGO_solaris)
350 SysRes res = VG_(do_syscall2)(__NR_kill, pid, signo);
351 # elif defined(VGO_darwin)
352 SysRes res = VG_(do_syscall3)(__NR_kill,
353 pid, signo, 1/*posix-compliant*/);
354 # else
355 # error "Unsupported OS"
356 # endif
357 return sr_isError(res) ? -1 : 0;
358 }
359
VG_(tkill)360 Int VG_(tkill)( Int lwpid, Int signo )
361 {
362 # if defined(__NR_tkill)
363 SysRes res = VG_(mk_SysRes_Error)(VKI_ENOSYS);
364 res = VG_(do_syscall2)(__NR_tkill, lwpid, signo);
365 if (sr_isError(res) && sr_Err(res) == VKI_ENOSYS)
366 res = VG_(do_syscall2)(__NR_kill, lwpid, signo);
367 return sr_isError(res) ? -1 : 0;
368
369 # elif defined(VGO_darwin)
370 // Note that the __pthread_kill syscall takes a Mach thread, not a pthread.
371 SysRes res;
372 res = VG_(do_syscall2)(__NR___pthread_kill, lwpid, signo);
373 return sr_isError(res) ? -1 : 0;
374
375 # elif defined(VGO_solaris)
376 SysRes res;
377 # if defined(SOLARIS_LWP_SIGQUEUE_SYSCALL)
378 # if defined(SOLARIS_LWP_SIGQUEUE_SYSCALL_TAKES_PID)
379 res = VG_(do_syscall6)(__NR_lwp_sigqueue, 0, lwpid, signo,
380 0, VKI_SI_LWP, 0);
381 # else
382 res = VG_(do_syscall5)(__NR_lwp_sigqueue, lwpid, signo,
383 0, VKI_SI_LWP, 0);
384 # endif
385 # else
386 res = VG_(do_syscall2)(__NR_lwp_kill, lwpid, signo);
387 # endif
388 return sr_isError(res) ? -1 : 0;
389
390 # else
391 # error "Unsupported plat"
392 # endif
393 }
394
395 /* ---------------------- sigtimedwait_zero ----------------------- */
396
397 /* A cut-down version of POSIX sigtimedwait: poll for pending signals
398 mentioned in the sigset_t, and if any are present, select one
399 arbitrarily, return its number (which must be > 0), and put
400 auxiliary info about it in the siginfo_t, and make it
401 not-pending-any-more. If none are pending, return zero. The _zero
402 refers to the fact that there is zero timeout, so if no signals are
403 pending it returns immediately. Perhaps a better name would be
404 'sigpoll'. Returns -1 on error, 0 if no signals pending, and n > 0
405 if signal n was selected.
406
407 The Linux implementation is trivial: do the corresponding syscall.
408
409 The Darwin implementation is horrible and probably broken in a dozen
410 obscure ways. I suspect it's only thread-safe because V forces
411 single-threadedness. */
412
413 /* ---------- sigtimedwait_zero: Linux ----------- */
414
415 #if defined(VGO_linux)
VG_(sigtimedwait_zero)416 Int VG_(sigtimedwait_zero)( const vki_sigset_t *set,
417 vki_siginfo_t *info )
418 {
419 static const struct vki_timespec zero = { 0, 0 };
420 SysRes res = VG_(do_syscall4)(__NR_rt_sigtimedwait, (UWord)set, (UWord)info,
421 (UWord)&zero, sizeof(*set));
422 return sr_isError(res) ? -1 : sr_Res(res);
423 }
424
425 /* ---------- sigtimedwait_zero: Darwin ----------- */
426
427 #elif defined(VGO_darwin)
428
429 //static void show_set ( HChar* str, const vki_sigset_t* set ) {
430 // Int i;
431 // VG_(printf)("%s { ", str);
432 // for (i = 1; i <= _VKI_NSIG; i++) {
433 // if (VG_(sigismember)(set, i))
434 // VG_(printf)("%u ", i);
435 // }
436 // VG_(printf)("}\n");
437 //}
438
439 /* The general idea is:
440 - use sigpending to find out which signals are pending
441 - choose one
442 - temporarily set its handler to sigtimedwait_zero_handler
443 - use sigsuspend atomically unblock it and wait for the signal.
444 Upon return, sigsuspend restores the signal mask to what it
445 was to start with.
446 - Restore the handler for the signal to whatever it was before.
447 */
448
449 /* A signal handler which does nothing (it doesn't need to). It does
450 however check that it's not handing a sync signal for which
451 returning is meaningless. */
sigtimedwait_zero_handler(Int sig)452 static void sigtimedwait_zero_handler ( Int sig )
453 {
454 /* XXX this is wrong -- get rid of these. We could
455 get _any_ signal here */
456 vg_assert(sig != VKI_SIGILL);
457 vg_assert(sig != VKI_SIGSEGV);
458 vg_assert(sig != VKI_SIGBUS);
459 vg_assert(sig != VKI_SIGTRAP);
460 /* do nothing */
461 }
462
VG_(sigtimedwait_zero)463 Int VG_(sigtimedwait_zero)( const vki_sigset_t *set,
464 vki_siginfo_t *info )
465 {
466 const Bool debug = False;
467 Int i, ir;
468 SysRes sr;
469 vki_sigset_t pending, blocked, allbutone;
470 vki_sigaction_toK_t sa, saved_sa2;
471 vki_sigaction_fromK_t saved_sa;
472
473 //show_set("STWZ: looking for", set);
474
475 /* Find out what's pending: Darwin sigpending */
476 sr = VG_(do_syscall1)(__NR_sigpending, (UWord)&pending);
477 vg_assert(!sr_isError(sr));
478
479 /* don't try for signals not in 'set' */
480 /* pending = pending `intersect` set */
481 VG_(sigintersectset)(&pending, (const vki_sigset_t*)set);
482
483 /* don't try for signals not blocked at the moment */
484 ir = VG_(sigprocmask)(VKI_SIG_SETMASK, NULL, &blocked);
485 vg_assert(ir == 0);
486
487 /* pending = pending `intersect` blocked */
488 VG_(sigintersectset)(&pending, &blocked);
489
490 /* decide which signal we're going to snarf */
491 for (i = 1; i < _VKI_NSIG; i++)
492 if (VG_(sigismember)(&pending,i))
493 break;
494
495 if (i == _VKI_NSIG)
496 return 0;
497
498 if (debug)
499 VG_(debugLog)(0, "libcsignal",
500 "sigtimedwait_zero: snarfing signal %d\n", i );
501
502 /* fetch signal i.
503 pre: i is blocked and pending
504 pre: we are the only thread running
505 */
506 /* Set up alternative signal handler */
507 VG_(sigfillset)(&sa.sa_mask);
508 sa.ksa_handler = &sigtimedwait_zero_handler;
509 sa.sa_flags = 0;
510 ir = VG_(sigaction)(i, &sa, &saved_sa);
511 vg_assert(ir == 0);
512
513 /* Switch signal masks and wait for the signal. This should happen
514 immediately, since we've already established it is pending and
515 blocked. */
516 VG_(sigfillset)(&allbutone);
517 VG_(sigdelset)(&allbutone, i);
518 /* Note: pass the sig mask by value here, not reference (!) */
519 vg_assert(_VKI_NSIG_WORDS == 1);
520 sr = VG_(do_syscall3)(__NR_sigsuspend_nocancel,
521 (UWord)allbutone.sig[0], 0,0);
522 if (debug)
523 VG_(debugLog)(0, "libcsignal",
524 "sigtimedwait_zero: sigsuspend got "
525 "res: %s %#lx\n",
526 sr_isError(sr) ? "FAIL" : "SUCCESS",
527 sr_isError(sr) ? sr_Err(sr) : sr_Res(sr));
528 vg_assert(sr_isError(sr));
529 vg_assert(sr_Err(sr) == VKI_EINTR);
530
531 /* Restore signal's handler to whatever it was before */
532 VG_(convert_sigaction_fromK_to_toK)( &saved_sa, &saved_sa2 );
533 ir = VG_(sigaction)(i, &saved_sa2, NULL);
534 vg_assert(ir == 0);
535
536 /* This is bogus - we could get more info from the sighandler. */
537 VG_(memset)( info, 0, sizeof(*info) );
538 info->si_signo = i;
539
540 return i;
541 }
542
543 #elif defined(VGO_solaris)
VG_(sigtimedwait_zero)544 Int VG_(sigtimedwait_zero)( const vki_sigset_t *set, vki_siginfo_t *info )
545 {
546 /* Trivial as on Linux. */
547 static const struct vki_timespec zero = { 0, 0 };
548 SysRes res = VG_(do_syscall3)(__NR_sigtimedwait, (UWord)set, (UWord)info,
549 (UWord)&zero);
550 return sr_isError(res) ? -1 : sr_Res(res);
551 }
552
553 #else
554 # error "Unknown OS"
555 #endif
556
557 /*--------------------------------------------------------------------*/
558 /*--- end ---*/
559 /*--------------------------------------------------------------------*/
560