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..6658160fbe168b2912248bcf8c2726a2a82c35c1 |
--- /dev/null |
+++ b/sandbox/linux/services/yama.cc |
@@ -0,0 +1,116 @@ |
+// 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/files/file_util.h" |
+#include "base/files/scoped_file.h" |
+#include "base/logging.h" |
+#include "base/posix/eintr_wrapper.h" |
+ |
+#if !defined(PR_SET_PTRACER_ANY) |
+#define PR_SET_PTRACER_ANY ((unsigned long)-1) |
+#endif |
+ |
+#if !defined(PR_SET_PTRACER) |
+#define PR_SET_PTRACER 0x59616d61 |
+#endif |
+ |
+namespace sandbox { |
+ |
+namespace { |
+ |
+// Enable or disable the Yama ptracers restrictions. |
+// Return false if Yama is not present on this kernel. |
+bool SetYamaPtracersRestriction(bool enable_restrictions) { |
+ unsigned long set_ptracer_arg; |
+ if (enable_restrictions) { |
+ set_ptracer_arg = 0; |
+ } else { |
+ set_ptracer_arg = PR_SET_PTRACER_ANY; |
+ } |
+ |
+ const int ret = prctl(PR_SET_PTRACER, set_ptracer_arg); |
+ const int prctl_errno = errno; |
+ |
+ if (0 == ret) { |
+ return true; |
+ } else { |
+ // ENOSYS or EINVAL means Yama is not in the current kernel. |
+ CHECK(ENOSYS == prctl_errno || EINVAL == prctl_errno); |
+ return false; |
+ } |
+} |
+ |
+bool CanAccessProcFS() { |
+ static const char kProcfsKernelSysPath[] = "/proc/sys/kernel/"; |
+ int ret = access(kProcfsKernelSysPath, F_OK); |
+ if (ret) { |
+ return false; |
+ } |
+ return true; |
+} |
+ |
+} // namespace |
+ |
+// static |
+bool Yama::RestrictPtracersToAncestors() { |
+ return SetYamaPtracersRestriction(true /* enable_restrictions */); |
+} |
+ |
+// static |
+bool Yama::DisableYamaRestrictions() { |
+ return SetYamaPtracersRestriction(false /* enable_restrictions */); |
+} |
+ |
+// static |
+int Yama::GetStatus() { |
+ if (!CanAccessProcFS()) { |
+ return 0; |
+ } |
+ |
+ static const char kPtraceScopePath[] = "/proc/sys/kernel/yama/ptrace_scope"; |
+ |
+ base::ScopedFD yama_scope(HANDLE_EINTR(open(kPtraceScopePath, O_RDONLY))); |
+ |
+ if (!yama_scope.is_valid()) { |
+ const int open_errno = errno; |
+ DCHECK(ENOENT == open_errno); |
+ // The status is known, yama is not present. |
+ return STATUS_KNOWN; |
+ } |
+ |
+ char yama_scope_value = 0; |
+ ssize_t num_read = HANDLE_EINTR(read(yama_scope.get(), &yama_scope_value, 1)); |
+ PCHECK(1 == num_read); |
+ |
+ switch (yama_scope_value) { |
+ case '0': |
+ return STATUS_KNOWN | STATUS_PRESENT; |
+ case '1': |
+ return STATUS_KNOWN | STATUS_PRESENT | STATUS_ENFORCING; |
+ case '2': |
+ case '3': |
+ return STATUS_KNOWN | STATUS_PRESENT | STATUS_ENFORCING | |
+ STATUS_STRICT_ENFORCING; |
+ default: |
+ NOTREACHED(); |
+ return 0; |
+ } |
+} |
+ |
+// static |
+bool Yama::IsPresent() { return GetStatus() & STATUS_PRESENT; } |
+ |
+// static |
+bool Yama::IsEnforcing() { return GetStatus() & STATUS_ENFORCING; } |
+ |
+} // namespace sandbox |