Loading include/linux/seccomp.h +0 −6 Original line number Diff line number Diff line Loading @@ -35,12 +35,6 @@ static inline int secure_computing(const struct seccomp_data *sd) return __secure_computing(sd); return 0; } #define SECCOMP_PHASE1_OK 0 #define SECCOMP_PHASE1_SKIP 1 extern u32 seccomp_phase1(struct seccomp_data *sd); int seccomp_phase2(u32 phase1_result); #else extern void secure_computing_strict(int this_syscall); #endif Loading kernel/seccomp.c +41 −88 Original line number Diff line number Diff line Loading @@ -173,7 +173,7 @@ static int seccomp_check_filter(struct sock_filter *filter, unsigned int flen) * * Returns valid seccomp BPF response codes. */ static u32 seccomp_run_filters(struct seccomp_data *sd) static u32 seccomp_run_filters(const struct seccomp_data *sd) { struct seccomp_data sd_local; u32 ret = SECCOMP_RET_ALLOW; Loading Loading @@ -554,20 +554,9 @@ void secure_computing_strict(int this_syscall) BUG(); } #else int __secure_computing(const struct seccomp_data *sd) { u32 phase1_result = seccomp_phase1(sd); if (likely(phase1_result == SECCOMP_PHASE1_OK)) return 0; else if (likely(phase1_result == SECCOMP_PHASE1_SKIP)) return -1; else return seccomp_phase2(phase1_result); } #ifdef CONFIG_SECCOMP_FILTER static u32 __seccomp_phase1_filter(int this_syscall, struct seccomp_data *sd) static int __seccomp_filter(int this_syscall, const struct seccomp_data *sd) { u32 filter_ret, action; int data; Loading Loading @@ -599,10 +588,33 @@ static u32 __seccomp_phase1_filter(int this_syscall, struct seccomp_data *sd) goto skip; case SECCOMP_RET_TRACE: return filter_ret; /* Save the rest for phase 2. */ /* ENOSYS these calls if there is no tracer attached. */ if (!ptrace_event_enabled(current, PTRACE_EVENT_SECCOMP)) { syscall_set_return_value(current, task_pt_regs(current), -ENOSYS, 0); goto skip; } /* Allow the BPF to provide the event message */ ptrace_event(PTRACE_EVENT_SECCOMP, data); /* * The delivery of a fatal signal during event * notification may silently skip tracer notification. * Terminating the task now avoids executing a system * call that may not be intended. */ if (fatal_signal_pending(current)) do_exit(SIGSYS); /* Check if the tracer forced the syscall to be skipped. */ this_syscall = syscall_get_nr(current, task_pt_regs(current)); if (this_syscall < 0) goto skip; return 0; case SECCOMP_RET_ALLOW: return SECCOMP_PHASE1_OK; return 0; case SECCOMP_RET_KILL: default: Loading @@ -614,96 +626,37 @@ static u32 __seccomp_phase1_filter(int this_syscall, struct seccomp_data *sd) skip: audit_seccomp(this_syscall, 0, action); return SECCOMP_PHASE1_SKIP; return -1; } #else static int __seccomp_filter(int this_syscall, const struct seccomp_data *sd) { BUG(); } #endif /** * seccomp_phase1() - run fast path seccomp checks on the current syscall * @arg sd: The seccomp_data or NULL * * This only reads pt_regs via the syscall_xyz helpers. The only change * it will make to pt_regs is via syscall_set_return_value, and it will * only do that if it returns SECCOMP_PHASE1_SKIP. * * If sd is provided, it will not read pt_regs at all. * * It may also call do_exit or force a signal; these actions must be * safe. * * If it returns SECCOMP_PHASE1_OK, the syscall passes checks and should * be processed normally. * * If it returns SECCOMP_PHASE1_SKIP, then the syscall should not be * invoked. In this case, seccomp_phase1 will have set the return value * using syscall_set_return_value. * * If it returns anything else, then the return value should be passed * to seccomp_phase2 from a context in which ptrace hooks are safe. */ u32 seccomp_phase1(struct seccomp_data *sd) int __secure_computing(const struct seccomp_data *sd) { int mode = current->seccomp.mode; int this_syscall = sd ? sd->nr : syscall_get_nr(current, task_pt_regs(current)); int this_syscall; if (config_enabled(CONFIG_CHECKPOINT_RESTORE) && unlikely(current->ptrace & PT_SUSPEND_SECCOMP)) return SECCOMP_PHASE1_OK; return 0; this_syscall = sd ? sd->nr : syscall_get_nr(current, task_pt_regs(current)); switch (mode) { case SECCOMP_MODE_STRICT: __secure_computing_strict(this_syscall); /* may call do_exit */ return SECCOMP_PHASE1_OK; #ifdef CONFIG_SECCOMP_FILTER return 0; case SECCOMP_MODE_FILTER: return __seccomp_phase1_filter(this_syscall, sd); #endif return __seccomp_filter(this_syscall, sd); default: BUG(); } } /** * seccomp_phase2() - finish slow path seccomp work for the current syscall * @phase1_result: The return value from seccomp_phase1() * * This must be called from a context in which ptrace hooks can be used. * * Returns 0 if the syscall should be processed or -1 to skip the syscall. */ int seccomp_phase2(u32 phase1_result) { struct pt_regs *regs = task_pt_regs(current); u32 action = phase1_result & SECCOMP_RET_ACTION; int data = phase1_result & SECCOMP_RET_DATA; BUG_ON(action != SECCOMP_RET_TRACE); audit_seccomp(syscall_get_nr(current, regs), 0, action); /* Skip these calls if there is no tracer. */ if (!ptrace_event_enabled(current, PTRACE_EVENT_SECCOMP)) { syscall_set_return_value(current, regs, -ENOSYS, 0); return -1; } /* Allow the BPF to provide the event message */ ptrace_event(PTRACE_EVENT_SECCOMP, data); /* * The delivery of a fatal signal during event * notification may silently skip tracer notification. * Terminating the task now avoids executing a system * call that may not be intended. */ if (fatal_signal_pending(current)) do_exit(SIGSYS); if (syscall_get_nr(current, regs) < 0) return -1; /* Explicit request to skip. */ return 0; } #endif /* CONFIG_HAVE_ARCH_SECCOMP_FILTER */ long prctl_get_seccomp(void) Loading Loading
include/linux/seccomp.h +0 −6 Original line number Diff line number Diff line Loading @@ -35,12 +35,6 @@ static inline int secure_computing(const struct seccomp_data *sd) return __secure_computing(sd); return 0; } #define SECCOMP_PHASE1_OK 0 #define SECCOMP_PHASE1_SKIP 1 extern u32 seccomp_phase1(struct seccomp_data *sd); int seccomp_phase2(u32 phase1_result); #else extern void secure_computing_strict(int this_syscall); #endif Loading
kernel/seccomp.c +41 −88 Original line number Diff line number Diff line Loading @@ -173,7 +173,7 @@ static int seccomp_check_filter(struct sock_filter *filter, unsigned int flen) * * Returns valid seccomp BPF response codes. */ static u32 seccomp_run_filters(struct seccomp_data *sd) static u32 seccomp_run_filters(const struct seccomp_data *sd) { struct seccomp_data sd_local; u32 ret = SECCOMP_RET_ALLOW; Loading Loading @@ -554,20 +554,9 @@ void secure_computing_strict(int this_syscall) BUG(); } #else int __secure_computing(const struct seccomp_data *sd) { u32 phase1_result = seccomp_phase1(sd); if (likely(phase1_result == SECCOMP_PHASE1_OK)) return 0; else if (likely(phase1_result == SECCOMP_PHASE1_SKIP)) return -1; else return seccomp_phase2(phase1_result); } #ifdef CONFIG_SECCOMP_FILTER static u32 __seccomp_phase1_filter(int this_syscall, struct seccomp_data *sd) static int __seccomp_filter(int this_syscall, const struct seccomp_data *sd) { u32 filter_ret, action; int data; Loading Loading @@ -599,10 +588,33 @@ static u32 __seccomp_phase1_filter(int this_syscall, struct seccomp_data *sd) goto skip; case SECCOMP_RET_TRACE: return filter_ret; /* Save the rest for phase 2. */ /* ENOSYS these calls if there is no tracer attached. */ if (!ptrace_event_enabled(current, PTRACE_EVENT_SECCOMP)) { syscall_set_return_value(current, task_pt_regs(current), -ENOSYS, 0); goto skip; } /* Allow the BPF to provide the event message */ ptrace_event(PTRACE_EVENT_SECCOMP, data); /* * The delivery of a fatal signal during event * notification may silently skip tracer notification. * Terminating the task now avoids executing a system * call that may not be intended. */ if (fatal_signal_pending(current)) do_exit(SIGSYS); /* Check if the tracer forced the syscall to be skipped. */ this_syscall = syscall_get_nr(current, task_pt_regs(current)); if (this_syscall < 0) goto skip; return 0; case SECCOMP_RET_ALLOW: return SECCOMP_PHASE1_OK; return 0; case SECCOMP_RET_KILL: default: Loading @@ -614,96 +626,37 @@ static u32 __seccomp_phase1_filter(int this_syscall, struct seccomp_data *sd) skip: audit_seccomp(this_syscall, 0, action); return SECCOMP_PHASE1_SKIP; return -1; } #else static int __seccomp_filter(int this_syscall, const struct seccomp_data *sd) { BUG(); } #endif /** * seccomp_phase1() - run fast path seccomp checks on the current syscall * @arg sd: The seccomp_data or NULL * * This only reads pt_regs via the syscall_xyz helpers. The only change * it will make to pt_regs is via syscall_set_return_value, and it will * only do that if it returns SECCOMP_PHASE1_SKIP. * * If sd is provided, it will not read pt_regs at all. * * It may also call do_exit or force a signal; these actions must be * safe. * * If it returns SECCOMP_PHASE1_OK, the syscall passes checks and should * be processed normally. * * If it returns SECCOMP_PHASE1_SKIP, then the syscall should not be * invoked. In this case, seccomp_phase1 will have set the return value * using syscall_set_return_value. * * If it returns anything else, then the return value should be passed * to seccomp_phase2 from a context in which ptrace hooks are safe. */ u32 seccomp_phase1(struct seccomp_data *sd) int __secure_computing(const struct seccomp_data *sd) { int mode = current->seccomp.mode; int this_syscall = sd ? sd->nr : syscall_get_nr(current, task_pt_regs(current)); int this_syscall; if (config_enabled(CONFIG_CHECKPOINT_RESTORE) && unlikely(current->ptrace & PT_SUSPEND_SECCOMP)) return SECCOMP_PHASE1_OK; return 0; this_syscall = sd ? sd->nr : syscall_get_nr(current, task_pt_regs(current)); switch (mode) { case SECCOMP_MODE_STRICT: __secure_computing_strict(this_syscall); /* may call do_exit */ return SECCOMP_PHASE1_OK; #ifdef CONFIG_SECCOMP_FILTER return 0; case SECCOMP_MODE_FILTER: return __seccomp_phase1_filter(this_syscall, sd); #endif return __seccomp_filter(this_syscall, sd); default: BUG(); } } /** * seccomp_phase2() - finish slow path seccomp work for the current syscall * @phase1_result: The return value from seccomp_phase1() * * This must be called from a context in which ptrace hooks can be used. * * Returns 0 if the syscall should be processed or -1 to skip the syscall. */ int seccomp_phase2(u32 phase1_result) { struct pt_regs *regs = task_pt_regs(current); u32 action = phase1_result & SECCOMP_RET_ACTION; int data = phase1_result & SECCOMP_RET_DATA; BUG_ON(action != SECCOMP_RET_TRACE); audit_seccomp(syscall_get_nr(current, regs), 0, action); /* Skip these calls if there is no tracer. */ if (!ptrace_event_enabled(current, PTRACE_EVENT_SECCOMP)) { syscall_set_return_value(current, regs, -ENOSYS, 0); return -1; } /* Allow the BPF to provide the event message */ ptrace_event(PTRACE_EVENT_SECCOMP, data); /* * The delivery of a fatal signal during event * notification may silently skip tracer notification. * Terminating the task now avoids executing a system * call that may not be intended. */ if (fatal_signal_pending(current)) do_exit(SIGSYS); if (syscall_get_nr(current, regs) < 0) return -1; /* Explicit request to skip. */ return 0; } #endif /* CONFIG_HAVE_ARCH_SECCOMP_FILTER */ long prctl_get_seccomp(void) Loading