1 /*
2  * Copyright (C) 2018 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 
17 #include "ueventd_parser.h"
18 
19 #include <android-base/file.h>
20 #include <gtest/gtest.h>
21 #include <private/android_filesystem_config.h>
22 
23 #include "firmware_handler.h"
24 
25 namespace android {
26 namespace init {
27 
TestSubsystems(const Subsystem & expected,const Subsystem & test)28 void TestSubsystems(const Subsystem& expected, const Subsystem& test) {
29     EXPECT_EQ(expected.name_, test.name_);
30     EXPECT_EQ(expected.devname_source_, test.devname_source_) << expected.name_;
31     EXPECT_EQ(expected.dir_name_, test.dir_name_) << expected.name_;
32 }
33 
TestPermissions(const Permissions & expected,const Permissions & test)34 void TestPermissions(const Permissions& expected, const Permissions& test) {
35     EXPECT_EQ(expected.name_, test.name_);
36     EXPECT_EQ(expected.perm_, test.perm_) << expected.name_;
37     EXPECT_EQ(expected.uid_, test.uid_) << expected.name_;
38     EXPECT_EQ(expected.gid_, test.gid_) << expected.name_;
39     EXPECT_EQ(expected.prefix_, test.prefix_) << expected.name_;
40     EXPECT_EQ(expected.wildcard_, test.wildcard_) << expected.name_;
41 }
42 
TestSysfsPermissions(const SysfsPermissions & expected,const SysfsPermissions & test)43 void TestSysfsPermissions(const SysfsPermissions& expected, const SysfsPermissions& test) {
44     TestPermissions(expected, test);
45     EXPECT_EQ(expected.attribute_, test.attribute_);
46 }
47 
48 template <typename T, typename F>
TestVector(const T & expected,const T & test,F function)49 void TestVector(const T& expected, const T& test, F function) {
50     ASSERT_EQ(expected.size(), test.size());
51     auto expected_it = expected.begin();
52     auto test_it = test.begin();
53 
54     for (; expected_it != expected.end(); ++expected_it, ++test_it) {
55         function(*expected_it, *test_it);
56     }
57 }
58 
TestUeventdFile(const std::string & content,const UeventdConfiguration & expected)59 void TestUeventdFile(const std::string& content, const UeventdConfiguration& expected) {
60     TemporaryFile tf;
61     ASSERT_TRUE(tf.fd != -1);
62     ASSERT_TRUE(android::base::WriteStringToFd(content, tf.fd));
63 
64     auto result = ParseConfig({tf.path});
65 
66     TestVector(expected.subsystems, result.subsystems, TestSubsystems);
67     TestVector(expected.sysfs_permissions, result.sysfs_permissions, TestSysfsPermissions);
68     TestVector(expected.dev_permissions, result.dev_permissions, TestPermissions);
69     EXPECT_EQ(expected.firmware_directories, result.firmware_directories);
70 }
71 
TEST(ueventd_parser,EmptyFile)72 TEST(ueventd_parser, EmptyFile) {
73     TestUeventdFile("", {});
74 }
75 
TEST(ueventd_parser,Subsystems)76 TEST(ueventd_parser, Subsystems) {
77     auto ueventd_file = R"(
78 subsystem test_devname
79     devname uevent_devname
80 
81 subsystem test_devpath_no_dirname
82     devname uevent_devpath
83 
84 subsystem test_devname2
85     devname uevent_devname
86 
87 subsystem test_devpath_dirname
88     devname uevent_devpath
89     dirname /dev/graphics
90 )";
91 
92     auto subsystems = std::vector<Subsystem>{
93             {"test_devname", Subsystem::DEVNAME_UEVENT_DEVNAME, "/dev"},
94             {"test_devpath_no_dirname", Subsystem::DEVNAME_UEVENT_DEVPATH, "/dev"},
95             {"test_devname2", Subsystem::DEVNAME_UEVENT_DEVNAME, "/dev"},
96             {"test_devpath_dirname", Subsystem::DEVNAME_UEVENT_DEVPATH, "/dev/graphics"}};
97 
98     TestUeventdFile(ueventd_file, {subsystems, {}, {}, {}, {}});
99 }
100 
TEST(ueventd_parser,Permissions)101 TEST(ueventd_parser, Permissions) {
102     auto ueventd_file = R"(
103 /dev/rtc0                 0640   system     system
104 /dev/graphics/*           0660   root       graphics
105 /dev/*/test               0660   root       system
106 
107 /sys/devices/platform/trusty.*      trusty_version        0440  root   log
108 /sys/devices/virtual/input/input   enable      0660  root   input
109 /sys/devices/virtual/*/input   poll_delay  0660  root   input
110 )";
111 
112     auto permissions = std::vector<Permissions>{
113             {"/dev/rtc0", 0640, AID_SYSTEM, AID_SYSTEM},
114             {"/dev/graphics/*", 0660, AID_ROOT, AID_GRAPHICS},
115             {"/dev/*/test", 0660, AID_ROOT, AID_SYSTEM},
116     };
117 
118     auto sysfs_permissions = std::vector<SysfsPermissions>{
119             {"/sys/devices/platform/trusty.*", "trusty_version", 0440, AID_ROOT, AID_LOG},
120             {"/sys/devices/virtual/input/input", "enable", 0660, AID_ROOT, AID_INPUT},
121             {"/sys/devices/virtual/*/input", "poll_delay", 0660, AID_ROOT, AID_INPUT},
122     };
123 
124     TestUeventdFile(ueventd_file, {{}, sysfs_permissions, permissions, {}, {}});
125 }
126 
TEST(ueventd_parser,FirmwareDirectories)127 TEST(ueventd_parser, FirmwareDirectories) {
128     auto ueventd_file = R"(
129 firmware_directories /first/ /second /third
130 firmware_directories /more
131 )";
132 
133     auto firmware_directories = std::vector<std::string>{
134             "/first/",
135             "/second",
136             "/third",
137             "/more",
138     };
139 
140     TestUeventdFile(ueventd_file, {{}, {}, {}, firmware_directories, {}});
141 }
142 
TEST(ueventd_parser,ExternalFirmwareHandlers)143 TEST(ueventd_parser, ExternalFirmwareHandlers) {
144     auto ueventd_file = R"(
145 external_firmware_handler devpath root handler_path
146 external_firmware_handler /devices/path/firmware/something001.bin system /vendor/bin/firmware_handler.sh
147 external_firmware_handler /devices/path/firmware/something001.bin radio "/vendor/bin/firmware_handler.sh --has --arguments"
148 )";
149 
150     auto external_firmware_handlers = std::vector<ExternalFirmwareHandler>{
151             {
152                     "devpath",
153                     AID_ROOT,
154                     "handler_path",
155             },
156             {
157                     "/devices/path/firmware/something001.bin",
158                     AID_SYSTEM,
159                     "/vendor/bin/firmware_handler.sh",
160             },
161             {
162                     "/devices/path/firmware/something001.bin",
163                     AID_RADIO,
164                     "/vendor/bin/firmware_handler.sh --has --arguments",
165             },
166     };
167 
168     TestUeventdFile(ueventd_file, {{}, {}, {}, {}, external_firmware_handlers});
169 }
170 
TEST(ueventd_parser,ExternalFirmwareHandlersDuplicate)171 TEST(ueventd_parser, ExternalFirmwareHandlersDuplicate) {
172     auto ueventd_file = R"(
173 external_firmware_handler devpath root handler_path
174 external_firmware_handler devpath root handler_path2
175 )";
176 
177     auto external_firmware_handlers = std::vector<ExternalFirmwareHandler>{
178             {
179                     "devpath",
180                     AID_ROOT,
181                     "handler_path",
182             },
183     };
184 
185     TestUeventdFile(ueventd_file, {{}, {}, {}, {}, external_firmware_handlers});
186 }
187 
TEST(ueventd_parser,UeventSocketRcvbufSize)188 TEST(ueventd_parser, UeventSocketRcvbufSize) {
189     auto ueventd_file = R"(
190 uevent_socket_rcvbuf_size 8k
191 uevent_socket_rcvbuf_size 8M
192 )";
193 
194     TestUeventdFile(ueventd_file, {{}, {}, {}, {}, {}, false, 8 * 1024 * 1024});
195 }
196 
TEST(ueventd_parser,EnabledDisabledLines)197 TEST(ueventd_parser, EnabledDisabledLines) {
198     auto ueventd_file = R"(
199 modalias_handling enabled
200 parallel_restorecon enabled
201 modalias_handling disabled
202 )";
203 
204     TestUeventdFile(ueventd_file, {{}, {}, {}, {}, {}, false, 0, true});
205 
206     auto ueventd_file2 = R"(
207 parallel_restorecon enabled
208 modalias_handling enabled
209 parallel_restorecon disabled
210 )";
211 
212     TestUeventdFile(ueventd_file2, {{}, {}, {}, {}, {}, true, 0, false});
213 }
214 
TEST(ueventd_parser,AllTogether)215 TEST(ueventd_parser, AllTogether) {
216     auto ueventd_file = R"(
217 
218 /dev/rtc0                 0640   system     system
219 firmware_directories /first/ /second /third
220 /sys/devices/platform/trusty.*      trusty_version        0440  root   log
221 
222 subsystem test_devname
223     devname uevent_devname
224 
225 /dev/graphics/*           0660   root       graphics
226 
227 subsystem test_devpath_no_dirname
228     devname uevent_devpath
229 
230 /sys/devices/virtual/input/input   enable      0660  root   input
231 
232 ## this is a comment
233 
234 subsystem test_devname2
235 ## another comment
236     devname uevent_devname
237 
238 subsystem test_devpath_dirname
239     devname uevent_devpath
240     dirname /dev/graphics
241 
242 /dev/*/test               0660   root       system
243 /sys/devices/virtual/*/input   poll_delay  0660  root   input
244 firmware_directories /more
245 
246 external_firmware_handler /devices/path/firmware/firmware001.bin root /vendor/bin/touch.sh
247 
248 uevent_socket_rcvbuf_size 6M
249 modalias_handling enabled
250 parallel_restorecon enabled
251 
252 #ending comment
253 )";
254 
255     auto subsystems = std::vector<Subsystem>{
256             {"test_devname", Subsystem::DEVNAME_UEVENT_DEVNAME, "/dev"},
257             {"test_devpath_no_dirname", Subsystem::DEVNAME_UEVENT_DEVPATH, "/dev"},
258             {"test_devname2", Subsystem::DEVNAME_UEVENT_DEVNAME, "/dev"},
259             {"test_devpath_dirname", Subsystem::DEVNAME_UEVENT_DEVPATH, "/dev/graphics"}};
260 
261     auto permissions = std::vector<Permissions>{
262             {"/dev/rtc0", 0640, AID_SYSTEM, AID_SYSTEM},
263             {"/dev/graphics/*", 0660, AID_ROOT, AID_GRAPHICS},
264             {"/dev/*/test", 0660, AID_ROOT, AID_SYSTEM},
265     };
266 
267     auto sysfs_permissions = std::vector<SysfsPermissions>{
268             {"/sys/devices/platform/trusty.*", "trusty_version", 0440, AID_ROOT, AID_LOG},
269             {"/sys/devices/virtual/input/input", "enable", 0660, AID_ROOT, AID_INPUT},
270             {"/sys/devices/virtual/*/input", "poll_delay", 0660, AID_ROOT, AID_INPUT},
271     };
272 
273     auto firmware_directories = std::vector<std::string>{
274             "/first/",
275             "/second",
276             "/third",
277             "/more",
278     };
279 
280     auto external_firmware_handlers = std::vector<ExternalFirmwareHandler>{
281             {"/devices/path/firmware/firmware001.bin", AID_ROOT, "/vendor/bin/touch.sh"},
282     };
283 
284     size_t uevent_socket_rcvbuf_size = 6 * 1024 * 1024;
285 
286     TestUeventdFile(ueventd_file,
287                     {subsystems, sysfs_permissions, permissions, firmware_directories,
288                      external_firmware_handlers, true, uevent_socket_rcvbuf_size, true});
289 }
290 
291 // All of these lines are ill-formed, so test that there is 0 output.
TEST(ueventd_parser,ParseErrors)292 TEST(ueventd_parser, ParseErrors) {
293     auto ueventd_file = R"(
294 
295 /dev/rtc0                 badmode   baduidbad     system
296 /dev/rtc0                 0640   baduidbad     system
297 /dev/rtc0                 0640   system     baduidbad
298 firmware_directories #no directory listed
299 /sys/devices/platform/trusty.*      trusty_version        badmode  root   log
300 /sys/devices/platform/trusty.*      trusty_version        0440  baduidbad   log
301 /sys/devices/platform/trusty.*      trusty_version        0440  root   baduidbad
302 
303 uevent_socket_rcvbuf_size blah
304 
305 subsystem #no name
306 
307 modalias_handling
308 modalias_handling enabled enabled
309 modalias_handling blah
310 
311 parallel_restorecon
312 parallel_restorecon enabled enabled
313 parallel_restorecon blah
314 
315 external_firmware_handler
316 external_firmware_handler blah blah
317 external_firmware_handler blah blah blah blah
318 
319 )";
320 
321     TestUeventdFile(ueventd_file, {});
322 }
323 
324 }  // namespace init
325 }  // namespace android
326