Don't preload rarely seen large images
[chromium-blink-merge.git] / sandbox / linux / services / yama_unittests.cc
blob398eafecf2ad2ffba82e84ea9707b92b1952423c
1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include <errno.h>
6 #include <fcntl.h>
7 #include <sys/ptrace.h>
8 #include <sys/stat.h>
9 #include <sys/types.h>
10 #include <unistd.h>
12 #include "base/bind.h"
13 #include "base/bind_helpers.h"
14 #include "base/compiler_specific.h"
15 #include "base/posix/eintr_wrapper.h"
16 #include "base/strings/string_util.h"
17 #include "base/sys_info.h"
18 #include "sandbox/linux/services/scoped_process.h"
19 #include "sandbox/linux/services/yama.h"
20 #include "sandbox/linux/tests/unit_tests.h"
21 #include "testing/gtest/include/gtest/gtest.h"
23 namespace sandbox {
25 namespace {
27 bool HasLinux32Bug() {
28 #if defined(__i386__)
29 // On 3.2 kernels, yama doesn't work for 32-bit binaries on 64-bit kernels.
30 // This is fixed in 3.4.
31 bool is_kernel_64bit =
32 base::SysInfo::OperatingSystemArchitecture() == "x86_64";
33 bool is_linux = base::SysInfo::OperatingSystemName() == "Linux";
34 bool is_3_dot_2 = base::StartsWithASCII(
35 base::SysInfo::OperatingSystemVersion(), "3.2", /*case_sensitive=*/false);
36 if (is_kernel_64bit && is_linux && is_3_dot_2)
37 return true;
38 #endif // defined(__i386__)
39 return false;
42 bool CanPtrace(pid_t pid) {
43 int ret;
44 ret = ptrace(PTRACE_ATTACH, pid, NULL, NULL);
45 if (ret == -1) {
46 CHECK_EQ(EPERM, errno);
47 return false;
49 // Wait for the process to be stopped so that it can be detached.
50 siginfo_t process_info;
51 int wait_ret = HANDLE_EINTR(waitid(P_PID, pid, &process_info, WSTOPPED));
52 PCHECK(0 == wait_ret);
53 PCHECK(0 == ptrace(PTRACE_DETACH, pid, NULL, NULL));
54 return true;
57 // _exit(0) if pid can be ptraced by the current process.
58 // _exit(1) otherwise.
59 void ExitZeroIfCanPtrace(pid_t pid) {
60 if (CanPtrace(pid)) {
61 _exit(0);
62 } else {
63 _exit(1);
67 bool CanSubProcessPtrace(pid_t pid) {
68 ScopedProcess process(base::Bind(&ExitZeroIfCanPtrace, pid));
69 bool signaled;
70 int exit_code = process.WaitForExit(&signaled);
71 CHECK(!signaled);
72 return 0 == exit_code;
75 // The tests below assume that the system-level configuration will not change
76 // while they run.
78 TEST(Yama, GetStatus) {
79 int status1 = Yama::GetStatus();
81 // Check that the value is a possible bitmask.
82 ASSERT_LE(0, status1);
83 ASSERT_GE(Yama::STATUS_KNOWN | Yama::STATUS_PRESENT | Yama::STATUS_ENFORCING |
84 Yama::STATUS_STRICT_ENFORCING,
85 status1);
87 // The status should not just be a random value.
88 int status2 = Yama::GetStatus();
89 EXPECT_EQ(status1, status2);
91 // This test is not running sandboxed, there is no reason to not know the
92 // status.
93 EXPECT_NE(0, Yama::STATUS_KNOWN & status1);
95 if (status1 & Yama::STATUS_STRICT_ENFORCING) {
96 // If Yama is strictly enforcing, it is also enforcing.
97 EXPECT_TRUE(status1 & Yama::STATUS_ENFORCING);
100 if (status1 & Yama::STATUS_ENFORCING) {
101 // If Yama is enforcing, Yama is present.
102 EXPECT_NE(0, status1 & Yama::STATUS_PRESENT);
105 // Verify that the helper functions work as intended.
106 EXPECT_EQ(static_cast<bool>(status1 & Yama::STATUS_ENFORCING),
107 Yama::IsEnforcing());
108 EXPECT_EQ(static_cast<bool>(status1 & Yama::STATUS_PRESENT),
109 Yama::IsPresent());
111 fprintf(stdout,
112 "Yama present: %s - enforcing: %s\n",
113 Yama::IsPresent() ? "Y" : "N",
114 Yama::IsEnforcing() ? "Y" : "N");
117 SANDBOX_TEST(Yama, RestrictPtraceSucceedsWhenYamaPresent) {
118 // This call will succeed iff Yama is present.
119 bool restricted = Yama::RestrictPtracersToAncestors();
120 CHECK_EQ(restricted, Yama::IsPresent());
123 // Attempts to enable or disable Yama restrictions.
124 void SetYamaRestrictions(bool enable_restriction) {
125 if (enable_restriction) {
126 Yama::RestrictPtracersToAncestors();
127 } else {
128 Yama::DisableYamaRestrictions();
132 TEST(Yama, RestrictPtraceWorks) {
133 if (HasLinux32Bug())
134 return;
136 ScopedProcess process1(base::Bind(&SetYamaRestrictions, true));
137 ASSERT_TRUE(process1.WaitForClosureToRun());
139 if (Yama::IsEnforcing()) {
140 // A sibling process cannot ptrace process1.
141 ASSERT_FALSE(CanSubProcessPtrace(process1.GetPid()));
144 if (!(Yama::GetStatus() & Yama::STATUS_STRICT_ENFORCING)) {
145 // However, parent can ptrace process1.
146 ASSERT_TRUE(CanPtrace(process1.GetPid()));
148 // A sibling can ptrace process2 which disables any Yama protection.
149 ScopedProcess process2(base::Bind(&SetYamaRestrictions, false));
150 ASSERT_TRUE(process2.WaitForClosureToRun());
151 ASSERT_TRUE(CanSubProcessPtrace(process2.GetPid()));
155 SANDBOX_TEST(Yama, RestrictPtraceIsDefault) {
156 if (!Yama::IsPresent() || HasLinux32Bug())
157 return;
159 CHECK(Yama::DisableYamaRestrictions());
160 ScopedProcess process1(base::Bind(&base::DoNothing));
162 if (Yama::IsEnforcing()) {
163 // Check that process1 is protected by Yama, even though it has
164 // been created from a process that disabled Yama.
165 CHECK(!CanSubProcessPtrace(process1.GetPid()));
169 } // namespace
171 } // namespace sandbox