blob: 5813cccff55ac78860a3022e3ea27bf7f26e4bcc [file] [log] [blame]
// Copyright 2021 The Chromium OS Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include <cstddef>
#include <cstdint>
#include <iostream>
#include <stdio.h>
#include <string>
#include <utility>
#include <base/files/file_path.h>
#include <base/files/scoped_temp_dir.h>
#include <base/logging.h>
#include <fuzzer/FuzzedDataProvider.h>
#include <session_manager/dbus-proxy-mocks.h>
#include "crash-reporter/missed_crash_collector.h"
#include "crash-reporter/paths.h"
#include "crash-reporter/test_util.h"
class Environment {
public:
Environment() {
// Disable logging per instructions.
logging::SetMinLogLevel(logging::LOGGING_FATAL);
}
};
class MissedCrashCollectorForFuzzing : public MissedCrashCollector {
public:
explicit MissedCrashCollectorForFuzzing(std::string user_name,
std::string user_hash)
: user_name_(std::move(user_name)), user_hash_(std::move(user_hash)) {}
void SetUpDBus() override {
// Mock out all DBus calls so (a) we don't actually call DBus and (b) we
// don't CHECK fail when the DBus calls fail.
auto mock =
std::make_unique<org::chromium::SessionManagerInterfaceProxyMock>();
test_util::SetActiveSessions(mock.get(), {{user_name_, user_hash_}});
session_manager_proxy_ = std::move(mock);
}
private:
// Results from the fake RetrieveActiveSessions call
const std::string user_name_;
const std::string user_hash_;
};
extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
static Environment env;
// Put all files into a per-run temp directory.
base::ScopedTempDir temp_dir;
CHECK(temp_dir.CreateUniqueTempDir());
base::FilePath test_dir = temp_dir.GetPath();
paths::SetPrefixForTesting(test_dir);
FuzzedDataProvider provider(data, size);
// Force daemon store on or off, since fuzzers should not have
// non-deterministic behavior.
bool use_daemon_store = provider.ConsumeBool();
const int kArbitraryMaxNameLength = 4096;
std::string user_name =
provider.ConsumeRandomLengthString(kArbitraryMaxNameLength);
std::string user_hash =
provider.ConsumeRandomLengthString(kArbitraryMaxNameLength);
// If the user_hash looks like an absolute directory path,
// GetDaemonStoreCrashDirectories will CHECK fail when calling
// base::FilePath::Append().
base::FilePath user_hash_path(user_hash);
if (user_hash_path.IsAbsolute()) {
return 0;
}
// If the user_hash_path uses "..", the fuzzer can "escape" from the temp
// directory and overwrite random files.
if (user_hash_path.ReferencesParent()) {
return 0;
}
std::string input = provider.ConsumeRemainingBytesAsString();
FILE* file = fmemopen(input.data(), input.size(), "r");
if (!file) {
return 0;
}
MissedCrashCollectorForFuzzing collector(std::move(user_name),
std::move(user_hash));
collector.set_input_file_for_testing(file);
collector.force_daemon_store_for_testing(use_daemon_store);
collector.Collect(/*pid=*/111,
/*recent_miss_count=*/222,
/*recent_match_count=*/333,
/*pending_miss_count=*/444);
fclose(file);
return 0;
}