OLD | NEW |
---|---|
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 Loading... | |
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, ®s) != -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, ®s) != -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, ®s) != -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 |
OLD | NEW |