Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(12)

Side by Side Diff: sandbox/linux/seccomp-bpf/sandbox_bpf_unittest.cc

Issue 278583005: Linux Sandbox: Add support for SECCOMP_RET_TRACE. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Test change Created 6 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include <errno.h> 5 #include <errno.h>
6 #include <pthread.h> 6 #include <pthread.h>
7 #include <sched.h> 7 #include <sched.h>
8 #include <signal.h>
8 #include <sys/prctl.h> 9 #include <sys/prctl.h>
10 #include <sys/ptrace.h>
9 #include <sys/syscall.h> 11 #include <sys/syscall.h>
10 #include <sys/time.h> 12 #include <sys/time.h>
11 #include <sys/types.h> 13 #include <sys/types.h>
12 #include <sys/utsname.h> 14 #include <sys/utsname.h>
13 #include <unistd.h> 15 #include <unistd.h>
14 16
15 #if defined(ANDROID) 17 #if defined(ANDROID)
16 // Work-around for buggy headers in Android's NDK 18 // Work-around for buggy headers in Android's NDK
17 #define __user 19 #define __user
18 #endif 20 #endif
19 #include <linux/futex.h> 21 #include <linux/futex.h>
20 22
21 #include <ostream> 23 #include <ostream>
22 24
23 #include "base/bind.h" 25 #include "base/bind.h"
24 #include "base/logging.h" 26 #include "base/logging.h"
25 #include "base/memory/scoped_ptr.h" 27 #include "base/memory/scoped_ptr.h"
28 #include "base/posix/eintr_wrapper.h"
26 #include "build/build_config.h" 29 #include "build/build_config.h"
27 #include "sandbox/linux/seccomp-bpf/bpf_tests.h" 30 #include "sandbox/linux/seccomp-bpf/bpf_tests.h"
28 #include "sandbox/linux/seccomp-bpf/syscall.h" 31 #include "sandbox/linux/seccomp-bpf/syscall.h"
29 #include "sandbox/linux/seccomp-bpf/trap.h" 32 #include "sandbox/linux/seccomp-bpf/trap.h"
30 #include "sandbox/linux/seccomp-bpf/verifier.h" 33 #include "sandbox/linux/seccomp-bpf/verifier.h"
31 #include "sandbox/linux/services/broker_process.h" 34 #include "sandbox/linux/services/broker_process.h"
32 #include "sandbox/linux/services/linux_syscalls.h" 35 #include "sandbox/linux/services/linux_syscalls.h"
33 #include "sandbox/linux/tests/unit_tests.h" 36 #include "sandbox/linux/tests/unit_tests.h"
34 #include "testing/gtest/include/gtest/gtest.h" 37 #include "testing/gtest/include/gtest/gtest.h"
35 38
(...skipping 1763 matching lines...) Expand 10 before | Expand all | Expand 10 after
1799 CLONE_CHILD_CLEARTID | CLONE_CHILD_SETTID | SIGCHLD, 1802 CLONE_CHILD_CLEARTID | CLONE_CHILD_SETTID | SIGCHLD,
1800 0, 1803 0,
1801 0, 1804 0,
1802 &pid) == -EPERM); 1805 &pid) == -EPERM);
1803 } 1806 }
1804 1807
1805 BPF_TEST(SandboxBPF, PthreadEquality, PthreadPolicyEquality) { PthreadTest(); } 1808 BPF_TEST(SandboxBPF, PthreadEquality, PthreadPolicyEquality) { PthreadTest(); }
1806 1809
1807 BPF_TEST(SandboxBPF, PthreadBitMask, PthreadPolicyBitMask) { PthreadTest(); } 1810 BPF_TEST(SandboxBPF, PthreadBitMask, PthreadPolicyBitMask) { PthreadTest(); }
1808 1811
1812 // It is possible that libc does not define these, but the kernel supports this.
1813 // We define them here anyway. The test will give up silently if it gets an
1814 // EINVAL as a result of these not being supported.
1815 #ifndef PTRACE_O_TRACESECCOMP
1816 #define PTRACE_O_TRACESECCOMP 0x00000080
1817 #endif
1818 #ifndef PTRACE_EVENT_SECCOMP
1819 #define PTRACE_EVENT_SECCOMP 8
1820 #endif
1821
1822 const uint16_t kTraceData = 0xcc;
1823
1824 class TraceAllPolicy : public SandboxBPFPolicy {
1825 public:
1826 TraceAllPolicy() {}
1827 virtual ~TraceAllPolicy() {}
1828
1829 virtual ErrorCode EvaluateSyscall(SandboxBPF* sandbox_compiler,
1830 int system_call_number) const OVERRIDE {
1831 if (!SandboxBPF::IsValidSyscallNumber(system_call_number)) {
jln (very slow on Chromium) 2014/05/20 03:02:10 This if is not needed anymore (due to a recent CL)
rickyz (Google) 2014/05/20 22:34:01 Done.
1832 return ErrorCode(ENOSYS);
1833 }
1834 return ErrorCode(ErrorCode::ERR_TRACE + kTraceData);
1835 }
1836
1837 private:
1838 DISALLOW_COPY_AND_ASSIGN(TraceAllPolicy);
1839 };
1840
1841 SANDBOX_TEST(SandboxBPF, DISABLE_ON_TSAN(SeccompRetTrace)) {
1842 if (SandboxBPF::SupportsSeccompSandbox(-1) !=
1843 sandbox::SandboxBPF::STATUS_AVAILABLE) {
1844 return;
1845 }
1846
1847 pid_t pid = fork();
1848 BPF_ASSERT(pid != -1);
jln (very slow on Chromium) 2014/05/20 03:02:10 BPF_ASSERT_NE()
rickyz (Google) 2014/05/20 22:34:01 Done.
1849 if (pid == 0) {
1850 pid_t my_pid = getpid();
1851 BPF_ASSERT(ptrace(PTRACE_TRACEME, -1, NULL, NULL) != -1);
1852 BPF_ASSERT(raise(SIGSTOP) == 0);
jln (very slow on Chromium) 2014/05/20 03:02:10 BPF_ASSERT_EQ() (etc. for the rest of the test).
rickyz (Google) 2014/05/20 22:34:01 Done.
1853 SandboxBPF sandbox;
1854 sandbox.SetSandboxPolicy(new TraceAllPolicy);
1855 BPF_ASSERT(sandbox.StartSandbox(SandboxBPF::PROCESS_SINGLE_THREADED));
1856
1857 // getpid is allowed.
1858 BPF_ASSERT(syscall(__NR_getpid) == my_pid);
1859
1860 // write is skipped and returns a fake value.
1861 BPF_ASSERT(write(STDERR_FILENO, "A", 1) == kExpectedReturnValue);
1862
1863 // kill is rewritten to exit(kExpectedReturnValue).
1864 syscall(__NR_kill, my_pid, SIGKILL);
1865
1866 // Should not be reached.
1867 BPF_ASSERT(0);
jln (very slow on Chromium) 2014/05/20 03:02:10 s/0/false/
rickyz (Google) 2014/05/20 22:34:01 Done.
1868 }
1869
1870 int status;
1871 BPF_ASSERT(HANDLE_EINTR(waitpid(pid, &status, WUNTRACED)) != -1);
1872 BPF_ASSERT(WIFSTOPPED(status));
1873
1874 errno = 0;
1875 if (ptrace(PTRACE_SETOPTIONS, pid, NULL, PTRACE_O_TRACESECCOMP) == -1) {
1876 // Give up (but don't fail) if PTRACE_O_TRACESECCOMP is not supported.
jln (very slow on Chromium) 2014/05/20 03:02:10 It should now be supported anywhere seccomp-bpf is
rickyz (Google) 2014/05/20 22:34:01 Yeah, I don't see any release with seccomp-bpf and
1877 BPF_ASSERT(errno == EINVAL);
1878 BPF_ASSERT(ptrace(PTRACE_CONT, pid, NULL, SIGKILL) != -1);
1879 return;
1880 }
1881
1882 BPF_ASSERT(ptrace(PTRACE_CONT, pid, NULL, NULL) != -1);
1883 while (true) {
1884 BPF_ASSERT(HANDLE_EINTR(waitpid(pid, &status, 0)) != -1);
1885 if (WIFEXITED(status) || WIFSIGNALED(status)) {
1886 BPF_ASSERT(WIFEXITED(status) &&
1887 WEXITSTATUS(status) == kExpectedReturnValue);
1888 break;
1889 }
1890
1891 if (!WIFSTOPPED(status) || WSTOPSIG(status) != SIGTRAP ||
1892 (status >> 16) != PTRACE_EVENT_SECCOMP) {
1893 BPF_ASSERT(ptrace(PTRACE_CONT, pid, NULL, NULL) != -1);
1894 continue;
1895 }
1896
1897 unsigned long data;
1898 BPF_ASSERT(ptrace(PTRACE_GETEVENTMSG, pid, NULL, &data) != -1);
1899 BPF_ASSERT(data == kTraceData);
1900
1901 struct pt_regs regs;
1902 BPF_ASSERT(ptrace(PTRACE_GETREGS, pid, NULL, &regs) != -1);
1903 switch (SECCOMP_PT_SYSCALL(regs)) {
1904 case __NR_write:
1905 // Skip write, make it return kExpectedReturnValue.
1906 SECCOMP_PT_SYSCALL(regs) = -1;
1907 SECCOMP_PT_RESULT(regs) = kExpectedReturnValue;
1908 BPF_ASSERT(ptrace(PTRACE_SETREGS, pid, NULL, &regs) != -1);
1909 break;
1910
1911 case __NR_kill:
1912 // Rewrite to exit(kExpectedReturnValue).
1913 SECCOMP_PT_SYSCALL(regs) = __NR_exit;
1914 SECCOMP_PT_PARM1(regs) = kExpectedReturnValue;
1915 BPF_ASSERT(ptrace(PTRACE_SETREGS, pid, NULL, &regs) != -1);
1916 break;
1917
1918 default:
1919 // Allow all other syscalls.
1920 break;
1921 }
1922
1923 BPF_ASSERT(ptrace(PTRACE_CONT, pid, NULL, NULL) != -1);
1924 }
1925 }
1926
1809 } // namespace 1927 } // namespace
1810 1928
1811 } // namespace sandbox 1929 } // namespace sandbox
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698