1*6777b538SAndroid Build Coastguard Worker // Copyright 2016 The Chromium Authors
2*6777b538SAndroid Build Coastguard Worker // Use of this source code is governed by a BSD-style license that can be
3*6777b538SAndroid Build Coastguard Worker // found in the LICENSE file.
4*6777b538SAndroid Build Coastguard Worker
5*6777b538SAndroid Build Coastguard Worker #include "base/syslog_logging.h"
6*6777b538SAndroid Build Coastguard Worker
7*6777b538SAndroid Build Coastguard Worker #include "build/build_config.h"
8*6777b538SAndroid Build Coastguard Worker
9*6777b538SAndroid Build Coastguard Worker #if BUILDFLAG(IS_WIN)
10*6777b538SAndroid Build Coastguard Worker // clang-format off
11*6777b538SAndroid Build Coastguard Worker #include <windows.h> // Must be in front of other Windows header files.
12*6777b538SAndroid Build Coastguard Worker // clang-format on
13*6777b538SAndroid Build Coastguard Worker
14*6777b538SAndroid Build Coastguard Worker #include <sddl.h>
15*6777b538SAndroid Build Coastguard Worker
16*6777b538SAndroid Build Coastguard Worker #include "base/debug/stack_trace.h"
17*6777b538SAndroid Build Coastguard Worker #include "base/strings/string_util.h"
18*6777b538SAndroid Build Coastguard Worker #include "base/win/scoped_handle.h"
19*6777b538SAndroid Build Coastguard Worker #include "base/win/win_util.h"
20*6777b538SAndroid Build Coastguard Worker #elif BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS)
21*6777b538SAndroid Build Coastguard Worker // <syslog.h> defines LOG_INFO, LOG_WARNING macros that could conflict with
22*6777b538SAndroid Build Coastguard Worker // base::LOG_INFO, base::LOG_WARNING.
23*6777b538SAndroid Build Coastguard Worker #include <syslog.h>
24*6777b538SAndroid Build Coastguard Worker #undef LOG_INFO
25*6777b538SAndroid Build Coastguard Worker #undef LOG_WARNING
26*6777b538SAndroid Build Coastguard Worker #endif
27*6777b538SAndroid Build Coastguard Worker
28*6777b538SAndroid Build Coastguard Worker #include <ostream>
29*6777b538SAndroid Build Coastguard Worker #include <string>
30*6777b538SAndroid Build Coastguard Worker
31*6777b538SAndroid Build Coastguard Worker namespace logging {
32*6777b538SAndroid Build Coastguard Worker
33*6777b538SAndroid Build Coastguard Worker namespace {
34*6777b538SAndroid Build Coastguard Worker
35*6777b538SAndroid Build Coastguard Worker // The syslog logging is on by default, but tests or fuzzers can disable it.
36*6777b538SAndroid Build Coastguard Worker bool g_logging_enabled = true;
37*6777b538SAndroid Build Coastguard Worker
38*6777b538SAndroid Build Coastguard Worker } // namespace
39*6777b538SAndroid Build Coastguard Worker
40*6777b538SAndroid Build Coastguard Worker #if BUILDFLAG(IS_WIN)
41*6777b538SAndroid Build Coastguard Worker
42*6777b538SAndroid Build Coastguard Worker namespace {
43*6777b538SAndroid Build Coastguard Worker
44*6777b538SAndroid Build Coastguard Worker std::string* g_event_source_name = nullptr;
45*6777b538SAndroid Build Coastguard Worker uint16_t g_category = 0;
46*6777b538SAndroid Build Coastguard Worker uint32_t g_event_id = 0;
47*6777b538SAndroid Build Coastguard Worker std::wstring* g_user_sid = nullptr;
48*6777b538SAndroid Build Coastguard Worker
49*6777b538SAndroid Build Coastguard Worker class EventLogHandleTraits {
50*6777b538SAndroid Build Coastguard Worker public:
51*6777b538SAndroid Build Coastguard Worker using Handle = HANDLE;
52*6777b538SAndroid Build Coastguard Worker
53*6777b538SAndroid Build Coastguard Worker EventLogHandleTraits() = delete;
54*6777b538SAndroid Build Coastguard Worker EventLogHandleTraits(const EventLogHandleTraits&) = delete;
55*6777b538SAndroid Build Coastguard Worker EventLogHandleTraits& operator=(const EventLogHandleTraits&) = delete;
56*6777b538SAndroid Build Coastguard Worker
57*6777b538SAndroid Build Coastguard Worker // Closes the handle.
CloseHandle(HANDLE handle)58*6777b538SAndroid Build Coastguard Worker static bool CloseHandle(HANDLE handle) {
59*6777b538SAndroid Build Coastguard Worker return ::DeregisterEventSource(handle) != FALSE;
60*6777b538SAndroid Build Coastguard Worker }
61*6777b538SAndroid Build Coastguard Worker
62*6777b538SAndroid Build Coastguard Worker // Returns true if the handle value is valid.
IsHandleValid(HANDLE handle)63*6777b538SAndroid Build Coastguard Worker static bool IsHandleValid(HANDLE handle) { return handle != nullptr; }
64*6777b538SAndroid Build Coastguard Worker
65*6777b538SAndroid Build Coastguard Worker // Returns null handle value.
NullHandle()66*6777b538SAndroid Build Coastguard Worker static HANDLE NullHandle() { return nullptr; }
67*6777b538SAndroid Build Coastguard Worker };
68*6777b538SAndroid Build Coastguard Worker
69*6777b538SAndroid Build Coastguard Worker using ScopedEventLogHandle =
70*6777b538SAndroid Build Coastguard Worker base::win::GenericScopedHandle<EventLogHandleTraits,
71*6777b538SAndroid Build Coastguard Worker base::win::DummyVerifierTraits>;
72*6777b538SAndroid Build Coastguard Worker
73*6777b538SAndroid Build Coastguard Worker } // namespace
74*6777b538SAndroid Build Coastguard Worker
SetEventSource(const std::string & name,uint16_t category,uint32_t event_id)75*6777b538SAndroid Build Coastguard Worker void SetEventSource(const std::string& name,
76*6777b538SAndroid Build Coastguard Worker uint16_t category,
77*6777b538SAndroid Build Coastguard Worker uint32_t event_id) {
78*6777b538SAndroid Build Coastguard Worker DCHECK_EQ(nullptr, g_event_source_name);
79*6777b538SAndroid Build Coastguard Worker g_event_source_name = new std::string(name);
80*6777b538SAndroid Build Coastguard Worker g_category = category;
81*6777b538SAndroid Build Coastguard Worker g_event_id = event_id;
82*6777b538SAndroid Build Coastguard Worker DCHECK_EQ(nullptr, g_user_sid);
83*6777b538SAndroid Build Coastguard Worker g_user_sid = new std::wstring();
84*6777b538SAndroid Build Coastguard Worker base::win::GetUserSidString(g_user_sid);
85*6777b538SAndroid Build Coastguard Worker }
86*6777b538SAndroid Build Coastguard Worker
ResetEventSourceForTesting()87*6777b538SAndroid Build Coastguard Worker void ResetEventSourceForTesting() {
88*6777b538SAndroid Build Coastguard Worker delete g_event_source_name;
89*6777b538SAndroid Build Coastguard Worker g_event_source_name = nullptr;
90*6777b538SAndroid Build Coastguard Worker delete g_user_sid;
91*6777b538SAndroid Build Coastguard Worker g_user_sid = nullptr;
92*6777b538SAndroid Build Coastguard Worker }
93*6777b538SAndroid Build Coastguard Worker
94*6777b538SAndroid Build Coastguard Worker #endif // BUILDFLAG(IS_WIN)
95*6777b538SAndroid Build Coastguard Worker
EventLogMessage(const char * file,int line,LogSeverity severity)96*6777b538SAndroid Build Coastguard Worker EventLogMessage::EventLogMessage(const char* file,
97*6777b538SAndroid Build Coastguard Worker int line,
98*6777b538SAndroid Build Coastguard Worker LogSeverity severity)
99*6777b538SAndroid Build Coastguard Worker : log_message_(file, line, severity) {
100*6777b538SAndroid Build Coastguard Worker }
101*6777b538SAndroid Build Coastguard Worker
~EventLogMessage()102*6777b538SAndroid Build Coastguard Worker EventLogMessage::~EventLogMessage() {
103*6777b538SAndroid Build Coastguard Worker if (!g_logging_enabled)
104*6777b538SAndroid Build Coastguard Worker return;
105*6777b538SAndroid Build Coastguard Worker
106*6777b538SAndroid Build Coastguard Worker #if BUILDFLAG(IS_WIN)
107*6777b538SAndroid Build Coastguard Worker // If g_event_source_name is nullptr (which it is per default) SYSLOG will
108*6777b538SAndroid Build Coastguard Worker // degrade gracefully to regular LOG. If you see this happening most probably
109*6777b538SAndroid Build Coastguard Worker // you are using SYSLOG before you called SetEventSourceName.
110*6777b538SAndroid Build Coastguard Worker if (g_event_source_name == nullptr)
111*6777b538SAndroid Build Coastguard Worker return;
112*6777b538SAndroid Build Coastguard Worker
113*6777b538SAndroid Build Coastguard Worker ScopedEventLogHandle event_log_handle(
114*6777b538SAndroid Build Coastguard Worker RegisterEventSourceA(nullptr, g_event_source_name->c_str()));
115*6777b538SAndroid Build Coastguard Worker
116*6777b538SAndroid Build Coastguard Worker if (!event_log_handle.is_valid()) {
117*6777b538SAndroid Build Coastguard Worker stream() << " !!NOT ADDED TO EVENTLOG!!";
118*6777b538SAndroid Build Coastguard Worker return;
119*6777b538SAndroid Build Coastguard Worker }
120*6777b538SAndroid Build Coastguard Worker
121*6777b538SAndroid Build Coastguard Worker std::string message(log_message_.str());
122*6777b538SAndroid Build Coastguard Worker WORD log_type = EVENTLOG_ERROR_TYPE;
123*6777b538SAndroid Build Coastguard Worker switch (log_message_.severity()) {
124*6777b538SAndroid Build Coastguard Worker case LOGGING_INFO:
125*6777b538SAndroid Build Coastguard Worker log_type = EVENTLOG_INFORMATION_TYPE;
126*6777b538SAndroid Build Coastguard Worker break;
127*6777b538SAndroid Build Coastguard Worker case LOGGING_WARNING:
128*6777b538SAndroid Build Coastguard Worker log_type = EVENTLOG_WARNING_TYPE;
129*6777b538SAndroid Build Coastguard Worker break;
130*6777b538SAndroid Build Coastguard Worker case LOGGING_ERROR:
131*6777b538SAndroid Build Coastguard Worker case LOGGING_FATAL:
132*6777b538SAndroid Build Coastguard Worker // The price of getting the stack trace is not worth the hassle for
133*6777b538SAndroid Build Coastguard Worker // non-error conditions.
134*6777b538SAndroid Build Coastguard Worker base::debug::StackTrace trace;
135*6777b538SAndroid Build Coastguard Worker message.append(trace.ToString());
136*6777b538SAndroid Build Coastguard Worker log_type = EVENTLOG_ERROR_TYPE;
137*6777b538SAndroid Build Coastguard Worker break;
138*6777b538SAndroid Build Coastguard Worker }
139*6777b538SAndroid Build Coastguard Worker LPCSTR strings[1] = {message.data()};
140*6777b538SAndroid Build Coastguard Worker PSID user_sid = nullptr;
141*6777b538SAndroid Build Coastguard Worker if (!::ConvertStringSidToSid(g_user_sid->c_str(), &user_sid)) {
142*6777b538SAndroid Build Coastguard Worker stream() << " !!ERROR GETTING USER SID!!";
143*6777b538SAndroid Build Coastguard Worker }
144*6777b538SAndroid Build Coastguard Worker
145*6777b538SAndroid Build Coastguard Worker if (!ReportEventA(event_log_handle.get(), log_type, g_category, g_event_id,
146*6777b538SAndroid Build Coastguard Worker user_sid, 1, 0, strings, nullptr)) {
147*6777b538SAndroid Build Coastguard Worker stream() << " !!NOT ADDED TO EVENTLOG!!";
148*6777b538SAndroid Build Coastguard Worker }
149*6777b538SAndroid Build Coastguard Worker
150*6777b538SAndroid Build Coastguard Worker if (user_sid != nullptr)
151*6777b538SAndroid Build Coastguard Worker ::LocalFree(user_sid);
152*6777b538SAndroid Build Coastguard Worker #elif BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS)
153*6777b538SAndroid Build Coastguard Worker const char kEventSource[] = "chrome";
154*6777b538SAndroid Build Coastguard Worker openlog(kEventSource, LOG_NOWAIT | LOG_PID, LOG_USER);
155*6777b538SAndroid Build Coastguard Worker // We can't use the defined names for the logging severity from syslog.h
156*6777b538SAndroid Build Coastguard Worker // because they collide with the names of our own severity levels. Therefore
157*6777b538SAndroid Build Coastguard Worker // we use the actual values which of course do not match ours.
158*6777b538SAndroid Build Coastguard Worker // See sys/syslog.h for reference.
159*6777b538SAndroid Build Coastguard Worker int priority = 3;
160*6777b538SAndroid Build Coastguard Worker switch (log_message_.severity()) {
161*6777b538SAndroid Build Coastguard Worker case LOGGING_INFO:
162*6777b538SAndroid Build Coastguard Worker priority = 6;
163*6777b538SAndroid Build Coastguard Worker break;
164*6777b538SAndroid Build Coastguard Worker case LOGGING_WARNING:
165*6777b538SAndroid Build Coastguard Worker priority = 4;
166*6777b538SAndroid Build Coastguard Worker break;
167*6777b538SAndroid Build Coastguard Worker case LOGGING_ERROR:
168*6777b538SAndroid Build Coastguard Worker priority = 3;
169*6777b538SAndroid Build Coastguard Worker break;
170*6777b538SAndroid Build Coastguard Worker case LOGGING_FATAL:
171*6777b538SAndroid Build Coastguard Worker priority = 2;
172*6777b538SAndroid Build Coastguard Worker break;
173*6777b538SAndroid Build Coastguard Worker }
174*6777b538SAndroid Build Coastguard Worker syslog(priority, "%s", log_message_.str().c_str());
175*6777b538SAndroid Build Coastguard Worker closelog();
176*6777b538SAndroid Build Coastguard Worker #endif // BUILDFLAG(IS_WIN)
177*6777b538SAndroid Build Coastguard Worker }
178*6777b538SAndroid Build Coastguard Worker
SetSyslogLoggingForTesting(bool logging_enabled)179*6777b538SAndroid Build Coastguard Worker void SetSyslogLoggingForTesting(bool logging_enabled) {
180*6777b538SAndroid Build Coastguard Worker g_logging_enabled = logging_enabled;
181*6777b538SAndroid Build Coastguard Worker }
182*6777b538SAndroid Build Coastguard Worker
183*6777b538SAndroid Build Coastguard Worker } // namespace logging
184