aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorWill Drewry <wad@chromium.org>2012-04-12 17:48:01 -0400
committerJames Morris <james.l.morris@oracle.com>2012-04-13 21:13:21 -0400
commitbb6ea4301a1109afdacaee576fedbfcd7152fc86 (patch)
tree5412219057d8e0ec2a30d0a1ad4f6b7dd398c754
parenta0727e8ce513fe6890416da960181ceb10fbfae6 (diff)
seccomp: Add SECCOMP_RET_TRAP
Adds a new return value to seccomp filters that triggers a SIGSYS to be delivered with the new SYS_SECCOMP si_code. This allows in-process system call emulation, including just specifying an errno or cleanly dumping core, rather than just dying. Suggested-by: Markus Gutschke <markus@chromium.org> Suggested-by: Julien Tinnes <jln@chromium.org> Signed-off-by: Will Drewry <wad@chromium.org> Acked-by: Eric Paris <eparis@redhat.com> v18: - acked-by, rebase - don't mention secure_computing_int() anymore v15: - use audit_seccomp/skip - pad out error spacing; clean up switch (indan@nul.nu) v14: - n/a v13: - rebase on to 88ebdda6159ffc15699f204c33feb3e431bf9bdc v12: - rebase on to linux-next v11: - clarify the comment (indan@nul.nu) - s/sigtrap/sigsys v10: - use SIGSYS, syscall_get_arch, updates arch/Kconfig note suggested-by (though original suggestion had other behaviors) v9: - changes to SIGILL v8: - clean up based on changes to dependent patches v7: - introduction Signed-off-by: James Morris <james.l.morris@oracle.com>
-rw-r--r--arch/Kconfig14
-rw-r--r--include/asm-generic/siginfo.h2
-rw-r--r--include/linux/seccomp.h1
-rw-r--r--kernel/seccomp.c26
4 files changed, 37 insertions, 6 deletions
diff --git a/arch/Kconfig b/arch/Kconfig
index beaab68c13b7..66aef13f6038 100644
--- a/arch/Kconfig
+++ b/arch/Kconfig
@@ -219,11 +219,15 @@ config ARCH_WANT_OLD_COMPAT_IPC
219config HAVE_ARCH_SECCOMP_FILTER 219config HAVE_ARCH_SECCOMP_FILTER
220 bool 220 bool
221 help 221 help
222 This symbol should be selected by an architecure if it provides 222 This symbol should be selected by an architecure if it provides:
223 asm/syscall.h, specifically syscall_get_arguments(), 223 asm/syscall.h:
224 syscall_get_arch(), and syscall_set_return_value(). Additionally, 224 - syscall_get_arch()
225 its system call entry path must respect a return value of -1 from 225 - syscall_get_arguments()
226 __secure_computing() and/or secure_computing(). 226 - syscall_rollback()
227 - syscall_set_return_value()
228 SIGSYS siginfo_t support must be implemented.
229 __secure_computing()/secure_computing()'s return value must be
230 checked, with -1 resulting in the syscall being skipped.
227 231
228config SECCOMP_FILTER 232config SECCOMP_FILTER
229 def_bool y 233 def_bool y
diff --git a/include/asm-generic/siginfo.h b/include/asm-generic/siginfo.h
index 31306f55eb02..af5d0350f84c 100644
--- a/include/asm-generic/siginfo.h
+++ b/include/asm-generic/siginfo.h
@@ -93,7 +93,7 @@ typedef struct siginfo {
93 93
94 /* SIGSYS */ 94 /* SIGSYS */
95 struct { 95 struct {
96 void __user *_call_addr; /* calling insn */ 96 void __user *_call_addr; /* calling user insn */
97 int _syscall; /* triggering system call number */ 97 int _syscall; /* triggering system call number */
98 unsigned int _arch; /* AUDIT_ARCH_* of syscall */ 98 unsigned int _arch; /* AUDIT_ARCH_* of syscall */
99 } _sigsys; 99 } _sigsys;
diff --git a/include/linux/seccomp.h b/include/linux/seccomp.h
index b4ce2c816e06..317ccb78cf40 100644
--- a/include/linux/seccomp.h
+++ b/include/linux/seccomp.h
@@ -19,6 +19,7 @@
19 * selects the least permissive choice. 19 * selects the least permissive choice.
20 */ 20 */
21#define SECCOMP_RET_KILL 0x00000000U /* kill the task immediately */ 21#define SECCOMP_RET_KILL 0x00000000U /* kill the task immediately */
22#define SECCOMP_RET_TRAP 0x00030000U /* disallow and force a SIGSYS */
22#define SECCOMP_RET_ERRNO 0x00050000U /* returns an errno */ 23#define SECCOMP_RET_ERRNO 0x00050000U /* returns an errno */
23#define SECCOMP_RET_ALLOW 0x7fff0000U /* allow */ 24#define SECCOMP_RET_ALLOW 0x7fff0000U /* allow */
24 25
diff --git a/kernel/seccomp.c b/kernel/seccomp.c
index 5f78fb6d2212..9c3830692a08 100644
--- a/kernel/seccomp.c
+++ b/kernel/seccomp.c
@@ -332,6 +332,26 @@ void put_seccomp_filter(struct task_struct *tsk)
332 kfree(freeme); 332 kfree(freeme);
333 } 333 }
334} 334}
335
336/**
337 * seccomp_send_sigsys - signals the task to allow in-process syscall emulation
338 * @syscall: syscall number to send to userland
339 * @reason: filter-supplied reason code to send to userland (via si_errno)
340 *
341 * Forces a SIGSYS with a code of SYS_SECCOMP and related sigsys info.
342 */
343static void seccomp_send_sigsys(int syscall, int reason)
344{
345 struct siginfo info;
346 memset(&info, 0, sizeof(info));
347 info.si_signo = SIGSYS;
348 info.si_code = SYS_SECCOMP;
349 info.si_call_addr = (void __user *)KSTK_EIP(current);
350 info.si_errno = reason;
351 info.si_arch = syscall_get_arch(current, task_pt_regs(current));
352 info.si_syscall = syscall;
353 force_sig_info(SIGSYS, &info, current);
354}
335#endif /* CONFIG_SECCOMP_FILTER */ 355#endif /* CONFIG_SECCOMP_FILTER */
336 356
337/* 357/*
@@ -382,6 +402,12 @@ int __secure_computing(int this_syscall)
382 syscall_set_return_value(current, task_pt_regs(current), 402 syscall_set_return_value(current, task_pt_regs(current),
383 -data, 0); 403 -data, 0);
384 goto skip; 404 goto skip;
405 case SECCOMP_RET_TRAP:
406 /* Show the handler the original registers. */
407 syscall_rollback(current, task_pt_regs(current));
408 /* Let the filter pass back 16 bits of data. */
409 seccomp_send_sigsys(this_syscall, data);
410 goto skip;
385 case SECCOMP_RET_ALLOW: 411 case SECCOMP_RET_ALLOW:
386 return 0; 412 return 0;
387 case SECCOMP_RET_KILL: 413 case SECCOMP_RET_KILL: