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

Commit 41c2e628 authored by Treehugger Robot's avatar Treehugger Robot Committed by Gerrit Code Review
Browse files

Merge changes Ie9da525c,I9911f02c,Iad18af1f,I5f432a3d

* changes:
  trusty: provide coverage to gatekeeper fuzzer
  trusty: fuzz: Example TA fuzzer
  trusty: fuzz: Helper lib for libFuzzer extra counters
  trusty: coverage: Coverage client library
parents 9a79c844 a1008a1e
Loading
Loading
Loading
Loading
+45 −0
Original line number Diff line number Diff line
// Copyright (C) 2020 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_library {
    name: "libtrusty_coverage",
    srcs: [
        "coverage.cpp",
    ],
    export_include_dirs: [
        "include",
    ],
    static_libs: [
        "libtrusty_test",
    ],
    shared_libs: [
        "libbase",
        "liblog",
    ],
}

cc_test {
    name: "libtrusty_coverage_test",
    srcs: [
        "coverage_test.cpp",
    ],
    static_libs: [
        "libtrusty_coverage",
        "libtrusty_test",
    ],
    shared_libs: [
        "libbase",
        "liblog",
    ],
}
+172 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2020 The Android Open Sourete 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.
 */

#define LOG_TAG "coverage"

#include <android-base/logging.h>
#include <android-base/unique_fd.h>
#include <assert.h>
#include <sys/mman.h>
#include <sys/uio.h>
#include <trusty/coverage/coverage.h>
#include <trusty/coverage/tipc.h>
#include <trusty/tipc.h>

#define COVERAGE_CLIENT_PORT "com.android.trusty.coverage.client"

namespace android {
namespace trusty {
namespace coverage {

using android::base::ErrnoError;
using android::base::Error;
using std::string;

static inline uintptr_t RoundPageUp(uintptr_t val) {
    return (val + (PAGE_SIZE - 1)) & ~(PAGE_SIZE - 1);
}

CoverageRecord::CoverageRecord(string tipc_dev, struct uuid* uuid)
    : tipc_dev_(std::move(tipc_dev)),
      coverage_srv_fd_(-1),
      uuid_(*uuid),
      record_len_(0),
      shm_(NULL),
      shm_len_(0) {}

CoverageRecord::~CoverageRecord() {
    if (shm_) {
        munmap((void*)shm_, shm_len_);
    }
}

Result<void> CoverageRecord::Rpc(coverage_client_req* req, int req_fd, coverage_client_resp* resp) {
    int rc;

    if (req_fd < 0) {
        rc = write(coverage_srv_fd_, req, sizeof(*req));
    } else {
        iovec iov = {
                .iov_base = req,
                .iov_len = sizeof(*req),
        };

        trusty_shm shm = {
                .fd = req_fd,
                .transfer = TRUSTY_SHARE,
        };

        rc = tipc_send(coverage_srv_fd_, &iov, 1, &shm, 1);
    }

    if (rc != (int)sizeof(*req)) {
        return ErrnoError() << "failed to send request to coverage server: ";
    }

    rc = read(coverage_srv_fd_, resp, sizeof(*resp));
    if (rc != (int)sizeof(*resp)) {
        return ErrnoError() << "failed to read reply from coverage server: ";
    }

    if (resp->hdr.cmd != (req->hdr.cmd | COVERAGE_CLIENT_CMD_RESP_BIT)) {
        return ErrnoError() << "unknown response cmd: " << resp->hdr.cmd;
    }

    return {};
}

Result<void> CoverageRecord::Open() {
    coverage_client_req req;
    coverage_client_resp resp;

    if (shm_) {
        return {}; /* already initialized */
    }

    int fd = tipc_connect(tipc_dev_.c_str(), COVERAGE_CLIENT_PORT);
    if (fd < 0) {
        return ErrnoError() << "failed to connect to Trusty coverarge server: ";
    }
    coverage_srv_fd_.reset(fd);

    req.hdr.cmd = COVERAGE_CLIENT_CMD_OPEN;
    req.open_args.uuid = uuid_;
    auto ret = Rpc(&req, -1, &resp);
    if (!ret.ok()) {
        return Error() << "failed to open coverage client: ";
    }
    record_len_ = resp.open_args.record_len;
    shm_len_ = RoundPageUp(record_len_);

    fd = memfd_create("trusty-coverage", 0);
    if (fd < 0) {
        return ErrnoError() << "failed to create memfd: ";
    }
    unique_fd memfd(fd);

    if (ftruncate(memfd, shm_len_) < 0) {
        return ErrnoError() << "failed to resize memfd: ";
    }

    void* shm = mmap(0, shm_len_, PROT_READ | PROT_WRITE, MAP_SHARED, memfd, 0);
    if (shm == MAP_FAILED) {
        return ErrnoError() << "failed to map memfd: ";
    }

    req.hdr.cmd = COVERAGE_CLIENT_CMD_SHARE_RECORD;
    req.share_record_args.shm_len = shm_len_;
    ret = Rpc(&req, memfd, &resp);
    if (!ret.ok()) {
        return Error() << "failed to send shared memory: ";
    }

    shm_ = shm;
    return {};
}

void CoverageRecord::Reset() {
    for (size_t i = 0; i < shm_len_; i++) {
        *((volatile uint8_t*)shm_ + i) = 0;
    }
}

void CoverageRecord::GetRawData(volatile void** begin, volatile void** end) {
    assert(shm_);

    *begin = shm_;
    *end = (uint8_t*)(*begin) + record_len_;
}

uint64_t CoverageRecord::CountEdges() {
    assert(shm_);

    uint64_t counter = 0;

    volatile uint8_t* begin = NULL;
    volatile uint8_t* end = NULL;

    GetRawData((volatile void**)&begin, (volatile void**)&end);

    for (volatile uint8_t* x = begin; x < end; x++) {
        counter += *x;
    }

    return counter;
}

}  // namespace coverage
}  // namespace trusty
}  // namespace android
+95 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2020 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 <gtest/gtest.h>
#include <trusty/coverage/coverage.h>
#include <trusty/tipc.h>
#include <array>
#include <memory>

