1 /*
2  * Copyright (C) 2019 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 <functional>
18 
19 #include <android-base/file.h>
20 #include <android-base/macros.h>
21 #include <android-base/unique_fd.h>
22 #include <gtest/gtest.h>
23 
24 #include <modprobe/modprobe.h>
25 
26 #include "libmodprobe_test.h"
27 
28 // Used by libmodprobe_ext_test to check if requested modules are present.
29 std::vector<std::string> test_modules;
30 
31 // Used by libmodprobe_ext_test to report which modules would have been loaded.
32 std::vector<std::string> modules_loaded;
33 
34 // Used by libmodprobe_ext_test to fake a kernel commandline
35 std::string kernel_cmdline;
36 
TEST(libmodprobe,Test)37 TEST(libmodprobe, Test) {
38     kernel_cmdline =
39             "flag1 flag2 test1.option1=50 test4.option3=\"set x\" test1.option2=60 "
40             "test8. test5.option1= test10.option1=1";
41     test_modules = {
42             "/test1.ko",  "/test2.ko",  "/test3.ko",  "/test4.ko",  "/test5.ko",
43             "/test6.ko",  "/test7.ko",  "/test8.ko",  "/test9.ko",  "/test10.ko",
44             "/test11.ko", "/test12.ko", "/test13.ko", "/test14.ko", "/test15.ko",
45     };
46 
47     std::vector<std::string> expected_modules_loaded = {
48             "/test14.ko",
49             "/test15.ko",
50             "/test3.ko",
51             "/test4.ko option3=\"set x\"",
52             "/test1.ko option1=50 option2=60",
53             "/test6.ko",
54             "/test2.ko",
55             "/test5.ko option1=",
56             "/test8.ko",
57             "/test7.ko param1=4",
58             "/test9.ko param_x=1 param_y=2 param_z=3",
59             "/test10.ko option1=1",
60             "/test12.ko",
61             "/test11.ko",
62             "/test13.ko",
63     };
64 
65     std::vector<std::string> expected_after_remove = {
66             "/test14.ko",
67             "/test15.ko",
68             "/test1.ko option1=50 option2=60",
69             "/test6.ko",
70             "/test2.ko",
71             "/test5.ko option1=",
72             "/test8.ko",
73             "/test7.ko param1=4",
74             "/test9.ko param_x=1 param_y=2 param_z=3",
75             "/test10.ko option1=1",
76             "/test12.ko",
77             "/test11.ko",
78             "/test13.ko",
79     };
80 
81     const std::string modules_dep =
82             "test1.ko:\n"
83             "test2.ko:\n"
84             "test3.ko:\n"
85             "test4.ko: test3.ko\n"
86             "test5.ko: test2.ko test6.ko\n"
87             "test6.ko:\n"
88             "test7.ko:\n"
89             "test8.ko:\n"
90             "test9.ko:\n"
91             "test10.ko:\n"
92             "test11.ko:\n"
93             "test12.ko:\n"
94             "test13.ko:\n"
95             "test14.ko:\n"
96             "test15.ko:\n";
97 
98     const std::string modules_softdep =
99             "softdep test7 pre: test8\n"
100             "softdep test9 post: test10\n"
101             "softdep test11 pre: test12 post: test13\n"
102             "softdep test3 pre: test141516\n";
103 
104     const std::string modules_alias =
105             "# Aliases extracted from modules themselves.\n"
106             "\n"
107             "alias test141516 test14\n"
108             "alias test141516 test15\n"
109             "alias test141516 test16\n";
110 
111     const std::string modules_options =
112             "options test7.ko param1=4\n"
113             "options test9.ko param_x=1 param_y=2 param_z=3\n"
114             "options test100.ko param_1=1\n";
115 
116     const std::string modules_blocklist =
117             "blocklist test9.ko\n"
118             "blocklist test3.ko\n";
119 
120     const std::string modules_load =
121             "test4.ko\n"
122             "test1.ko\n"
123             "test3.ko\n"
124             "test5.ko\n"
125             "test7.ko\n"
126             "test9.ko\n"
127             "test11.ko\n";
128 
129     TemporaryDir dir;
130     auto dir_path = std::string(dir.path);
131     ASSERT_TRUE(android::base::WriteStringToFile(modules_alias, dir_path + "/modules.alias", 0600,
132                                                  getuid(), getgid()));
133 
134     ASSERT_TRUE(android::base::WriteStringToFile(modules_dep, dir_path + "/modules.dep", 0600,
135                                                  getuid(), getgid()));
136     ASSERT_TRUE(android::base::WriteStringToFile(modules_softdep, dir_path + "/modules.softdep",
137                                                  0600, getuid(), getgid()));
138     ASSERT_TRUE(android::base::WriteStringToFile(modules_options, dir_path + "/modules.options",
139                                                  0600, getuid(), getgid()));
140     ASSERT_TRUE(android::base::WriteStringToFile(modules_load, dir_path + "/modules.load", 0600,
141                                                  getuid(), getgid()));
142     ASSERT_TRUE(android::base::WriteStringToFile(modules_blocklist, dir_path + "/modules.blocklist",
143                                                  0600, getuid(), getgid()));
144 
145     for (auto i = test_modules.begin(); i != test_modules.end(); ++i) {
146         *i = dir.path + *i;
147     }
148 
149     Modprobe m({dir.path});
150     EXPECT_TRUE(m.LoadListedModules());
151 
152     GTEST_LOG_(INFO) << "Expected modules loaded (in order):";
153     for (auto i = expected_modules_loaded.begin(); i != expected_modules_loaded.end(); ++i) {
154         *i = dir.path + *i;
155         GTEST_LOG_(INFO) << "\"" << *i << "\"";
156     }
157     GTEST_LOG_(INFO) << "Actual modules loaded (in order):";
158     for (auto i = modules_loaded.begin(); i != modules_loaded.end(); ++i) {
159         GTEST_LOG_(INFO) << "\"" << *i << "\"";
160     }
161 
162     EXPECT_TRUE(modules_loaded == expected_modules_loaded);
163 
164     EXPECT_TRUE(m.GetModuleCount() == 15);
165     EXPECT_TRUE(m.Remove("test4"));
166 
167     GTEST_LOG_(INFO) << "Expected modules loaded after removing test4 (in order):";
168     for (auto i = expected_after_remove.begin(); i != expected_after_remove.end(); ++i) {
169         *i = dir.path + *i;
170         GTEST_LOG_(INFO) << "\"" << *i << "\"";
171     }
172     GTEST_LOG_(INFO) << "Actual modules loaded after removing test4 (in order):";
173     for (auto i = modules_loaded.begin(); i != modules_loaded.end(); ++i) {
174         GTEST_LOG_(INFO) << "\"" << *i << "\"";
175     }
176 
177     EXPECT_TRUE(modules_loaded == expected_after_remove);
178 
179     m.EnableBlocklist(true);
180     EXPECT_FALSE(m.LoadWithAliases("test4", true));
181 }
182