Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

i#5256 sigprocmask: enable linux.sigaction on MacOS #5258

Merged
merged 38 commits into from
Dec 22, 2021
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
Show all changes
38 commits
Select commit Hold shift + click to select a range
0497e50
i#5256 sigprocmask: add tests for MacOS.
abhinav92003 Dec 17, 2021
268e105
Debug stuff.
abhinav92003 Dec 17, 2021
40ff890
Fix sigaction test for Mac.
abhinav92003 Dec 18, 2021
db2f04f
Fix mac test bug.
abhinav92003 Dec 18, 2021
27ef6e6
Add a native run for linux.sigaction
abhinav92003 Dec 18, 2021
5e6c372
Enable linux.sigaction.native on MacOS.
abhinav92003 Dec 18, 2021
4723ba7
Fix test names
abhinav92003 Dec 18, 2021
f7573e2
Fix handling of bad old sigset on Mac.
abhinav92003 Dec 18, 2021
5d37fd5
Remove tmate debug statements.
abhinav92003 Dec 18, 2021
085257a
Fix issue comments.
abhinav92003 Dec 18, 2021
b2f748a
Add tmate debug statements.
abhinav92003 Dec 18, 2021
e85f09c
Block some signals to make other tests better.
abhinav92003 Dec 18, 2021
95f3f3a
Add test for no_intercept_all_signals
abhinav92003 Dec 18, 2021
3615f96
Enable new tests on MacOS.
abhinav92003 Dec 18, 2021
45110af
Try fixing new sigmask.
abhinav92003 Dec 18, 2021
c12a318
Try fixing new sigmask.
abhinav92003 Dec 18, 2021
fd49014
Block SIGBUS only.
abhinav92003 Dec 18, 2021
20c5755
Add fix for non-writable oset on mac.
abhinav92003 Dec 18, 2021
b89c421
Fix sys_kill detection for MacOS.
abhinav92003 Dec 19, 2021
04150be
Fix MacOS sig kill issues.
abhinav92003 Dec 19, 2021
8a2bec2
Remove stray code.
abhinav92003 Dec 19, 2021
d655145
Add constant for unix class syscalls on Mac.
abhinav92003 Dec 19, 2021
99c194c
Revert tmate
abhinav92003 Dec 19, 2021
dd64447
Fix MacOS build.
abhinav92003 Dec 19, 2021
adb3c46
Add tmate back
abhinav92003 Dec 19, 2021
8104fa7
Revert tmate.
abhinav92003 Dec 19, 2021
a225c7e
Comments fix.
abhinav92003 Dec 19, 2021
61feb3f
Reviewer suggested edits.
abhinav92003 Dec 20, 2021
43091ed
Handle EFAULT due to old sigset still setting the new mask.
abhinav92003 Dec 20, 2021
90c415e
Test readability improvements.
abhinav92003 Dec 20, 2021
4abbf12
Remove signal_intercept prefix for CMake tests
abhinav92003 Dec 21, 2021
c660d4a
Add clarifying comment.
abhinav92003 Dec 21, 2021
978e091
Add tmate
abhinav92003 Dec 21, 2021
42b4ffb
Revert tmate
abhinav92003 Dec 21, 2021
4de1c96
Add more comments.
abhinav92003 Dec 22, 2021
55a43f2
Add tmate.
abhinav92003 Dec 22, 2021
0387c70
Revert "Add tmate."
abhinav92003 Dec 22, 2021
c914866
Merge branch 'master' into i5256-sigprocmask-macos
abhinav92003 Dec 22, 2021
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion core/arch/x86/x86.asm
Original file line number Diff line number Diff line change
Expand Up @@ -641,6 +641,10 @@ cat_have_lock:
mov REG_XDI, REG_XAX /* esp to use */
#endif
mov REG_XSI, [2*ARG_SZ + REG_XBP] /* sysnum */
#ifdef MACOS64
/* For now we assume a BSD syscall */
or REG_XSI, SYSCALL_NUM_MARKER_BSD
#endif
pop REG_XAX /* syscall */
pop REG_XCX /* dstack */
#if defined(UNIX) && !defined(X64)
Expand Down Expand Up @@ -1261,7 +1265,7 @@ dynamorio_sys_exit_next:
mov ARG2, REG_XAX /* kernel port, which we just acquired */
mov ARG1, 0 /* join semaphore: SEMAPHORE_NULL */
mov eax, SYS_bsdthread_terminate
or eax, HEX(2000000) /* 2<<24 for BSD syscall */
or eax, SYSCALL_NUM_MARKER_BSD
mov r10, rcx
syscall
# else
Expand Down
6 changes: 3 additions & 3 deletions core/drlibc/drlibc_x86.asm
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@
#include "../arch/asm_defines.asm"
#include "../arch/x86/x86_asm_defines.asm" /* PUSHGPR, POPGPR, etc. */
#ifdef MACOS
# include "include/syscall_mach.h" /* SYSCALL_NUM_MARKER_MACH */
# include "include/syscall_mach.h" /* SYSCALL_NUM_MARKER_* */
#endif
START_FILE

