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 namespace mozilla {
21 
22 // Alters an iovec array to remove the first `toDrop` bytes.  This
23 // complexity is necessary because writev can return a short write
24 // (e.g., if stderr is a pipe and the buffer is almost full).
IOVecDrop(struct iovec * iov,int iovcnt,size_t toDrop)25 static void IOVecDrop(struct iovec* iov, int iovcnt, size_t toDrop) {
26   while (toDrop > 0 && iovcnt > 0) {
27     size_t toDropHere = std::min(toDrop, iov->iov_len);
28     iov->iov_base = static_cast<char*>(iov->iov_base) + toDropHere;
29     iov->iov_len -= toDropHere;
30     toDrop -= toDropHere;
31     ++iov;
32     --iovcnt;
33   }
34 }
35 
SandboxLogError(const char * message)36 void SandboxLogError(const char* message) {
37 #ifdef ANDROID
38   // This uses writev internally and appears to be async signal safe.
39   __android_log_write(ANDROID_LOG_ERROR, "Sandbox", message);
40 #endif
41   static const char logPrefix[] = "Sandbox: ", logSuffix[] = "\n";
42   struct iovec iovs[3] = {
43       {const_cast<char*>(logPrefix), sizeof(logPrefix) - 1},
44       {const_cast<char*>(message), strlen(message)},
45       {const_cast<char*>(logSuffix), sizeof(logSuffix) - 1},
46   };
47   while (iovs[2].iov_len > 0) {
48     ssize_t written = HANDLE_EINTR(writev(STDERR_FILENO, iovs, 3));
49     if (written <= 0) {
50       break;
51     }
52     IOVecDrop(iovs, 3, static_cast<size_t>(written));
53   }
54 }
55 
56 }  // namespace mozilla
57