using android::base::unique_fd;
using std::array;
using std::make_unique;
using std::unique_ptr;

#define TIPC_DEV "/dev/trusty-ipc-dev0"
#define TEST_SRV_PORT "com.android.trusty.sancov.test.srv"

namespace android {
namespace trusty {
namespace coverage {

/* Test server's UUID is 77f68803-c514-43ba-bdce-3254531c3d24 */
static struct uuid test_srv_uuid = {
        0x77f68803,
        0xc514,
        0x43ba,
        {0xbd, 0xce, 0x32, 0x54, 0x53, 0x1c, 0x3d, 0x24},
};

class CoverageTest : public ::testing::Test {
  public:
    void SetUp() override {
        record_ = make_unique<CoverageRecord>(TIPC_DEV, &test_srv_uuid);
        auto ret = record_->Open();
        ASSERT_TRUE(ret.ok()) << ret.error();
    }

    void TearDown() override { record_.reset(); }

    unique_ptr<CoverageRecord> record_;
};

TEST_F(CoverageTest, CoverageReset) {
    record_->Reset();
    auto counter = record_->CountEdges();
    ASSERT_EQ(counter, 0);
}

TEST_F(CoverageTest, TestServerCoverage) {
    unique_fd test_srv(tipc_connect(TIPC_DEV, TEST_SRV_PORT));
    ASSERT_GE(test_srv, 0);

    uint32_t mask = (uint32_t)-1;
    uint32_t magic = 0xdeadbeef;
    uint64_t high_watermark = 0;

    for (size_t i = 1; i < sizeof(magic) * 8; i++) {
        /* Reset coverage */
        record_->Reset();

        /* Send message to test server */
        uint32_t msg = magic & ~(mask << i);
        int rc = write(test_srv, &msg, sizeof(msg));
        ASSERT_EQ(rc, sizeof(msg));

        /* Read message from test server */
        rc = read(test_srv, &msg, sizeof(msg));
        ASSERT_EQ(rc, sizeof(msg));

        /* Count number of non-unique blocks executed */
        auto counter = record_->CountEdges();
        /* Each consecutive input should exercise more or same blocks */
        ASSERT_GE(counter, high_watermark);
        high_watermark = counter;
    }

    ASSERT_GT(high_watermark, 0);
}

}  // namespace coverage
}  // namespace trusty
}  // namespace android
+55 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2020 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.
 */

#pragma once

#include <string>

#include <android-base/result.h>
#include <android-base/unique_fd.h>
#include <stdint.h>
#include <trusty/coverage/tipc.h>

namespace android {
namespace trusty {
namespace coverage {

using android::base::Result;
using android::base::unique_fd;

class CoverageRecord {
  public:
    CoverageRecord(std::string tipc_dev, struct uuid* uuid);
    ~CoverageRecord();
    Result<void> Open();
    void Reset();
    void GetRawData(volatile void** begin, volatile void** end);
    uint64_t CountEdges();

  private:
    Result<void> Rpc(coverage_client_req* req, int req_fd, coverage_client_resp* resp);

    std::string tipc_dev_;
    unique_fd coverage_srv_fd_;
    struct uuid uuid_;
    size_t record_len_;
    volatile void* shm_;
    size_t shm_len_;
};

}  // namespace coverage
}  // namespace trusty
}  // namespace android
+68 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2020 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.
 */

/* This file needs to be kept in-sync with it's counterpart on Trusty side */

#pragma once

#include <stdint.h>

#define COVERAGE_CLIENT_PORT "com.android.trusty.coverage.client"

struct uuid {
    uint32_t time_low;
    uint16_t time_mid;
    uint16_t time_hi_and_version;
    uint8_t clock_seq_and_node[8];
};

enum coverage_client_cmd {
    COVERAGE_CLIENT_CMD_RESP_BIT = 1U,
    COVERAGE_CLIENT_CMD_SHIFT = 1U,
    COVERAGE_CLIENT_CMD_OPEN = (1U << COVERAGE_CLIENT_CMD_SHIFT),
    COVERAGE_CLIENT_CMD_SHARE_RECORD = (2U << COVERAGE_CLIENT_CMD_SHIFT),
};

struct coverage_client_hdr {
    uint32_t cmd;
};

struct coverage_client_open_req {
    struct uuid uuid;
};

struct coverage_client_open_resp {
    uint32_t record_len;
};

struct coverage_client_share_record_req {
    uint32_t shm_len;
};

struct coverage_client_req {
    struct coverage_client_hdr hdr;
    union {
        struct coverage_client_open_req open_args;
        struct coverage_client_share_record_req share_record_args;
    };
};

struct coverage_client_resp {
    struct coverage_client_hdr hdr;
    union {
        struct coverage_client_open_resp open_args;
    };
};
Loading