tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

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