Coverage Report

Created: 2018-09-25 14:53

/src/mozilla-central/security/sandbox/linux/SandboxHooks.cpp
Line
Count
Source (jump to first uncovered line)
1
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
3
/* This Source Code Form is subject to the terms of the Mozilla Public
4
 * License, v. 2.0. If a copy of the MPL was not distributed with this file,
5
 * You can obtain one at http://mozilla.org/MPL/2.0/. */
6
7
#include "mozilla/Atomics.h"
8
#include "mozilla/Types.h"
9
10
#include <dlfcn.h>
11
#include <signal.h>
12
#include <errno.h>
13
#include <signal.h>
14
#include <stdio.h>
15
#include <stdlib.h>
16
#include <sys/inotify.h>
17
#ifdef MOZ_X11
18
#include <X11/Xlib.h>
19
#endif
20
21
// Signal number used to enable seccomp on each thread.
22
extern mozilla::Atomic<int> gSeccompTsyncBroadcastSignum;
23
24
static bool
25
SigSetNeedsFixup(const sigset_t* aSet)
26
0
{
27
0
  int tsyncSignum = gSeccompTsyncBroadcastSignum;
28
0
29
0
  return aSet != nullptr &&
30
0
         (sigismember(aSet, SIGSYS) ||
31
0
          (tsyncSignum != 0 &&
32
0
           sigismember(aSet, tsyncSignum)));
33
0
}
34
35
static void
36
SigSetFixup(sigset_t* aSet)
37
0
{
38
0
  int tsyncSignum = gSeccompTsyncBroadcastSignum;
39
0
  int rv = sigdelset(aSet, SIGSYS);
40
0
  MOZ_RELEASE_ASSERT(rv == 0);
41
0
  if (tsyncSignum != 0) {
42
0
    rv = sigdelset(aSet, tsyncSignum);
43
0
    MOZ_RELEASE_ASSERT(rv == 0);
44
0
  }
45
0
}
46
47
// This file defines a hook for sigprocmask() and pthread_sigmask().
48
// Bug 1176099: some threads block SIGSYS signal which breaks our seccomp-bpf
49
// sandbox. To avoid this, we intercept the call and remove SIGSYS.
50
//
51
// ENOSYS indicates an error within the hook function itself.
52
static int
53
HandleSigset(int (*aRealFunc)(int, const sigset_t*, sigset_t*),
54
             int aHow, const sigset_t* aSet,
55
             sigset_t* aOldSet, bool aUseErrno)
56
0
{
57
0
  if (!aRealFunc) {
58
0
    if (aUseErrno) {
59
0
      errno = ENOSYS;
60
0
      return -1;
61
0
    }
62
0
63
0
    return ENOSYS;
64
0
  }
65
0
66
0
  // Avoid unnecessary work
67
0
  if (aHow == SIG_UNBLOCK || !SigSetNeedsFixup(aSet)) {
68
0
    return aRealFunc(aHow, aSet, aOldSet);
69
0
  }
70
0
71
0
  sigset_t newSet = *aSet;
72
0
  SigSetFixup(&newSet);
73
0
  return aRealFunc(aHow, &newSet, aOldSet);
74
0
}
75
76
extern "C" MOZ_EXPORT int
77
sigprocmask(int how, const sigset_t* set, sigset_t* oldset)
78
0
{
79
0
  static auto sRealFunc = (int (*)(int, const sigset_t*, sigset_t*))
80
0
    dlsym(RTLD_NEXT, "sigprocmask");
81
0
82
0
  return HandleSigset(sRealFunc, how, set, oldset, true);
83
0
}
84
85
extern "C" MOZ_EXPORT int
86
pthread_sigmask(int how, const sigset_t* set, sigset_t* oldset)
87
0
{
88
0
  static auto sRealFunc = (int (*)(int, const sigset_t*, sigset_t*))
89
0
    dlsym(RTLD_NEXT, "pthread_sigmask");
90
0
91
0
  return HandleSigset(sRealFunc, how, set, oldset, false);
92
0
}
93
94
extern "C" MOZ_EXPORT int
95
sigaction(int signum, const struct sigaction* act, struct sigaction* oldact)
96
0
{
97
0
  static auto sRealFunc =
98
0
    (int (*)(int, const struct sigaction*, struct sigaction*))
99
0
    dlsym(RTLD_NEXT, "sigaction");
100
0
101
0
  if (!sRealFunc) {
102
0
    errno = ENOSYS;
103
0
    return -1;
104
0
  }
105
0
106
0
  if (act == nullptr || !SigSetNeedsFixup(&act->sa_mask)) {
107
0
    return sRealFunc(signum, act, oldact);
108
0
  }
109
0
110
0
  struct sigaction newact = *act;
111
0
  SigSetFixup(&newact.sa_mask);
112
0
  return sRealFunc(signum, &newact, oldact);
113
0
}
114
115
extern "C" MOZ_EXPORT int
116
inotify_init(void)
117
0
{
118
0
  return inotify_init1(0);
119
0
}
120
121
extern "C" MOZ_EXPORT int
122
inotify_init1(int flags)
123
0
{
124
0
  errno = ENOSYS;
125
0
  return -1;
126
0
}