|
@@ -332,6 +332,26 @@ void put_seccomp_filter(struct task_struct *tsk)
|
|
|
kfree(freeme);
|
|
|
}
|
|
|
}
|
|
|
+
|
|
|
+/**
|
|
|
+ * seccomp_send_sigsys - signals the task to allow in-process syscall emulation
|
|
|
+ * @syscall: syscall number to send to userland
|
|
|
+ * @reason: filter-supplied reason code to send to userland (via si_errno)
|
|
|
+ *
|
|
|
+ * Forces a SIGSYS with a code of SYS_SECCOMP and related sigsys info.
|
|
|
+ */
|
|
|
+static void seccomp_send_sigsys(int syscall, int reason)
|
|
|
+{
|
|
|
+ struct siginfo info;
|
|
|
+ memset(&info, 0, sizeof(info));
|
|
|
+ info.si_signo = SIGSYS;
|
|
|
+ info.si_code = SYS_SECCOMP;
|
|
|
+ info.si_call_addr = (void __user *)KSTK_EIP(current);
|
|
|
+ info.si_errno = reason;
|
|
|
+ info.si_arch = syscall_get_arch(current, task_pt_regs(current));
|
|
|
+ info.si_syscall = syscall;
|
|
|
+ force_sig_info(SIGSYS, &info, current);
|
|
|
+}
|
|
|
#endif /* CONFIG_SECCOMP_FILTER */
|
|
|
|
|
|
/*
|
|
@@ -382,6 +402,12 @@ int __secure_computing(int this_syscall)
|
|
|
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_ALLOW:
|
|
|
return 0;
|
|
|
case SECCOMP_RET_KILL:
|