| // Copyright 2020 The Chromium OS Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| // Defines base class LogReader and its derived classes AuditReader and |
| // MessageReader. AuditReader parses SELinux logs from /var/log/audit/audit.log |
| // and MessageReader parses other logs from /var/log/messages and |
| // /var/log/upstart.log. |
| |
| #ifndef CRASH_REPORTER_ANOMALY_DETECTOR_LOG_READER_H_ |
| #define CRASH_REPORTER_ANOMALY_DETECTOR_LOG_READER_H_ |
| |
| #include "crash-reporter/anomaly_detector_text_file_reader.h" |
| |
| #include <string> |
| |
| #include <base/files/file_util.h> |
| #include <base/time/time.h> |
| #include <re2/re2.h> |
| |
| namespace anomaly { |
| |
| // First group captures unix timestamp. |
| // Second group captures the log message. |
| // e.g. |
| // `type=AVC msg=audit(1588751099.358:13): avc: denied { module_request }` |
| // ` for pid=1795 comm="init" kmod="fs-cgroup2" scontext=u:r:init:s0` |
| // ` tcontext=u:r:kernel:s0 tclass=system permissive=0` |
| constexpr char kAuditLogPattern[] = R"([^(]+\(([\d\.]+)\S+ (.+))"; |
| |
| // First group captures timestamp in RFC3339 format. |
| // Second group captures the tag (i.e. service name). |
| // Third group captures the log message. |
| // e.g. |
| // `2020-05-10T22:45:04.419261Z ERR tpm_managerd[790]: TPM error` |
| // ` 0x3011 (Communication failure): Failed to connect context.` |
| // e.g.2 |
| // `2020-05-10T22:45:04.419261Z ERR kernel: [ 893.009245]` |
| // ` atme1_mxt_ts 3-004b: Status: 00 Config Checksum: 673e89` |
| // e.g.3 |
| // `2020-05-14T19:37:04.202906Z INFO VM(3)[8947]:` |
| // ` [devices/src/virtio/balloon.rs:290] ballon config changed` |
| constexpr char kMessageLogPattern[] = R"((\S+) \S+ (\S*?)(?:\[\d+\])?:\s+(.+))"; |
| |
| // First group captures timestamp in RFC3339 format. |
| // Second group captures the service name. |
| // Third group captures the log message. |
| // e.g. |
| // `2020-05-15T16:34:00.678394Z INFO kernel:` |
| // ` [ 1608.687863] init: Connection from private client` |
| constexpr char kUpstartLogPattern[] = |
| R"((\S+) \S+ \S+: \[\s*\S+\] (\w+):\s+(.+))"; |
| |
| // Describes an entry in log files. |
| // tag: name of the service that generated the log. |
| // message: content of the log. |
| // timestamp: timestamp of the log. |
| struct LogEntry { |
| std::string tag; |
| std::string message; |
| base::Time timestamp; |
| }; |
| |
| // LogReader parses newline-delimited log entries into structs that can |
| // be parsed by log parsers (in anomaly_detector.h) to be analysed for errors. |
| // It uses anomaly::TextFileReader for reading lines in the log files and |
| // handling log rotations. |
| class LogReader { |
| public: |
| explicit LogReader(const base::FilePath& path); |
| LogReader(const LogReader&) = delete; |
| LogReader& operator=(const LogReader&) = delete; |
| |
| virtual ~LogReader() = 0; |
| |
| // Returns true while there are log entries in the log file. It will update |
| // the output parameter 'entry' if one is found. |
| bool GetNextEntry(LogEntry* entry); |
| |
| private: |
| const base::FilePath log_file_path_; |
| |
| // TextFileReader is defined in anomaly_detector_text_file_reader.h. |
| TextFileReader log_file_; |
| |
| // Parses a line from log_file_ to generate LogEntry. |
| virtual bool ReadLine(const std::string& line, LogEntry* entry) = 0; |
| |
| // Moves the position of log_file_ to the beginning. |
| // Only used for testing. |
| void SeekToBegin(); |
| |
| FRIEND_TEST(AnomalyDetectorLogReaderTest, AuditReaderTest); |
| FRIEND_TEST(AnomalyDetectorLogReaderTest, MessageReaderTest); |
| FRIEND_TEST(AnomalyDetectorLogReaderTest, UpstartMessageReaderTest); |
| }; |
| |
| // AuditReader specialises in parsing log entries generated by SELinux. |
| class AuditReader : public LogReader { |
| public: |
| explicit AuditReader(const base::FilePath& path, const char* pattern) |
| : LogReader(path), pattern_(pattern) {} |
| |
| // Each line in log file is checked against pattern_ to retrieve relevant |
| // info. |
| const RE2 pattern_; |
| |
| private: |
| bool ReadLine(const std::string& line, LogEntry* entry) override; |
| }; |
| |
| // MessageReader specialises in parsing syslog formatted logs in |
| // /var/log/messages and /var/log/upstart.log. |
| class MessageReader : public LogReader { |
| public: |
| explicit MessageReader(const base::FilePath& path, const char* pattern) |
| : LogReader(path), pattern_(pattern) {} |
| |
| // Each line in log file is checked against pattern_ to retrieve relevant |
| // info. |
| const RE2 pattern_; |
| |
| private: |
| bool ReadLine(const std::string& line, LogEntry* entry) override; |
| }; |
| |
| } // namespace anomaly |
| |
| #endif // CRASH_REPORTER_ANOMALY_DETECTOR_LOG_READER_H_ |