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