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

Side by Side Diff: sandbox/linux/services/yama_unittests.cc

Issue 188193002: Linux sandbox: add basic Yama support (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Address comments. Add testing. Created 6 years, 9 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 | Annotate | Revision Log
OLDNEW
(Empty)
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.
4
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>
11
12 #include "base/bind.h"
13 #include "base/compiler_specific.h"
14 #include "base/posix/eintr_wrapper.h"
15 #include "sandbox/linux/services/scoped_process.h"
16 #include "sandbox/linux/services/yama.h"
17 #include "sandbox/linux/tests/unit_tests.h"
18 #include "testing/gtest/include/gtest/gtest.h"
19
20 namespace sandbox {
21
22 namespace {
23
24 void WaitForever() {
Jorge Lucangeli Obes 2014/03/06 15:42:09 test_utils.{h|cc} for these functions eventually?
jln (very slow on Chromium) 2014/03/06 21:43:46 I've removed this anyways now.
25 while (true)
26 pause();
27 }
28
29 bool CanPtrace(pid_t pid) {
30 int ret;
31 ret = ptrace(PTRACE_ATTACH, pid, NULL, NULL);
32 if (ret == -1) {
33 CHECK_EQ(EPERM, errno);
34 return false;
35 }
36 // Wait for the process to be stopped so that it can be detached.
37 siginfo_t process_info;
38 int wait_ret = HANDLE_EINTR(waitid(P_PID, pid, &process_info, WSTOPPED));
39 PCHECK(0 == wait_ret);
40 PCHECK(0 == ptrace(PTRACE_DETACH, pid, NULL, NULL));
41 return true;
42 }
43
44 // _exit(0) if pid can be ptraced by the current process.
45 // _exit(1) otherwise.
46 void ExitZeroIfCanPtrace(pid_t pid) {
47 if (CanPtrace(pid)) {
48 _exit(0);
49 } else {
50 _exit(1);
51 }
52 }
53
54 bool CanSubProcessPtrace(pid_t pid) {
55 ScopedProcess process(base::Bind(&ExitZeroIfCanPtrace, pid));
56 bool signaled;
57 int exit_code = process.WaitForExit(&signaled);
58 CHECK(!signaled);
59 return 0 == exit_code;
60 }
61
62 // The tests below assume that the system-level configuration will not change
63 // while they run.
64
65 TEST(Yama, GetStatus) {
66 int status1 = Yama::GetStatus();
67
68 // Check that the value is a possible bitmask.
69 ASSERT_LE(0, status1);
70 ASSERT_GE(Yama::STATUS_KNOWN | Yama::STATUS_PRESENT | Yama::STATUS_ENFORCING |
71 Yama::STATUS_STRICT_ENFORCING,
72 status1);
73
74 // The status should not just be a random value.
75 int status2 = Yama::GetStatus();
76 EXPECT_EQ(status1, status2);
77
78 // This test is not running sandboxed, there is no reason to not know the
79 // status.
80 EXPECT_NE(0, Yama::STATUS_KNOWN & status1);
81
82 if (status1 & Yama::STATUS_STRICT_ENFORCING) {
83 // If Yama is strictly enforcing, it is also enforcing.
84 EXPECT_TRUE(status1 & Yama::STATUS_ENFORCING);
85 }
86
87 if (status1 & Yama::STATUS_ENFORCING) {
88 // If Yama is enforcing, Yama is present.
89 EXPECT_NE(0, status1 & Yama::STATUS_PRESENT);
90 }
91
92 // Verify that the helper functions work as intended.
93 EXPECT_EQ(static_cast<bool>(status1 & Yama::STATUS_ENFORCING),
94 Yama::IsEnforcing());
95 EXPECT_EQ(static_cast<bool>(status1 & Yama::STATUS_PRESENT),
96 Yama::IsPresent());
97
98 fprintf(stdout,
99 "Yama present: %s - enforcing: %s\n",
100 Yama::IsPresent() ? "Y" : "N",
101 Yama::IsEnforcing() ? "Y" : "N");
102 }
103
104 // Attempts to enable or disable Yama restrictions.
105 void SetYamaRestrictionsAndPause(bool enable_restriction) {
106 if (enable_restriction) {
107 Yama::RestrictPtracersToAncestors();
108 } else {
109 Yama::DisableYamaRestrictions();
110 }
111 WaitForever();
112 }
113
114 SANDBOX_TEST(Yama, RestrictPtraceSucceedsWhenYamaPresent) {
115 // This call will always succeed if Yama is present (however it may not be
116 // enforcing.
117 bool restricted = Yama::RestrictPtracersToAncestors();
118 CHECK_EQ(restricted, static_cast<bool>(Yama::IsPresent()));
119 }
120
121 TEST(Yama, RestrictPtraceWorks) {
122 ScopedProcess process1(base::Bind(&SetYamaRestrictionsAndPause, true));
123
124 if (Yama::IsEnforcing()) {
125 // A sibling process cannot ptrace process1.
126 ASSERT_FALSE(CanSubProcessPtrace(process1.GetPid()));
127 }
128
129 if (!(Yama::GetStatus() & Yama::STATUS_STRICT_ENFORCING)) {
130 // However, parent can ptrace process1.
131 ASSERT_TRUE(CanPtrace(process1.GetPid()));
132
133 // A sibling can ptrace process2 which disables any Yama protection.
134 ScopedProcess process2(base::Bind(&SetYamaRestrictionsAndPause, false));
135 ASSERT_TRUE(CanSubProcessPtrace(process2.GetPid()));
136 }
137 }
138
139 SANDBOX_TEST(Yama, RestrictPtraceIsDefault) {
140 if (!Yama::IsPresent())
141 return;
142
143 CHECK(Yama::DisableYamaRestrictions());
144 ScopedProcess process1(base::Bind(&WaitForever));
145 if (Yama::IsEnforcing()) {
146 // Check that process1 is protected by Yama, even though it has
147 // been created from a process that disabled Yama.
148 CHECK(!CanSubProcessPtrace(process1.GetPid()));
149 }
150 }
151
152 } // namespace
153
154 } // namespace sandbox
OLDNEW
« sandbox/linux/services/yama.cc ('K') | « sandbox/linux/services/yama.cc ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698