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 "sandbox/linux/services/yama.h" 6 7 #include <fcntl.h> 8 #include <sys/prctl.h> 9 #include <sys/stat.h> 10 #include <sys/types.h> 11 #include <unistd.h> 12 13 #include "base/basictypes.h" 14 #include "base/file_util.h" 15 #include "base/files/scoped_file.h" 16 #include "base/logging.h" 17 #include "base/posix/eintr_wrapper.h" 18 19 #if !defined(PR_SET_PTRACER_ANY) 20 #define PR_SET_PTRACER_ANY ((unsigned long)-1) 21 #endif 22 23 #if !defined(PR_SET_PTRACER) 24 #define PR_SET_PTRACER 0x59616d61 25 #endif 26 27 namespace sandbox { 28 29 namespace { 30 31 // Enable or disable the Yama ptracers restrictions. 32 // Return false if Yama is not present on this kernel. SetYamaPtracersRestriction(bool enable_restrictions)33bool SetYamaPtracersRestriction(bool enable_restrictions) { 34 unsigned long set_ptracer_arg; 35 if (enable_restrictions) { 36 set_ptracer_arg = 0; 37 } else { 38 set_ptracer_arg = PR_SET_PTRACER_ANY; 39 } 40 41 const int ret = prctl(PR_SET_PTRACER, set_ptracer_arg); 42 const int prctl_errno = errno; 43 44 if (0 == ret) { 45 return true; 46 } else { 47 // ENOSYS or EINVAL means Yama is not in the current kernel. 48 CHECK(ENOSYS == prctl_errno || EINVAL == prctl_errno); 49 return false; 50 } 51 } 52 CanAccessProcFS()53bool CanAccessProcFS() { 54 static const char kProcfsKernelSysPath[] = "/proc/sys/kernel/"; 55 int ret = access(kProcfsKernelSysPath, F_OK); 56 if (ret) { 57 return false; 58 } 59 return true; 60 } 61 62 } // namespace 63 64 // static RestrictPtracersToAncestors()65bool Yama::RestrictPtracersToAncestors() { 66 return SetYamaPtracersRestriction(true /* enable_restrictions */); 67 } 68 69 // static DisableYamaRestrictions()70bool Yama::DisableYamaRestrictions() { 71 return SetYamaPtracersRestriction(false /* enable_restrictions */); 72 } 73 74 // static GetStatus()75int Yama::GetStatus() { 76 if (!CanAccessProcFS()) { 77 return 0; 78 } 79 80 static const char kPtraceScopePath[] = "/proc/sys/kernel/yama/ptrace_scope"; 81 82 base::ScopedFD yama_scope(HANDLE_EINTR(open(kPtraceScopePath, O_RDONLY))); 83 84 if (!yama_scope.is_valid()) { 85 const int open_errno = errno; 86 DCHECK(ENOENT == open_errno); 87 // The status is known, yama is not present. 88 return STATUS_KNOWN; 89 } 90 91 char yama_scope_value = 0; 92 ssize_t num_read = HANDLE_EINTR(read(yama_scope.get(), &yama_scope_value, 1)); 93 PCHECK(1 == num_read); 94 95 switch (yama_scope_value) { 96 case '0': 97 return STATUS_KNOWN | STATUS_PRESENT; 98 case '1': 99 return STATUS_KNOWN | STATUS_PRESENT | STATUS_ENFORCING; 100 case '2': 101 case '3': 102 return STATUS_KNOWN | STATUS_PRESENT | STATUS_ENFORCING | 103 STATUS_STRICT_ENFORCING; 104 default: 105 NOTREACHED(); 106 return 0; 107 } 108 } 109 110 // static IsPresent()111bool Yama::IsPresent() { return GetStatus() & STATUS_PRESENT; } 112 113 // static IsEnforcing()114bool Yama::IsEnforcing() { return GetStatus() & STATUS_ENFORCING; } 115 116 } // namespace sandbox 117