Home | History | Annotate | Download | only in init
      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/scopeguard.h>
     20 #include <android-base/test_utils.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:
     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 
     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 
     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 
     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 
    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 
    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 
    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 
    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 
    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 
    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 
    182 TEST(device_handler, sanitize_null) {
    183     SanitizePartitionName(nullptr);
    184 }
    185 
    186 TEST(device_handler, sanitize_empty) {
    187     std::string empty;
    188     SanitizePartitionName(&empty);
    189     EXPECT_EQ(0u, empty.size());
    190 }
    191 
    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 
    203 TEST(device_handler, sanitize_somebad) {
    204     std::string string = "abc!@#$%^&*()";
    205     SanitizePartitionName(&string);
    206     EXPECT_EQ("abc__________", string);
    207 }
    208 
    209 TEST(device_handler, sanitize_allbad) {
    210     std::string string = "!@#$%^&*()";
    211     SanitizePartitionName(&string);
    212     EXPECT_EQ("__________", string);
    213 }
    214 
    215 TEST(device_handler, sanitize_onebad) {
    216     std::string string = ")";
    217     SanitizePartitionName(&string);
    218     EXPECT_EQ("_", string);
    219 }
    220 
    221 TEST(device_handler, DevPermissionsMatchNormal) {
    222     // Basic from ueventd.rc
    223     // /dev/null                 0666   root       root
    224     Permissions permissions("/dev/null", 0666, 0, 0);
    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 
    233 TEST(device_handler, DevPermissionsMatchPrefix) {
    234     // Prefix from ueventd.rc
    235     // /dev/dri/*                0666   root       graphics
    236     Permissions permissions("/dev/dri/*", 0666, 0, 1000);
    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 
    246 TEST(device_handler, DevPermissionsMatchWildcard) {
    247     // Wildcard example
    248     // /dev/device*name                0666   root       graphics
    249     Permissions permissions("/dev/device*name", 0666, 0, 1000);
    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 
    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);
    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/deviceame"));
    271     EXPECT_EQ(0666U, permissions.perm());
    272     EXPECT_EQ(0U, permissions.uid());
    273     EXPECT_EQ(1000U, permissions.gid());
    274 }
    275 
    276 TEST(device_handler, SysfsPermissionsMatchWithSubsystemNormal) {
    277     // /sys/devices/virtual/input/input*   enable      0660  root   input
    278     SysfsPermissions permissions("/sys/devices/virtual/input/input*", "enable", 0660, 0, 1001);
    279     EXPECT_TRUE(permissions.MatchWithSubsystem("/sys/devices/virtual/input/input0", "input"));
    280     EXPECT_FALSE(permissions.MatchWithSubsystem("/sys/devices/virtual/input/not_input0", "input"));
    281     EXPECT_EQ(0660U, permissions.perm());
    282     EXPECT_EQ(0U, permissions.uid());
    283     EXPECT_EQ(1001U, permissions.gid());
    284 }
    285 
    286 TEST(device_handler, SysfsPermissionsMatchWithSubsystemClass) {
    287     // /sys/class/input/event*   enable      0660  root   input
    288     SysfsPermissions permissions("/sys/class/input/event*", "enable", 0660, 0, 1001);
    289     EXPECT_TRUE(permissions.MatchWithSubsystem(
    290         "/sys/devices/soc.0/f9924000.i2c/i2c-2/2-0020/input/input0/event0", "input"));
    291     EXPECT_FALSE(permissions.MatchWithSubsystem(
    292         "/sys/devices/soc.0/f9924000.i2c/i2c-2/2-0020/input/input0/not_event0", "input"));
    293     EXPECT_FALSE(permissions.MatchWithSubsystem(
    294         "/sys/devices/soc.0/f9924000.i2c/i2c-2/2-0020/input/input0/event0", "not_input"));
    295     EXPECT_EQ(0660U, permissions.perm());
    296     EXPECT_EQ(0U, permissions.uid());
    297     EXPECT_EQ(1001U, permissions.gid());
    298 }
    299 
    300 TEST(device_handler, SysfsPermissionsMatchWithSubsystemBus) {
    301     // /sys/bus/i2c/devices/i2c-*   enable      0660  root   input
    302     SysfsPermissions permissions("/sys/bus/i2c/devices/i2c-*", "enable", 0660, 0, 1001);
    303     EXPECT_TRUE(permissions.MatchWithSubsystem("/sys/devices/soc.0/f9967000.i2c/i2c-5", "i2c"));
    304     EXPECT_FALSE(permissions.MatchWithSubsystem("/sys/devices/soc.0/f9967000.i2c/not-i2c", "i2c"));
    305     EXPECT_FALSE(
    306         permissions.MatchWithSubsystem("/sys/devices/soc.0/f9967000.i2c/i2c-5", "not_i2c"));
    307     EXPECT_EQ(0660U, permissions.perm());
    308     EXPECT_EQ(0U, permissions.uid());
    309     EXPECT_EQ(1001U, permissions.gid());
    310 }
    311 
    312 }  // namespace init
    313 }  // namespace android
    314