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
TestExternalFirmwareHandler(const ExternalFirmwareHandler & expected,const ExternalFirmwareHandler & test)48 void TestExternalFirmwareHandler(const ExternalFirmwareHandler& expected,
49 const ExternalFirmwareHandler& test) {
50 EXPECT_EQ(expected.devpath, test.devpath) << expected.devpath;
51 EXPECT_EQ(expected.uid, test.uid) << expected.uid;
52 EXPECT_EQ(expected.gid, test.gid) << expected.gid;
53 EXPECT_EQ(expected.handler_path, test.handler_path) << expected.handler_path;
54 }
55
56 template <typename T, typename F>
TestVector(const T & expected,const T & test,F function)57 void TestVector(const T& expected, const T& test, F function) {
58 ASSERT_EQ(expected.size(), test.size());
59 auto expected_it = expected.begin();
60 auto test_it = test.begin();
61
62 for (; expected_it != expected.end(); ++expected_it, ++test_it) {
63 function(*expected_it, *test_it);
64 }
65 }
66
TestUeventdFile(const std::string & content,const UeventdConfiguration & expected)67 void TestUeventdFile(const std::string& content, const UeventdConfiguration& expected) {
68 TemporaryFile tf;
69 ASSERT_TRUE(tf.fd != -1);
70 ASSERT_TRUE(android::base::WriteStringToFd(content, tf.fd));
71
72 auto result = ParseConfig({tf.path});
73
74 TestVector(expected.subsystems, result.subsystems, TestSubsystems);
75 TestVector(expected.sysfs_permissions, result.sysfs_permissions, TestSysfsPermissions);
76 TestVector(expected.dev_permissions, result.dev_permissions, TestPermissions);
77 EXPECT_EQ(expected.firmware_directories, result.firmware_directories);
78 TestVector(expected.external_firmware_handlers, result.external_firmware_handlers,
79 TestExternalFirmwareHandler);
80 EXPECT_EQ(expected.parallel_restorecon_dirs, result.parallel_restorecon_dirs);
81 }
82
TEST(ueventd_parser,EmptyFile)83 TEST(ueventd_parser, EmptyFile) {
84 TestUeventdFile("", {});
85 }
86
TEST(ueventd_parser,Subsystems)87 TEST(ueventd_parser, Subsystems) {
88 auto ueventd_file = R"(
89 subsystem test_devname
90 devname uevent_devname
91
92 subsystem test_devpath_no_dirname
93 devname uevent_devpath
94
95 subsystem test_devname2
96 devname uevent_devname
97
98 subsystem test_devpath_dirname
99 devname uevent_devpath
100 dirname /dev/graphics
101 )";
102
103 auto subsystems = std::vector<Subsystem>{
104 {"test_devname", Subsystem::DEVNAME_UEVENT_DEVNAME, "/dev"},
105 {"test_devpath_no_dirname", Subsystem::DEVNAME_UEVENT_DEVPATH, "/dev"},
106 {"test_devname2", Subsystem::DEVNAME_UEVENT_DEVNAME, "/dev"},
107 {"test_devpath_dirname", Subsystem::DEVNAME_UEVENT_DEVPATH, "/dev/graphics"}};
108
109 TestUeventdFile(ueventd_file, {subsystems, {}, {}, {}, {}, {}, {}});
110 }
111
TEST(ueventd_parser,Drivers)112 TEST(ueventd_parser, Drivers) {
113 auto ueventd_file = R"(
114 driver test_devname
115 devname uevent_devname
116
117 driver test_devpath_no_dirname
118 devname uevent_devpath
119
120 driver test_devname2
121 devname uevent_devname
122
123 driver test_devpath_dirname
124 devname uevent_devpath
125 dirname /dev/graphics
126 )";
127
128 auto drivers = std::vector<Subsystem>{
129 {"test_devname", Subsystem::DEVNAME_UEVENT_DEVNAME, "/dev"},
130 {"test_devpath_no_dirname", Subsystem::DEVNAME_UEVENT_DEVPATH, "/dev"},
131 {"test_devname2", Subsystem::DEVNAME_UEVENT_DEVNAME, "/dev"},
132 {"test_devpath_dirname", Subsystem::DEVNAME_UEVENT_DEVPATH, "/dev/graphics"}};
133
134 TestUeventdFile(ueventd_file, {{}, drivers, {}, {}, {}, {}, {}, {}});
135 }
136
TEST(ueventd_parser,Permissions)137 TEST(ueventd_parser, Permissions) {
138 auto ueventd_file = R"(
139 /dev/rtc0 0640 system system
140 /dev/graphics/* 0660 root graphics
141 /dev/*/test 0660 root system
142
143 /sys/devices/platform/trusty.* trusty_version 0440 root log
144 /sys/devices/virtual/input/input enable 0660 root input
145 /sys/devices/virtual/*/input poll_delay 0660 root input no_fnm_pathname
146 )";
147
148 auto permissions = std::vector<Permissions>{
149 {"/dev/rtc0", 0640, AID_SYSTEM, AID_SYSTEM, false},
150 {"/dev/graphics/*", 0660, AID_ROOT, AID_GRAPHICS, false},
151 {"/dev/*/test", 0660, AID_ROOT, AID_SYSTEM, false},
152 };
153
154 auto sysfs_permissions = std::vector<SysfsPermissions>{
155 {"/sys/devices/platform/trusty.*", "trusty_version", 0440, AID_ROOT, AID_LOG, false},
156 {"/sys/devices/virtual/input/input", "enable", 0660, AID_ROOT, AID_INPUT, false},
157 {"/sys/devices/virtual/*/input", "poll_delay", 0660, AID_ROOT, AID_INPUT, true},
158 };
159
160 TestUeventdFile(ueventd_file, {{}, {}, sysfs_permissions, permissions, {}, {}, {}});
161 }
162
TEST(ueventd_parser,FirmwareDirectories)163 TEST(ueventd_parser, FirmwareDirectories) {
164 auto ueventd_file = R"(
165 firmware_directories /first/ /second /third
166 firmware_directories /more
167 )";
168
169 auto firmware_directories = std::vector<std::string>{
170 "/first/",
171 "/second",
172 "/third",
173 "/more",
174 };
175
176 TestUeventdFile(ueventd_file, {{}, {}, {}, {}, firmware_directories, {}, {}});
177 }
178
TEST(ueventd_parser,ExternalFirmwareHandlers)179 TEST(ueventd_parser, ExternalFirmwareHandlers) {
180 auto ueventd_file = R"(
181 external_firmware_handler devpath root handler_path
182 external_firmware_handler /devices/path/firmware/something001.bin system /vendor/bin/firmware_handler.sh
183 external_firmware_handler /devices/path/firmware/something002.bin radio "/vendor/bin/firmware_handler.sh --has --arguments"
184 external_firmware_handler /devices/path/firmware/* root "/vendor/bin/firmware_handler.sh"
185 external_firmware_handler /devices/path/firmware/something* system "/vendor/bin/firmware_handler.sh"
186 external_firmware_handler /devices/path/*/firmware/something*.bin radio "/vendor/bin/firmware_handler.sh"
187 external_firmware_handler /devices/path/firmware/something003.bin system system /vendor/bin/firmware_handler.sh
188 external_firmware_handler /devices/path/firmware/something004.bin radio radio "/vendor/bin/firmware_handler.sh --has --arguments"
189 )";
190
191 auto external_firmware_handlers = std::vector<ExternalFirmwareHandler>{
192 {
193 "devpath",
194 AID_ROOT,
195 AID_ROOT,
196 "handler_path",
197 },
198 {
199 "/devices/path/firmware/something001.bin",
200 AID_SYSTEM,
201 AID_ROOT,
202 "/vendor/bin/firmware_handler.sh",
203 },
204 {
205 "/devices/path/firmware/something002.bin",
206 AID_RADIO,
207 AID_ROOT,
208 "/vendor/bin/firmware_handler.sh --has --arguments",
209 },
210 {
211 "/devices/path/firmware/",
212 AID_ROOT,
213 AID_ROOT,
214 "/vendor/bin/firmware_handler.sh",
215 },
216 {
217 "/devices/path/firmware/something",
218 AID_SYSTEM,
219 AID_ROOT,
220 "/vendor/bin/firmware_handler.sh",
221 },
222 {
223 "/devices/path/*/firmware/something*.bin",
224 AID_RADIO,
225 AID_ROOT,
226 "/vendor/bin/firmware_handler.sh",
227 },
228 {
229 "/devices/path/firmware/something003.bin",
230 AID_SYSTEM,
231 AID_SYSTEM,
232 "/vendor/bin/firmware_handler.sh",
233 },
234 {
235 "/devices/path/firmware/something004.bin",
236 AID_RADIO,
237 AID_RADIO,
238 "/vendor/bin/firmware_handler.sh --has --arguments",
239 },
240 };
241
242 TestUeventdFile(ueventd_file, {{}, {}, {}, {}, {}, external_firmware_handlers, {}});
243 }
244
TEST(ueventd_parser,ExternalFirmwareHandlersDuplicate)245 TEST(ueventd_parser, ExternalFirmwareHandlersDuplicate) {
246 auto ueventd_file = R"(
247 external_firmware_handler devpath root handler_path
248 external_firmware_handler devpath root handler_path2
249 )";
250
251 auto external_firmware_handlers = std::vector<ExternalFirmwareHandler>{
252 {
253 "devpath",
254 AID_ROOT,
255 AID_ROOT,
256 "handler_path",
257 },
258 };
259
260 TestUeventdFile(ueventd_file, {{}, {}, {}, {}, {}, external_firmware_handlers, {}});
261 }
262
TEST(ueventd_parser,ParallelRestoreconDirs)263 TEST(ueventd_parser, ParallelRestoreconDirs) {
264 auto ueventd_file = R"(
265 parallel_restorecon_dir /sys
266 parallel_restorecon_dir /sys/devices
267 )";
268
269 auto parallel_restorecon_dirs = std::vector<std::string>{
270 "/sys",
271 "/sys/devices",
272 };
273
274 TestUeventdFile(ueventd_file, {{}, {}, {}, {}, {}, {}, parallel_restorecon_dirs});
275 }
276
TEST(ueventd_parser,UeventSocketRcvbufSize)277 TEST(ueventd_parser, UeventSocketRcvbufSize) {
278 auto ueventd_file = R"(
279 uevent_socket_rcvbuf_size 8k
280 uevent_socket_rcvbuf_size 8M
281 )";
282
283 TestUeventdFile(ueventd_file, {{}, {}, {}, {}, {}, {}, {}, false, 8 * 1024 * 1024});
284 }
285
TEST(ueventd_parser,EnabledDisabledLines)286 TEST(ueventd_parser, EnabledDisabledLines) {
287 auto ueventd_file = R"(
288 modalias_handling enabled
289 parallel_restorecon enabled
290 modalias_handling disabled
291 )";
292
293 TestUeventdFile(ueventd_file, {{}, {}, {}, {}, {}, {}, {}, false, 0, true});
294
295 auto ueventd_file2 = R"(
296 parallel_restorecon enabled
297 modalias_handling enabled
298 parallel_restorecon disabled
299 )";
300
301 TestUeventdFile(ueventd_file2, {{}, {}, {}, {}, {}, {}, {}, true, 0, false});
302 }
303
TEST(ueventd_parser,AllTogether)304 TEST(ueventd_parser, AllTogether) {
305 auto ueventd_file = R"(
306
307 /dev/rtc0 0640 system system
308 firmware_directories /first/ /second /third
309 /sys/devices/platform/trusty.* trusty_version 0440 root log
310
311 subsystem test_devname
312 devname uevent_devname
313
314 driver d_test_devpath
315 devname uevent_devpath
316
317 /dev/graphics/* 0660 root graphics
318
319 subsystem test_devpath_no_dirname
320 devname uevent_devpath
321
322 /sys/devices/virtual/input/input enable 0660 root input
323
324 ## this is a comment
325
326 subsystem test_devname2
327 ## another comment
328 devname uevent_devname
329
330 subsystem test_devpath_dirname
331 devname uevent_devpath
332 dirname /dev/graphics
333
334 driver d_test_devname_dirname
335 devname uevent_devname
336 dirname /dev/sound
337
338 /dev/*/test 0660 root system
339 /sys/devices/virtual/*/input poll_delay 0660 root input no_fnm_pathname
340 firmware_directories /more
341
342 external_firmware_handler /devices/path/firmware/firmware001.bin root /vendor/bin/touch.sh
343
344 uevent_socket_rcvbuf_size 6M
345 modalias_handling enabled
346 parallel_restorecon enabled
347
348 parallel_restorecon_dir /sys
349 parallel_restorecon_dir /sys/devices
350
351 #ending comment
352 )";
353
354 auto subsystems = std::vector<Subsystem>{
355 {"test_devname", Subsystem::DEVNAME_UEVENT_DEVNAME, "/dev"},
356 {"test_devpath_no_dirname", Subsystem::DEVNAME_UEVENT_DEVPATH, "/dev"},
357 {"test_devname2", Subsystem::DEVNAME_UEVENT_DEVNAME, "/dev"},
358 {"test_devpath_dirname", Subsystem::DEVNAME_UEVENT_DEVPATH, "/dev/graphics"}};
359
360 auto drivers = std::vector<Subsystem>{
361 {"d_test_devpath", Subsystem::DEVNAME_UEVENT_DEVPATH, "/dev"},
362 {"d_test_devname_dirname", Subsystem::DEVNAME_UEVENT_DEVNAME, "/dev/graphics"}};
363
364 auto permissions = std::vector<Permissions>{
365 {"/dev/rtc0", 0640, AID_SYSTEM, AID_SYSTEM, false},
366 {"/dev/graphics/*", 0660, AID_ROOT, AID_GRAPHICS, false},
367 {"/dev/*/test", 0660, AID_ROOT, AID_SYSTEM, false},
368 };
369
370 auto sysfs_permissions = std::vector<SysfsPermissions>{
371 {"/sys/devices/platform/trusty.*", "trusty_version", 0440, AID_ROOT, AID_LOG, false},
372 {"/sys/devices/virtual/input/input", "enable", 0660, AID_ROOT, AID_INPUT, false},
373 {"/sys/devices/virtual/*/input", "poll_delay", 0660, AID_ROOT, AID_INPUT, true},
374 };
375
376 auto firmware_directories = std::vector<std::string>{
377 "/first/",
378 "/second",
379 "/third",
380 "/more",
381 };
382
383 auto external_firmware_handlers = std::vector<ExternalFirmwareHandler>{
384 {"/devices/path/firmware/firmware001.bin", AID_ROOT, AID_ROOT, "/vendor/bin/touch.sh"},
385 };
386
387 auto parallel_restorecon_dirs = std::vector<std::string>{
388 "/sys",
389 "/sys/devices",
390 };
391
392 size_t uevent_socket_rcvbuf_size = 6 * 1024 * 1024;
393
394 TestUeventdFile(ueventd_file,
395 {subsystems, drivers, sysfs_permissions, permissions, firmware_directories,
396 external_firmware_handlers, parallel_restorecon_dirs, true,
397 uevent_socket_rcvbuf_size, true});
398 }
399
400 // All of these lines are ill-formed, so test that there is 0 output.
TEST(ueventd_parser,ParseErrors)401 TEST(ueventd_parser, ParseErrors) {
402 auto ueventd_file = R"(
403
404 /dev/rtc0 badmode baduidbad system
405 /dev/rtc0 0640 baduidbad system
406 /dev/rtc0 0640 system baduidbad
407 firmware_directories #no directory listed
408 /sys/devices/platform/trusty.* trusty_version badmode root log
409 /sys/devices/platform/trusty.* trusty_version 0440 baduidbad log
410 /sys/devices/platform/trusty.* trusty_version 0440 root baduidbad
411 /sys/devices/platform/trusty.* trusty_version 0440 root root bad_option
412
413 uevent_socket_rcvbuf_size blah
414
415 subsystem #no name
416
417 modalias_handling
418 modalias_handling enabled enabled
419 modalias_handling blah
420
421 parallel_restorecon
422 parallel_restorecon enabled enabled
423 parallel_restorecon blah
424
425 external_firmware_handler
426 external_firmware_handler blah blah
427 external_firmware_handler blah blah blah blah
428
429 parallel_restorecon_dir
430 parallel_restorecon_dir /sys /sys/devices
431
432 )";
433
434 TestUeventdFile(ueventd_file, {});
435 }
436
437 } // namespace init
438 } // namespace android
439