Expand All @@ -67,8 +67,8 @@ GLOBAL_LABEL(dynamorio_syscall:)
mov REG_XBX, ARG2 /* put num_args where we can reference it longer */
mov rax, ARG1 /* sysnum: only need eax, but need rax for ARG1 (or movzx) */
# ifdef MACOS
/* for now we assume a BSD syscall */
or rax, 0x2000000
/* For now we assume a BSD syscall */
or rax, SYSCALL_NUM_MARKER_BSD
# endif
cmp REG_XBX, 0
je syscall_ready
Expand Down
2 changes: 1 addition & 1 deletion core/unix/include/syscall_mach.h
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@
#define _SYSCALL_MACH_H_ 1

#define SYSCALL_NUM_MARKER_MACH 0x1000000
#define SYSCALL_NUM_MARKER_UNIX 0x2000000
#define SYSCALL_NUM_MARKER_BSD 0x2000000
#define SYSCALL_NUM_MARKER_MACHDEP 0x3000000

#define MACH__kernelrpc_mach_vm_allocate_trap 10
Expand Down
2 changes: 1 addition & 1 deletion core/unix/os.c
Original file line number Diff line number Diff line change
Expand Up @@ -4880,7 +4880,7 @@ os_normalized_sysnum(int num_raw, instr_t *gateway, dcontext_t *dcontext)
}
}
# ifdef X64
if (num_raw >> 24 == 0x2)
if (num_raw & SYSCALL_NUM_MARKER_BSD)
abhinav92003 marked this conversation as resolved.
Show resolved Hide resolved
return (int)(num_raw & 0xffffff); /* Drop BSD bit */
else
num = (int)num_raw; /* Keep Mach and Machdep bits */
Expand Down
20 changes: 5 additions & 15 deletions core/unix/signal.c
Original file line number Diff line number Diff line change
Expand Up @@ -2321,19 +2321,6 @@ handle_sigprocmask(dcontext_t *dcontext, int how, kernel_sigset_t *app_set,
*error_code = EINVAL;
return false;
}
/* On MacOS, sigprocmask does not fail if the old sigset is not readable
* or not writeable.
*/
if (IF_MACOS_ELSE(false, oset != NULL)) {
kernel_sigset_t safe_old_set;
/* Old sigset should be writable too. */
derekbruening marked this conversation as resolved.
Show resolved Hide resolved
if (!d_r_safe_read(oset, sizeof(safe_old_set), &safe_old_set) ||
!safe_write_ex(oset, sizeof(safe_old_set), &safe_old_set, NULL)) {
if (error_code != NULL)
*error_code = EFAULT;
return false;
}
}
/* If we're intercepting all, we emulate the whole thing */
bool execute_syscall = !DYNAMO_OPTION(intercept_all_signals);
LOG(THREAD, LOG_ASYNCH, 2, "handle_sigprocmask\n");
Expand Down Expand Up @@ -2408,7 +2395,10 @@ handle_sigprocmask(dcontext_t *dcontext, int how, kernel_sigset_t *app_set,
check_signals_pending(dcontext, info);
}
if (!execute_syscall) {
handle_post_sigprocmask(dcontext, how, app_set, oset, sigsetsize);
int status = handle_post_sigprocmask(dcontext, how, app_set, oset, sigsetsize);
derekbruening marked this conversation as resolved.
Show resolved Hide resolved
if (status != 0 && error_code != NULL) {
*error_code = status;
}
return false; /* skip syscall */
} else
return true;
Expand Down Expand Up @@ -6205,7 +6195,7 @@ terminate_via_kill(dcontext_t *dcontext)
* this may not exit all threads in the address space
*/
block_cleanup_and_terminate(
dcontext, IF_MACOS(SYSCALL_NUM_MARKER_UNIX +) SYS_kill,
dcontext, SYS_kill,
/* Pass -pid in case main thread has exited
* in which case will get -ESRCH
*/
Expand Down
13 changes: 7 additions & 6 deletions suite/tests/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,8 @@ set(main_run_list
# our main configuration
"SHORT::-code_api"
# no_intercept_all_signals tests.
"SHORT::ONLY::signal_intercept$::-no_code_api -no_intercept_all_signals"
# TODO i#5261: Remove this suite when -intercept_all_signals is deprecated.
"SHORT::LIN::ONLY::sigaction$::-no_code_api -no_intercept_all_signals"
# sanity check: run single app to make sure these options aren't totally broken
# i#1575: ARM doesn't yet support -coarse_units
"SHORT::X86::ONLY::client.events$::-code_api -opt_memory"
Expand Down Expand Up @@ -4143,9 +4144,9 @@ if (UNIX)
tobuild(linux.sigplain101 linux/sigplain101.c)
tobuild(linux.sigplain110 linux/sigplain110.c)
tobuild(linux.sigplain111 linux/sigplain111.c)
tobuild(linux.sigaction.signal_intercept linux/sigaction.c)
tobuild(linux.sigaction linux/sigaction.c)
# We want a native run to verify our assumptions of kernel behaviour.
torunonly_native(code_api|linux.sigaction.native linux.sigaction.signal_intercept
torunonly_native(code_api|linux.sigaction.native linux.sigaction
"" linux/sigaction.c "")
if (LINUX)
tobuild(linux.syscall_pwait linux/syscall_pwait.cpp)
Expand Down Expand Up @@ -4794,8 +4795,8 @@ if (APPLE)
code_api|api.dis
code_api|api.ir-static
code_api|api.drdecode
code_api|linux.sigaction.signal_intercept
no_code_api,no_intercept_all_signals|linux.sigaction.signal_intercept
code_api|linux.sigaction
no_code_api,no_intercept_all_signals|linux.sigaction
code_api|linux.sigaction.native
PROPERTIES LABELS OSX)
if (DEBUG) # FIXME i#1806: fails in release
Expand Down Expand Up @@ -4829,7 +4830,7 @@ if (NOT ANDROID AND AARCHXX)
code_api|linux.infinite
code_api|linux.longjmp
code_api|linux.readlink
code_api|linux.sigaction.signal_intercept
code_api|linux.sigaction
code_api|linux.signalfd
code_api|linux.signal_racesys
code_api|security-common.codemod
Expand Down
64 changes: 37 additions & 27 deletions suite/tests/linux/sigaction.c
Original file line number Diff line number Diff line change
Expand Up @@ -45,10 +45,16 @@

#define SENTINEL 0x12345678UL

#ifdef MACOS
typedef int si_mask_t;
#else
typedef unsigned long si_mask_t;
#endif

#if !defined(MACOS) && !defined(X64)
typedef struct old_sigaction_t {
void (*handler)(int, siginfo_t *, void *);
unsigned int sa_mask;
si_mask_t sa_mask;
unsigned long sa_flags;
void (*sa_restorer)(void);
} old_sigaction_t;
Expand Down Expand Up @@ -78,13 +84,9 @@ test_query(int sig)
memset((void *)&old_act, 0xff, sizeof(old_act));
rc = sigaction(sig, NULL, &old_act);
assert(rc == 0 && old_act.sa_sigaction == first_act.sa_sigaction &&
/* The flags do not match due to SA_RESTORER. */
/* The rest of mask is uninit stack values from the libc wrapper. */
#if defined(MACOS)
*(int *)&old_act.sa_mask == *(int *)&first_act.sa_mask);
#else
*(long *)&old_act.sa_mask == *(long *)&first_act.sa_mask);
#endif
/* The flags do not match due to SA_RESTORER. */
/* The rest of mask is uninit stack values from the libc wrapper. */
*(si_mask_t *)&old_act.sa_mask == *(si_mask_t *)&first_act.sa_mask);

