Merge changes Ic7620978,I6d5bab58,Id1668c26,Icdb56b6f,Ic0c86a2b
* changes: logd: remove FlushCommand logd: rename mOldest -> oldest_ logd: separate PruneList from LogBuffer logd: don't use SIGHUP to reinitialize logd: decouple LogTags from LogBuffer
This commit is contained in:
commit
794acfc0fe
14 changed files with 146 additions and 421 deletions
|
|
@ -36,7 +36,6 @@ cc_library_static {
|
|||
"CommandListener.cpp",
|
||||
"LogListener.cpp",
|
||||
"LogReader.cpp",
|
||||
"FlushCommand.cpp",
|
||||
"LogBuffer.cpp",
|
||||
"LogBufferElement.cpp",
|
||||
"LogTimes.cpp",
|
||||
|
|
|
|||
|
|
@ -31,6 +31,7 @@
|
|||
|
||||
#include <android-base/stringprintf.h>
|
||||
#include <cutils/sockets.h>
|
||||
#include <log/log_properties.h>
|
||||
#include <private/android_filesystem_config.h>
|
||||
#include <sysutils/SocketClient.h>
|
||||
|
||||
|
|
@ -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 <length>\n<data>\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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -14,85 +14,53 @@
|
|||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef _COMMANDLISTENER_H__
|
||||
#define _COMMANDLISTENER_H__
|
||||
#pragma once
|
||||
|
||||
#include <sysutils/FrameworkListener.h>
|
||||
|
||||
#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
|
||||
|
|
|
|||
|
|
@ -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 <stdlib.h>
|
||||
|
||||
#include <private/android_filesystem_config.h>
|
||||
|
||||
#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);
|
||||
}
|
||||
|
|
@ -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 <android/log.h>
|
||||
#include <sysutils/SocketClientCommand.h>
|
||||
|
||||
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
|
||||
|
|
@ -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++;
|
||||
|
|
|
|||
|
|
@ -14,8 +14,7 @@
|
|||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef _LOGD_LOG_BUFFER_H__
|
||||
#define _LOGD_LOG_BUFFER_H__
|
||||
#pragma once
|
||||
|
||||
#include <sys/types.h>
|
||||
|
||||
|
|
@ -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<LogBufferElementCollection::iterator> mOldest[LOG_ID_MAX];
|
||||
// watermark of any worst/chatty uid processing
|
||||
typedef std::unordered_map<uid_t, LogBufferElementCollection::iterator>
|
||||
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<LogBufferElementCollection::iterator> oldest_[LOG_ID_MAX];
|
||||
};
|
||||
|
|
|
|||
|
|
@ -24,21 +24,35 @@
|
|||
#include <cutils/sockets.h>
|
||||
#include <private/android_logger.h>
|
||||
|
||||
#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<LogTimeEntry>(*this, cli, nonBlock, tail, logMask, pid, start,
|
||||
sequence, timeout);
|
||||
sequence, timeout, privileged, can_read_security);
|
||||
if (!entry->startReader_Locked()) {
|
||||
LogTimeEntry::unlock();
|
||||
return false;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -18,7 +18,6 @@
|
|||
#include <string.h>
|
||||
#include <sys/prctl.h>
|
||||
|
||||
#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
|
||||
|
|
|
|||
|
|
@ -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<std::unique_ptr<LogTimeEntry>> LastLogTimes;
|
||||
|
|
|
|||
|
|
@ -14,8 +14,7 @@
|
|||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef _LOGD_LOG_UTILS_H__
|
||||
#define _LOGD_LOG_UTILS_H__
|
||||
#pragma once
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
#include <sys/types.h>
|
||||
|
|
@ -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__
|
||||
|
|
|
|||
|
|
@ -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); }
|
||||
|
||||
|
|
|
|||
|
|
@ -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.<property>
|
||||
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;
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue