Skip to content

Commit f07cf01

Browse files
authored
Merge branch 'main' into tor-test
2 parents e40070c + 6b78e41 commit f07cf01

31 files changed

Lines changed: 461 additions & 129 deletions

.github/pr_labeler_conf.yml

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
"Component: Build":
2+
- **/CMakeLists.txt
3+
- **/Cargo.toml
4+
- **/Cargo.lock
5+
6+
"Component: Documentation":
7+
- **/*.md
8+
- docs/**/*
9+
10+
"Component: Libraries":
11+
- src/shim/**/*
12+
- src/support/**/*
13+
14+
"Component: Main":
15+
- src/main/**/*
16+
17+
"Component: Testing":
18+
- src/test/**/*
19+
- .github/**/*.yml
20+
- !.github/pr_labeler_conf.yml
21+
- !.github/workflows/pr_metadata.yml
22+
23+
"Component: Tools":
24+
- src/tools/**/*

.github/workflows/pr_metadata.yml

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
# Auto-update metadata on pull requests
2+
# https://docs.github.com/en/actions/reference/workflow-syntax-for-github-actions
3+
name: "Pull Request Metadata"
4+
5+
on:
6+
pull_request_target:
7+
types: [opened]
8+
9+
permissions:
10+
pull-requests: write
11+
12+
jobs:
13+
Triage:
14+
runs-on: ubuntu-latest
15+
steps:
16+
- name: Assign Author
17+
# Add the author as an assignee of the PR
18+
# https://github.com/marketplace/actions/auto-author-assign
19+
# before updating the version of this untrusted action, check the code manually
20+
uses: toshimaru/auto-author-assign@084de2241839f0a3433adfd18d2906e8e786380e
21+
with:
22+
repo-token: "${{ secrets.GITHUB_TOKEN }}"
23+
- name: Apply Labels
24+
# Add labels based on paths modified in PR
25+
# https://github.com/actions/labeler
26+
uses: actions/labeler@v3
27+
with:
28+
repo-token: "${{ secrets.GITHUB_TOKEN }}"
29+
configuration-path: .github/pr_labeler_conf.yml
30+
sync-labels: true

ci/container_scripts/install_deps.sh

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -82,8 +82,6 @@ case "$CONTAINER" in
8282
--slave /usr/local/bin/cpack cpack /usr/bin/cpack3 \
8383
--slave /usr/local/bin/ccmake ccmake /usr/bin/ccmake3 \
8484
--family cmake
85-
# Install interposable libc to work around https://github.com/shadow/shadow/issues/892
86-
(mkdir -p /opt && cd /opt && curl -sSfL https://github.com/sporksmith/glibc/releases/download/interpose-centos7-v0.0.1/libc-interpose-centos7-v0.0.1.tar.xz | tar -xJvf -)
8785
;;
8886
centos:8)
8987
dnf remove -y procps-ng procps-ng-devel

ci/container_scripts/test.sh

Lines changed: 3 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -15,16 +15,9 @@ else
1515
fi
1616

1717
EXTRA_FLAGS=""
18-
if [ "$CONTAINER" = "centos:7" ]
19-
then
20-
# On centos:7 we enable extra tests that currently require a patched libc.
21-
# https://github.com/shadow/shadow/issues/892
22-
CONFIG="ilibc"
23-
else
24-
# On all other platforms, we run extra tests that we don't generally require (for
25-
# example tests that require additional dependencies).
26-
CONFIG="extra"
27-
fi
18+
# Run extra tests that we don't generally require (for
19+
# example tests that require additional dependencies).
20+
CONFIG="extra"
2821

2922
# Array of flags to be passed on to setup script
3023
FLAGS=()

