Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 8954ef98 authored by Treehugger Robot's avatar Treehugger Robot Committed by Gerrit Code Review
Browse files

Merge "logd: sepolicy dynamic rate limiting"

parents fe05f1cd 247d682f
Loading
Loading
Loading
Loading
+47 −4
Original line number Diff line number Diff line
@@ -43,7 +43,7 @@
    '>'

LogAudit::LogAudit(LogBuffer *buf, LogReader *reader, int fdDmesg) :
        SocketListener(getLogSocket(), false),
        SocketListener(mSock = getLogSocket(), false),
        logbuf(buf),
        reader(reader),
        fdDmesg(fdDmesg),
@@ -51,19 +51,62 @@ LogAudit::LogAudit(LogBuffer *buf, LogReader *reader, int fdDmesg) :
                                                BOOL_DEFAULT_TRUE)),
        events(__android_logger_property_get_bool("ro.logd.auditd.events",
                                                  BOOL_DEFAULT_TRUE)),
        initialized(false) {
        initialized(false),
        tooFast(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));
}

void LogAudit::checkRateLimit() {

    // trim list for AUDIT_RATE_LIMIT_BURST_DURATION of history
    log_time oldest(AUDIT_RATE_LIMIT_BURST_DURATION, 0);
    bucket.emplace(android_log_clockid());
    oldest = bucket.back() - oldest;
    while (bucket.front() < oldest) bucket.pop();

    static const size_t upperThreshold =
        ((AUDIT_RATE_LIMIT_BURST_DURATION *
          (AUDIT_RATE_LIMIT_DEFAULT + AUDIT_RATE_LIMIT_MAX)) + 1) /
                              2;
    if (bucket.size() >= upperThreshold) {
        // Hit peak, slow down source
        if (!tooFast) {
            tooFast = true;
            audit_rate_limit(mSock, AUDIT_RATE_LIMIT_MAX);
        }

        // We do not need to hold on to the full set of timing data history,
        // let's ensure it does not grow without bounds.  This also ensures
        // that std::dequeue underneath behaves almost like a ring buffer.
        do {
            bucket.pop();
        } while (bucket.size() >= upperThreshold);
        return;
    }

    if (!tooFast) return;

    static const size_t lowerThreshold = AUDIT_RATE_LIMIT_BURST_DURATION *
                                         AUDIT_RATE_LIMIT_MAX;

    if (bucket.size() >= lowerThreshold) return;

    tooFast = false;
    // Went below max sustained rate, allow source to speed up
    audit_rate_limit(mSock, AUDIT_RATE_LIMIT_DEFAULT);
}

bool LogAudit::onDataAvailable(SocketClient *cli) {
    if (!initialized) {
        prctl(PR_SET_NAME, "logd.auditd");
        initialized = true;
    }

    checkRateLimit();

    struct audit_message rep;

    rep.nlh.nlmsg_type = 0;
@@ -75,8 +118,7 @@ bool LogAudit::onDataAvailable(SocketClient *cli) {
        return false;
    }

    logPrint("type=%d %.*s",
        rep.nlh.nlmsg_type, rep.nlh.nlmsg_len, rep.data);
    logPrint("type=%d %.*s", rep.nlh.nlmsg_type, rep.nlh.nlmsg_len, rep.data);

    return true;
}
@@ -351,5 +393,6 @@ int LogAudit::getLogSocket() {
        audit_close(fd);
        fd = -1;
    }
    (void)audit_rate_limit(fd, AUDIT_RATE_LIMIT_DEFAULT);
    return fd;
}
+7 −0
Original line number Diff line number Diff line
@@ -17,6 +17,8 @@
#ifndef _LOGD_LOG_AUDIT_H__
#define _LOGD_LOG_AUDIT_H__

#include <queue>

#include <sysutils/SocketListener.h>

#include "LogBuffer.h"
@@ -31,6 +33,11 @@ class LogAudit : public SocketListener {
    bool events;
    bool initialized;

    bool tooFast;
    int mSock;
    std::queue<log_time> bucket;
    void checkRateLimit();

public:
    LogAudit(LogBuffer *buf, LogReader *reader, int fdDmesg);
    int log(char *buf, size_t len);
+23 −3
Original line number Diff line number Diff line
@@ -149,7 +149,7 @@ out:
    return rc;
}

