Index: sandbox/linux/bpf_dsl/bpf_dsl_unittest.cc |
diff --git a/sandbox/linux/bpf_dsl/bpf_dsl_unittest.cc b/sandbox/linux/bpf_dsl/bpf_dsl_unittest.cc |
index 46c8be13580b4f5830355739df656501b991f278..f4760a6593762f436e49ceef4ca8734bf70c6671 100644 |
--- a/sandbox/linux/bpf_dsl/bpf_dsl_unittest.cc |
+++ b/sandbox/linux/bpf_dsl/bpf_dsl_unittest.cc |
@@ -9,6 +9,7 @@ |
#include <sys/socket.h> |
#include <sys/utsname.h> |
+#include "base/files/scoped_file.h" |
#include "base/macros.h" |
#include "build/build_config.h" |
#include "sandbox/linux/seccomp-bpf/bpf_tests.h" |
@@ -16,6 +17,8 @@ |
#include "sandbox/linux/seccomp-bpf/sandbox_bpf_policy.h" |
#include "sandbox/linux/seccomp-bpf/syscall.h" |
+#define CASES SANDBOX_BPF_DSL_CASES |
+ |
// Helper macro to assert that invoking system call |sys| directly via |
// Syscall::Call with arguments |...| returns |res|. |
// Errors can be asserted by specifying a value like "-EINVAL". |
@@ -36,6 +39,10 @@ class Stubs { |
return Syscall::Call(__NR_setpgid, pid, pgid); |
} |
+ static int fcntl(int fd, int cmd, unsigned long arg = 0) { |
+ return Syscall::Call(__NR_fcntl, fd, cmd, arg); |
+ } |
+ |
static int uname(struct utsname* buf) { |
return Syscall::Call(__NR_uname, buf); |
} |
@@ -275,6 +282,42 @@ BPF_TEST_C(BPFDSL, ElseIfTest, ElseIfPolicy) { |
ASSERT_SYSCALL_RESULT(-EACCES, setuid, 0x0222); |
} |
+class SwitchPolicy : public SandboxBPFDSLPolicy { |
+ public: |
+ SwitchPolicy() {} |
+ virtual ~SwitchPolicy() {} |
+ virtual ResultExpr EvaluateSyscall(int sysno) const OVERRIDE { |
+ if (sysno == __NR_fcntl) { |
+ const Arg<int> cmd(1); |
+ const Arg<unsigned long> long_arg(2); |
+ return Switch(cmd) |
+ .CASES((F_GETFL, F_GETFD), Error(ENOENT)) |
+ .Case(F_SETFD, If(long_arg == O_CLOEXEC, Allow()).Else(Error(EINVAL))) |
+ .Case(F_SETFL, Error(EPERM)) |
+ .Default(Error(EACCES)); |
+ } |
+ return Allow(); |
+ } |
+ |
+ private: |
+ DISALLOW_COPY_AND_ASSIGN(SwitchPolicy); |
+}; |
+ |
+BPF_TEST_C(BPFDSL, SwitchTest, SwitchPolicy) { |
+ base::ScopedFD sock_fd(socket(AF_UNIX, SOCK_STREAM, 0)); |
+ BPF_ASSERT(sock_fd.is_valid()); |
+ |
+ ASSERT_SYSCALL_RESULT(-ENOENT, fcntl, sock_fd.get(), F_GETFD); |
+ ASSERT_SYSCALL_RESULT(-ENOENT, fcntl, sock_fd.get(), F_GETFL); |
+ |
+ ASSERT_SYSCALL_RESULT(0, fcntl, sock_fd.get(), F_SETFD, O_CLOEXEC); |
+ ASSERT_SYSCALL_RESULT(-EINVAL, fcntl, sock_fd.get(), F_SETFD, 0); |
+ |
+ ASSERT_SYSCALL_RESULT(-EPERM, fcntl, sock_fd.get(), F_SETFL, O_RDONLY); |
+ |
+ ASSERT_SYSCALL_RESULT(-EACCES, fcntl, sock_fd.get(), F_DUPFD, 0); |
+} |
+ |
} // namespace |
} // namespace bpf_dsl |
} // namespace sandbox |