address_is_readable.cc (3560B)
1 // Copyright 2017 The Abseil Authors. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // https://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 // base::AddressIsReadable() probes an address to see whether it is readable, 16 // without faulting. 17 18 #include "absl/debugging/internal/address_is_readable.h" 19 20 #if !defined(__linux__) || defined(__ANDROID__) 21 22 namespace absl { 23 ABSL_NAMESPACE_BEGIN 24 namespace debugging_internal { 25 26 // On platforms other than Linux, just return true. 27 bool AddressIsReadable(const void* /* addr */) { return true; } 28 29 } // namespace debugging_internal 30 ABSL_NAMESPACE_END 31 } // namespace absl 32 33 #else // __linux__ && !__ANDROID__ 34 35 #include <stdint.h> 36 #include <syscall.h> 37 #include <unistd.h> 38 39 #include "absl/base/internal/errno_saver.h" 40 #include "absl/base/internal/raw_logging.h" 41 42 namespace absl { 43 ABSL_NAMESPACE_BEGIN 44 namespace debugging_internal { 45 46 // NOTE: be extra careful about adding any interposable function calls here 47 // (such as open(), read(), etc.). These symbols may be interposed and will get 48 // invoked in contexts they don't expect. 49 // 50 // NOTE: any new system calls here may also require sandbox reconfiguration. 51 // 52 bool AddressIsReadable(const void *addr) { 53 // rt_sigprocmask below checks 8 contiguous bytes. If addr resides in the 54 // last 7 bytes of a page (unaligned), rt_sigprocmask would additionally 55 // check the readability of the next page, which is not desired. Align 56 // address on 8-byte boundary to check only the current page. 57 const uintptr_t u_addr = reinterpret_cast<uintptr_t>(addr) & ~uintptr_t{7}; 58 addr = reinterpret_cast<const void *>(u_addr); 59 60 // rt_sigprocmask below will succeed for this input. 61 if (addr == nullptr) return false; 62 63 absl::base_internal::ErrnoSaver errno_saver; 64 65 // Here we probe with some syscall which 66 // - accepts an 8-byte region of user memory as input 67 // - tests for EFAULT before other validation 68 // - has no problematic side-effects 69 // 70 // rt_sigprocmask(2) works for this. It copies sizeof(kernel_sigset_t)==8 71 // bytes from the address into the kernel memory before any validation. 72 // 73 // The call can never succeed, since the `how` parameter is not one of 74 // SIG_BLOCK, SIG_UNBLOCK, SIG_SETMASK. 75 // 76 // This strategy depends on Linux implementation details, 77 // so we rely on the test to alert us if it stops working. 78 // 79 // Some discarded past approaches: 80 // - msync() doesn't reject PROT_NONE regions 81 // - write() on /dev/null doesn't return EFAULT 82 // - write() on a pipe requires creating it and draining the writes 83 // - connect() works but is problematic for sandboxes and needs a valid 84 // file descriptor 85 // 86 // This can never succeed (invalid first argument to sigprocmask). 87 ABSL_RAW_CHECK(syscall(SYS_rt_sigprocmask, ~0, addr, nullptr, 88 /*sizeof(kernel_sigset_t)*/ 8) == -1, 89 "unexpected success"); 90 ABSL_RAW_CHECK(errno == EFAULT || errno == EINVAL, "unexpected errno"); 91 return errno != EFAULT; 92 } 93 94 } // namespace debugging_internal 95 ABSL_NAMESPACE_END 96 } // namespace absl 97 98 #endif // __linux__ && !__ANDROID__