Chromium Code Reviews| 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 |