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