sandbox_logging.cc 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157
  1. // Copyright 2017 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. #include "sandbox/mac/sandbox_logging.h"
  5. #include <errno.h>
  6. #include <os/log.h>
  7. #include <stdarg.h>
  8. #include <stdio.h>
  9. #include <string.h>
  10. #include <syslog.h>
  11. #include <unistd.h>
  12. #include <limits>
  13. #include <string>
  14. #include "build/build_config.h"
  15. #if defined(ARCH_CPU_X86_64)
  16. #define ABORT() \
  17. { \
  18. asm volatile( \
  19. "int3; ud2; push %0;" ::"i"(static_cast<unsigned char>(__COUNTER__))); \
  20. __builtin_unreachable(); \
  21. }
  22. #elif defined(ARCH_CPU_ARM64)
  23. #define ABORT() \
  24. { \
  25. asm volatile("udf %0;" ::"i"(static_cast<unsigned char>(__COUNTER__))); \
  26. __builtin_unreachable(); \
  27. }
  28. #endif
  29. extern "C" {
  30. void abort_report_np(const char*, ...);
  31. }
  32. namespace sandbox::logging {
  33. namespace {
  34. enum class Level { FATAL, ERR, WARN, INFO };
  35. void SendOsLog(Level level, const char* message) {
  36. const class OSLog {
  37. public:
  38. explicit OSLog()
  39. : os_log_(os_log_create("org.chromium.sandbox", "chromium_logging")) {}
  40. OSLog(const OSLog&) = delete;
  41. OSLog& operator=(const OSLog&) = delete;
  42. ~OSLog() { os_release(os_log_); }
  43. os_log_t get() const { return os_log_; }
  44. private:
  45. os_log_t os_log_;
  46. } log;
  47. const os_log_type_t os_log_type = [](Level level) {
  48. switch (level) {
  49. case Level::FATAL:
  50. return OS_LOG_TYPE_FAULT;
  51. case Level::ERR:
  52. return OS_LOG_TYPE_ERROR;
  53. case Level::WARN:
  54. return OS_LOG_TYPE_DEFAULT;
  55. case Level::INFO:
  56. return OS_LOG_TYPE_INFO;
  57. }
  58. }(level);
  59. os_log_with_type(log.get(), os_log_type, "%{public}s", message);
  60. if (level == Level::FATAL) {
  61. abort_report_np(message);
  62. }
  63. }
  64. // |error| is strerror(errno) when a P* logging function is called. Pass
  65. // |nullptr| if no errno is set.
  66. void DoLogging(Level level,
  67. const char* fmt,
  68. va_list args,
  69. const std::string* error) {
  70. char message[4096];
  71. int ret = vsnprintf(message, sizeof(message), fmt, args);
  72. if (ret < 0) {
  73. SendOsLog(level, "warning: log message could not be formatted");
  74. return;
  75. }
  76. // int |ret| is not negative so casting to a larger type is safe.
  77. bool truncated = static_cast<unsigned long>(ret) > sizeof(message) - 1;
  78. std::string final_message = message;
  79. if (error)
  80. final_message += ": " + *error;
  81. SendOsLog(level, final_message.c_str());
  82. if (truncated) {
  83. SendOsLog(level, "warning: previous log message truncated");
  84. }
  85. }
  86. } // namespace
  87. void Info(const char* fmt, ...) {
  88. va_list args;
  89. va_start(args, fmt);
  90. DoLogging(Level::INFO, fmt, args, nullptr);
  91. va_end(args);
  92. }
  93. void Warning(const char* fmt, ...) {
  94. va_list args;
  95. va_start(args, fmt);
  96. DoLogging(Level::WARN, fmt, args, nullptr);
  97. va_end(args);
  98. }
  99. void Error(const char* fmt, ...) {
  100. va_list args;
  101. va_start(args, fmt);
  102. DoLogging(Level::ERR, fmt, args, nullptr);
  103. va_end(args);
  104. }
  105. void Fatal(const char* fmt, ...) {
  106. va_list args;
  107. va_start(args, fmt);
  108. DoLogging(Level::FATAL, fmt, args, nullptr);
  109. va_end(args);
  110. ABORT();
  111. }
  112. void PError(const char* fmt, ...) {
  113. std::string error = strerror(errno);
  114. va_list args;
  115. va_start(args, fmt);
  116. DoLogging(Level::ERR, fmt, args, &error);
  117. va_end(args);
  118. }
  119. void PFatal(const char* fmt, ...) {
  120. std::string error = strerror(errno);
  121. va_list args;
  122. va_start(args, fmt);
  123. DoLogging(Level::FATAL, fmt, args, &error);
  124. va_end(args);
  125. ABORT();
  126. }
  127. } // namespace sandbox::logging