SandboxLogging.cpp (4104B)
1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */ 3 /* This Source Code Form is subject to the terms of the Mozilla Public 4 * License, v. 2.0. If a copy of the MPL was not distributed with this file, 5 * You can obtain one at http://mozilla.org/MPL/2.0/. */ 6 7 #include "SandboxLogging.h" 8 9 #ifdef ANDROID 10 # include <android/log.h> 11 #endif 12 #include <algorithm> 13 #include <stdio.h> 14 #include <string.h> 15 #include <sys/uio.h> 16 #include <unistd.h> 17 18 #include "base/posix/eintr_wrapper.h" 19 20 #ifdef __GLIBC_PREREQ 21 # if __GLIBC_PREREQ(2, 32) 22 # define HAVE_STRERRORNAME_NP 1 23 # endif 24 #endif 25 26 namespace mozilla { 27 28 // Alters an iovec array to remove the first `toDrop` bytes. This 29 // complexity is necessary because writev can return a short write 30 // (e.g., if stderr is a pipe and the buffer is almost full). 31 static void IOVecDrop(struct iovec* iov, int iovcnt, size_t toDrop) { 32 while (toDrop > 0 && iovcnt > 0) { 33 size_t toDropHere = std::min(toDrop, iov->iov_len); 34 iov->iov_base = static_cast<char*>(iov->iov_base) + toDropHere; 35 iov->iov_len -= toDropHere; 36 toDrop -= toDropHere; 37 ++iov; 38 --iovcnt; 39 } 40 } 41 42 void SandboxLogError(const char* message) { 43 #ifdef ANDROID 44 // This uses writev internally and appears to be async signal safe. 45 __android_log_write(ANDROID_LOG_ERROR, "Sandbox", message); 46 #endif 47 static char logPrefixProcess[16]; 48 static const ssize_t printfSize = 49 ::base::strings::SafeSPrintf(logPrefixProcess, "[%d] ", getpid()); 50 static const size_t pidSize = 51 std::clamp(static_cast<size_t>(printfSize), static_cast<size_t>(0), 52 static_cast<size_t>(sizeof(logPrefixProcess) - 1)); 53 static const char logPrefix[] = "Sandbox: ", logSuffix[] = "\n"; 54 struct iovec iovs[4] = { 55 {const_cast<char*>(logPrefixProcess), pidSize}, 56 {const_cast<char*>(logPrefix), sizeof(logPrefix) - 1}, 57 {const_cast<char*>(message), strlen(message)}, 58 {const_cast<char*>(logSuffix), sizeof(logSuffix) - 1}, 59 }; 60 while (iovs[2].iov_len > 0) { 61 ssize_t written = HANDLE_EINTR(writev(STDERR_FILENO, iovs, 4)); 62 if (written <= 0) { 63 break; 64 } 65 IOVecDrop(iovs, 4, static_cast<size_t>(written)); 66 } 67 } 68 69 ssize_t GetLibcErrorName(char* aBuf, size_t aSize, int aErr) { 70 const char* errStr; 71 72 #ifdef HAVE_STRERRORNAME_NP 73 // This is the function we'd like to have, but it's a glibc 74 // extension and present only in newer versions. 75 errStr = strerrorname_np(aErr); 76 #else 77 // Otherwise, handle most of the basic / common errors with a big 78 // switch statement. 79 switch (aErr) { 80 81 # define HANDLE_ERR(x) \ 82 case x: \ 83 errStr = #x; \ 84 break 85 86 // errno-base.h 87 HANDLE_ERR(EPERM); 88 HANDLE_ERR(ENOENT); 89 HANDLE_ERR(ESRCH); 90 HANDLE_ERR(EINTR); 91 HANDLE_ERR(EIO); 92 HANDLE_ERR(ENXIO); 93 HANDLE_ERR(E2BIG); 94 HANDLE_ERR(ENOEXEC); 95 HANDLE_ERR(EBADF); 96 HANDLE_ERR(ECHILD); 97 HANDLE_ERR(EAGAIN); 98 HANDLE_ERR(ENOMEM); 99 HANDLE_ERR(EACCES); 100 HANDLE_ERR(EFAULT); 101 HANDLE_ERR(ENOTBLK); 102 HANDLE_ERR(EBUSY); 103 HANDLE_ERR(EEXIST); 104 HANDLE_ERR(EXDEV); 105 HANDLE_ERR(ENODEV); 106 HANDLE_ERR(ENOTDIR); 107 HANDLE_ERR(EISDIR); 108 HANDLE_ERR(EINVAL); 109 HANDLE_ERR(ENFILE); 110 HANDLE_ERR(EMFILE); 111 HANDLE_ERR(ENOTTY); 112 HANDLE_ERR(ETXTBSY); 113 HANDLE_ERR(EFBIG); 114 HANDLE_ERR(ENOSPC); 115 HANDLE_ERR(ESPIPE); 116 HANDLE_ERR(EROFS); 117 HANDLE_ERR(EMLINK); 118 HANDLE_ERR(EPIPE); 119 HANDLE_ERR(EDOM); 120 HANDLE_ERR(ERANGE); 121 122 // selected other errors 123 HANDLE_ERR(ENAMETOOLONG); 124 HANDLE_ERR(ENOSYS); 125 HANDLE_ERR(ENOTEMPTY); 126 HANDLE_ERR(ELOOP); 127 HANDLE_ERR(ENOTSOCK); 128 HANDLE_ERR(EMSGSIZE); 129 HANDLE_ERR(ECONNRESET); 130 HANDLE_ERR(ECONNREFUSED); 131 HANDLE_ERR(EHOSTUNREACH); 132 HANDLE_ERR(ESTALE); 133 134 # undef HANDLE_ERR 135 136 default: 137 errStr = nullptr; 138 } 139 #endif // no strerrorname_np 140 141 if (errStr) { 142 return base::strings::SafeSNPrintf(aBuf, aSize, "%s", errStr); 143 } 144 145 return base::strings::SafeSNPrintf(aBuf, aSize, "error %d", aErr); 146 } 147 148 } // namespace mozilla