Skip to content

Commit

Permalink
Merge branch 'oreo-seccomp'
Browse files Browse the repository at this point in the history
  • Loading branch information
michalbednarski committed Nov 26, 2017
2 parents 6671bfe + ada5d05 commit 454b0b1
Show file tree
Hide file tree
Showing 6 changed files with 89 additions and 13 deletions.
9 changes: 9 additions & 0 deletions src/cli/cli.c
Original file line number Diff line number Diff line change
Expand Up @@ -453,6 +453,15 @@ int main(int argc, char *const argv[])
goto error;
tracee->pid = getpid();

/* Set verboseness from env variable, may be overriden by option */
{
const char *verbose_env = getenv("PROOT_VERBOSE");
if (verbose_env != NULL) {
tracee->verbose = strtol(verbose_env, NULL, 10);
global_verbose_level = tracee->verbose;
}
}

/* Pre-configure the first tracee. */
status = parse_config(tracee, argc, argv);
if (status < 0)
Expand Down
5 changes: 4 additions & 1 deletion src/path/proc.c
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,10 @@ Action readlink_proc(const Tracee *tracee, char result[PATH_MAX],
int status;
pid_t pid;

assert(comparison == compare_paths("/proc", base));
/* TODO: Following assertion fails on some devices
* https://github.com/termux/termux-packages/issues/1679
*/
//assert(comparison == compare_paths("/proc", base));

/* Remember: comparison = compare_paths("/proc", base) */
switch (comparison) {
Expand Down
5 changes: 5 additions & 0 deletions src/syscall/chain.c
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
#include <errno.h> /* E*, */
#include <assert.h> /* assert(3), */

#include "cli/note.h"
#include "syscall/chain.h"
#include "syscall/sysnum.h"
#include "tracee/tracee.h"
Expand Down Expand Up @@ -118,9 +119,13 @@ void chain_next_syscall(Tracee *tracee)
tracee->chain.force_final_result = false;
tracee->chain.final_result = 0;

VERBOSE(tracee, 2, "chain_next_syscall finish");

return;
}

VERBOSE(tracee, 2, "chain_next_syscall continue");

/* Original register values will be restored right after the
* last chained syscall. */
tracee->restore_original_regs = false;
Expand Down
31 changes: 21 additions & 10 deletions src/syscall/syscall.c
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,8 @@ void translate_syscall(Tracee *tracee)
if (status < 0)
return;

int suppressed_syscall_status = 0;

if (is_enter_stage) {
/* Never restore original register values at the end
* of this stage. */
Expand Down Expand Up @@ -151,6 +153,7 @@ void translate_syscall(Tracee *tracee)
* the sysexit stage (i.e. when seccomp is enabled and
* there's nothing else to do). */
if (tracee->restart_how == PTRACE_CONT) {
suppressed_syscall_status = tracee->status;
tracee->status = 0;
poke_reg(tracee, STACK_POINTER, peek_reg(tracee, ORIGINAL, STACK_POINTER));
}
Expand Down Expand Up @@ -187,29 +190,37 @@ void translate_syscall(Tracee *tracee)
int push_regs_status = push_specific_regs(tracee, override_sysnum);

/* Handle inability to change syscall number */
print_current_regs(tracee, 4, "pre_push");
if (push_regs_status < 0 && override_sysnum) {
word_t orig_sysnum = peek_reg(tracee, ORIGINAL, SYSARG_NUM);
word_t current_sysnum = peek_reg(tracee, CURRENT, SYSARG_NUM);
if (orig_sysnum != current_sysnum) {
/* Restart current syscall as chained */
if (current_sysnum != SYSCALL_AVOIDER) {
restart_current_syscall_as_chained(tracee);
} else if (suppressed_syscall_status) {
/* If we've decided to fail this syscall
* by setting it to no-op and continuing, but turns out
* that we can't just make syscall nop, restore tracee->status
* and intercept syscall exit */
tracee->status = suppressed_syscall_status;
tracee->restart_how = PTRACE_SYSCALL;
}

/* Set syscall arguments to make it fail
* TODO: More reliable way to make invalid arguments */
* TODO: More reliable way to make invalid arguments
* For most syscalls we set all args to -1
* Hoping there is among them invalid request/address/fd/value that will make syscall fail */
poke_reg(tracee, SYSARG_1, -1);
poke_reg(tracee, SYSARG_2, -1);
poke_reg(tracee, SYSARG_3, -1);
poke_reg(tracee, SYSARG_4, -1);
poke_reg(tracee, SYSARG_5, -1);
poke_reg(tracee, SYSARG_6, -1);

if (get_sysnum(tracee, ORIGINAL) == PR_brk) {
/* For brk() we pass 0 as first arg; this is used to query value without changing it */
poke_reg(tracee, SYSARG_1, 0);
} else {
/* For other syscalls we set all args to -1
* Hoping there is among them invalid request/address/fd/value that will make syscall fail */
poke_reg(tracee, SYSARG_1, -1);
poke_reg(tracee, SYSARG_2, -1);
poke_reg(tracee, SYSARG_3, -1);
poke_reg(tracee, SYSARG_4, -1);
poke_reg(tracee, SYSARG_5, -1);
poke_reg(tracee, SYSARG_6, -1);
}

/* Push regs again without changing syscall */
Expand Down
51 changes: 49 additions & 2 deletions src/tracee/event.c
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,10 @@
#include "attribute.h"
#include "compat.h"

#ifndef SYS_SECCOMP
#define SYS_SECCOMP 1
#endif

/**
* Start @tracee->exe with the given @argv[]. This function
* returns -errno if an error occurred, otherwise 0.
Expand Down Expand Up @@ -377,7 +381,7 @@ int handle_tracee_event(Tracee *tracee, int tracee_status)
* seccomp) is not cleared due to an event that would happen
* before the exit stage, eg. PTRACE_EVENT_EXEC for the exit
* stage of execve(2). */
if (tracee->seccomp == ENABLED && !tracee->sysexit_pending)
if (tracee->seccomp == ENABLED && !tracee->sysexit_pending && tracee->chain.syscalls == NULL)
tracee->restart_how = PTRACE_CONT;
else
tracee->restart_how = PTRACE_SYSCALL;
Expand Down Expand Up @@ -475,6 +479,14 @@ int handle_tracee_event(Tracee *tracee, int tracee_status)
if (!tracee->seccomp_already_handled_enter)
{
translate_syscall(tracee);

/* Redeliver signal suppressed during
* syscall chain once it's finished. */
if (tracee->chain.suppressed_signal && tracee->chain.syscalls == NULL) {
signal = tracee->chain.suppressed_signal;
tracee->chain.suppressed_signal = 0;
VERBOSE(tracee, 6, "vpid %" PRIu64 ": redelivering suppressed signal %d", tracee->vpid, signal);
}
}
else {
assert(!IS_IN_SYSENTER(tracee));
Expand Down Expand Up @@ -580,8 +592,43 @@ int handle_tracee_event(Tracee *tracee, int tracee_status)
}
break;

case SIGSYS: {
siginfo_t siginfo = {};
ptrace(PTRACE_GETSIGINFO, tracee->pid, NULL, &siginfo);
if (siginfo.si_code == SYS_SECCOMP) {
/* Set errno to -ENOSYS */
int sigsys_fetch_status = fetch_regs(tracee);
if (sigsys_fetch_status != 0) {
VERBOSE(tracee, 1, "Couldn't fetch regs on seccomp SIGSYS");
break;
}
print_current_regs(tracee, 3, "seccomp SIGSYS");
poke_reg(tracee, SYSARG_RESULT, -ENOSYS);
tracee->restore_original_regs = false;
push_specific_regs(tracee, false);

/* Swallow signal */
signal = 0;

/* Reset status so next SIGTRAP | 0x80 is
* recognized as syscall entry */
tracee->status = 0;
} else {
VERBOSE(tracee, 1, "non-seccomp SIGSYS");
}
break;
}

default:
/* Deliver this signal as-is. */
/* Deliver this signal as-is,
* unless we're chaining syscall. */
if (tracee->chain.syscalls != NULL) {
VERBOSE(tracee, 5,
"vpid %" PRIu64 ": suppressing signal during chain signal=%d, prev suppressed_signal=%d",
tracee->vpid, signal, tracee->chain.suppressed_signal);
tracee->chain.suppressed_signal = signal;
signal = 0;
}
break;
}
}
Expand Down
1 change: 1 addition & 0 deletions src/tracee/tracee.h
Original file line number Diff line number Diff line change
Expand Up @@ -202,6 +202,7 @@ typedef struct tracee {
SYSNUM_WORKAROUND_PROCESS_FAULTY_CALL,
SYSNUM_WORKAROUND_PROCESS_REPLACED_CALL
} sysnum_workaround_state;
int suppressed_signal;
} chain;

/* Load info generated during execve sysenter and used during
Expand Down

0 comments on commit 454b0b1

Please sign in to comment.