1 /*
2  * Copyright (C) 2017 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 "devices.h"
18 
19 #include <android-base/file.h>
20 #include <android-base/scopeguard.h>
21 #include <gtest/gtest.h>
22 
23 #include "util.h"
24 
25 using namespace std::string_literals;
26 
27 namespace android {
28 namespace init {
29 
30 class DeviceHandlerTester {
31   public:
TestGetSymlinks(const std::string & platform_device,const Uevent & uevent,const std::vector<std::string> & expected_links)32     void TestGetSymlinks(const std::string& platform_device, const Uevent& uevent,
33                          const std::vector<std::string>& expected_links) {
34         TemporaryDir fake_sys_root;
35         device_handler_.sysfs_mount_point_ = fake_sys_root.path;
36 
37         std::string platform_device_dir = fake_sys_root.path + platform_device;
38         mkdir_recursive(platform_device_dir, 0777);
39 
40         std::string platform_bus = fake_sys_root.path + "/bus/platform"s;
41         mkdir_recursive(platform_bus, 0777);
42         symlink(platform_bus.c_str(), (platform_device_dir + "/subsystem").c_str());
43 
44         mkdir_recursive(android::base::Dirname(fake_sys_root.path + uevent.path), 0777);
45 
46         std::vector<std::string> result;
47         result = device_handler_.GetBlockDeviceSymlinks(uevent);
48 
49         auto expected_size = expected_links.size();
50         ASSERT_EQ(expected_size, result.size());
51         if (expected_size == 0) return;
52 
53         // Explicitly iterate so the results are visible if a failure occurs
54         for (unsigned int i = 0; i < expected_size; ++i) {
55             EXPECT_EQ(expected_links[i], result[i]);
56         }
57     }
58 
59   private:
60     DeviceHandler device_handler_;
61 };
62 
TEST(device_handler,get_block_device_symlinks_success_platform)63 TEST(device_handler, get_block_device_symlinks_success_platform) {
64     // These are actual paths from bullhead
65     const char* platform_device = "/devices/soc.0/f9824900.sdhci";
66     Uevent uevent = {
67         .path = "/devices/soc.0/f9824900.sdhci/mmc_host/mmc0/mmc0:0001/block/mmcblk0",
68         .partition_name = "",
69         .partition_num = -1,
70     };
71     std::vector<std::string> expected_result{"/dev/block/platform/soc.0/f9824900.sdhci/mmcblk0"};
72 
73     DeviceHandlerTester device_handler_tester_;
74     device_handler_tester_.TestGetSymlinks(platform_device, uevent, expected_result);
75 }
76 
TEST(device_handler,get_block_device_symlinks_success_platform_with_partition)77 TEST(device_handler, get_block_device_symlinks_success_platform_with_partition) {
78     // These are actual paths from bullhead
79     const char* platform_device = "/devices/soc.0/f9824900.sdhci";
80     Uevent uevent = {
81         .path = "/devices/soc.0/f9824900.sdhci/mmc_host/mmc0/mmc0:0001/block/mmcblk0p1",
82         .partition_name = "modem",
83         .partition_num = 1,
84     };
85     std::vector<std::string> expected_result{
86         "/dev/block/platform/soc.0/f9824900.sdhci/by-name/modem",
87         "/dev/block/platform/soc.0/f9824900.sdhci/mmcblk0p1",
88     };
89 
90     DeviceHandlerTester device_handler_tester_;
91     device_handler_tester_.TestGetSymlinks(platform_device, uevent, expected_result);
92 }
93 
TEST(device_handler,get_block_device_symlinks_success_platform_with_partition_only_num)94 TEST(device_handler, get_block_device_symlinks_success_platform_with_partition_only_num) {
95     const char* platform_device = "/devices/soc.0/f9824900.sdhci";
96     Uevent uevent = {
97         .path = "/devices/soc.0/f9824900.sdhci/mmc_host/mmc0/mmc0:0001/block/mmcblk0p1",
98         .partition_name = "",
99         .partition_num = 1,
100     };
101     std::vector<std::string> expected_result{
102         "/dev/block/platform/soc.0/f9824900.sdhci/mmcblk0p1",
103     };
104 
105     DeviceHandlerTester device_handler_tester_;
106     device_handler_tester_.TestGetSymlinks(platform_device, uevent, expected_result);
107 }
108 
TEST(device_handler,get_block_device_symlinks_success_platform_with_partition_only_name)109 TEST(device_handler, get_block_device_symlinks_success_platform_with_partition_only_name) {
110     const char* platform_device = "/devices/soc.0/f9824900.sdhci";
111     Uevent uevent = {
112         .path = "/devices/soc.0/f9824900.sdhci/mmc_host/mmc0/mmc0:0001/block/mmcblk0p1",
113         .partition_name = "modem",
114         .partition_num = -1,
115     };
116     std::vector<std::string> expected_result{
117         "/dev/block/platform/soc.0/f9824900.sdhci/by-name/modem",
118         "/dev/block/platform/soc.0/f9824900.sdhci/mmcblk0p1",
119     };
120 
121     DeviceHandlerTester device_handler_tester_;
122     device_handler_tester_.TestGetSymlinks(platform_device, uevent, expected_result);
123 }
124 
TEST(device_handler,get_block_device_symlinks_success_pci)125 TEST(device_handler, get_block_device_symlinks_success_pci) {
126     const char* platform_device = "/devices/do/not/match";
127     Uevent uevent = {
128         .path = "/devices/pci0000:00/0000:00:1f.2/mmcblk0", .partition_name = "", .partition_num = -1,
129     };
130     std::vector<std::string> expected_result{"/dev/block/pci/pci0000:00/0000:00:1f.2/mmcblk0"};
131 
132     DeviceHandlerTester device_handler_tester_;
133     device_handler_tester_.TestGetSymlinks(platform_device, uevent, expected_result);
134 }
135 
TEST(device_handler,get_block_device_symlinks_pci_bad_format)136 TEST(device_handler, get_block_device_symlinks_pci_bad_format) {
137     const char* platform_device = "/devices/do/not/match";
138     Uevent uevent = {
139         .path = "/devices/pci//mmcblk0", .partition_name = "", .partition_num = -1,
140     };
141     std::vector<std::string> expected_result{};
142 
143     DeviceHandlerTester device_handler_tester_;
144     device_handler_tester_.TestGetSymlinks(platform_device, uevent, expected_result);
145 }
146 
TEST(device_handler,get_block_device_symlinks_success_vbd)147 TEST(device_handler, get_block_device_symlinks_success_vbd) {
148     const char* platform_device = "/devices/do/not/match";
149     Uevent uevent = {
150         .path = "/devices/vbd-1234/mmcblk0", .partition_name = "", .partition_num = -1,
151     };
152     std::vector<std::string> expected_result{"/dev/block/vbd/1234/mmcblk0"};
153 
154     DeviceHandlerTester device_handler_tester_;
155     device_handler_tester_.TestGetSymlinks(platform_device, uevent, expected_result);
156 }
157 
TEST(device_handler,get_block_device_symlinks_vbd_bad_format)158 TEST(device_handler, get_block_device_symlinks_vbd_bad_format) {
159     const char* platform_device = "/devices/do/not/match";
160     Uevent uevent = {
161         .path = "/devices/vbd-/mmcblk0", .partition_name = "", .partition_num = -1,
162     };
163     std::vector<std::string> expected_result{};
164 
165     DeviceHandlerTester device_handler_tester_;
166     device_handler_tester_.TestGetSymlinks(platform_device, uevent, expected_result);
167 }
168 
TEST(device_handler,get_block_device_symlinks_no_matches)169 TEST(device_handler, get_block_device_symlinks_no_matches) {
170     const char* platform_device = "/devices/soc.0/f9824900.sdhci";
171     Uevent uevent = {
172         .path = "/devices/soc.0/not_the_device/mmc_host/mmc0/mmc0:0001/block/mmcblk0p1",
173         .partition_name = "",
174         .partition_num = -1,
175     };
176     std::vector<std::string> expected_result;
177 
178     DeviceHandlerTester device_handler_tester_;
179     device_handler_tester_.TestGetSymlinks(platform_device, uevent, expected_result);
180 }
181 
TEST(device_handler,sanitize_null)182 TEST(device_handler, sanitize_null) {
183     SanitizePartitionName(nullptr);
184 }
185 
TEST(device_handler,sanitize_empty)186 TEST(device_handler, sanitize_empty) {
187     std::string empty;
188     SanitizePartitionName(&empty);
189     EXPECT_EQ(0u, empty.size());
190 }
191 
TEST(device_handler,sanitize_allgood)192 TEST(device_handler, sanitize_allgood) {
193     std::string good =
194         "abcdefghijklmnopqrstuvwxyz"
195         "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
196         "0123456789"
197         "_-.";
198     std::string good_copy = good;
199     SanitizePartitionName(&good);
200     EXPECT_EQ(good_copy, good);
201 }
202 
TEST(device_handler,sanitize_somebad)203 TEST(device_handler, sanitize_somebad) {
204     std::string string = "abc!@#$%^&*()";
205     SanitizePartitionName(&string);
206     EXPECT_EQ("abc__________", string);
207 }
208 
TEST(device_handler,sanitize_allbad)209 TEST(device_handler, sanitize_allbad) {
210     std::string string = "!@#$%^&*()";
211     SanitizePartitionName(&string);
212     EXPECT_EQ("__________", string);
213 }
214 
TEST(device_handler,sanitize_onebad)215 TEST(device_handler, sanitize_onebad) {
216     std::string string = ")";
217     SanitizePartitionName(&string);
218     EXPECT_EQ("_", string);
219 }
220 
TEST(device_handler,DevPermissionsMatchNormal)221 TEST(device_handler, DevPermissionsMatchNormal) {
222     // Basic from ueventd.rc
223     // /dev/null                 0666   root       root
224     Permissions permissions("/dev/null", 0666, 0, 0, false);
225     EXPECT_TRUE(permissions.Match("/dev/null"));
226     EXPECT_FALSE(permissions.Match("/dev/nullsuffix"));
227     EXPECT_FALSE(permissions.Match("/dev/nul"));
228     EXPECT_EQ(0666U, permissions.perm());
229     EXPECT_EQ(0U, permissions.uid());
230     EXPECT_EQ(0U, permissions.gid());
231 }
232 
TEST(device_handler,DevPermissionsMatchPrefix)233 TEST(device_handler, DevPermissionsMatchPrefix) {
234     // Prefix from ueventd.rc
235     // /dev/dri/*                0666   root       graphics
236     Permissions permissions("/dev/dri/*", 0666, 0, 1000, false);
237     EXPECT_TRUE(permissions.Match("/dev/dri/some_dri_device"));
238     EXPECT_TRUE(permissions.Match("/dev/dri/some_other_dri_device"));
239     EXPECT_TRUE(permissions.Match("/dev/dri/"));
240     EXPECT_FALSE(permissions.Match("/dev/dr/non_match"));
241     EXPECT_EQ(0666U, permissions.perm());
242     EXPECT_EQ(0U, permissions.uid());
243     EXPECT_EQ(1000U, permissions.gid());
244 }
245 
TEST(device_handler,DevPermissionsMatchWildcard)246 TEST(device_handler, DevPermissionsMatchWildcard) {
247     // Wildcard example
248     // /dev/device*name                0666   root       graphics
249     Permissions permissions("/dev/device*name", 0666, 0, 1000, false);
250     EXPECT_TRUE(permissions.Match("/dev/devicename"));
251     EXPECT_TRUE(permissions.Match("/dev/device123name"));
252     EXPECT_TRUE(permissions.Match("/dev/deviceabcname"));
253     EXPECT_FALSE(permissions.Match("/dev/device123name/subdevice"));
254     EXPECT_FALSE(permissions.Match("/dev/deviceame"));
255     EXPECT_EQ(0666U, permissions.perm());
256     EXPECT_EQ(0U, permissions.uid());
257     EXPECT_EQ(1000U, permissions.gid());
258 }
259 
TEST(device_handler,DevPermissionsMatchWildcardPrefix)260 TEST(device_handler, DevPermissionsMatchWildcardPrefix) {
261     // Wildcard+Prefix example
262     // /dev/device*name*                0666   root       graphics
263     Permissions permissions("/dev/device*name*", 0666, 0, 1000, false);
264     EXPECT_TRUE(permissions.Match("/dev/devicename"));
265     EXPECT_TRUE(permissions.Match("/dev/device123name"));
266     EXPECT_TRUE(permissions.Match("/dev/deviceabcname"));
267     EXPECT_TRUE(permissions.Match("/dev/device123namesomething"));
268     // FNM_PATHNAME doesn't match '/' with *
269     EXPECT_FALSE(permissions.Match("/dev/device123name/something"));
270     EXPECT_FALSE(permissions.Match("/dev/device/1/2/3name/something"));
271     EXPECT_FALSE(permissions.Match("/dev/deviceame"));
272     EXPECT_EQ(0666U, permissions.perm());
273     EXPECT_EQ(0U, permissions.uid());
274     EXPECT_EQ(1000U, permissions.gid());
275 }
276 
TEST(device_handler,DevPermissionsMatchWildcardPrefix_NoFnmPathName)277 TEST(device_handler, DevPermissionsMatchWildcardPrefix_NoFnmPathName) {
278     // Wildcard+Prefix example with no_fnm_pathname
279     // /dev/device*name*                0666   root       graphics
280     Permissions permissions("/dev/device*name*", 0666, 0, 1000, true);
281     EXPECT_TRUE(permissions.Match("/dev/devicename"));
282     EXPECT_TRUE(permissions.Match("/dev/device123name"));
283     EXPECT_TRUE(permissions.Match("/dev/deviceabcname"));
284     EXPECT_TRUE(permissions.Match("/dev/device123namesomething"));
285     // With NoFnmPathName, the below matches, unlike DevPermissionsMatchWildcardPrefix.
286     EXPECT_TRUE(permissions.Match("/dev/device123name/something"));
287     EXPECT_TRUE(permissions.Match("/dev/device/1/2/3name/something"));
288     EXPECT_FALSE(permissions.Match("/dev/deviceame"));
289     EXPECT_EQ(0666U, permissions.perm());
290     EXPECT_EQ(0U, permissions.uid());
291     EXPECT_EQ(1000U, permissions.gid());
292 }
293 
TEST(device_handler,SysfsPermissionsMatchWithSubsystemNormal)294 TEST(device_handler, SysfsPermissionsMatchWithSubsystemNormal) {
295     // /sys/devices/virtual/input/input*   enable      0660  root   input
296     SysfsPermissions permissions("/sys/devices/virtual/input/input*", "enable", 0660, 0, 1001,
297                                  false);
298     EXPECT_TRUE(permissions.MatchWithSubsystem("/sys/devices/virtual/input/input0", "input"));
299     EXPECT_FALSE(permissions.MatchWithSubsystem("/sys/devices/virtual/input/not_input0", "input"));
300     EXPECT_EQ(0660U, permissions.perm());
301     EXPECT_EQ(0U, permissions.uid());
302     EXPECT_EQ(1001U, permissions.gid());
303 }
304 
TEST(device_handler,SysfsPermissionsMatchWithSubsystemClass)305 TEST(device_handler, SysfsPermissionsMatchWithSubsystemClass) {
306     // /sys/class/input/event*   enable      0660  root   input
307     SysfsPermissions permissions("/sys/class/input/event*", "enable", 0660, 0, 1001, false);
308     EXPECT_TRUE(permissions.MatchWithSubsystem(
309         "/sys/devices/soc.0/f9924000.i2c/i2c-2/2-0020/input/input0/event0", "input"));
310     EXPECT_FALSE(permissions.MatchWithSubsystem(
311         "/sys/devices/soc.0/f9924000.i2c/i2c-2/2-0020/input/input0/not_event0", "input"));
312     EXPECT_FALSE(permissions.MatchWithSubsystem(
313         "/sys/devices/soc.0/f9924000.i2c/i2c-2/2-0020/input/input0/event0", "not_input"));
314     EXPECT_EQ(0660U, permissions.perm());
315     EXPECT_EQ(0U, permissions.uid());
316     EXPECT_EQ(1001U, permissions.gid());
317 }
318 
TEST(device_handler,SysfsPermissionsMatchWithSubsystemBus)319 TEST(device_handler, SysfsPermissionsMatchWithSubsystemBus) {
320     // /sys/bus/i2c/devices/i2c-*   enable      0660  root   input
321     SysfsPermissions permissions("/sys/bus/i2c/devices/i2c-*", "enable", 0660, 0, 1001, false);
322     EXPECT_TRUE(permissions.MatchWithSubsystem("/sys/devices/soc.0/f9967000.i2c/i2c-5", "i2c"));
323     EXPECT_FALSE(permissions.MatchWithSubsystem("/sys/devices/soc.0/f9967000.i2c/not-i2c", "i2c"));
324     EXPECT_FALSE(
325         permissions.MatchWithSubsystem("/sys/devices/soc.0/f9967000.i2c/i2c-5", "not_i2c"));
326     EXPECT_EQ(0660U, permissions.perm());
327     EXPECT_EQ(0U, permissions.uid());
328     EXPECT_EQ(1001U, permissions.gid());
329 }
330 
331 }  // namespace init
332 }  // namespace android
333