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