• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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