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

Commit 2f32c28f authored by Max Spector's avatar Max Spector Committed by Gerrit Code Review
Browse files

Merge "Liblogd log fuzzer"

parents 81a0738c ace90bd9
Loading
Loading
Loading
Loading
+15 −13
Original line number Diff line number Diff line
// Copyright (C) 2019 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.
/*
 * Copyright 2019 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.
 */
cc_fuzz {
    name: "log_buffer_log_fuzzer",
    srcs: [
+35 −18
Original line number Diff line number Diff line
/*
 * Copyright (C) 2019 The Android Open Source Project
 * Copyright 2019 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.
@@ -13,64 +13,79 @@
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
#include <string>

#include "../LogBuffer.h"
#include "../LogTimes.h"

// We don't want to waste a lot of entropy on messages
#define MAX_MSG_LENGTH 5

// Tag IDs usually start at 1000, we only want to try 1000 through 1009
#define MIN_TAG_ID 1000
#define TAG_MOD 10

namespace android {
struct LogInput {
  public:
    log_id_t log_id;  // char
    log_id_t log_id;
    log_time realtime;
    uid_t uid;
    pid_t pid;
    pid_t tid;
    unsigned int log_mask;
};

int write_log_messages(const uint8_t* data, size_t* data_left, LogBuffer* log_buffer) {
int write_log_messages(const uint8_t** pdata, size_t* data_left, LogBuffer* log_buffer) {
    const uint8_t* data = *pdata;
    const LogInput* logInput = reinterpret_cast<const LogInput*>(data);
    data += sizeof(LogInput);
    *data_left -= sizeof(LogInput);

    uint8_t tag_length = data[0] % 32;
    uint8_t msg_length = data[1] % 32;
    if (tag_length < 2 || msg_length < 2) {
        // Not enough data for tag and message
    uint32_t tag = MIN_TAG_ID + data[0] % TAG_MOD;
    uint8_t msg_length = data[1] % MAX_MSG_LENGTH;
    if (msg_length < 2) {
        // Not enough data for message
        return 0;
    }

    data += 2 * sizeof(uint8_t);
    *data_left -= 2 * sizeof(uint8_t);

    if (*data_left < tag_length + msg_length) {
    if (*data_left < msg_length) {
        // Not enough data for tag and message
        *pdata = data;
        return 0;
    }

    // We need nullterm'd strings
    char* msg = new char[tag_length + msg_length + 2];
    char* msg_only = msg + tag_length + 1;
    memcpy(msg, data, tag_length);
    msg[tag_length] = '\0';
    char msg[sizeof(uint32_t) + MAX_MSG_LENGTH + sizeof(char)];
    char* msg_only = msg + sizeof(uint32_t);
    memcpy(msg, &tag, sizeof(uint32_t));
    memcpy(msg_only, data, msg_length);
    msg_only[msg_length] = '\0';
    data += tag_length + msg_length;
    *data_left -= tag_length + msg_length;
    data += msg_length;
    *data_left -= msg_length;

    // Other elements not in enum.
    log_id_t log_id = static_cast<log_id_t>(unsigned(logInput->log_id) % (LOG_ID_MAX + 1));
    log_buffer->log(log_id, logInput->realtime, logInput->uid, logInput->pid, logInput->tid, msg,
                    tag_length + msg_length + 2);
    delete[] msg;
                    sizeof(uint32_t) + msg_length + 1);
    log_buffer->formatStatistics(logInput->uid, logInput->pid, logInput->log_mask);
    *pdata = data;
    return 1;
}

// Because system/core/logd/main.cpp redefines this.
// Because system/core/logd/main.cpp redefines these.
void prdebug(char const* fmt, ...) {
    va_list ap;
    va_start(ap, fmt);
    vfprintf(stderr, fmt, ap);
    va_end(ap);
}
char* uidToName(uid_t) {
    return strdup("fake");
}

extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
    // We want a random tag length and a random remaining message length
@@ -81,13 +96,15 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
    LastLogTimes times;
    LogBuffer log_buffer(&times);
    size_t data_left = size;
    const uint8_t** pdata = &data;

    log_buffer.enableStatistics();
    log_buffer.initPrune(nullptr);
    // We want to get pruning code to get called.
    log_id_for_each(i) { log_buffer.setSize(i, 10000); }

    while (data_left >= sizeof(LogInput) + 2 * sizeof(uint8_t)) {
        if (!write_log_messages(data, &data_left, &log_buffer)) {
        if (!write_log_messages(pdata, &data_left, &log_buffer)) {
            return 0;
        }
    }