Set the restart_how field in a newly created child tracee. (#308)

This eliminates unexpected SIGTRAPs in newly forked processes,
allowing removal of ugly (and broken) workarounds in
the handle_tracee_event_kernel_4_8 event handler.

"Useless" seccomp traps still may happen if a tracee has
explicity disabled seccomp (like during ptrace emulation),
but handling these is much easier.

This fixes following tests: test-d92b57ca, test-2db65cd2.
Additionaly test-230f47ch is not skipped now, but it fails
under seccomp due to missing seccomp handling in handle_ptracee_event.
This commit is contained in:
Jakub Zakrzewski 2022-01-22 17:49:01 +01:00 committed by GitHub
parent d92431accd
commit 9e9cd23baa
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 8 additions and 27 deletions

View File

@ -398,7 +398,6 @@ static int handle_tracee_event_kernel_4_8(Tracee *tracee, int tracee_status)
static bool seccomp_enabled = false; /* added for 4.8.0 */
long status;
int signal;
bool need_exit = true;
/* Don't overwrite restart_how if it is explicitly set
* elsewhere, i.e in the ptrace emulation when single
@ -499,35 +498,16 @@ static int handle_tracee_event_kernel_4_8(Tracee *tracee, int tracee_status)
unsigned long flags = 0;
signal = 0;
/* Use the common ptrace flow if seccomp was
* explicitly disabled for this tracee. */
if (tracee->seccomp != ENABLED)
break;
status = ptrace(PTRACE_GETEVENTMSG, tracee->pid, NULL, &flags);
if (status < 0)
break;
need_exit = flags & FILTER_SYSEXIT;
/* SECCOMP TRAP can only be received for
* sysenter events. It is sometimes possible for sysenter
* to be handled at the normal PTRACE_SYSCALL SIGTRAP handler,
* before seccomp trap arrives.
* This may happen for example during handling of the first
* syscall the traced process makes, before seccomp is enabled,
* however there is some other random and unknown factor that affects that.
* If this happened, then continue until the next syscall
* or sysexit if necessary. */
if (!IS_IN_SYSENTER(tracee)) {
if (need_exit || tracee->restart_how == PTRACE_SYSCALL) {
tracee->restart_how = PTRACE_SYSCALL;
}
else {
// We are not interested in the sysexit
// continue to the next sysenter
// and clear the status to expect a sysenter next.
tracee->restart_how = PTRACE_CONT;
tracee->status = 0;
}
break;
}
if (tracee->seccomp == ENABLED && (flags & FILTER_SYSEXIT) == 0) {
if ((flags & FILTER_SYSEXIT) == 0) {
tracee->restart_how = PTRACE_CONT;
translate_syscall(tracee);
@ -553,7 +533,7 @@ static int handle_tracee_event_kernel_4_8(Tracee *tracee, int tracee_status)
switch (tracee->seccomp) {
case ENABLED:
if (IS_IN_SYSENTER(tracee) && need_exit) {
if (IS_IN_SYSENTER(tracee)) {
/* sysenter: ensure the sysexit
* stage will be hit under seccomp. */
tracee->restart_how = PTRACE_SYSCALL;

View File

@ -432,6 +432,7 @@ int new_child(Tracee *parent, word_t clone_flags)
child->verbose = parent->verbose;
child->seccomp = parent->seccomp;
child->sysexit_pending = parent->sysexit_pending;
child->restart_how = parent->restart_how;
/* If CLONE_VM is set, the calling process and the child
* process run in the same memory space [...] any memory