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,Permissions)112 TEST(ueventd_parser, Permissions) {
113 auto ueventd_file = R"(
114 /dev/rtc0 0640 system system
115 /dev/graphics/* 0660 root graphics
116 /dev/*/test 0660 root system
117
118 /sys/devices/platform/trusty.* trusty_version 0440 root log
119 /sys/devices/virtual/input/input enable 0660 root input
120 /sys/devices/virtual/*/input poll_delay 0660 root input no_fnm_pathname
121 )";
122
123 auto permissions = std::vector<Permissions>{
124 {"/dev/rtc0", 0640, AID_SYSTEM, AID_SYSTEM, false},
125 {"/dev/graphics/*", 0660, AID_ROOT, AID_GRAPHICS, false},
126 {"/dev/*/test", 0660, AID_ROOT, AID_SYSTEM, false},
127 };
128
129 auto sysfs_permissions = std::vector<SysfsPermissions>{
130 {"/sys/devices/platform/trusty.*", "trusty_version", 0440, AID_ROOT, AID_LOG, false},
131 {"/sys/devices/virtual/input/input", "enable", 0660, AID_ROOT, AID_INPUT, false},
132 {"/sys/devices/virtual/*/input", "poll_delay", 0660, AID_ROOT, AID_INPUT, true},
133 };
134
135 TestUeventdFile(ueventd_file, {{}, sysfs_permissions, permissions, {}, {}, {}});
136 }
137
TEST(ueventd_parser,FirmwareDirectories)138 TEST(ueventd_parser, FirmwareDirectories) {
139 auto ueventd_file = R"(
140 firmware_directories /first/ /second /third
141 firmware_directories /more
142 )";
143
144 auto firmware_directories = std::vector<std::string>{
145 "/first/",
146 "/second",
147 "/third",
148 "/more",
149 };
150
151 TestUeventdFile(ueventd_file, {{}, {}, {}, firmware_directories, {}, {}});
152 }
153
TEST(ueventd_parser,ExternalFirmwareHandlers)154 TEST(ueventd_parser, ExternalFirmwareHandlers) {
155 auto ueventd_file = R"(
156 external_firmware_handler devpath root handler_path
157 external_firmware_handler /devices/path/firmware/something001.bin system /vendor/bin/firmware_handler.sh
158 external_firmware_handler /devices/path/firmware/something002.bin radio "/vendor/bin/firmware_handler.sh --has --arguments"
159 external_firmware_handler /devices/path/firmware/* root "/vendor/bin/firmware_handler.sh"
160 external_firmware_handler /devices/path/firmware/something* system "/vendor/bin/firmware_handler.sh"
161 external_firmware_handler /devices/path/*/firmware/something*.bin radio "/vendor/bin/firmware_handler.sh"
162 external_firmware_handler /devices/path/firmware/something003.bin system system /vendor/bin/firmware_handler.sh
163 external_firmware_handler /devices/path/firmware/something004.bin radio radio "/vendor/bin/firmware_handler.sh --has --arguments"
164 )";
165
166 auto external_firmware_handlers = std::vector<ExternalFirmwareHandler>{
167 {
168 "devpath",
169 AID_ROOT,
170 AID_ROOT,
171 "handler_path",
172 },
173 {
174 "/devices/path/firmware/something001.bin",
175 AID_SYSTEM,
176 AID_ROOT,
177 "/vendor/bin/firmware_handler.sh",
178 },
179 {
180 "/devices/path/firmware/something002.bin",
181 AID_RADIO,
182 AID_ROOT,
183 "/vendor/bin/firmware_handler.sh --has --arguments",
184 },
185 {
186 "/devices/path/firmware/",
187 AID_ROOT,
188 AID_ROOT,
189 "/vendor/bin/firmware_handler.sh",
190 },
191 {
192 "/devices/path/firmware/something",
193 AID_SYSTEM,
194 AID_ROOT,
195 "/vendor/bin/firmware_handler.sh",
196 },
197 {
198 "/devices/path/*/firmware/something*.bin",
199 AID_RADIO,
200 AID_ROOT,
201 "/vendor/bin/firmware_handler.sh",
202 },
203 {
204 "/devices/path/firmware/something003.bin",
205 AID_SYSTEM,
206 AID_SYSTEM,
207 "/vendor/bin/firmware_handler.sh",
208 },
209 {
210 "/devices/path/firmware/something004.bin",
211 AID_RADIO,
212 AID_RADIO,
213 "/vendor/bin/firmware_handler.sh --has --arguments",
214 },
215 };
216
217 TestUeventdFile(ueventd_file, {{}, {}, {}, {}, external_firmware_handlers, {}});
218 }
219
TEST(ueventd_parser,ExternalFirmwareHandlersDuplicate)220 TEST(ueventd_parser, ExternalFirmwareHandlersDuplicate) {
221 auto ueventd_file = R"(
222 external_firmware_handler devpath root handler_path
223 external_firmware_handler devpath root handler_path2
224 )";
225
226 auto external_firmware_handlers = std::vector<ExternalFirmwareHandler>{
227 {
228 "devpath",
229 AID_ROOT,
230 AID_ROOT,
231 "handler_path",
232 },
233 };
234
235 TestUeventdFile(ueventd_file, {{}, {}, {}, {}, external_firmware_handlers, {}});
236 }
237
TEST(ueventd_parser,ParallelRestoreconDirs)238 TEST(ueventd_parser, ParallelRestoreconDirs) {
239 auto ueventd_file = R"(
240 parallel_restorecon_dir /sys
241 parallel_restorecon_dir /sys/devices
242 )";
243
244 auto parallel_restorecon_dirs = std::vector<std::string>{
245 "/sys",
246 "/sys/devices",
247 };
248
249 TestUeventdFile(ueventd_file, {{}, {}, {}, {}, {}, parallel_restorecon_dirs});
250 }
251
TEST(ueventd_parser,UeventSocketRcvbufSize)252 TEST(ueventd_parser, UeventSocketRcvbufSize) {
253 auto ueventd_file = R"(
254 uevent_socket_rcvbuf_size 8k
255 uevent_socket_rcvbuf_size 8M
256 )";
257
258 TestUeventdFile(ueventd_file, {{}, {}, {}, {}, {}, {}, false, 8 * 1024 * 1024});
259 }
260
TEST(ueventd_parser,EnabledDisabledLines)261 TEST(ueventd_parser, EnabledDisabledLines) {
262 auto ueventd_file = R"(
263 modalias_handling enabled
264 parallel_restorecon enabled
265 modalias_handling disabled
266 )";
267
268 TestUeventdFile(ueventd_file, {{}, {}, {}, {}, {}, {}, false, 0, true});
269
270 auto ueventd_file2 = R"(
271 parallel_restorecon enabled
272 modalias_handling enabled
273 parallel_restorecon disabled
274 )";
275
276 TestUeventdFile(ueventd_file2, {{}, {}, {}, {}, {}, {}, true, 0, false});
277 }
278
TEST(ueventd_parser,AllTogether)279 TEST(ueventd_parser, AllTogether) {
280 auto ueventd_file = R"(
281
282 /dev/rtc0 0640 system system
283 firmware_directories /first/ /second /third
284 /sys/devices/platform/trusty.* trusty_version 0440 root log
285
286 subsystem test_devname
287 devname uevent_devname
288
289 /dev/graphics/* 0660 root graphics
290
291 subsystem test_devpath_no_dirname
292 devname uevent_devpath
293
294 /sys/devices/virtual/input/input enable 0660 root input
295
296 ## this is a comment
297
298 subsystem test_devname2
299 ## another comment
300 devname uevent_devname
301
302 subsystem test_devpath_dirname
303 devname uevent_devpath
304 dirname /dev/graphics
305
306 /dev/*/test 0660 root system
307 /sys/devices/virtual/*/input poll_delay 0660 root input no_fnm_pathname
308 firmware_directories /more
309
310 external_firmware_handler /devices/path/firmware/firmware001.bin root /vendor/bin/touch.sh
311
312 uevent_socket_rcvbuf_size 6M
313 modalias_handling enabled
314 parallel_restorecon enabled
315
316 parallel_restorecon_dir /sys
317 parallel_restorecon_dir /sys/devices
318
319 #ending comment
320 )";
321
322 auto subsystems = std::vector<Subsystem>{
323 {"test_devname", Subsystem::DEVNAME_UEVENT_DEVNAME, "/dev"},
324 {"test_devpath_no_dirname", Subsystem::DEVNAME_UEVENT_DEVPATH, "/dev"},
325 {"test_devname2", Subsystem::DEVNAME_UEVENT_DEVNAME, "/dev"},
326 {"test_devpath_dirname", Subsystem::DEVNAME_UEVENT_DEVPATH, "/dev/graphics"}};
327
328 auto permissions = std::vector<Permissions>{
329 {"/dev/rtc0", 0640, AID_SYSTEM, AID_SYSTEM, false},
330 {"/dev/graphics/*", 0660, AID_ROOT, AID_GRAPHICS, false},
331 {"/dev/*/test", 0660, AID_ROOT, AID_SYSTEM, false},
332 };
333
334 auto sysfs_permissions = std::vector<SysfsPermissions>{
335 {"/sys/devices/platform/trusty.*", "trusty_version", 0440, AID_ROOT, AID_LOG, false},
336 {"/sys/devices/virtual/input/input", "enable", 0660, AID_ROOT, AID_INPUT, false},
337 {"/sys/devices/virtual/*/input", "poll_delay", 0660, AID_ROOT, AID_INPUT, true},
338 };
339
340 auto firmware_directories = std::vector<std::string>{
341 "/first/",
342 "/second",
343 "/third",
344 "/more",
345 };
346
347 auto external_firmware_handlers = std::vector<ExternalFirmwareHandler>{
348 {"/devices/path/firmware/firmware001.bin", AID_ROOT, AID_ROOT, "/vendor/bin/touch.sh"},
349 };
350
351 auto parallel_restorecon_dirs = std::vector<std::string>{
352 "/sys",
353 "/sys/devices",
354 };
355
356 size_t uevent_socket_rcvbuf_size = 6 * 1024 * 1024;
357
358 TestUeventdFile(ueventd_file,
359 {subsystems, sysfs_permissions, permissions, firmware_directories,
360 external_firmware_handlers, parallel_restorecon_dirs, true,
361 uevent_socket_rcvbuf_size, true});
362 }
363
364 // All of these lines are ill-formed, so test that there is 0 output.
TEST(ueventd_parser,ParseErrors)365 TEST(ueventd_parser, ParseErrors) {
366 auto ueventd_file = R"(
367
368 /dev/rtc0 badmode baduidbad system
369 /dev/rtc0 0640 baduidbad system
370 /dev/rtc0 0640 system baduidbad
371 firmware_directories #no directory listed
372 /sys/devices/platform/trusty.* trusty_version badmode root log
373 /sys/devices/platform/trusty.* trusty_version 0440 baduidbad log
374 /sys/devices/platform/trusty.* trusty_version 0440 root baduidbad
375 /sys/devices/platform/trusty.* trusty_version 0440 root root bad_option
376
377 uevent_socket_rcvbuf_size blah
378
379 subsystem #no name
380
381 modalias_handling
382 modalias_handling enabled enabled
383 modalias_handling blah
384
385 parallel_restorecon
386 parallel_restorecon enabled enabled
387 parallel_restorecon blah
388
389 external_firmware_handler
390 external_firmware_handler blah blah
391 external_firmware_handler blah blah blah blah
392
393 parallel_restorecon_dir
394 parallel_restorecon_dir /sys /sys/devices
395
396 )";
397
398 TestUeventdFile(ueventd_file, {});
399 }
400
401 } // namespace init
402 } // namespace android
403