Merge "logd: enforce policy integrity"
This commit is contained in:
commit
d1ac932330
5 changed files with 95 additions and 22 deletions
|
@ -42,6 +42,10 @@ event_flag := -DAUDITD_LOG_TAG=1003 -DLOGD_LOG_TAG=1004
|
|||
|
||||
LOCAL_CFLAGS := -Werror $(event_flag)
|
||||
|
||||
ifeq ($(TARGET_BUILD_VARIANT),user)
|
||||
LOCAL_CFLAGS += -DAUDITD_ENFORCE_INTEGRITY=true
|
||||
endif
|
||||
|
||||
include $(BUILD_EXECUTABLE)
|
||||
|
||||
include $(call first-makefiles-under,$(LOCAL_PATH))
|
||||
|
|
|
@ -24,6 +24,7 @@
|
|||
#include <sys/uio.h>
|
||||
#include <syslog.h>
|
||||
|
||||
#include <cutils/properties.h>
|
||||
#include <log/logger.h>
|
||||
#include <private/android_filesystem_config.h>
|
||||
#include <private/android_logger.h>
|
||||
|
@ -32,6 +33,10 @@
|
|||
#include "LogAudit.h"
|
||||
#include "LogKlog.h"
|
||||
|
||||
#ifndef AUDITD_ENFORCE_INTEGRITY
|
||||
#define AUDITD_ENFORCE_INTEGRITY false
|
||||
#endif
|
||||
|
||||
#define KMSG_PRIORITY(PRI) \
|
||||
'<', \
|
||||
'0' + LOG_MAKEPRI(LOG_AUTH, LOG_PRI(PRI)) / 10, \
|
||||
|
@ -43,11 +48,10 @@ LogAudit::LogAudit(LogBuffer *buf, LogReader *reader, int fdDmesg) :
|
|||
logbuf(buf),
|
||||
reader(reader),
|
||||
fdDmesg(fdDmesg),
|
||||
policyLoaded(false),
|
||||
rebootToSafeMode(false),
|
||||
initialized(false) {
|
||||
static const char auditd_message[] = { KMSG_PRIORITY(LOG_INFO),
|
||||
'l', 'o', 'g', 'd', '.', 'a', 'u', 'd', 'i', 't', 'd', ':',
|
||||
' ', 's', 't', 'a', 'r', 't', '\n' };
|
||||
write(fdDmesg, auditd_message, sizeof(auditd_message));
|
||||
logToDmesg("start");
|
||||
}
|
||||
|
||||
bool LogAudit::onDataAvailable(SocketClient *cli) {
|
||||
|
@ -73,6 +77,46 @@ bool LogAudit::onDataAvailable(SocketClient *cli) {
|
|||
return true;
|
||||
}
|
||||
|
||||
void LogAudit::logToDmesg(const std::string& str)
|
||||
{
|
||||
static const char prefix[] = { KMSG_PRIORITY(LOG_INFO),
|
||||
'l', 'o', 'g', 'd', '.', 'a', 'u', 'd', 'i', 't', 'd', ':',
|
||||
' ', '\0' };
|
||||
std::string message = prefix + str + "\n";
|
||||
write(fdDmesg, message.c_str(), message.length());
|
||||
}
|
||||
|
||||
std::string LogAudit::getProperty(const std::string& name)
|
||||
{
|
||||
char value[PROP_VALUE_MAX] = {0};
|
||||
property_get(name.c_str(), value, "");
|
||||
return value;
|
||||
}
|
||||
|
||||
void LogAudit::enforceIntegrity() {
|
||||
if (!AUDITD_ENFORCE_INTEGRITY) {
|
||||
logToDmesg("integrity enforcement suppressed; not rebooting");
|
||||
} else if (rebootToSafeMode) {
|
||||
if (getProperty("persist.sys.safemode") == "1") {
|
||||
logToDmesg("integrity enforcement suppressed; in safe mode");
|
||||
return;
|
||||
}
|
||||
|
||||
logToDmesg("enforcing integrity; rebooting to safe mode");
|
||||
property_set("persist.sys.safemode", "1");
|
||||
|
||||
std::string buildDate = getProperty("ro.build.date.utc");
|
||||
if (!buildDate.empty()) {
|
||||
property_set("persist.sys.audit_safemode", buildDate.c_str());
|
||||
}
|
||||
|
||||
property_set("sys.powerctl", "reboot");
|
||||
} else {
|
||||
logToDmesg("enforcing integrity: rebooting to recovery");
|
||||
property_set("sys.powerctl", "reboot,recovery");
|
||||
}
|
||||
}
|
||||
|
||||
int LogAudit::logPrint(const char *fmt, ...) {
|
||||
if (fmt == NULL) {
|
||||
return -EINVAL;
|
||||
|
@ -94,7 +138,27 @@ int LogAudit::logPrint(const char *fmt, ...) {
|
|||
memmove(cp, cp + 1, strlen(cp + 1) + 1);
|
||||
}
|
||||
|
||||
bool info = strstr(str, " permissive=1") || strstr(str, " policy loaded ");
|
||||
bool loaded = strstr(str, " policy loaded ");
|
||||
|
||||
if (loaded) {
|
||||
if (policyLoaded) {
|
||||
// SELinux policy changes are not allowed
|
||||
enforceIntegrity();
|
||||
} else {
|
||||
logToDmesg("policy loaded");
|
||||
policyLoaded = true;
|
||||
}
|
||||
}
|
||||
|
||||
bool permissive = strstr(str, " enforcing=0") ||
|
||||
strstr(str, " permissive=1");
|
||||
|
||||
if (permissive) {
|
||||
// SELinux in permissive mode is not allowed
|
||||
enforceIntegrity();
|
||||
}
|
||||
|
||||
bool info = loaded || permissive;
|
||||
if ((fdDmesg >= 0) && initialized) {
|
||||
struct iovec iov[3];
|
||||
static const char log_info[] = { KMSG_PRIORITY(LOG_INFO) };
|
||||
|
|
|
@ -24,12 +24,15 @@ class LogAudit : public SocketListener {
|
|||
LogBuffer *logbuf;
|
||||
LogReader *reader;
|
||||
int fdDmesg;
|
||||
bool policyLoaded;
|
||||
bool rebootToSafeMode;
|
||||
bool initialized;
|
||||
|
||||
public:
|
||||
LogAudit(LogBuffer *buf, LogReader *reader, int fdDmesg);
|
||||
int log(char *buf, size_t len);
|
||||
bool isMonotonic() { return logbuf->isMonotonic(); }
|
||||
void allowSafeMode(bool allow = true) { rebootToSafeMode = allow; }
|
||||
|
||||
protected:
|
||||
virtual bool onDataAvailable(SocketClient *cli);
|
||||
|
@ -38,6 +41,9 @@ private:
|
|||
static int getLogSocket();
|
||||
int logPrint(const char *fmt, ...)
|
||||
__attribute__ ((__format__ (__printf__, 2, 3)));
|
||||
void logToDmesg(const std::string& str);
|
||||
std::string getProperty(const std::string& name);
|
||||
void enforceIntegrity();
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
The properties that logd responds to are:
|
||||
|
||||
name type default description
|
||||
ro.logd.auditd bool true Enable selinux audit daemon
|
||||
ro.logd.auditd.dmesg bool true selinux audit messages duplicated and
|
||||
sent on to dmesg log
|
||||
persist.logd.security bool false Enable security buffer.
|
||||
|
|
|
@ -245,6 +245,7 @@ static char *name;
|
|||
static sem_t reinit;
|
||||
static bool reinit_running = false;
|
||||
static LogBuffer *logBuf = NULL;
|
||||
static LogAudit *logAudit = NULL;
|
||||
|
||||
static bool package_list_parser_cb(pkg_info *info, void * /* userdata */) {
|
||||
|
||||
|
@ -292,6 +293,10 @@ static void *reinit_thread_start(void * /*obj*/) {
|
|||
logBuf->init();
|
||||
logBuf->initPrune(NULL);
|
||||
}
|
||||
|
||||
if (logAudit) {
|
||||
logAudit->allowSafeMode();
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
|
@ -512,25 +517,19 @@ int main(int argc, char *argv[]) {
|
|||
// initiated log messages. New log entries are added to LogBuffer
|
||||
// and LogReader is notified to send updates to connected clients.
|
||||
|
||||
bool auditd = property_get_bool("logd.auditd",
|
||||
BOOL_DEFAULT_TRUE |
|
||||
BOOL_DEFAULT_FLAG_PERSIST);
|
||||
LogAudit *al = NULL;
|
||||
if (auditd) {
|
||||
al = new LogAudit(logBuf, reader,
|
||||
property_get_bool("logd.auditd.dmesg",
|
||||
BOOL_DEFAULT_TRUE |
|
||||
BOOL_DEFAULT_FLAG_PERSIST)
|
||||
? fdDmesg
|
||||
: -1);
|
||||
}
|
||||
logAudit = new LogAudit(logBuf, reader,
|
||||
property_get_bool("logd.auditd.dmesg",
|
||||
BOOL_DEFAULT_TRUE |
|
||||
BOOL_DEFAULT_FLAG_PERSIST)
|
||||
? fdDmesg
|
||||
: -1);
|
||||
|
||||
LogKlog *kl = NULL;
|
||||
if (klogd) {
|
||||
kl = new LogKlog(logBuf, reader, fdDmesg, fdPmesg, al != NULL);
|
||||
kl = new LogKlog(logBuf, reader, fdDmesg, fdPmesg, logAudit != NULL);
|
||||
}
|
||||
|
||||
readDmesg(al, kl);
|
||||
readDmesg(logAudit, kl);
|
||||
|
||||
// failure is an option ... messages are in dmesg (required by standard)
|
||||
|
||||
|
@ -538,8 +537,9 @@ int main(int argc, char *argv[]) {
|
|||
delete kl;
|
||||
}
|
||||
|
||||
if (al && al->startListener()) {
|
||||
delete al;
|
||||
if (logAudit && logAudit->startListener()) {
|
||||
delete logAudit;
|
||||
logAudit = NULL;
|
||||
}
|
||||
|
||||
TEMP_FAILURE_RETRY(pause());
|
||||
|
|
Loading…
Reference in a new issue