1 /*
2 * Copyright (C) 2022 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16 #include <persistent_properties.h>
17 #include <property_type.h>
18 #include <sys/stat.h>
19 #include <fstream>
20 #include "fuzzer/FuzzedDataProvider.h"
21
22 using namespace android;
23 using namespace android::init;
24 using android::init::persistent_property_filename;
25
26 const std::string kTempDir = "/data/local/tmp/";
27 const std::string kFuzzerPropertyFile = kTempDir + "persistent_properties";
28 constexpr int32_t kMaxPropertyLength = 10;
29 const std::string kPrefix = "persist.";
30 const std::string kPropertyName = kPrefix + "sys.timezone";
31 const std::string kPropertyValue = "America/Los_Angeles";
32 const std::string kLegacyPropertyFile = "/data/property/persist.properties";
33 const std::string kSizeSuffix[3] = {"g", "k", "m"};
34 constexpr int32_t kMinNumStrings = 1;
35 constexpr int32_t kMaxNumStrings = 10;
36
37 enum PropertyType { STRING, BOOL, INT, UINT, DOUBLE, SIZE, ENUM, RANDOM, kMaxValue = RANDOM };
38
39 class InitPropertyFuzzer {
40 public:
InitPropertyFuzzer(const uint8_t * data,size_t size)41 InitPropertyFuzzer(const uint8_t* data, size_t size) : fdp_(data, size){};
42 void process();
43
44 private:
45 void InvokeCheckType();
46 void InvokeWritePersistentProperty();
47 void RemoveFiles();
48 void CreateFuzzerPropertyFile(const std::string property_file);
49 FuzzedDataProvider fdp_;
50 };
51
InvokeCheckType()52 void InitPropertyFuzzer::InvokeCheckType() {
53 std::string property_type;
54 std::string value;
55 int type = fdp_.ConsumeEnum<PropertyType>();
56 switch (type) {
57 case STRING:
58 value = fdp_.ConsumeRandomLengthString(kMaxPropertyLength);
59 property_type = "string";
60 break;
61 case BOOL:
62 value = fdp_.ConsumeBool();
63 property_type = "bool";
64 break;
65 case INT:
66 value = fdp_.ConsumeIntegral<int>();
67 property_type = "int";
68 break;
69 case UINT:
70 value = fdp_.ConsumeIntegral<uint_t>();
71 property_type = "uint";
72 break;
73 case DOUBLE:
74 value = fdp_.ConsumeFloatingPoint<double>();
75 property_type = "double";
76 break;
77 case SIZE:
78 value = fdp_.ConsumeIntegral<uint_t>();
79 value = value.append(fdp_.PickValueInArray(kSizeSuffix));
80 property_type = "size";
81 break;
82 case ENUM:
83 value = fdp_.ConsumeIntegral<uint_t>();
84 property_type = "enum";
85 break;
86 case RANDOM:
87 value = fdp_.ConsumeRandomLengthString(kMaxPropertyLength);
88 property_type = fdp_.ConsumeRandomLengthString(kMaxPropertyLength);
89 break;
90 }
91
92 CheckType(property_type, value);
93 }
94
InvokeWritePersistentProperty()95 void InitPropertyFuzzer::InvokeWritePersistentProperty() {
96 if (fdp_.ConsumeBool()) {
97 WritePersistentProperty(kPropertyName, kPropertyValue);
98 } else {
99 WritePersistentProperty((kPrefix + fdp_.ConsumeRandomLengthString(kMaxPropertyLength)),
100 fdp_.ConsumeRandomLengthString(kMaxPropertyLength));
101 }
102 }
103
RemoveFiles()104 void InitPropertyFuzzer::RemoveFiles() {
105 remove(kFuzzerPropertyFile.c_str());
106 remove(kLegacyPropertyFile.c_str());
107 }
108
CreateFuzzerPropertyFile(const std::string property_file)109 void InitPropertyFuzzer::CreateFuzzerPropertyFile(const std::string property_file) {
110 std::ofstream out;
111 out.open(property_file, std::ios::binary | std::ofstream::trunc);
112 chmod(property_file.c_str(), S_IRWXU);
113 const int32_t numStrings = fdp_.ConsumeIntegralInRange(kMinNumStrings, kMaxNumStrings);
114 for (int32_t i = 0; i < numStrings; ++i) {
115 out << fdp_.ConsumeRandomLengthString(kMaxPropertyLength) << "\n";
116 }
117 out.close();
118 }
119
process()120 void InitPropertyFuzzer::process() {
121 persistent_property_filename = kFuzzerPropertyFile;
122 /* Property and legacy files are created using createFuzzerPropertyFile() and */
123 /* are used in the below APIs. Hence createFuzzerPropertyFile() is not a part */
124 /* of the lambda construct. */
125 CreateFuzzerPropertyFile(kFuzzerPropertyFile);
126 CreateFuzzerPropertyFile(kLegacyPropertyFile);
127 auto property_type = fdp_.PickValueInArray<const std::function<void()>>({
128 [&]() { InvokeCheckType(); },
129 [&]() { InvokeWritePersistentProperty(); },
130 [&]() { LoadPersistentProperties(); },
131 });
132 property_type();
133 RemoveFiles();
134 }
135
LLVMFuzzerTestOneInput(const uint8_t * data,size_t size)136 extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
137 InitPropertyFuzzer initPropertyFuzzer(data, size);
138 initPropertyFuzzer.process();
139 return 0;
140 }
141