docs/shadow_config_spec.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,7 @@ hosts:
6161
- [`experimental.use_object_counters`](#experimentaluse_object_counters)
6262
- [`experimental.use_sched_fifo`](#experimentaluse_sched_fifo)
6363
- [`experimental.use_shim_syscall_handler`](#experimentaluse_shim_syscall_handler)
64+
- [`experimental.use_seccomp`](#experimentaluse_seccomp)
6465
- [`experimental.use_syscall_counters`](#experimentaluse_syscall_counters)
6566
- [`experimental.worker_threads`](#experimentalworker_threads)
6667
- [`host_defaults`](#host_defaults)
@@ -348,6 +349,13 @@ Type: Bool
348349
Use shim-side syscall handler to force hot-path syscalls to be handled via an
349350
inter-process syscall with Shadow.
350351

352+
#### `experimental.use_seccomp`
353+
354+
Default: true iff experimental.interpose_method == preload.
355+
Type: Bool
356+
357+
Use seccomp to trap syscalls.
358+
351359
#### `experimental.use_syscall_counters`
352360

353361
Default: false

src/main/bindings/c/bindings.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -180,6 +180,8 @@ bool config_getUseOnWaitpidWorkarounds(const struct ConfigOptions *config);
180180

181181
bool config_getUseExplicitBlockMessage(const struct ConfigOptions *config);
182182

183+
bool config_getUseSeccomp(const struct ConfigOptions *config);
184+
183185
bool config_getUseSyscallCounters(const struct ConfigOptions *config);
184186

185187
bool config_getUseObjectCounters(const struct ConfigOptions *config);

src/main/core/support/configuration.rs

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -244,6 +244,11 @@ pub struct ExperimentalOptions {
244244
#[clap(about = EXP_HELP.get("use_explicit_block_message").unwrap())]
245245
use_explicit_block_message: Option<bool>,
246246

247+
/// Use seccomp to trap syscalls. Default is true for preload mode, false otherwise.
248+
#[clap(long, value_name = "bool")]
249+
#[clap(about = EXP_HELP.get("use_seccomp").unwrap())]
250+
use_seccomp: Option<bool>,
251+
247252
/// Count the number of occurrences for individual syscalls
248253
#[clap(long, value_name = "bool")]
249254
#[clap(about = EXP_HELP.get("use_syscall_counters").unwrap())]
@@ -348,6 +353,7 @@ impl Default for ExperimentalOptions {
348353
use_sched_fifo: Some(false),
349354
use_o_n_waitpid_workarounds: Some(false),
350355
use_explicit_block_message: Some(false),
356+
use_seccomp: None,
351357
use_syscall_counters: Some(false),
352358
use_object_counters: Some(true),
353359
preload_spin_max: Some(0),
@@ -1121,6 +1127,16 @@ mod export {
11211127
config.experimental.use_explicit_block_message.unwrap()
11221128
}
11231129

1130+
#[no_mangle]
1131+
pub extern "C" fn config_getUseSeccomp(config: *const ConfigOptions) -> bool {
1132+
assert!(!config.is_null());
1133+
let config = unsafe { &*config };
1134+
match config.experimental.use_seccomp {
1135+
Some(b) => b,
1136+
None => config_getInterposeMethod(config) == InterposeMethod::Preload,
1137+
}
1138+
}
1139+
11241140
#[no_mangle]
11251141
pub extern "C" fn config_getUseSyscallCounters(config: *const ConfigOptions) -> bool {
11261142
assert!(!config.is_null());

src/main/host/shimipc.c

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,12 @@
1010

1111
static bool _useExplicitBlockMessage = true;
1212
ADD_CONFIG_HANDLER(config_getUseExplicitBlockMessage, _useExplicitBlockMessage)
13-
1413
bool shimipc_sendExplicitBlockMessageEnabled() { return _useExplicitBlockMessage; }
1514

15+
static bool _useSeccomp = true;
16+
ADD_CONFIG_HANDLER(config_getUseSeccomp, _useSeccomp)
17+
bool shimipc_getUseSeccomp() { return _useSeccomp; }
18+
1619
static int _spinMax = -1;
1720
ADD_CONFIG_HANDLER(config_getPreloadSpinMax, _spinMax)
1821

src/main/host/shimipc.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,3 +17,8 @@ bool shimipc_sendExplicitBlockMessageEnabled();
1717
// Number of iterations to spin when waiting on IPC between Shadow and the shim
1818
// before blocking.
1919
ssize_t shimipc_spinMax();
20+
21+
22+
// Whether to use a seccomp filter in the shim to catch syscalls that would
23+
// otherwise not be interposed.
24+
bool shimipc_getUseSeccomp();

src/main/host/syscall/signal.c

Lines changed: 127 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
#include <sys/syscall.h>
1111

1212
#include "main/host/host.h"
13+
#include "main/host/shimipc.h"
1314
#include "main/host/syscall/protected.h"
1415
#include "main/host/thread.h"
1516
#include "main/utility/syscall.h"
@@ -124,3 +125,129 @@ SysCallReturn syscallhandler_tkill(SysCallHandler* sys, const SysCallArgs* args)
124125
trace("translated virtual tid %i to native tid %i", tid, native_tid);
125126
return _syscallhandler_killHelper(sys, 0, native_tid, sig, SYS_tkill);
126127
}
128+
129+
// Removes `signal` from the sigset_t pointed to by `maskPtr`, if present.
130+
// Returns 0 on success (including if the signal wasn't present), or a negative
131+
// errno on failure.
132+
static int _removeSignalFromSet(SysCallHandler* sys, PluginPtr maskPtr, int signal) {
133+
sigset_t mask;
134+
int rv = process_readPtr(sys->process, &mask, maskPtr, sizeof(mask));
135+
if (rv < 0) {
136+
trace("Error reading %p: %s", (void*)maskPtr.val, g_strerror(-rv));
137+
return rv;
138+
}
139+
rv = sigismember(&mask, SIGSYS);
140+
if (rv < 0) {
141+
panic("sigismember: %s", g_strerror(errno));
142+
}
143+
if (!rv) {
144+
trace("Signal %d wasn't in set", signal);
145+
return 0;
146+
}
147+
trace("Clearing %d from sigprocmask(SIG_BLOCK) set", signal);
148+
rv = sigdelset(&mask, SIGSYS);
149+
if (rv < 0) {
150+
panic("sigdelset: %s", g_strerror(errno));
151+
}
152+
rv = process_writePtr(sys->process, maskPtr, &mask, sizeof(mask));
153+
if (rv < 0) {
154+
trace("Error writing %p: %s", (void*)maskPtr.val, g_strerror(-rv));
155+
return rv;
156+
}
157+
return 0;
158+
}
159+
160+
SysCallReturn syscallhandler_sigaction(SysCallHandler* sys, const SysCallArgs* args) {
161+
utility_assert(sys && args);
162+
163+
if (!shimipc_getUseSeccomp()) {
164+
return (SysCallReturn){.state = SYSCALL_NATIVE};
165+
}
166+
// Prevent interference with shim's SIGSYS handler.
167+
168+
int signum = (int)args->args[0].as_i64;
169+
PluginPtr sigaction_ptr = args->args[1].as_ptr;
170+
PluginPtr sa_mask_ptr = (PluginPtr){sigaction_ptr.val + offsetof(struct sigaction, sa_mask)};
171+
172+
if (signum == SIGSYS) {
173+
warning("Blocking `sigaction` for SIGSYS");
174+
return (SysCallReturn){.state = SYSCALL_DONE, .retval = -ENOSYS};
175+
}
176+
_removeSignalFromSet(sys, sa_mask_ptr, SIGSYS);
177+
178+
return (SysCallReturn){.state = SYSCALL_NATIVE};
179+
}
180+
181+
SysCallReturn syscallhandler_rt_sigaction(SysCallHandler* sys, const SysCallArgs* args) {
182+
utility_assert(sys && args);
183+
if (!shimipc_getUseSeccomp()) {
184+
return (SysCallReturn){.state = SYSCALL_NATIVE};
185+
}
186+
// Prevent interference with shim's SIGSYS handler.
187+
188+
int signum = (int)args->args[0].as_i64;
189+
PluginPtr sigaction_ptr = args->args[1].as_ptr;
190+
PluginPtr sa_mask_ptr = (PluginPtr){sigaction_ptr.val + offsetof(struct sigaction, sa_mask)};
191+
192+
if (signum == SIGSYS) {
193+
warning("Blocking `rt_sigaction` for SIGSYS");
194+
return (SysCallReturn){.state = SYSCALL_DONE, .retval = -ENOSYS};
195+
}
196+
_removeSignalFromSet(sys, sa_mask_ptr, SIGSYS);
197+
198+
return (SysCallReturn){.state = SYSCALL_NATIVE};
199+
}
200+
201+
SysCallReturn syscallhandler_signal(SysCallHandler* sys, const SysCallArgs* args) {
202+
utility_assert(sys && args);
203+
if (!shimipc_getUseSeccomp()) {
204+
return (SysCallReturn){.state = SYSCALL_NATIVE};
205+
}
206+
// Prevent interference with shim's SIGSYS handler.
207+
208+
int signum = (int)args->args[0].as_i64;
209+
210+
if (signum == SIGSYS) {
211+
warning("Blocking `signal` for SIGSYS");
212+
return (SysCallReturn){.state = SYSCALL_DONE, .retval = -ENOSYS};
213+
}
214+
return (SysCallReturn){.state = SYSCALL_NATIVE};
215+
}
216+
217+
SysCallReturn syscallhandler_sigprocmask(SysCallHandler* sys, const SysCallArgs* args) {
218+
utility_assert(sys && args);
219+
if (!shimipc_getUseSeccomp()) {
220+
return (SysCallReturn){.state = SYSCALL_NATIVE};
221+
}
222+
// Prevent interference with shim's SIGSYS handler.
223+
224+
int how = (int)args->args[0].as_i64;
225+
PluginPtr maskPtr = args->args[1].as_ptr;
226+
227+
if (how == SIG_BLOCK || how == SIG_SETMASK) {
228+
int rv = _removeSignalFromSet(sys, maskPtr, SIGSYS);
229+
if (rv != 0) {
230+
return (SysCallReturn){.state = SYSCALL_DONE, .retval = rv};
231+
}
232+
}
233+
return (SysCallReturn){.state = SYSCALL_NATIVE};
234+
}
235+
236+
SysCallReturn syscallhandler_rt_sigprocmask(SysCallHandler* sys, const SysCallArgs* args) {
237+
utility_assert(sys && args);
238+
if (!shimipc_getUseSeccomp()) {
239+
return (SysCallReturn){.state = SYSCALL_NATIVE};
240+
}
241+
// Prevent interference with shim's SIGSYS handler.
242+
243+
int how = (int)args->args[0].as_i64;
244+
PluginPtr maskPtr = args->args[1].as_ptr;
245+
246+
if (how == SIG_BLOCK || how == SIG_SETMASK) {
247+
int rv = _removeSignalFromSet(sys, maskPtr, SIGSYS);
248+
if (rv != 0) {
249+
return (SysCallReturn){.state = SYSCALL_DONE, .retval = rv};
250+
}
251+
}
252+
return (SysCallReturn){.state = SYSCALL_NATIVE};
253+
}

0 commit comments

Comments
 (0)