int __secure_computing(int this_syscall) { int mode = current->seccomp.mode; int exit_sig = 0; int *syscall; u32 ret; switch (mode) { case SECCOMP_MODE_STRICT: syscall = mode1_syscalls; #ifdef CONFIG_COMPAT if (is_compat_task()) syscall = mode1_syscalls_32; #endif do { if (*syscall == this_syscall) return 0; } while (*++syscall); exit_sig = SIGKILL; ret = SECCOMP_RET_KILL; break; #ifdef CONFIG_SECCOMP_FILTER case SECCOMP_MODE_FILTER: { int data; struct pt_regs *regs = task_pt_regs(current); ret = seccomp_run_filters(this_syscall); data = ret & SECCOMP_RET_DATA; ret &= SECCOMP_RET_ACTION; switch (ret) { case SECCOMP_RET_ERRNO: /* Set the low-order 16-bits as a errno. */ syscall_set_return_value(current, regs, -data, 0); goto skip; case SECCOMP_RET_TRAP: /* Show the handler the original registers. */ syscall_rollback(current, regs); /* Let the filter pass back 16 bits of data. */ seccomp_send_sigsys(this_syscall, data); goto skip; case SECCOMP_RET_TRACE: /* Skip these calls if there is no tracer. */ if (!ptrace_event_enabled(current, PTRACE_EVENT_SECCOMP)) { syscall_set_return_value(current, regs, -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)) break; if (syscall_get_nr(current, regs) < 0) goto skip; /* Explicit request to skip. */ return 0; case SECCOMP_RET_ALLOW: return 0; case SECCOMP_RET_KILL: default: break; } exit_sig = SIGSYS; break; } #endif default: BUG(); } #ifdef SECCOMP_DEBUG dump_stack(); #endif audit_seccomp(this_syscall, exit_sig, ret); do_exit(exit_sig); #ifdef CONFIG_SECCOMP_FILTER skip: audit_seccomp(this_syscall, exit_sig, ret); #endif return -1; }
int __secure_computing_int(int this_syscall) { int mode = current->seccomp.mode; int exit_sig = 0; int *syscall; u32 ret = SECCOMP_RET_KILL; int data; switch (mode) { case SECCOMP_MODE_STRICT: syscall = mode1_syscalls; #ifdef CONFIG_COMPAT if (is_compat_task()) syscall = mode1_syscalls_32; #endif do { if (*syscall == this_syscall) return 0; } while (*++syscall); exit_sig = SIGKILL; break; #ifdef CONFIG_SECCOMP_FILTER case SECCOMP_MODE_FILTER: ret = seccomp_run_filters(this_syscall); data = ret & SECCOMP_RET_DATA; switch (ret & SECCOMP_RET_ACTION) { case SECCOMP_RET_ERRNO: /* Set the low-order 16-bits as a errno. */ syscall_set_return_value(current, task_pt_regs(current), -data, 0); goto skip; case SECCOMP_RET_TRAP: /* Show the handler the original registers. */ syscall_rollback(current, task_pt_regs(current)); /* Let the filter pass back 16 bits of data. */ seccomp_send_sigsys(this_syscall, data); goto skip; case SECCOMP_RET_TRACE: /* Skip these calls if there is no tracer. */ if (!ptrace_event_enabled(current, PTRACE_EVENT_SECCOMP)) goto skip; /* Allow the BPF to provide the event message */ ptrace_event(PTRACE_EVENT_SECCOMP, data); if (fatal_signal_pending(current)) break; return 0; case SECCOMP_RET_ALLOW: return 0; case SECCOMP_RET_KILL: default: break; } exit_sig = SIGSYS; break; #endif default: BUG(); } #ifdef SECCOMP_DEBUG dump_stack(); #endif __audit_seccomp(this_syscall, exit_sig, ret); do_exit(exit_sig); skip: audit_seccomp(this_syscall, exit_sig, ret); return -1; }