Index: sandbox/linux/services/yama.cc |
diff --git a/sandbox/linux/services/yama.cc b/sandbox/linux/services/yama.cc |
new file mode 100644 |
index 0000000000000000000000000000000000000000..101590861ded6b922789ea795dd25d73afb2605a |
--- /dev/null |
+++ b/sandbox/linux/services/yama.cc |
@@ -0,0 +1,107 @@ |
+// Copyright 2014 The Chromium Authors. All rights reserved. |
+// Use of this source code is governed by a BSD-style license that can be |
+// found in the LICENSE file. |
+ |
+#include "sandbox/linux/services/yama.h" |
+ |
+#include <fcntl.h> |
+#include <sys/prctl.h> |
+#include <sys/stat.h> |
+#include <sys/types.h> |
+#include <unistd.h> |
+ |
+#include "base/basictypes.h" |
+#include "base/file_util.h" |
+#include "base/logging.h" |
+#include "base/posix/eintr_wrapper.h" |
+ |
+namespace sandbox { |
+ |
+namespace { |
+ |
+// Enable or disable the Yama ptracers restrictions. |
+// Return false if Yama is not present on this kernel. |
+bool SetYamaPtracersRestriction(bool enabled) { |
+ unsigned long set_ptracer_arg; |
+ if (enabled) { |
+ set_ptracer_arg = 0; |
+ } else { |
+ set_ptracer_arg = PR_SET_PTRACER_ANY; |
Kees Cook
2014/03/06 00:49:30
PR_SET_PTRACE_ANY is an extreme disabling state --
jln (very slow on Chromium)
2014/03/06 05:06:08
This is mostly for testing.
I've added a comment
|
+ } |
+ |
+ const int ret = prctl(PR_SET_PTRACER, set_ptracer_arg); |
+ const int prctl_errno = errno; |
+ |
+ if (0 == ret) { |
+ return true; |
+ } else { |
+ // This means Yama is not available on this kernel and should be the |
+ // only possibility of failure. |
+ CHECK(ENOSYS == prctl_errno || EINVAL == prctl_errno); |
+ return false; |
+ } |
+} |
+ |
+bool CanAccessProcFS() { |
+ const char kProcfsKernelSysPath[] = "/proc/sys/kernel/"; |
mdempsky
2014/03/06 01:56:28
Can this be made static? (kPtraceScopePath below
jln (very slow on Chromium)
2014/03/06 05:06:08
Done.
|
+ struct stat buf; |
+ int ret = stat(kProcfsKernelSysPath, &buf); |
mdempsky
2014/03/06 01:56:28
Since you don't care about the 'stat' buf, would a
jln (very slow on Chromium)
2014/03/06 05:06:08
Done.
|
+ if (ret) { |
+ return false; |
+ } |
+ return true; |
+} |
+ |
+} // namespace |
+ |
+// static |
+bool Yama::RestrictPtracersToAncestors() { |
+ return SetYamaPtracersRestriction(true /* enabled */); |
+} |
+ |
+// static |
+bool Yama::DisableYamaRestrictions() { |
+ return SetYamaPtracersRestriction(false /* enabled */); |
+} |
+ |
+// static |
+Yama::GlobalStatus Yama::GetStatus() { |
+ if (!CanAccessProcFS()) { |
+ return STATUS_DONT_KNOW; |
+ } |
+ |
+ const char kPtraceScopePath[] = "/proc/sys/kernel/yama/ptrace_scope"; |
+ |
+ int yama_scope = open(kPtraceScopePath, O_RDONLY); |
+ |
+ if (yama_scope < 0) { |
+ const int open_errno = errno; |
+ DCHECK(ENOENT == open_errno); |
+ return STATUS_NOT_PRESENT; |
+ } |
+ |
+ file_util::ScopedFDCloser yama_scope_closer(&yama_scope); |
+ char yama_scope_value = 0; |
+ ssize_t num_read = read(yama_scope, &yama_scope_value, 1); |
+ PCHECK(1 == num_read); |
+ |
+ switch (yama_scope_value) { |
+ case '0': |
+ return STATUS_NOT_ENFORCING; |
+ case '1': |
+ case '2': |
+ case '3': |
+ return STATUS_ENFORCING; |
+ default: |
+ NOTREACHED(); |
+ return STATUS_DONT_KNOW; |
+ } |
+} |
+ |
+// static |
+bool Yama::IsAvailable() { |
+ const GlobalStatus status = GetStatus(); |
+ return (STATUS_NOT_ENFORCING == status) || (STATUS_ENFORCING == status); |
+} |
+ |
+} // namespace sandbox |