/* * Copyright (C) 2019 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include #include #include #include #include #include #include "libmodprobe_test.h" // Used by libmodprobe_ext_test to check if requested modules are present. std::vector test_modules; // Used by libmodprobe_ext_test to report which modules would have been loaded. std::vector modules_loaded; // Used by libmodprobe_ext_test to fake a kernel commandline std::string kernel_cmdline; TEST(libmodprobe, Test) { kernel_cmdline = "flag1 flag2 test1.option1=50 test4.option3=\"set x\" test1.option2=60 " "test8. test5.option1= test10.option1=1"; test_modules = { "/test1.ko", "/test2.ko", "/test3.ko", "/test4.ko", "/test5.ko", "/test6.ko", "/test7.ko", "/test8.ko", "/test9.ko", "/test10.ko", "/test11.ko", "/test12.ko", "/test13.ko", "/test14.ko", "/test15.ko", }; std::vector expected_modules_loaded = { "/test14.ko", "/test15.ko", "/test3.ko", "/test4.ko option3=\"set x\"", "/test1.ko option1=50 option2=60", "/test6.ko", "/test2.ko", "/test5.ko option1=", "/test8.ko", "/test7.ko param1=4", "/test9.ko param_x=1 param_y=2 param_z=3", "/test10.ko option1=1", "/test12.ko", "/test11.ko", "/test13.ko", }; std::vector expected_after_remove = { "/test14.ko", "/test15.ko", "/test1.ko option1=50 option2=60", "/test6.ko", "/test2.ko", "/test5.ko option1=", "/test8.ko", "/test7.ko param1=4", "/test9.ko param_x=1 param_y=2 param_z=3", "/test10.ko option1=1", "/test12.ko", "/test11.ko", "/test13.ko", }; std::vector expected_modules_blocklist_enabled = { "/test1.ko option1=50 option2=60", "/test6.ko", "/test2.ko", "/test5.ko option1=", "/test8.ko", "/test7.ko param1=4", "/test12.ko", "/test11.ko", "/test13.ko", }; const std::string modules_dep = "test1.ko:\n" "test2.ko:\n" "test3.ko:\n" "test4.ko: test3.ko\n" "test5.ko: test2.ko test6.ko\n" "test6.ko:\n" "test7.ko:\n" "test8.ko:\n" "test9.ko:\n" "test10.ko:\n" "test11.ko:\n" "test12.ko:\n" "test13.ko:\n" "test14.ko:\n" "test15.ko:\n"; const std::string modules_softdep = "softdep test7 pre: test8\n" "softdep test9 post: test10\n" "softdep test11 pre: test12 post: test13\n" "softdep test3 pre: test141516\n"; const std::string modules_alias = "# Aliases extracted from modules themselves.\n" "\n" "alias test141516 test14\n" "alias test141516 test15\n" "alias test141516 test16\n"; const std::string modules_options = "options test7.ko param1=4\n" "options test9.ko param_x=1 param_y=2 param_z=3\n" "options test100.ko param_1=1\n"; const std::string modules_blocklist = "blocklist test9.ko\n" "blocklist test3.ko\n"; const std::string modules_load = "test4.ko\n" "test1.ko\n" "test3.ko\n" "test5.ko\n" "test7.ko\n" "test9.ko\n" "test11.ko\n"; TemporaryDir dir; auto dir_path = std::string(dir.path); ASSERT_TRUE(android::base::WriteStringToFile(modules_alias, dir_path + "/modules.alias", 0600, getuid(), getgid())); ASSERT_TRUE(android::base::WriteStringToFile(modules_dep, dir_path + "/modules.dep", 0600, getuid(), getgid())); ASSERT_TRUE(android::base::WriteStringToFile(modules_softdep, dir_path + "/modules.softdep", 0600, getuid(), getgid())); ASSERT_TRUE(android::base::WriteStringToFile(modules_options, dir_path + "/modules.options", 0600, getuid(), getgid())); ASSERT_TRUE(android::base::WriteStringToFile(modules_load, dir_path + "/modules.load", 0600, getuid(), getgid())); ASSERT_TRUE(android::base::WriteStringToFile(modules_blocklist, dir_path + "/modules.blocklist", 0600, getuid(), getgid())); for (auto i = test_modules.begin(); i != test_modules.end(); ++i) { *i = dir.path + *i; } Modprobe m({dir.path}, "modules.load", false); EXPECT_TRUE(m.LoadListedModules()); GTEST_LOG_(INFO) << "Expected modules loaded (in order):"; for (auto i = expected_modules_loaded.begin(); i != expected_modules_loaded.end(); ++i) { *i = dir.path + *i; GTEST_LOG_(INFO) << "\"" << *i << "\""; } GTEST_LOG_(INFO) << "Actual modules loaded (in order):"; for (auto i = modules_loaded.begin(); i != modules_loaded.end(); ++i) { GTEST_LOG_(INFO) << "\"" << *i << "\""; } EXPECT_TRUE(modules_loaded == expected_modules_loaded); EXPECT_TRUE(m.GetModuleCount() == 15); EXPECT_TRUE(m.Remove("test4")); GTEST_LOG_(INFO) << "Expected modules loaded after removing test4 (in order):"; for (auto i = expected_after_remove.begin(); i != expected_after_remove.end(); ++i) { *i = dir.path + *i; GTEST_LOG_(INFO) << "\"" << *i << "\""; } GTEST_LOG_(INFO) << "Actual modules loaded after removing test4 (in order):"; for (auto i = modules_loaded.begin(); i != modules_loaded.end(); ++i) { GTEST_LOG_(INFO) << "\"" << *i << "\""; } EXPECT_TRUE(modules_loaded == expected_after_remove); m = Modprobe({dir.path}); EXPECT_FALSE(m.LoadWithAliases("test4", true)); while (modules_loaded.size() > 0) EXPECT_TRUE(m.Remove(modules_loaded.front())); EXPECT_TRUE(m.LoadListedModules()); GTEST_LOG_(INFO) << "Expected modules loaded after enabling blocklist (in order):"; for (auto i = expected_modules_blocklist_enabled.begin(); i != expected_modules_blocklist_enabled.end(); ++i) { *i = dir.path + *i; GTEST_LOG_(INFO) << "\"" << *i << "\""; } GTEST_LOG_(INFO) << "Actual modules loaded with blocklist enabled (in order):"; for (auto i = modules_loaded.begin(); i != modules_loaded.end(); ++i) { GTEST_LOG_(INFO) << "\"" << *i << "\""; } EXPECT_TRUE(modules_loaded == expected_modules_blocklist_enabled); } TEST(libmodprobe, ModuleDepLineWithoutColonIsSkipped) { TemporaryDir dir; auto dir_path = std::string(dir.path); ASSERT_TRUE(android::base::WriteStringToFile( "no_colon.ko no_colon.ko\n", dir_path + "/modules.dep", 0600, getuid(), getgid())); kernel_cmdline = ""; test_modules = {dir_path + "/no_colon.ko"}; Modprobe m({dir.path}); EXPECT_FALSE(m.LoadWithAliases("no_colon", true)); }