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.
7 #include <sys/ptrace.h>
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"
24 bool CanPtrace(pid_t pid
) {
26 ret
= ptrace(PTRACE_ATTACH
, pid
, NULL
, NULL
);
28 CHECK_EQ(EPERM
, errno
);
31 // Wait for the process to be stopped so that it can be detached.
32 siginfo_t process_info
;
33 int wait_ret
= HANDLE_EINTR(waitid(P_PID
, pid
, &process_info
, WSTOPPED
));
34 PCHECK(0 == wait_ret
);
35 PCHECK(0 == ptrace(PTRACE_DETACH
, pid
, NULL
, NULL
));
39 // _exit(0) if pid can be ptraced by the current process.
40 // _exit(1) otherwise.
41 void ExitZeroIfCanPtrace(pid_t pid
) {
49 bool CanSubProcessPtrace(pid_t pid
) {
50 ScopedProcess
process(base::Bind(&ExitZeroIfCanPtrace
, pid
));
52 int exit_code
= process
.WaitForExit(&signaled
);
54 return 0 == exit_code
;
57 // The tests below assume that the system-level configuration will not change
60 TEST(Yama
, GetStatus
) {
61 int status1
= Yama::GetStatus();
63 // Check that the value is a possible bitmask.
64 ASSERT_LE(0, status1
);
65 ASSERT_GE(Yama::STATUS_KNOWN
| Yama::STATUS_PRESENT
| Yama::STATUS_ENFORCING
|
66 Yama::STATUS_STRICT_ENFORCING
,
69 // The status should not just be a random value.
70 int status2
= Yama::GetStatus();
71 EXPECT_EQ(status1
, status2
);
73 // This test is not running sandboxed, there is no reason to not know the
75 EXPECT_NE(0, Yama::STATUS_KNOWN
& status1
);
77 if (status1
& Yama::STATUS_STRICT_ENFORCING
) {
78 // If Yama is strictly enforcing, it is also enforcing.
79 EXPECT_TRUE(status1
& Yama::STATUS_ENFORCING
);
82 if (status1
& Yama::STATUS_ENFORCING
) {
83 // If Yama is enforcing, Yama is present.
84 EXPECT_NE(0, status1
& Yama::STATUS_PRESENT
);
87 // Verify that the helper functions work as intended.
88 EXPECT_EQ(static_cast<bool>(status1
& Yama::STATUS_ENFORCING
),
90 EXPECT_EQ(static_cast<bool>(status1
& Yama::STATUS_PRESENT
),
94 "Yama present: %s - enforcing: %s\n",
95 Yama::IsPresent() ? "Y" : "N",
96 Yama::IsEnforcing() ? "Y" : "N");
99 SANDBOX_TEST(Yama
, RestrictPtraceSucceedsWhenYamaPresent
) {
100 // This call will succeed iff Yama is present.
101 bool restricted
= Yama::RestrictPtracersToAncestors();
102 CHECK_EQ(restricted
, Yama::IsPresent());
105 // Attempts to enable or disable Yama restrictions.
106 void SetYamaRestrictions(bool enable_restriction
) {
107 if (enable_restriction
) {
108 Yama::RestrictPtracersToAncestors();
110 Yama::DisableYamaRestrictions();
114 TEST(Yama
, RestrictPtraceWorks
) {
115 ScopedProcess
process1(base::Bind(&SetYamaRestrictions
, true));
116 ASSERT_TRUE(process1
.WaitForClosureToRun());
118 if (Yama::IsEnforcing()) {
119 // A sibling process cannot ptrace process1.
120 ASSERT_FALSE(CanSubProcessPtrace(process1
.GetPid()));
123 if (!(Yama::GetStatus() & Yama::STATUS_STRICT_ENFORCING
)) {
124 // However, parent can ptrace process1.
125 ASSERT_TRUE(CanPtrace(process1
.GetPid()));
127 // A sibling can ptrace process2 which disables any Yama protection.
128 ScopedProcess
process2(base::Bind(&SetYamaRestrictions
, false));
129 ASSERT_TRUE(process2
.WaitForClosureToRun());
130 ASSERT_TRUE(CanSubProcessPtrace(process2
.GetPid()));
136 SANDBOX_TEST(Yama
, RestrictPtraceIsDefault
) {
137 if (!Yama::IsPresent())
140 CHECK(Yama::DisableYamaRestrictions());
141 ScopedProcess
process1(base::Bind(&DoNothing
));
143 if (Yama::IsEnforcing()) {
144 // Check that process1 is protected by Yama, even though it has
145 // been created from a process that disabled Yama.
146 CHECK(!CanSubProcessPtrace(process1
.GetPid()));
152 } // namespace sandbox