|
@@ -74,7 +74,12 @@
|
|
#define SECCOMP_RET_ERRNO 0x00050000U /* returns an errno */
|
|
#define SECCOMP_RET_ERRNO 0x00050000U /* returns an errno */
|
|
#define SECCOMP_RET_TRACE 0x7ff00000U /* pass to a tracer or disallow */
|
|
#define SECCOMP_RET_TRACE 0x7ff00000U /* pass to a tracer or disallow */
|
|
#define SECCOMP_RET_ALLOW 0x7fff0000U /* allow */
|
|
#define SECCOMP_RET_ALLOW 0x7fff0000U /* allow */
|
|
|
|
+#endif
|
|
|
|
+#ifndef SECCOMP_RET_LOG
|
|
|
|
+#define SECCOMP_RET_LOG 0x7ffc0000U /* allow after logging */
|
|
|
|
+#endif
|
|
|
|
|
|
|
|
+#ifndef SECCOMP_RET_ACTION
|
|
/* Masks for the return value sections. */
|
|
/* Masks for the return value sections. */
|
|
#define SECCOMP_RET_ACTION 0x7fff0000U
|
|
#define SECCOMP_RET_ACTION 0x7fff0000U
|
|
#define SECCOMP_RET_DATA 0x0000ffffU
|
|
#define SECCOMP_RET_DATA 0x0000ffffU
|
|
@@ -342,6 +347,28 @@ TEST(empty_prog)
|
|
EXPECT_EQ(EINVAL, errno);
|
|
EXPECT_EQ(EINVAL, errno);
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+TEST(log_all)
|
|
|
|
+{
|
|
|
|
+ struct sock_filter filter[] = {
|
|
|
|
+ BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_LOG),
|
|
|
|
+ };
|
|
|
|
+ struct sock_fprog prog = {
|
|
|
|
+ .len = (unsigned short)ARRAY_SIZE(filter),
|
|
|
|
+ .filter = filter,
|
|
|
|
+ };
|
|
|
|
+ long ret;
|
|
|
|
+ pid_t parent = getppid();
|
|
|
|
+
|
|
|
|
+ ret = prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0);
|
|
|
|
+ ASSERT_EQ(0, ret);
|
|
|
|
+
|
|
|
|
+ ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &prog);
|
|
|
|
+ ASSERT_EQ(0, ret);
|
|
|
|
+
|
|
|
|
+ /* getppid() should succeed and be logged (no check for logging) */
|
|
|
|
+ EXPECT_EQ(parent, syscall(__NR_getppid));
|
|
|
|
+}
|
|
|
|
+
|
|
TEST_SIGNAL(unknown_ret_is_kill_inside, SIGSYS)
|
|
TEST_SIGNAL(unknown_ret_is_kill_inside, SIGSYS)
|
|
{
|
|
{
|
|
struct sock_filter filter[] = {
|
|
struct sock_filter filter[] = {
|
|
@@ -756,6 +783,7 @@ TEST_F(TRAP, handler)
|
|
|
|
|
|
FIXTURE_DATA(precedence) {
|
|
FIXTURE_DATA(precedence) {
|
|
struct sock_fprog allow;
|
|
struct sock_fprog allow;
|
|
|
|
+ struct sock_fprog log;
|
|
struct sock_fprog trace;
|
|
struct sock_fprog trace;
|
|
struct sock_fprog error;
|
|
struct sock_fprog error;
|
|
struct sock_fprog trap;
|
|
struct sock_fprog trap;
|
|
@@ -767,6 +795,13 @@ FIXTURE_SETUP(precedence)
|
|
struct sock_filter allow_insns[] = {
|
|
struct sock_filter allow_insns[] = {
|
|
BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_ALLOW),
|
|
BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_ALLOW),
|
|
};
|
|
};
|
|
|
|
+ struct sock_filter log_insns[] = {
|
|
|
|
+ BPF_STMT(BPF_LD|BPF_W|BPF_ABS,
|
|
|
|
+ offsetof(struct seccomp_data, nr)),
|
|
|
|
+ BPF_JUMP(BPF_JMP|BPF_JEQ|BPF_K, __NR_getpid, 1, 0),
|
|
|
|
+ BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_ALLOW),
|
|
|
|
+ BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_LOG),
|
|
|
|
+ };
|
|
struct sock_filter trace_insns[] = {
|
|
struct sock_filter trace_insns[] = {
|
|
BPF_STMT(BPF_LD|BPF_W|BPF_ABS,
|
|
BPF_STMT(BPF_LD|BPF_W|BPF_ABS,
|
|
offsetof(struct seccomp_data, nr)),
|
|
offsetof(struct seccomp_data, nr)),
|
|
@@ -803,6 +838,7 @@ FIXTURE_SETUP(precedence)
|
|
memcpy(self->_x.filter, &_x##_insns, sizeof(_x##_insns)); \
|
|
memcpy(self->_x.filter, &_x##_insns, sizeof(_x##_insns)); \
|
|
self->_x.len = (unsigned short)ARRAY_SIZE(_x##_insns)
|
|
self->_x.len = (unsigned short)ARRAY_SIZE(_x##_insns)
|
|
FILTER_ALLOC(allow);
|
|
FILTER_ALLOC(allow);
|
|
|
|
+ FILTER_ALLOC(log);
|
|
FILTER_ALLOC(trace);
|
|
FILTER_ALLOC(trace);
|
|
FILTER_ALLOC(error);
|
|
FILTER_ALLOC(error);
|
|
FILTER_ALLOC(trap);
|
|
FILTER_ALLOC(trap);
|
|
@@ -813,6 +849,7 @@ FIXTURE_TEARDOWN(precedence)
|
|
{
|
|
{
|
|
#define FILTER_FREE(_x) if (self->_x.filter) free(self->_x.filter)
|
|
#define FILTER_FREE(_x) if (self->_x.filter) free(self->_x.filter)
|
|
FILTER_FREE(allow);
|
|
FILTER_FREE(allow);
|
|
|
|
+ FILTER_FREE(log);
|
|
FILTER_FREE(trace);
|
|
FILTER_FREE(trace);
|
|
FILTER_FREE(error);
|
|
FILTER_FREE(error);
|
|
FILTER_FREE(trap);
|
|
FILTER_FREE(trap);
|
|
@@ -830,6 +867,8 @@ TEST_F(precedence, allow_ok)
|
|
|
|
|
|
ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->allow);
|
|
ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->allow);
|
|
ASSERT_EQ(0, ret);
|
|
ASSERT_EQ(0, ret);
|
|
|
|
+ ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->log);
|
|
|
|
+ ASSERT_EQ(0, ret);
|
|
ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->trace);
|
|
ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->trace);
|
|
ASSERT_EQ(0, ret);
|
|
ASSERT_EQ(0, ret);
|
|
ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->error);
|
|
ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->error);
|
|
@@ -854,6 +893,8 @@ TEST_F_SIGNAL(precedence, kill_is_highest, SIGSYS)
|
|
|
|
|
|
ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->allow);
|
|
ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->allow);
|
|
ASSERT_EQ(0, ret);
|
|
ASSERT_EQ(0, ret);
|
|
|
|
+ ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->log);
|
|
|
|
+ ASSERT_EQ(0, ret);
|
|
ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->trace);
|
|
ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->trace);
|
|
ASSERT_EQ(0, ret);
|
|
ASSERT_EQ(0, ret);
|
|
ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->error);
|
|
ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->error);
|
|
@@ -885,6 +926,8 @@ TEST_F_SIGNAL(precedence, kill_is_highest_in_any_order, SIGSYS)
|
|
ASSERT_EQ(0, ret);
|
|
ASSERT_EQ(0, ret);
|
|
ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->error);
|
|
ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->error);
|
|
ASSERT_EQ(0, ret);
|
|
ASSERT_EQ(0, ret);
|
|
|
|
+ ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->log);
|
|
|
|
+ ASSERT_EQ(0, ret);
|
|
ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->trace);
|
|
ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->trace);
|
|
ASSERT_EQ(0, ret);
|
|
ASSERT_EQ(0, ret);
|
|
ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->trap);
|
|
ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->trap);
|
|
@@ -906,6 +949,8 @@ TEST_F_SIGNAL(precedence, trap_is_second, SIGSYS)
|
|
|
|
|
|
ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->allow);
|
|
ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->allow);
|
|
ASSERT_EQ(0, ret);
|
|
ASSERT_EQ(0, ret);
|
|
|
|
+ ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->log);
|
|
|
|
+ ASSERT_EQ(0, ret);
|
|
ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->trace);
|
|
ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->trace);
|
|
ASSERT_EQ(0, ret);
|
|
ASSERT_EQ(0, ret);
|
|
ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->error);
|
|
ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->error);
|
|
@@ -931,6 +976,8 @@ TEST_F_SIGNAL(precedence, trap_is_second_in_any_order, SIGSYS)
|
|
ASSERT_EQ(0, ret);
|
|
ASSERT_EQ(0, ret);
|
|
ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->trap);
|
|
ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->trap);
|
|
ASSERT_EQ(0, ret);
|
|
ASSERT_EQ(0, ret);
|
|
|
|
+ ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->log);
|
|
|
|
+ ASSERT_EQ(0, ret);
|
|
ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->trace);
|
|
ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->trace);
|
|
ASSERT_EQ(0, ret);
|
|
ASSERT_EQ(0, ret);
|
|
ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->error);
|
|
ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->error);
|
|
@@ -952,6 +999,8 @@ TEST_F(precedence, errno_is_third)
|
|
|
|
|
|
ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->allow);
|
|
ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->allow);
|
|
ASSERT_EQ(0, ret);
|
|
ASSERT_EQ(0, ret);
|
|
|
|
+ ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->log);
|
|
|
|
+ ASSERT_EQ(0, ret);
|
|
ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->trace);
|
|
ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->trace);
|
|
ASSERT_EQ(0, ret);
|
|
ASSERT_EQ(0, ret);
|
|
ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->error);
|
|
ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->error);
|
|
@@ -970,6 +1019,8 @@ TEST_F(precedence, errno_is_third_in_any_order)
|
|
ret = prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0);
|
|
ret = prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0);
|
|
ASSERT_EQ(0, ret);
|
|
ASSERT_EQ(0, ret);
|
|
|
|
|
|
|
|
+ ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->log);
|
|
|
|
+ ASSERT_EQ(0, ret);
|
|
ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->error);
|
|
ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->error);
|
|
ASSERT_EQ(0, ret);
|
|
ASSERT_EQ(0, ret);
|
|
ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->trace);
|
|
ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->trace);
|
|
@@ -992,6 +1043,8 @@ TEST_F(precedence, trace_is_fourth)
|
|
|
|
|
|
ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->allow);
|
|
ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->allow);
|
|
ASSERT_EQ(0, ret);
|
|
ASSERT_EQ(0, ret);
|
|
|
|
+ ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->log);
|
|
|
|
+ ASSERT_EQ(0, ret);
|
|
ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->trace);
|
|
ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->trace);
|
|
ASSERT_EQ(0, ret);
|
|
ASSERT_EQ(0, ret);
|
|
/* Should work just fine. */
|
|
/* Should work just fine. */
|
|
@@ -1013,12 +1066,54 @@ TEST_F(precedence, trace_is_fourth_in_any_order)
|
|
ASSERT_EQ(0, ret);
|
|
ASSERT_EQ(0, ret);
|
|
ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->allow);
|
|
ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->allow);
|
|
ASSERT_EQ(0, ret);
|
|
ASSERT_EQ(0, ret);
|
|
|
|
+ ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->log);
|
|
|
|
+ ASSERT_EQ(0, ret);
|
|
/* Should work just fine. */
|
|
/* Should work just fine. */
|
|
EXPECT_EQ(parent, syscall(__NR_getppid));
|
|
EXPECT_EQ(parent, syscall(__NR_getppid));
|
|
/* No ptracer */
|
|
/* No ptracer */
|
|
EXPECT_EQ(-1, syscall(__NR_getpid));
|
|
EXPECT_EQ(-1, syscall(__NR_getpid));
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+TEST_F(precedence, log_is_fifth)
|
|
|
|
+{
|
|
|
|
+ pid_t mypid, parent;
|
|
|
|
+ long ret;
|
|
|
|
+
|
|
|
|
+ mypid = getpid();
|
|
|
|
+ parent = getppid();
|
|
|
|
+ ret = prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0);
|
|
|
|
+ ASSERT_EQ(0, ret);
|
|
|
|
+
|
|
|
|
+ ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->allow);
|
|
|
|
+ ASSERT_EQ(0, ret);
|
|
|
|
+ ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->log);
|
|
|
|
+ ASSERT_EQ(0, ret);
|
|
|
|
+ /* Should work just fine. */
|
|
|
|
+ EXPECT_EQ(parent, syscall(__NR_getppid));
|
|
|
|
+ /* Should also work just fine */
|
|
|
|
+ EXPECT_EQ(mypid, syscall(__NR_getpid));
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+TEST_F(precedence, log_is_fifth_in_any_order)
|
|
|
|
+{
|
|
|
|
+ pid_t mypid, parent;
|
|
|
|
+ long ret;
|
|
|
|
+
|
|
|
|
+ mypid = getpid();
|
|
|
|
+ parent = getppid();
|
|
|
|
+ ret = prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0);
|
|
|
|
+ ASSERT_EQ(0, ret);
|
|
|
|
+
|
|
|
|
+ ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->log);
|
|
|
|
+ ASSERT_EQ(0, ret);
|
|
|
|
+ ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->allow);
|
|
|
|
+ ASSERT_EQ(0, ret);
|
|
|
|
+ /* Should work just fine. */
|
|
|
|
+ EXPECT_EQ(parent, syscall(__NR_getppid));
|
|
|
|
+ /* Should also work just fine */
|
|
|
|
+ EXPECT_EQ(mypid, syscall(__NR_getpid));
|
|
|
|
+}
|
|
|
|
+
|
|
#ifndef PTRACE_O_TRACESECCOMP
|
|
#ifndef PTRACE_O_TRACESECCOMP
|
|
#define PTRACE_O_TRACESECCOMP 0x00000080
|
|
#define PTRACE_O_TRACESECCOMP 0x00000080
|
|
#endif
|
|
#endif
|
|
@@ -2603,7 +2698,7 @@ TEST(get_action_avail)
|
|
{
|
|
{
|
|
__u32 actions[] = { SECCOMP_RET_KILL, SECCOMP_RET_TRAP,
|
|
__u32 actions[] = { SECCOMP_RET_KILL, SECCOMP_RET_TRAP,
|
|
SECCOMP_RET_ERRNO, SECCOMP_RET_TRACE,
|
|
SECCOMP_RET_ERRNO, SECCOMP_RET_TRACE,
|
|
- SECCOMP_RET_ALLOW };
|
|
|
|
|
|
+ SECCOMP_RET_LOG, SECCOMP_RET_ALLOW };
|
|
__u32 unknown_action = 0x10000000U;
|
|
__u32 unknown_action = 0x10000000U;
|
|
int i;
|
|
int i;
|
|
long ret;
|
|
long ret;
|
|
@@ -2640,6 +2735,7 @@ TEST(get_action_avail)
|
|
* - 64-bit arg prodding
|
|
* - 64-bit arg prodding
|
|
* - arch value testing (x86 modes especially)
|
|
* - arch value testing (x86 modes especially)
|
|
* - verify that FILTER_FLAG_LOG filters generate log messages
|
|
* - verify that FILTER_FLAG_LOG filters generate log messages
|
|
|
|
+ * - verify that RET_LOG generates log messages
|
|
* - ...
|
|
* - ...
|
|
*/
|
|
*/
|
|
|
|
|