/* Test with a new action. */
memset((void *)&old_act, 0xff, sizeof(old_act));
Expand All @@ -93,13 +95,9 @@ test_query(int sig)
sigemptyset(&new_act.sa_mask);
rc = sigaction(sig, &new_act, &old_act);
assert(rc == 0 && old_act.sa_sigaction == first_act.sa_sigaction &&
/* The flags do not match due to SA_RESTORER. */
/* The rest of mask is uninit stack values from the libc wrapper. */
#if defined(MACOS)
*(int *)&old_act.sa_mask == *(int *)&first_act.sa_mask);
#else
*(long *)&old_act.sa_mask == *(long *)&first_act.sa_mask);
#endif
/* The flags do not match due to SA_RESTORER. */
/* The rest of mask is uninit stack values from the libc wrapper. */
*(si_mask_t *)&old_act.sa_mask == *(si_mask_t *)&first_act.sa_mask);

/* Test pattern from i#1984 issue and ensure no assert. */
memset(&new_act, 0, sizeof(new_act));
Expand Down Expand Up @@ -138,14 +136,17 @@ static void
test_sigprocmask()
{
#if defined(MACOS)
sigset_t new = 0xf00d, old, original;
sigset_t new = 0xf00d, new2 = 0x1234, old, original;
/* We explicitly add SIGBUS to the blocked set as it is one of the
* signals that DR intercepts.
*/
sigaddset(&new, SIGBUS);
#else
uint64 new = 0xf00d | (1 << SIGBUS), old, original;
uint64 new = 0xf00d | (1 << SIGBUS), new2 = 0x1234, old, original;
#endif
void *fault_addr = (void *)0x123;
void *read_only_addr = test_sigprocmask;

/* Save original sigprocmask. Both return the current sigprocmask. */
assert(make_sigprocmask(SIG_SETMASK, NULL, &original,
/*sizeof(kernel_sigset_t)*/ 8) == 0);
Expand All @@ -167,23 +168,22 @@ test_sigprocmask()
* readable or not writeable.
*/
int expected_result_bad_old_sigset = IF_MACOS_ELSE(0, -1);
assert(make_sigprocmask(~0, NULL, (void *)0x123, 8) ==
expected_result_bad_old_sigset);
assert(make_sigprocmask(~0, NULL, fault_addr, 8) == expected_result_bad_old_sigset);
#if !defined(MACOS)
assert(errno == EFAULT);
#endif
assert(make_sigprocmask(SIG_BLOCK, (void *)0x123, NULL, 8) == -1);
assert(make_sigprocmask(SIG_BLOCK, fault_addr, NULL, 8) == -1);
assert(errno == EFAULT);
assert(make_sigprocmask(SIG_BLOCK, NULL, (void *)0x123, 8) ==
assert(make_sigprocmask(SIG_BLOCK, NULL, fault_addr, 8) ==
expected_result_bad_old_sigset);
#if !defined(MACOS)
assert(errno == EFAULT);
#endif
/* Bad new sigmask EFAULT gets reported before bad 'how' EINVAL. */
assert(make_sigprocmask(~0, (void *)0x123, NULL, 8) == -1);
assert(make_sigprocmask(~0, fault_addr, NULL, 8) == -1);
assert(errno == EFAULT);
/* EFAULT due to unwritable address. */
assert(make_sigprocmask(SIG_BLOCK, NULL, test_sigprocmask, 8) ==
assert(make_sigprocmask(SIG_BLOCK, NULL, read_only_addr, 8) ==
expected_result_bad_old_sigset);
#if !defined(MACOS)
assert(errno == EFAULT);
Expand All @@ -197,7 +197,7 @@ test_sigprocmask()
assert(make_sigprocmask(SIG_SETMASK, &new, NULL, 7) == -1);
assert(errno == EINVAL);
/* Bad size EINVAL gets reported before bad new sigmask EFAULT. */
assert(make_sigprocmask(SIG_SETMASK, (void *)0x123, NULL, 7) == -1);
assert(make_sigprocmask(SIG_SETMASK, fault_addr, NULL, 7) == -1);
assert(errno == EINVAL);

#endif
Expand All @@ -207,9 +207,19 @@ test_sigprocmask()
assert(make_sigprocmask(SIG_SETMASK + 1, &new, NULL, 8) == -1);
assert(errno == EINVAL);
/* Bad 'how' EINVAL gets reported before bad old sigset EFAULT. */
assert(make_sigprocmask(~0, &new, (void *)0x123, 8) == -1);
assert(make_sigprocmask(~0, &new, fault_addr, 8) == -1);
assert(errno == EINVAL);

/* EFAULT due to bad old sigset still sets the new mask. */
abhinav92003 marked this conversation as resolved.
Show resolved Hide resolved
assert(make_sigprocmask(SIG_SETMASK, &new, NULL, 8) == 0);
assert(make_sigprocmask(SIG_SETMASK, &new2, fault_addr, 8) ==
expected_result_bad_old_sigset);
#if !defined(MACOS)
assert(errno == EFAULT);
#endif
assert(make_sigprocmask(~0, NULL, &old, 8) == 0);
assert(new2 == old);

/* Restore original sigprocmask. */
assert(make_sigprocmask(SIG_SETMASK, &original, NULL, 8) == 0);
}
Expand Down Expand Up @@ -239,7 +249,7 @@ test_non_rt_sigaction(int sig)
assert(rc == 0 && old_act.handler == first_act.handler &&
/* The flags do not match due to SA_RESTORER. */
/* The rest of mask is uninit stack values from the libc wrapper. */
*(long *)&old_act.sa_mask == *(long *)&first_act.sa_mask);
*(si_mask_t *)&old_act.sa_mask == *(si_mask_t *)&first_act.sa_mask);

/* Test with a new action. */
memset((void *)&old_act, 0xff, sizeof(old_act));
Expand All @@ -249,7 +259,7 @@ test_non_rt_sigaction(int sig)
assert(rc == 0 && old_act.handler == first_act.handler &&
/* The flags do not match due to SA_RESTORER. */
/* The rest of mask is uninit stack values from the libc wrapper. */
*(long *)&old_act.sa_mask == *(long *)&first_act.sa_mask);
*(si_mask_t *)&old_act.sa_mask == *(si_mask_t *)&first_act.sa_mask);

/* Clear handler */
memset((void *)&new_act, 0, sizeof(new_act));
Expand Down