summaryrefslogtreecommitdiffstats
path: root/tools/testing/selftests
diff options
context:
space:
mode:
authorTyler Hicks <tyhicks@canonical.com>2017-08-11 00:33:56 -0400
committerKees Cook <keescook@chromium.org>2017-08-14 16:46:46 -0400
commite66a39977985b1e69e17c4042cb290768eca9b02 (patch)
tree1247786fccc6a57144930cfe4fd8fbf6f0a44a24 /tools/testing/selftests
parent2b7ea5b5b5799f2878ed454bb48032bed6d101d3 (diff)
seccomp: Filter flag to log all actions except SECCOMP_RET_ALLOW
Add a new filter flag, SECCOMP_FILTER_FLAG_LOG, that enables logging for all actions except for SECCOMP_RET_ALLOW for the given filter. SECCOMP_RET_KILL actions are always logged, when "kill" is in the actions_logged sysctl, and SECCOMP_RET_ALLOW actions are never logged, regardless of this flag. This flag can be used to create noisy filters that result in all non-allowed actions to be logged. A process may have one noisy filter, which is loaded with this flag, as well as a quiet filter that's not loaded with this flag. This allows for the actions in a set of filters to be selectively conveyed to the admin. Since a system could have a large number of allocated seccomp_filter structs, struct packing was taken in consideration. On 64 bit x86, the new log member takes up one byte of an existing four byte hole in the struct. On 32 bit x86, the new log member creates a new four byte hole (unavoidable) and consumes one of those bytes. Unfortunately, the tests added for SECCOMP_FILTER_FLAG_LOG are not capable of inspecting the audit log to verify that the actions taken in the filter were logged. With this patch, the logic for deciding if an action will be logged is: if action == RET_ALLOW: do not log else if action == RET_KILL && RET_KILL in actions_logged: log else if filter-requests-logging && action in actions_logged: log else if audit_enabled && process-is-being-audited: log else: do not log Signed-off-by: Tyler Hicks <tyhicks@canonical.com> Signed-off-by: Kees Cook <keescook@chromium.org>
Diffstat (limited to 'tools/testing/selftests')
-rw-r--r--tools/testing/selftests/seccomp/seccomp_bpf.c69
1 files changed, 68 insertions, 1 deletions
diff --git a/tools/testing/selftests/seccomp/seccomp_bpf.c b/tools/testing/selftests/seccomp/seccomp_bpf.c
index abf708e09892..1c8c22ce7740 100644
--- a/tools/testing/selftests/seccomp/seccomp_bpf.c
+++ b/tools/testing/selftests/seccomp/seccomp_bpf.c
@@ -1739,6 +1739,10 @@ TEST_F_SIGNAL(TRACE_syscall, kill_after_ptrace, SIGSYS)
1739#define SECCOMP_FILTER_FLAG_TSYNC 1 1739#define SECCOMP_FILTER_FLAG_TSYNC 1
1740#endif 1740#endif
1741 1741
1742#ifndef SECCOMP_FILTER_FLAG_LOG
1743#define SECCOMP_FILTER_FLAG_LOG 2
1744#endif
1745
1742#ifndef seccomp 1746#ifndef seccomp
1743int seccomp(unsigned int op, unsigned int flags, void *args) 1747int seccomp(unsigned int op, unsigned int flags, void *args)
1744{ 1748{
@@ -1844,7 +1848,8 @@ TEST(seccomp_syscall_mode_lock)
1844 */ 1848 */
1845TEST(detect_seccomp_filter_flags) 1849TEST(detect_seccomp_filter_flags)
1846{ 1850{
1847 unsigned int flags[] = { SECCOMP_FILTER_FLAG_TSYNC }; 1851 unsigned int flags[] = { SECCOMP_FILTER_FLAG_TSYNC,
1852 SECCOMP_FILTER_FLAG_LOG };
1848 unsigned int flag, all_flags; 1853 unsigned int flag, all_flags;
1849 int i; 1854 int i;
1850 long ret; 1855 long ret;
@@ -2533,6 +2538,67 @@ TEST(syscall_restart)
2533 _metadata->passed = 0; 2538 _metadata->passed = 0;
2534} 2539}
2535 2540
2541TEST_SIGNAL(filter_flag_log, SIGSYS)
2542{
2543 struct sock_filter allow_filter[] = {
2544 BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_ALLOW),
2545 };
2546 struct sock_filter kill_filter[] = {
2547 BPF_STMT(BPF_LD|BPF_W|BPF_ABS,
2548 offsetof(struct seccomp_data, nr)),
2549 BPF_JUMP(BPF_JMP|BPF_JEQ|BPF_K, __NR_getpid, 0, 1),
2550 BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_KILL),
2551 BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_ALLOW),
2552 };
2553 struct sock_fprog allow_prog = {
2554 .len = (unsigned short)ARRAY_SIZE(allow_filter),
2555 .filter = allow_filter,
2556 };
2557 struct sock_fprog kill_prog = {
2558 .len = (unsigned short)ARRAY_SIZE(kill_filter),
2559 .filter = kill_filter,
2560 };
2561 long ret;
2562 pid_t parent = getppid();
2563
2564 ret = prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0);
2565 ASSERT_EQ(0, ret);
2566
2567 /* Verify that the FILTER_FLAG_LOG flag isn't accepted in strict mode */
2568 ret = seccomp(SECCOMP_SET_MODE_STRICT, SECCOMP_FILTER_FLAG_LOG,
2569 &allow_prog);
2570 ASSERT_NE(ENOSYS, errno) {
2571 TH_LOG("Kernel does not support seccomp syscall!");
2572 }
2573 EXPECT_NE(0, ret) {
2574 TH_LOG("Kernel accepted FILTER_FLAG_LOG flag in strict mode!");
2575 }
2576 EXPECT_EQ(EINVAL, errno) {
2577 TH_LOG("Kernel returned unexpected errno for FILTER_FLAG_LOG flag in strict mode!");
2578 }
2579
2580 /* Verify that a simple, permissive filter can be added with no flags */
2581 ret = seccomp(SECCOMP_SET_MODE_FILTER, 0, &allow_prog);
2582 EXPECT_EQ(0, ret);
2583
2584 /* See if the same filter can be added with the FILTER_FLAG_LOG flag */
2585 ret = seccomp(SECCOMP_SET_MODE_FILTER, SECCOMP_FILTER_FLAG_LOG,
2586 &allow_prog);
2587 ASSERT_NE(EINVAL, errno) {
2588 TH_LOG("Kernel does not support the FILTER_FLAG_LOG flag!");
2589 }
2590 EXPECT_EQ(0, ret);
2591
2592 /* Ensure that the kill filter works with the FILTER_FLAG_LOG flag */
2593 ret = seccomp(SECCOMP_SET_MODE_FILTER, SECCOMP_FILTER_FLAG_LOG,
2594 &kill_prog);
2595 EXPECT_EQ(0, ret);
2596
2597 EXPECT_EQ(parent, syscall(__NR_getppid));
2598 /* getpid() should never return. */
2599 EXPECT_EQ(0, syscall(__NR_getpid));
2600}
2601
2536TEST(get_action_avail) 2602TEST(get_action_avail)
2537{ 2603{
2538 __u32 actions[] = { SECCOMP_RET_KILL, SECCOMP_RET_TRAP, 2604 __u32 actions[] = { SECCOMP_RET_KILL, SECCOMP_RET_TRAP,
@@ -2573,6 +2639,7 @@ TEST(get_action_avail)
2573 * - endianness checking when appropriate 2639 * - endianness checking when appropriate
2574 * - 64-bit arg prodding 2640 * - 64-bit arg prodding
2575 * - arch value testing (x86 modes especially) 2641 * - arch value testing (x86 modes especially)
2642 * - verify that FILTER_FLAG_LOG filters generate log messages
2576 * - ... 2643 * - ...
2577 */ 2644 */
2578 2645