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