diff --git a/logd/Android.bp b/logd/Android.bp index b337b7c2a..26632713d 100644 --- a/logd/Android.bp +++ b/logd/Android.bp @@ -36,7 +36,6 @@ cc_library_static { "CommandListener.cpp", "LogListener.cpp", "LogReader.cpp", - "FlushCommand.cpp", "LogBuffer.cpp", "LogBufferElement.cpp", "LogTimes.cpp", diff --git a/logd/CommandListener.cpp b/logd/CommandListener.cpp index 694b5fa3c..4044dc984 100644 --- a/logd/CommandListener.cpp +++ b/logd/CommandListener.cpp @@ -31,6 +31,7 @@ #include #include +#include #include #include @@ -38,37 +39,20 @@ #include "LogCommand.h" #include "LogUtils.h" -CommandListener::CommandListener(LogBuffer* buf, LogReader* /*reader*/, - LogListener* /*swl*/) - : FrameworkListener(getLogSocket()) { - // registerCmd(new ShutdownCmd(buf, writer, swl)); - registerCmd(new ClearCmd(buf)); - registerCmd(new GetBufSizeCmd(buf)); - registerCmd(new SetBufSizeCmd(buf)); - registerCmd(new GetBufSizeUsedCmd(buf)); - registerCmd(new GetStatisticsCmd(buf)); - registerCmd(new SetPruneListCmd(buf)); - registerCmd(new GetPruneListCmd(buf)); - registerCmd(new GetEventTagCmd(buf)); - registerCmd(new ReinitCmd()); +CommandListener::CommandListener(LogBuffer* buf, LogTags* tags, PruneList* prune) + : FrameworkListener(getLogSocket()), buf_(buf), tags_(tags), prune_(prune) { + registerCmd(new ClearCmd(this)); + registerCmd(new GetBufSizeCmd(this)); + registerCmd(new SetBufSizeCmd(this)); + registerCmd(new GetBufSizeUsedCmd(this)); + registerCmd(new GetStatisticsCmd(this)); + registerCmd(new SetPruneListCmd(this)); + registerCmd(new GetPruneListCmd(this)); + registerCmd(new GetEventTagCmd(this)); + registerCmd(new ReinitCmd(this)); registerCmd(new ExitCmd(this)); } -CommandListener::ShutdownCmd::ShutdownCmd(LogReader* reader, LogListener* swl) - : LogCommand("shutdown"), mReader(*reader), mSwl(*swl) { -} - -int CommandListener::ShutdownCmd::runCommand(SocketClient* /*cli*/, - int /*argc*/, char** /*argv*/) { - mSwl.stopListener(); - mReader.stopListener(); - exit(0); -} - -CommandListener::ClearCmd::ClearCmd(LogBuffer* buf) - : LogCommand("clear"), mBuf(*buf) { -} - static void setname() { static bool name_set; if (!name_set) { @@ -96,14 +80,10 @@ int CommandListener::ClearCmd::runCommand(SocketClient* cli, int argc, return 0; } - cli->sendMsg(mBuf.clear((log_id_t)id, uid) ? "busy" : "success"); + cli->sendMsg(buf()->clear((log_id_t)id, uid) ? "busy" : "success"); return 0; } -CommandListener::GetBufSizeCmd::GetBufSizeCmd(LogBuffer* buf) - : LogCommand("getLogSize"), mBuf(*buf) { -} - int CommandListener::GetBufSizeCmd::runCommand(SocketClient* cli, int argc, char** argv) { setname(); @@ -118,17 +98,13 @@ int CommandListener::GetBufSizeCmd::runCommand(SocketClient* cli, int argc, return 0; } - unsigned long size = mBuf.getSize((log_id_t)id); + unsigned long size = buf()->getSize((log_id_t)id); char buf[512]; snprintf(buf, sizeof(buf), "%lu", size); cli->sendMsg(buf); return 0; } -CommandListener::SetBufSizeCmd::SetBufSizeCmd(LogBuffer* buf) - : LogCommand("setLogSize"), mBuf(*buf) { -} - int CommandListener::SetBufSizeCmd::runCommand(SocketClient* cli, int argc, char** argv) { setname(); @@ -149,7 +125,7 @@ int CommandListener::SetBufSizeCmd::runCommand(SocketClient* cli, int argc, } unsigned long size = atol(argv[2]); - if (mBuf.setSize((log_id_t)id, size)) { + if (buf()->setSize((log_id_t)id, size)) { cli->sendMsg("Range Error"); return 0; } @@ -158,10 +134,6 @@ int CommandListener::SetBufSizeCmd::runCommand(SocketClient* cli, int argc, return 0; } -CommandListener::GetBufSizeUsedCmd::GetBufSizeUsedCmd(LogBuffer* buf) - : LogCommand("getLogSizeUsed"), mBuf(*buf) { -} - int CommandListener::GetBufSizeUsedCmd::runCommand(SocketClient* cli, int argc, char** argv) { setname(); @@ -176,17 +148,13 @@ int CommandListener::GetBufSizeUsedCmd::runCommand(SocketClient* cli, int argc, return 0; } - unsigned long size = mBuf.getSizeUsed((log_id_t)id); + unsigned long size = buf()->getSizeUsed((log_id_t)id); char buf[512]; snprintf(buf, sizeof(buf), "%lu", size); cli->sendMsg(buf); return 0; } -CommandListener::GetStatisticsCmd::GetStatisticsCmd(LogBuffer* buf) - : LogCommand("getStatistics"), mBuf(*buf) { -} - // This returns a string with a length prefix with the format \n\n\f. The length // prefix includes the length of the prefix itself. static std::string PackageString(const std::string& str) { @@ -241,25 +209,17 @@ int CommandListener::GetStatisticsCmd::runCommand(SocketClient* cli, int argc, } } - cli->sendMsg(PackageString(mBuf.formatStatistics(uid, pid, logMask)).c_str()); + cli->sendMsg(PackageString(buf()->formatStatistics(uid, pid, logMask)).c_str()); return 0; } -CommandListener::GetPruneListCmd::GetPruneListCmd(LogBuffer* buf) - : LogCommand("getPruneList"), mBuf(*buf) { -} - int CommandListener::GetPruneListCmd::runCommand(SocketClient* cli, int /*argc*/, char** /*argv*/) { setname(); - cli->sendMsg(PackageString(mBuf.formatPrune()).c_str()); + cli->sendMsg(PackageString(prune()->format()).c_str()); return 0; } -CommandListener::SetPruneListCmd::SetPruneListCmd(LogBuffer* buf) - : LogCommand("setPruneList"), mBuf(*buf) { -} - int CommandListener::SetPruneListCmd::runCommand(SocketClient* cli, int argc, char** argv) { setname(); @@ -276,7 +236,7 @@ int CommandListener::SetPruneListCmd::runCommand(SocketClient* cli, int argc, str += argv[i]; } - int ret = mBuf.initPrune(str.c_str()); + int ret = prune()->init(str.c_str()); if (ret) { cli->sendMsg("Invalid"); @@ -288,10 +248,6 @@ int CommandListener::SetPruneListCmd::runCommand(SocketClient* cli, int argc, return 0; } -CommandListener::GetEventTagCmd::GetEventTagCmd(LogBuffer* buf) - : LogCommand("getEventTag"), mBuf(*buf) { -} - int CommandListener::GetEventTagCmd::runCommand(SocketClient* cli, int argc, char** argv) { setname(); @@ -328,39 +284,45 @@ int CommandListener::GetEventTagCmd::runCommand(SocketClient* cli, int argc, cli->sendMsg("can not mix id= with either format= or name="); return 0; } - cli->sendMsg(PackageString(mBuf.formatEntry(atoi(id), uid)).c_str()); + cli->sendMsg(PackageString(tags()->formatEntry(atoi(id), uid)).c_str()); return 0; } - cli->sendMsg(PackageString(mBuf.formatGetEventTag(uid, name, format)).c_str()); + cli->sendMsg(PackageString(tags()->formatGetEventTag(uid, name, format)).c_str()); return 0; } -CommandListener::ReinitCmd::ReinitCmd() : LogCommand("reinit") { -} - int CommandListener::ReinitCmd::runCommand(SocketClient* cli, int /*argc*/, char** /*argv*/) { setname(); - reinit_signal_handler(SIGHUP); + android::prdebug("logd reinit"); + buf()->init(); + prune()->init(nullptr); + + // This only works on userdebug and eng devices to re-read the + // /data/misc/logd/event-log-tags file right after /data is mounted. + // The operation is near to boot and should only happen once. There + // are races associated with its use since it can trigger a Rebuild + // of the file, but that is a can-not-happen since the file was not + // read yet. More dangerous if called later, but if all is well it + // should just skip over everything and not write any new entries. + if (__android_log_is_debuggable()) { + tags()->ReadFileEventLogTags(tags()->debug_event_log_tags); + } cli->sendMsg("success"); return 0; } -CommandListener::ExitCmd::ExitCmd(CommandListener* parent) - : LogCommand("EXIT"), mParent(*parent) { -} - int CommandListener::ExitCmd::runCommand(SocketClient* cli, int /*argc*/, char** /*argv*/) { setname(); cli->sendMsg("success"); - release(cli); + parent_->release(cli); return 0; } diff --git a/logd/CommandListener.h b/logd/CommandListener.h index ed9941938..c90c247cb 100644 --- a/logd/CommandListener.h +++ b/logd/CommandListener.h @@ -14,85 +14,53 @@ * limitations under the License. */ -#ifndef _COMMANDLISTENER_H__ -#define _COMMANDLISTENER_H__ +#pragma once #include + #include "LogBuffer.h" #include "LogCommand.h" #include "LogListener.h" #include "LogReader.h" - -// See main.cpp for implementation -void reinit_signal_handler(int /*signal*/); +#include "LogTags.h" +#include "LogWhiteBlackList.h" class CommandListener : public FrameworkListener { - public: - CommandListener(LogBuffer* buf, LogReader* reader, LogListener* swl); - virtual ~CommandListener() { - } + public: + CommandListener(LogBuffer* buf, LogTags* tags, PruneList* prune); + virtual ~CommandListener() {} - private: + private: static int getLogSocket(); - class ShutdownCmd : public LogCommand { - LogReader& mReader; - LogListener& mSwl; + LogBuffer* buf_; + LogTags* tags_; + PruneList* prune_; - public: - ShutdownCmd(LogReader* reader, LogListener* swl); - virtual ~ShutdownCmd() { - } - int runCommand(SocketClient* c, int argc, char** argv); - }; - -#define LogBufferCmd(name) \ +#define LogCmd(name, command_string) \ class name##Cmd : public LogCommand { \ - LogBuffer& mBuf; \ + public: \ + explicit name##Cmd(CommandListener* parent) \ + : LogCommand(#command_string), parent_(parent) {} \ + virtual ~name##Cmd() {} \ + int runCommand(SocketClient* c, int argc, char** argv); \ \ - public: \ - explicit name##Cmd(LogBuffer* buf); \ - virtual ~name##Cmd() { \ - } \ - int runCommand(SocketClient* c, int argc, char** argv); \ + private: \ + LogBuffer* buf() const { return parent_->buf_; } \ + LogTags* tags() const { return parent_->tags_; } \ + PruneList* prune() const { return parent_->prune_; } \ + CommandListener* parent_; \ } - LogBufferCmd(Clear); - LogBufferCmd(GetBufSize); - LogBufferCmd(SetBufSize); - LogBufferCmd(GetBufSizeUsed); - LogBufferCmd(GetStatistics); - LogBufferCmd(GetPruneList); - LogBufferCmd(SetPruneList); - LogBufferCmd(GetEventTag); - -#define LogCmd(name) \ - class name##Cmd : public LogCommand { \ - public: \ - name##Cmd(); \ - virtual ~name##Cmd() { \ - } \ - int runCommand(SocketClient* c, int argc, char** argv); \ - } - - LogCmd(Reinit); - -#define LogParentCmd(name) \ - class name##Cmd : public LogCommand { \ - CommandListener& mParent; \ - \ - public: \ - name##Cmd(); \ - explicit name##Cmd(CommandListener* parent); \ - virtual ~name##Cmd() { \ - } \ - int runCommand(SocketClient* c, int argc, char** argv); \ - void release(SocketClient* c) { \ - mParent.release(c); \ - } \ - } - - LogParentCmd(Exit); + LogCmd(Clear, clear); + LogCmd(GetBufSize, getLogSize); + LogCmd(SetBufSize, setLogSize); + LogCmd(GetBufSizeUsed, getLogSizeUsed); + LogCmd(GetStatistics, getStatistics); + LogCmd(GetPruneList, getPruneList); + LogCmd(SetPruneList, setPruneList); + LogCmd(GetEventTag, getEventTag); + LogCmd(Reinit, reinit); + LogCmd(Exit, EXIT); +#undef LogCmd }; - -#endif diff --git a/logd/FlushCommand.cpp b/logd/FlushCommand.cpp deleted file mode 100644 index 0845504ac..000000000 --- a/logd/FlushCommand.cpp +++ /dev/null @@ -1,75 +0,0 @@ -/* - * Copyright (C) 2012-2014 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include - -#include - -#include "FlushCommand.h" -#include "LogBuffer.h" -#include "LogBufferElement.h" -#include "LogCommand.h" -#include "LogReader.h" -#include "LogTimes.h" -#include "LogUtils.h" - -// runSocketCommand is called once for every open client on the -// log reader socket. Here we manage and associated the reader -// client tracking and log region locks LastLogTimes list of -// LogTimeEntrys, and spawn a transitory per-client thread to -// work at filing data to the socket. -// -// global LogTimeEntry::wrlock() is used to protect access, -// reference counts are used to ensure that individual -// LogTimeEntry lifetime is managed when not protected. -void FlushCommand::runSocketCommand(SocketClient* client) { - LogTimeEntry* entry = nullptr; - LastLogTimes& times = mReader.logbuf().mTimes; - - LogTimeEntry::wrlock(); - LastLogTimes::iterator it = times.begin(); - while (it != times.end()) { - entry = it->get(); - if (entry->mClient == client) { - if (!entry->isWatchingMultiple(mLogMask)) { - LogTimeEntry::unlock(); - return; - } - if (entry->mTimeout.tv_sec || entry->mTimeout.tv_nsec) { - LogTimeEntry::unlock(); - return; - } - entry->triggerReader_Locked(); - LogTimeEntry::unlock(); - return; - } - it++; - } - - LogTimeEntry::unlock(); -} - -bool FlushCommand::hasReadLogs(SocketClient* client) { - return clientHasLogCredentials(client); -} - -static bool clientHasSecurityCredentials(SocketClient* client) { - return (client->getUid() == AID_SYSTEM) || (client->getGid() == AID_SYSTEM); -} - -bool FlushCommand::hasSecurityLogs(SocketClient* client) { - return clientHasSecurityCredentials(client); -} diff --git a/logd/FlushCommand.h b/logd/FlushCommand.h deleted file mode 100644 index a69d43922..000000000 --- a/logd/FlushCommand.h +++ /dev/null @@ -1,43 +0,0 @@ -/* - * Copyright (C) 2012-2013 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -#ifndef _FLUSH_COMMAND_H -#define _FLUSH_COMMAND_H - -#include -#include - -class LogBufferElement; - -#include "LogTimes.h" - -class LogReader; - -class FlushCommand : public SocketClientCommand { - LogReader& mReader; - log_mask_t mLogMask; - - public: - explicit FlushCommand(LogReader& reader, log_mask_t logMask) - : mReader(reader), mLogMask(logMask) { - } - - virtual void runSocketCommand(SocketClient* client); - - static bool hasReadLogs(SocketClient* client); - static bool hasSecurityLogs(SocketClient* client); -}; - -#endif diff --git a/logd/LogBuffer.cpp b/logd/LogBuffer.cpp index 36273deac..a3e4e094e 100644 --- a/logd/LogBuffer.cpp +++ b/logd/LogBuffer.cpp @@ -92,11 +92,7 @@ void LogBuffer::init() { unlock(); } - // We may have been triggered by a SIGHUP. Release any sleeping reader - // threads to dump their current content. - // - // NB: this is _not_ performed in the context of a SIGHUP, it is - // performed during startup, and in context of reinit administrative thread + // Release any sleeping reader threads to dump their current content. LogTimeEntry::wrlock(); LastLogTimes::iterator times = mTimes.begin(); @@ -109,8 +105,11 @@ void LogBuffer::init() { LogTimeEntry::unlock(); } -LogBuffer::LogBuffer(LastLogTimes* times) - : monotonic(android_log_clockid() == CLOCK_MONOTONIC), mTimes(*times) { +LogBuffer::LogBuffer(LastLogTimes* times, LogTags* tags, PruneList* prune) + : monotonic(android_log_clockid() == CLOCK_MONOTONIC), + mTimes(*times), + tags_(tags), + prune_(prune) { pthread_rwlock_init(&mLogElementsLock, nullptr); log_id_for_each(i) { @@ -130,14 +129,14 @@ LogBuffer::~LogBuffer() { LogBufferElementCollection::iterator LogBuffer::GetOldest(log_id_t log_id) { auto it = mLogElements.begin(); - if (mOldest[log_id]) { - it = *mOldest[log_id]; + if (oldest_[log_id]) { + it = *oldest_[log_id]; } while (it != mLogElements.end() && (*it)->getLogId() != log_id) { it++; } if (it != mLogElements.end()) { - mOldest[log_id] = it; + oldest_[log_id] = it; } return it; } @@ -232,7 +231,7 @@ int LogBuffer::log(log_id_t log_id, log_time realtime, uid_t uid, pid_t pid, const char* tag = nullptr; size_t tag_len = 0; if (log_id == LOG_ID_EVENTS || log_id == LOG_ID_STATS) { - tag = tagToName(elem->getTag()); + tag = tags_->tagToName(elem->getTag()); if (tag) { tag_len = strlen(tag); } @@ -461,7 +460,7 @@ LogBufferElementCollection::iterator LogBuffer::erase( bool setLast[LOG_ID_MAX]; bool doSetLast = false; - log_id_for_each(i) { doSetLast |= setLast[i] = mOldest[i] && it == *mOldest[i]; } + log_id_for_each(i) { doSetLast |= setLast[i] = oldest_[i] && it == *oldest_[i]; } #ifdef DEBUG_CHECK_FOR_STALE_ENTRIES LogBufferElementCollection::iterator bad = it; int key = ((id == LOG_ID_EVENTS) || (id == LOG_ID_SECURITY)) @@ -473,9 +472,9 @@ LogBufferElementCollection::iterator LogBuffer::erase( log_id_for_each(i) { if (setLast[i]) { if (__predict_false(it == mLogElements.end())) { - mOldest[i] = std::nullopt; + oldest_[i] = std::nullopt; } else { - mOldest[i] = it; // Store the next iterator even if it does not correspond to + oldest_[i] = it; // Store the next iterator even if it does not correspond to // the same log_id, as a starting point for GetOldest(). } } @@ -698,7 +697,7 @@ bool LogBuffer::prune(log_id_t id, unsigned long pruneRows, uid_t caller_uid) { } // prune by worst offenders; by blacklist, UID, and by PID of system UID - bool hasBlacklist = (id != LOG_ID_SECURITY) && mPrune.naughty(); + bool hasBlacklist = (id != LOG_ID_SECURITY) && prune_->naughty(); while (!clearAll && (pruneRows > 0)) { // recalculate the worst offender on every batched pass int worst = -1; // not valid for getUid() or getKey() @@ -706,7 +705,7 @@ bool LogBuffer::prune(log_id_t id, unsigned long pruneRows, uid_t caller_uid) { size_t second_worst_sizes = 0; pid_t worstPid = 0; // POSIX guarantees PID != 0 - if (worstUidEnabledForLogid(id) && mPrune.worstUidEnabled()) { + if (worstUidEnabledForLogid(id) && prune_->worstUidEnabled()) { // Calculate threshold as 12.5% of available storage size_t threshold = log_buffer_size(id) / 8; @@ -720,7 +719,7 @@ bool LogBuffer::prune(log_id_t id, unsigned long pruneRows, uid_t caller_uid) { .findWorst(worst, worst_sizes, second_worst_sizes, threshold); - if ((worst == AID_SYSTEM) && mPrune.worstPidOfSystemEnabled()) { + if ((worst == AID_SYSTEM) && prune_->worstPidOfSystemEnabled()) { stats.sortPids(worst, (pid_t)0, 2, id) .findWorst(worstPid, worst_sizes, second_worst_sizes); } @@ -802,7 +801,7 @@ bool LogBuffer::prune(log_id_t id, unsigned long pruneRows, uid_t caller_uid) { ? element->getTag() : element->getUid(); - if (hasBlacklist && mPrune.naughty(element)) { + if (hasBlacklist && prune_->naughty(element)) { last.clear(element); it = erase(it); if (dropped) { @@ -899,13 +898,13 @@ bool LogBuffer::prune(log_id_t id, unsigned long pruneRows, uid_t caller_uid) { } last.clear(); - if (!kick || !mPrune.worstUidEnabled()) { + if (!kick || !prune_->worstUidEnabled()) { break; // the following loop will ask bad clients to skip/drop } } bool whitelist = false; - bool hasWhitelist = (id != LOG_ID_SECURITY) && mPrune.nice() && !clearAll; + bool hasWhitelist = (id != LOG_ID_SECURITY) && prune_->nice() && !clearAll; it = GetOldest(id); while ((pruneRows > 0) && (it != mLogElements.end())) { LogBufferElement* element = *it; @@ -921,7 +920,7 @@ bool LogBuffer::prune(log_id_t id, unsigned long pruneRows, uid_t caller_uid) { break; } - if (hasWhitelist && !element->getDropped() && mPrune.nice(element)) { + if (hasWhitelist && !element->getDropped() && prune_->nice(element)) { // WhiteListed whitelist = true; it++; diff --git a/logd/LogBuffer.h b/logd/LogBuffer.h index 458fbbbd2..9a367127a 100644 --- a/logd/LogBuffer.h +++ b/logd/LogBuffer.h @@ -14,8 +14,7 @@ * limitations under the License. */ -#ifndef _LOGD_LOG_BUFFER_H__ -#define _LOGD_LOG_BUFFER_H__ +#pragma once #include @@ -81,10 +80,6 @@ class LogBuffer { LogStatistics stats; - PruneList mPrune; - // Keeps track of the iterator to the oldest log message of a given log type, as an - // optimization when pruning logs. Use GetOldest() to retrieve. - std::optional mOldest[LOG_ID_MAX]; // watermark of any worst/chatty uid processing typedef std::unordered_map LogBufferIteratorMap; @@ -98,8 +93,6 @@ class LogBuffer { bool monotonic; - LogTags tags; - LogBufferElement* lastLoggedElements[LOG_ID_MAX]; LogBufferElement* droppedElements[LOG_ID_MAX]; void log(LogBufferElement* elem); @@ -107,7 +100,7 @@ class LogBuffer { public: LastLogTimes& mTimes; - explicit LogBuffer(LastLogTimes* times); + LogBuffer(LastLogTimes* times, LogTags* tags, PruneList* prune); ~LogBuffer(); void init(); bool isMonotonic() { @@ -136,24 +129,6 @@ class LogBuffer { stats.enableStatistics(); } - int initPrune(const char* cp) { - return mPrune.init(cp); - } - std::string formatPrune() { - return mPrune.format(); - } - - std::string formatGetEventTag(uid_t uid, const char* name, - const char* format) { - return tags.formatGetEventTag(uid, name, format); - } - std::string formatEntry(uint32_t tag, uid_t uid) { - return tags.formatEntry(tag, uid); - } - const char* tagToName(uint32_t tag) { - return tags.tagToName(tag); - } - // helper must be protected directly or implicitly by wrlock()/unlock() const char* pidToName(pid_t pid) { return stats.pidToName(pid); @@ -186,6 +161,11 @@ class LogBuffer { // Returns an iterator to the oldest element for a given log type, or mLogElements.end() if // there are no logs for the given log type. Requires mLogElementsLock to be held. LogBufferElementCollection::iterator GetOldest(log_id_t log_id); -}; -#endif // _LOGD_LOG_BUFFER_H__ + LogTags* tags_; + PruneList* prune_; + + // Keeps track of the iterator to the oldest log message of a given log type, as an + // optimization when pruning logs. Use GetOldest() to retrieve. + std::optional oldest_[LOG_ID_MAX]; +}; diff --git a/logd/LogReader.cpp b/logd/LogReader.cpp index f79d39c9d..c6dea69f8 100644 --- a/logd/LogReader.cpp +++ b/logd/LogReader.cpp @@ -24,21 +24,35 @@ #include #include -#include "FlushCommand.h" #include "LogBuffer.h" #include "LogBufferElement.h" #include "LogReader.h" #include "LogUtils.h" +static bool CanReadSecurityLogs(SocketClient* client) { + return client->getUid() == AID_SYSTEM || client->getGid() == AID_SYSTEM; +} + LogReader::LogReader(LogBuffer* logbuf) : SocketListener(getLogSocket(), true), mLogbuf(*logbuf) { } // When we are notified a new log entry is available, inform // listening sockets who are watching this entry's log id. -void LogReader::notifyNewLog(log_mask_t logMask) { - FlushCommand command(*this, logMask); - runOnEachSocket(&command); +void LogReader::notifyNewLog(log_mask_t log_mask) { + LastLogTimes& times = mLogbuf.mTimes; + + LogTimeEntry::wrlock(); + for (const auto& entry : times) { + if (!entry->isWatchingMultiple(log_mask)) { + continue; + } + if (entry->mTimeout.tv_sec || entry->mTimeout.tv_nsec) { + continue; + } + entry->triggerReader_Locked(); + } + LogTimeEntry::unlock(); } // Note returning false will release the SocketClient instance. @@ -129,6 +143,9 @@ bool LogReader::onDataAvailable(SocketClient* cli) { nonBlock = true; } + bool privileged = clientHasLogCredentials(cli); + bool can_read_security = CanReadSecurityLogs(cli); + uint64_t sequence = 1; // Convert realtime to sequence number if (start != log_time::EPOCH) { @@ -178,8 +195,7 @@ bool LogReader::onDataAvailable(SocketClient* cli) { } logFindStart(logMask, pid, start, sequence, logbuf().isMonotonic() && android::isMonotonic(start)); - logbuf().flushTo(cli, sequence, nullptr, FlushCommand::hasReadLogs(cli), - FlushCommand::hasSecurityLogs(cli), + logbuf().flushTo(cli, sequence, nullptr, privileged, can_read_security, logFindStart.callback, &logFindStart); if (!logFindStart.found()) { @@ -203,7 +219,7 @@ bool LogReader::onDataAvailable(SocketClient* cli) { LogTimeEntry::wrlock(); auto entry = std::make_unique(*this, cli, nonBlock, tail, logMask, pid, start, - sequence, timeout); + sequence, timeout, privileged, can_read_security); if (!entry->startReader_Locked()) { LogTimeEntry::unlock(); return false; diff --git a/logd/LogTags.cpp b/logd/LogTags.cpp index e45cc8ae6..3e52b3871 100644 --- a/logd/LogTags.cpp +++ b/logd/LogTags.cpp @@ -391,23 +391,6 @@ const char* android::tagToName(uint32_t tag) { return me->tagToName(tag); } -// Prototype in LogUtils.h allowing external access to our database. -// -// This only works on userdebug and eng devices to re-read the -// /data/misc/logd/event-log-tags file right after /data is mounted. -// The operation is near to boot and should only happen once. There -// are races associated with its use since it can trigger a Rebuild -// of the file, but that is a can-not-happen since the file was not -// read yet. More dangerous if called later, but if all is well it -// should just skip over everything and not write any new entries. -void android::ReReadEventLogTags() { - LogTags* me = logtags; - - if (me && __android_log_is_debuggable()) { - me->ReadFileEventLogTags(me->debug_event_log_tags); - } -} - // converts an event tag into a format const char* LogTags::tagToFormat(uint32_t tag) const { tag2format_const_iterator iform; diff --git a/logd/LogTimes.cpp b/logd/LogTimes.cpp index ed8d2f527..ad150bdb6 100644 --- a/logd/LogTimes.cpp +++ b/logd/LogTimes.cpp @@ -18,7 +18,6 @@ #include #include -#include "FlushCommand.h" #include "LogBuffer.h" #include "LogReader.h" #include "LogTimes.h" @@ -27,7 +26,8 @@ pthread_mutex_t LogTimeEntry::timesLock = PTHREAD_MUTEX_INITIALIZER; LogTimeEntry::LogTimeEntry(LogReader& reader, SocketClient* client, bool nonBlock, unsigned long tail, log_mask_t logMask, pid_t pid, log_time start_time, - uint64_t start, uint64_t timeout) + uint64_t start, uint64_t timeout, bool privileged, + bool can_read_security_logs) : leadingDropped(false), mReader(reader), mLogMask(logMask), @@ -38,7 +38,9 @@ LogTimeEntry::LogTimeEntry(LogReader& reader, SocketClient* client, bool nonBloc mClient(client), mStartTime(start_time), mStart(start), - mNonBlock(nonBlock) { + mNonBlock(nonBlock), + privileged_(privileged), + can_read_security_logs_(can_read_security_logs) { mTimeout.tv_sec = timeout / NS_PER_SEC; mTimeout.tv_nsec = timeout % NS_PER_SEC; memset(mLastTid, 0, sizeof(mLastTid)); @@ -72,9 +74,6 @@ void* LogTimeEntry::threadStart(void* obj) { LogBuffer& logbuf = me->mReader.logbuf(); - bool privileged = FlushCommand::hasReadLogs(client); - bool security = FlushCommand::hasSecurityLogs(client); - me->leadingDropped = true; wrlock(); @@ -96,12 +95,12 @@ void* LogTimeEntry::threadStart(void* obj) { unlock(); if (me->mTail) { - logbuf.flushTo(client, start, nullptr, privileged, security, + logbuf.flushTo(client, start, nullptr, me->privileged_, me->can_read_security_logs_, FilterFirstPass, me); me->leadingDropped = true; } - start = logbuf.flushTo(client, start, me->mLastTid, privileged, - security, FilterSecondPass, me); + start = logbuf.flushTo(client, start, me->mLastTid, me->privileged_, + me->can_read_security_logs_, FilterSecondPass, me); // We only ignore entries before the original start time for the first flushTo(), if we // get entries after this first flush before the original start time, then the client diff --git a/logd/LogTimes.h b/logd/LogTimes.h index a99c73bc6..56c930a15 100644 --- a/logd/LogTimes.h +++ b/logd/LogTimes.h @@ -52,7 +52,7 @@ class LogTimeEntry { public: LogTimeEntry(LogReader& reader, SocketClient* client, bool nonBlock, unsigned long tail, log_mask_t logMask, pid_t pid, log_time start_time, uint64_t sequence, - uint64_t timeout); + uint64_t timeout, bool privileged, bool can_read_security_logs); SocketClient* mClient; log_time mStartTime; @@ -98,6 +98,10 @@ class LogTimeEntry { // flushTo filter callbacks static int FilterFirstPass(const LogBufferElement* element, void* me); static int FilterSecondPass(const LogBufferElement* element, void* me); + + private: + bool privileged_; + bool can_read_security_logs_; }; typedef std::list> LastLogTimes; diff --git a/logd/LogUtils.h b/logd/LogUtils.h index fa9f39895..f9cd42dcb 100644 --- a/logd/LogUtils.h +++ b/logd/LogUtils.h @@ -14,8 +14,7 @@ * limitations under the License. */ -#ifndef _LOGD_LOG_UTILS_H__ -#define _LOGD_LOG_UTILS_H__ +#pragma once #include #include @@ -41,7 +40,6 @@ char* tidToName(pid_t tid); // Furnished in LogTags.cpp. Thread safe. const char* tagToName(uint32_t tag); -void ReReadEventLogTags(); // Furnished by LogKlog.cpp char* log_strntok_r(char* s, ssize_t& len, char*& saveptr, ssize_t& sublen); @@ -72,5 +70,3 @@ static inline bool worstUidEnabledForLogid(log_id_t id) { return (id == LOG_ID_MAIN) || (id == LOG_ID_SYSTEM) || (id == LOG_ID_RADIO) || (id == LOG_ID_EVENTS); } - -#endif // _LOGD_LOG_UTILS_H__ diff --git a/logd/fuzz/log_buffer_log_fuzzer.cpp b/logd/fuzz/log_buffer_log_fuzzer.cpp index 4d1589b50..14c5163e2 100644 --- a/logd/fuzz/log_buffer_log_fuzzer.cpp +++ b/logd/fuzz/log_buffer_log_fuzzer.cpp @@ -94,12 +94,14 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) { } LastLogTimes times; - LogBuffer log_buffer(×); + LogTags tags; + PruneList prune_list; + LogBuffer log_buffer(×, &tags, &prune_list); size_t data_left = size; const uint8_t** pdata = &data; log_buffer.enableStatistics(); - log_buffer.initPrune(nullptr); + prune_list.init(nullptr); // We want to get pruning code to get called. log_id_for_each(i) { log_buffer.setSize(i, 10000); } diff --git a/logd/main.cpp b/logd/main.cpp index 23bbf864d..cc45eb3f3 100644 --- a/logd/main.cpp +++ b/logd/main.cpp @@ -52,6 +52,7 @@ #include "LogBuffer.h" #include "LogKlog.h" #include "LogListener.h" +#include "LogTags.h" #include "LogUtils.h" #define KMSG_PRIORITY(PRI) \ @@ -150,50 +151,6 @@ void android::prdebug(const char* fmt, ...) { } } -static sem_t reinit; -static bool reinit_running = false; -static LogBuffer* logBuf = nullptr; - -static void* reinit_thread_start(void* /*obj*/) { - prctl(PR_SET_NAME, "logd.daemon"); - - while (reinit_running && !sem_wait(&reinit) && reinit_running) { - if (fdDmesg >= 0) { - static const char reinit_message[] = { KMSG_PRIORITY(LOG_INFO), - 'l', - 'o', - 'g', - 'd', - '.', - 'd', - 'a', - 'e', - 'm', - 'o', - 'n', - ':', - ' ', - 'r', - 'e', - 'i', - 'n', - 'i', - 't', - '\n' }; - write(fdDmesg, reinit_message, sizeof(reinit_message)); - } - - // Anything that reads persist. - if (logBuf) { - logBuf->init(); - logBuf->initPrune(nullptr); - } - android::ReReadEventLogTags(); - } - - return nullptr; -} - char* android::uidToName(uid_t u) { struct Userdata { uid_t uid; @@ -220,12 +177,6 @@ char* android::uidToName(uid_t u) { return userdata.name; } -// Serves as a global method to trigger reinitialization -// and as a function that can be provided to signal(). -void reinit_signal_handler(int /*signal*/) { - sem_post(&reinit); -} - static void readDmesg(LogAudit* al, LogKlog* kl) { if (!al && !kl) { return; @@ -336,24 +287,10 @@ int main(int argc, char* argv[]) { return EXIT_FAILURE; } - // Reinit Thread - sem_init(&reinit, 0, 0); - pthread_attr_t attr; - if (!pthread_attr_init(&attr)) { - struct sched_param param; - - memset(¶m, 0, sizeof(param)); - pthread_attr_setschedparam(&attr, ¶m); - pthread_attr_setschedpolicy(&attr, SCHED_BATCH); - if (!pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED)) { - pthread_t thread; - reinit_running = true; - if (pthread_create(&thread, &attr, reinit_thread_start, nullptr)) { - reinit_running = false; - } - } - pthread_attr_destroy(&attr); - } + // A cache of event log tags + LogTags log_tags; + // Pruning configuration. + PruneList prune_list; // Serves the purpose of managing the last logs times read on a // socket connection, and as a reader lock on a range of log @@ -364,9 +301,7 @@ int main(int argc, char* argv[]) { // LogBuffer is the object which is responsible for holding all // log entries. - logBuf = new LogBuffer(times); - - signal(SIGHUP, reinit_signal_handler); + LogBuffer* logBuf = new LogBuffer(times, &log_tags, &prune_list); if (__android_logger_property_get_bool( "logd.statistics", BOOL_DEFAULT_TRUE | BOOL_DEFAULT_FLAG_PERSIST | @@ -396,7 +331,7 @@ int main(int argc, char* argv[]) { // Command listener listens on /dev/socket/logd for incoming logd // administrative commands. - CommandListener* cl = new CommandListener(logBuf, reader, swl); + CommandListener* cl = new CommandListener(logBuf, &log_tags, &prune_list); if (cl->startListener()) { return EXIT_FAILURE; }