/*
* Copyright (C) 2022 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
#include
#include
#include
#include
using namespace android;
using namespace android::init;
const std::vector<std::string> kValidInputs[] = {
{"", "cpu", "10", "10"}, {"", "RLIM_CPU", "10", "10"}, {"", "12", "unlimited", "10"},
{"", "13", "-1", "10"}, {"", "14", "10", "unlimited"}, {"", "15", "10", "-1"},
};
const std::string kValidPaths[] = {
"/system/etc/init/hw/init.rc",
"/system/etc/init",
};
const int32_t kMaxBytes = 256;
const std::string kValidInterfaces = "android.frameworks.vr.composer@2.0::IVrComposerClient";
class InitParserFuzzer {
public:
InitParserFuzzer(const uint8_t* data, size_t size) : fdp_(data, size){};
void Process();
private:
void InvokeParser();
void InvokeLimitParser();
void InvokeInterfaceUtils();
InterfaceInheritanceHierarchyMap GenerateHierarchyMap();
std::vector<HidlInterfaceMetadata> GenerateInterfaceMetadata();
FuzzedDataProvider fdp_;
};
void InitParserFuzzer::InvokeLimitParser() {
if (fdp_.ConsumeBool()) {
std::vector<std::string> input;
input.push_back("");
input.push_back(fdp_.ConsumeRandomLengthString(kMaxBytes));
input.push_back(fdp_.ConsumeRandomLengthString(kMaxBytes));
input.push_back(fdp_.ConsumeRandomLengthString(kMaxBytes));
ParseRlimit(input);
} else {
ParseRlimit(fdp_.PickValueInArray(kValidInputs));
}
}
std::vector<HidlInterfaceMetadata> InitParserFuzzer::GenerateInterfaceMetadata() {
std::vector<HidlInterfaceMetadata> random_interface;
for (size_t idx = 0; idx < fdp_.ConsumeIntegral<size_t>(); ++idx) {
HidlInterfaceMetadata metadata;
metadata.name = fdp_.ConsumeRandomLengthString(kMaxBytes);
for (size_t idx1 = 0; idx1 < fdp_.ConsumeIntegral<size_t>(); ++idx1) {
metadata.inherited.push_back(fdp_.ConsumeRandomLengthString(kMaxBytes));
}
random_interface.push_back(metadata);
}
return random_interface;
}
InterfaceInheritanceHierarchyMap InitParserFuzzer::GenerateHierarchyMap() {
InterfaceInheritanceHierarchyMap result;
std::vector<HidlInterfaceMetadata> random_interface;
if (fdp_.ConsumeBool()) {
random_interface = GenerateInterfaceMetadata();
} else {
random_interface = HidlInterfaceMetadata::all();
}
for (const HidlInterfaceMetadata& iface : random_interface) {
std::set<FQName> inherited_interfaces;
for (const std::string& intf : iface.inherited) {
FQName fqname;
(void)fqname.setTo(intf);
inherited_interfaces.insert(fqname);
}
FQName fqname;
(void)fqname.setTo(iface.name);
result[fqname] = inherited_interfaces;
}
return result;
}
void InitParserFuzzer::InvokeInterfaceUtils() {
InterfaceInheritanceHierarchyMap hierarchy_map = GenerateHierarchyMap();
SetKnownInterfaces(hierarchy_map);
IsKnownInterface(fdp_.ConsumeRandomLengthString(kMaxBytes));
std::set<std::string> interface_set;
for (size_t idx = 0; idx < fdp_.ConsumeIntegral<size_t>(); ++idx) {
auto set_interface_values = fdp_.PickValueInArray<const std::function<void()>>({
[&]() {
interface_set.insert(("aidl/" + fdp_.ConsumeRandomLengthString(kMaxBytes)));
},
[&]() { interface_set.insert(fdp_.ConsumeRandomLengthString(kMaxBytes)); },
[&]() { interface_set.insert(kValidInterfaces); },
});
set_interface_values();
}
CheckInterfaceInheritanceHierarchy(interface_set, hierarchy_map);
}
void InitParserFuzzer::InvokeParser() {
Parser parser;
std::string name = fdp_.ConsumeBool() ? fdp_.ConsumeRandomLengthString(kMaxBytes) : "import";
parser.AddSectionParser(name, std::make_unique<ImportParser>(&parser));
std::string path = fdp_.ConsumeBool() ? fdp_.PickValueInArray(kValidPaths)
: fdp_.ConsumeRandomLengthString(kMaxBytes);
parser.ParseConfig(path);
parser.ParseConfigFileInsecure(path, false /* follow_symlinks */);
}
void InitParserFuzzer::Process() {
while (fdp_.remaining_bytes()) {
auto invoke_parser_fuzzer = fdp_.PickValueInArray<const std::function<void()>>({
[&]() { InvokeParser(); },
[&]() { InvokeInterfaceUtils(); },
[&]() { InvokeLimitParser(); },
});
invoke_parser_fuzzer();
}
}
extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
InitParserFuzzer init_parser_fuzzer(data, size);
init_parser_fuzzer.Process();
return 0;
}
源码路径:
https://cs.android.com/android/platform/superproject/main/+/main:system/core/init/fuzzer/init_parser_fuzzer.cpp?hl=zh-cn
代码分析:
根据提供的代码,我分析了其逻辑和总结了代码的主要作用:
这是一个针对Android init解析器的Fuzz测试代码。
定义了相关的输入样本空间,包括init配置语句、init文件路径等。
InitParserFuzzer类封装了Fuzz测试逻辑。
Process()方法是主要的Fuzz逻辑,它会随机调用不同的解析组件进行测试。
InvokeParser()方法对init配置文件解析器进行Fuzz测试。
InvokeLimitParser()方法对rlimit解析进行测试。
InvokeInterfaceUtils()对AIDL接口分析代码进行测试。
GenerateHierarchyMap()随机生成接口继承关系。
GenerateInterfaceMetadata()随机生成接口元数据。
LLVMFuzzerTestOneInput()是LibFuzzer入口,将测试数据传入InitParserFuzzer。
总结:这是一段针对Android init框架各组件的Fuzzing测试代码。主要对init配置文件解析、rlimit解析和AIDL接口分析代码进行安全性Fuzz测试,通过随机的数据探测潜在的崩溃或异常,从而提高init框架的健壮性和安全性。
const std::vector<std::string> kValidInputs[] = {
{"", "cpu", "10", "10"}, {"", "RLIM_CPU", "10", "10"}, {"", "12", "unlimited", "10"},
{"", "13", "-1", "10"}, {"", "14", "10", "unlimited"}, {"", "15", "10", "-1"},
};
这是一段 C++ 代码,它定义了一个名为 kValidInputs 的常量数组,数组的元素类型是 std::vector,即字符串向量。¹
数组中有六个字符串向量,每个字符串向量包含四个字符串,分别表示资源限制的类型、软限制、硬限制和期望的结果。²
资源限制的类型可以是 cpu、RLIM_CPU 或一个整数,表示要设置或获取的资源的编号。³
软限制和硬限制可以是一个整数或 unlimited,表示要设置的资源使用量的上限。³
期望的结果可以是一个整数或 -1,表示要检查的资源使用量是否符合预期。⁴
这段代码可能是用于测试某个函数的输入和输出的,例如 setrlimit 或 getrlimit,这些函数可以用于控制进程的资源使用情况。.
const std::string kValidPaths[] = {
"/system/etc/init/hw/init.rc",
"/system/etc/init",
};
这是一段 C++ 代码,它定义了一个名为 kValidPaths 的常量数组,数组的元素类型是 std::string,即字符串。
数组中有两个字符串,分别表示两个 Android 系统的配置文件的路径。²
/system/etc/init/hw/init.rc 是一个用于初始化硬件相关的服务和属性的配置文件。³/system/etc/init 是一个用于存放其他 init.rc 文件的目录,这些文件可以用于定义不同的服务、动作和属性。const int32_t kMaxBytes = 256;
const std::string kValidInterfaces = "android.frameworks.vr.composer@2.0::IVrComposerClient";
这是一段 C++ 代码,它定义了两个常量变量,分别是 kMaxBytes 和 kValidInterfaces。
kMaxBytes 是一个 int32_t 类型的变量,它表示一个 32 位的有符号整数,它的值是 256。² 这个变量可能是用于限制字符串的最大长度的。kValidInterfaces 是一个 std::string 类型的变量,它表示一个字符串,它的值是 "android.frameworks.vr.composer@2.0::IVrComposerClient"。这个变量可能是用于表示一个 Android 系统的接口的名字,这个接口是一个用于虚拟现实的组件。class InitParserFuzzer {
public:
InitParserFuzzer(const uint8_t* data, size_t size) : fdp_(data, size){};
void Process();
private:
void InvokeParser();
void InvokeLimitParser();
void InvokeInterfaceUtils();
InterfaceInheritanceHierarchyMap GenerateHierarchyMap();
std::vector<HidlInterfaceMetadata> GenerateInterfaceMetadata();
FuzzedDataProvider fdp_;
};
这段代码的逻辑和作用是:
void InitParserFuzzer::InvokeLimitParser() {
if (fdp_.ConsumeBool()) {
std::vector<std::string> input;
input.push_back("");
input.push_back(fdp_.ConsumeRandomLengthString(kMaxBytes));
input.push_back(fdp_.ConsumeRandomLengthString(kMaxBytes));
input.push_back(fdp_.ConsumeRandomLengthString(kMaxBytes));
ParseRlimit(input);
} else {
ParseRlimit(fdp_.PickValueInArray(kValidInputs));
}
}
这段代码的逻辑和作用是:
InterfaceInheritanceHierarchyMap InitParserFuzzer::GenerateHierarchyMap() {
InterfaceInheritanceHierarchyMap result;
std::vector<HidlInterfaceMetadata> random_interface;
if (fdp_.ConsumeBool()) {
random_interface = GenerateInterfaceMetadata();
} else {
random_interface = HidlInterfaceMetadata::all();
}
for (const HidlInterfaceMetadata& iface : random_interface) {
std::set<FQName> inherited_interfaces;
for (const std::string& intf : iface.inherited) {
FQName fqname;
(void)fqname.setTo(intf);
inherited_interfaces.insert(fqname);
}
FQName fqname;
(void)fqname.setTo(iface.name);
result[fqname] = inherited_interfaces;
}
return result;
}
这段代码的逻辑和作用是:
void InitParserFuzzer::InvokeInterfaceUtils() {
InterfaceInheritanceHierarchyMap hierarchy_map = GenerateHierarchyMap();
SetKnownInterfaces(hierarchy_map);
IsKnownInterface(fdp_.ConsumeRandomLengthString(kMaxBytes));
std::set<std::string> interface_set;
for (size_t idx = 0; idx < fdp_.ConsumeIntegral<size_t>(); ++idx) {
auto set_interface_values = fdp_.PickValueInArray<const std::function<void()>>({
[&]() {
interface_set.insert(("aidl/" + fdp_.ConsumeRandomLengthString(kMaxBytes)));
},
[&]() { interface_set.insert(fdp_.ConsumeRandomLengthString(kMaxBytes)); },
[&]() { interface_set.insert(kValidInterfaces); },
});
set_interface_values();
}
CheckInterfaceInheritanceHierarchy(interface_set, hierarchy_map);
}
这段代码的逻辑和作用是:
这段代码的作用是用于测试 Android 系统服务的接口的正确性和效率。
void InitParserFuzzer::InvokeParser() {
Parser parser;
std::string name = fdp_.ConsumeBool() ? fdp_.ConsumeRandomLengthString(kMaxBytes) : "import";
parser.AddSectionParser(name, std::make_unique<ImportParser>(&parser));
std::string path = fdp_.ConsumeBool() ? fdp_.PickValueInArray(kValidPaths)
: fdp_.ConsumeRandomLengthString(kMaxBytes);
parser.ParseConfig(path);
parser.ParseConfigFileInsecure(path, false /* follow_symlinks */);
}
这段代码的逻辑和作用是:
void InitParserFuzzer::Process() {
while (fdp_.remaining_bytes()) {
auto invoke_parser_fuzzer = fdp_.PickValueInArray<const std::function<void()>>({
[&]() { InvokeParser(); },
[&]() { InvokeInterfaceUtils(); },
[&]() { InvokeLimitParser(); },
});
invoke_parser_fuzzer();
}
}
这段代码的逻辑和作用是:
extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
InitParserFuzzer init_parser_fuzzer(data, size);
init_parser_fuzzer.Process();
return 0;
}
这段代码的逻辑和作用是: