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