• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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