int audit_setup(int fd, uint32_t pid)
int audit_setup(int fd, pid_t pid)
{
    int rc;
    struct audit_message rep;
@@ -163,8 +163,7 @@ int audit_setup(int fd, uint32_t pid)
     * and the the mask set to AUDIT_STATUS_PID
     */
    status.pid = pid;
    status.mask = AUDIT_STATUS_PID | AUDIT_STATUS_RATE_LIMIT;
    status.rate_limit = 20; // audit entries per second
    status.mask = AUDIT_STATUS_PID;

    /* Let the kernel know this pid will be registering for audit events */
    rc = audit_send(fd, AUDIT_SET, &status, sizeof(status));
@@ -187,6 +186,27 @@ int audit_setup(int fd, uint32_t pid)
    return 0;
}

int audit_rate_limit(int fd, unsigned rate_limit)
{
    int rc;
    struct audit_message rep;
    struct audit_status status;

    memset(&status, 0, sizeof(status));

    status.mask = AUDIT_STATUS_RATE_LIMIT;
    status.rate_limit = rate_limit; /* audit entries per second */

    rc = audit_send(fd, AUDIT_SET, &status, sizeof(status));
    if (rc < 0) {
        return rc;
    }

    audit_get_reply(fd, &rep, GET_REPLY_NONBLOCKING, 0);

    return 0;
}

int audit_open()
{
    return socket(PF_NETLINK, SOCK_RAW | SOCK_CLOEXEC, NETLINK_AUDIT);
+24 −7
Original line number Diff line number Diff line
@@ -82,15 +82,32 @@ extern int audit_get_reply(int fd, struct audit_message *rep, reply_t block,
                           int peek);

/**
 * Sets a pid to recieve audit netlink events from the kernel
 * Sets a pid to receive audit netlink events from the kernel
 * @param fd
 *  The fd returned by a call to audit_open()
 * @param pid
 *  The pid whom to set as the reciever of audit messages
 *  The pid whom to set as the receiver of audit messages
 * @return
 *  This function returns 0 on success, -errno on error.
 */
extern int  audit_setup(int fd, uint32_t pid);
extern int audit_setup(int fd, pid_t pid);

/**
 * Sets the rate limit to receive audit netlink events from the kernel
 * @param fd
 *  The fd returned by a call to audit_open()
 * @param max_rate
 *  The cap of the maximum number of audit messages a second
 * @return
 *  This function returns 0 on success, -errno on error.
 */

/* Guidelines to follow for dynamic rate_limit */
#define AUDIT_RATE_LIMIT_DEFAULT 20        /* acceptable burst rate      */
#define AUDIT_RATE_LIMIT_BURST_DURATION 10 /* number of seconds of burst */
#define AUDIT_RATE_LIMIT_MAX     5         /* acceptable sustained rate  */

extern int audit_rate_limit(int fd, unsigned rate_limit);

__END_DECLS

+4 −1
Original line number Diff line number Diff line
@@ -27,12 +27,15 @@ test_tags := tests
# Unit tests.
# -----------------------------------------------------------------------------

event_flag := -DAUDITD_LOG_TAG=1003 -DCHATTY_LOG_TAG=1004

test_c_flags := \
    -fstack-protector-all \
    -g \
    -Wall -Wextra \
    -Werror \
    -fno-builtin \
    $(event_flag)

test_src_files := \
    logd_test.cpp
@@ -43,6 +46,6 @@ include $(CLEAR_VARS)
LOCAL_MODULE := $(test_module_prefix)unit-tests
LOCAL_MODULE_TAGS := $(test_tags)
LOCAL_CFLAGS += $(test_c_flags)
LOCAL_SHARED_LIBRARIES := libbase libcutils liblog
LOCAL_SHARED_LIBRARIES := libbase libcutils liblog libselinux
LOCAL_SRC_FILES := $(test_src_files)
include $(BUILD_NATIVE_TEST)
Loading