Commit | Line | Data |
---|---|---|
8660484e LC |
1 | /* SPDX-License-Identifier: GPL-2.0-or-later */ |
2 | /* | |
3 | * kmod dups - the kernel module autoloader duplicate suppressor | |
4 | * | |
5 | * Copyright (C) 2023 Luis Chamberlain <mcgrof@kernel.org> | |
6 | */ | |
7 | ||
8 | #define pr_fmt(fmt) "module: " fmt | |
9 | ||
10 | #include <linux/module.h> | |
11 | #include <linux/sched.h> | |
12 | #include <linux/sched/task.h> | |
13 | #include <linux/binfmts.h> | |
14 | #include <linux/syscalls.h> | |
15 | #include <linux/unistd.h> | |
16 | #include <linux/kmod.h> | |
17 | #include <linux/slab.h> | |
18 | #include <linux/completion.h> | |
19 | #include <linux/cred.h> | |
20 | #include <linux/file.h> | |
21 | #include <linux/fdtable.h> | |
22 | #include <linux/workqueue.h> | |
23 | #include <linux/security.h> | |
24 | #include <linux/mount.h> | |
25 | #include <linux/kernel.h> | |
26 | #include <linux/init.h> | |
27 | #include <linux/resource.h> | |
28 | #include <linux/notifier.h> | |
29 | #include <linux/suspend.h> | |
30 | #include <linux/rwsem.h> | |
31 | #include <linux/ptrace.h> | |
32 | #include <linux/async.h> | |
33 | #include <linux/uaccess.h> | |
34 | ||
0b891c83 AB |
35 | #include "internal.h" |
36 | ||
8660484e LC |
37 | #undef MODULE_PARAM_PREFIX |
38 | #define MODULE_PARAM_PREFIX "module." | |
39 | static bool enable_dups_trace = IS_ENABLED(CONFIG_MODULE_DEBUG_AUTOLOAD_DUPS_TRACE); | |
40 | module_param(enable_dups_trace, bool_enable_only, 0644); | |
41 | ||
42 | /* | |
43 | * Protects dup_kmod_reqs list, adds / removals with RCU. | |
44 | */ | |
45 | static DEFINE_MUTEX(kmod_dup_mutex); | |
46 | static LIST_HEAD(dup_kmod_reqs); | |
47 | ||
48 | struct kmod_dup_req { | |
49 | struct list_head list; | |
50 | char name[MODULE_NAME_LEN]; | |
51 | struct completion first_req_done; | |
52 | struct work_struct complete_work; | |
53 | struct delayed_work delete_work; | |
54 | int dup_ret; | |
55 | }; | |
56 | ||
57 | static struct kmod_dup_req *kmod_dup_request_lookup(char *module_name) | |
58 | { | |
59 | struct kmod_dup_req *kmod_req; | |
60 | ||
61 | list_for_each_entry_rcu(kmod_req, &dup_kmod_reqs, list, | |
62 | lockdep_is_held(&kmod_dup_mutex)) { | |
63 | if (strlen(kmod_req->name) == strlen(module_name) && | |
64 | !memcmp(kmod_req->name, module_name, strlen(module_name))) { | |
65 | return kmod_req; | |
66 | } | |
67 | } | |
68 | ||
69 | return NULL; | |
70 | } | |
71 | ||
72 | static void kmod_dup_request_delete(struct work_struct *work) | |
73 | { | |
74 | struct kmod_dup_req *kmod_req; | |
75 | kmod_req = container_of(to_delayed_work(work), struct kmod_dup_req, delete_work); | |
76 | ||
77 | /* | |
78 | * The typical situation is a module successully loaded. In that | |
79 | * situation the module will be present already in userspace. If | |
80 | * new requests come in after that, userspace will already know the | |
81 | * module is loaded so will just return 0 right away. There is still | |
82 | * a small chance right after we delete this entry new request_module() | |
83 | * calls may happen after that, they can happen. These heuristics | |
84 | * are to protect finit_module() abuse for auto-loading, if modules | |
85 | * are still tryign to auto-load even if a module is already loaded, | |
86 | * that's on them, and those inneficiencies should not be fixed by | |
87 | * kmod. The inneficies there are a call to modprobe and modprobe | |
88 | * just returning 0. | |
89 | */ | |
90 | mutex_lock(&kmod_dup_mutex); | |
91 | list_del_rcu(&kmod_req->list); | |
92 | synchronize_rcu(); | |
93 | mutex_unlock(&kmod_dup_mutex); | |
94 | kfree(kmod_req); | |
95 | } | |
96 | ||
97 | static void kmod_dup_request_complete(struct work_struct *work) | |
98 | { | |
99 | struct kmod_dup_req *kmod_req; | |
100 | ||
101 | kmod_req = container_of(work, struct kmod_dup_req, complete_work); | |
102 | ||
103 | /* | |
104 | * This will ensure that the kernel will let all the waiters get | |
105 | * informed its time to check the return value. It's time to | |
106 | * go home. | |
107 | */ | |
108 | complete_all(&kmod_req->first_req_done); | |
109 | ||
110 | /* | |
111 | * Now that we have allowed prior request_module() calls to go on | |
112 | * with life, let's schedule deleting this entry. We don't have | |
113 | * to do it right away, but we *eventually* want to do it so to not | |
114 | * let this linger forever as this is just a boot optimization for | |
115 | * possible abuses of vmalloc() incurred by finit_module() thrashing. | |
116 | */ | |
117 | queue_delayed_work(system_wq, &kmod_req->delete_work, 60 * HZ); | |
118 | } | |
119 | ||
120 | bool kmod_dup_request_exists_wait(char *module_name, bool wait, int *dup_ret) | |
121 | { | |
122 | struct kmod_dup_req *kmod_req, *new_kmod_req; | |
123 | int ret; | |
124 | ||
125 | /* | |
126 | * Pre-allocate the entry in case we have to use it later | |
127 | * to avoid contention with the mutex. | |
128 | */ | |
129 | new_kmod_req = kzalloc(sizeof(*new_kmod_req), GFP_KERNEL); | |
130 | if (!new_kmod_req) | |
131 | return false; | |
132 | ||
133 | memcpy(new_kmod_req->name, module_name, strlen(module_name)); | |
134 | INIT_WORK(&new_kmod_req->complete_work, kmod_dup_request_complete); | |
135 | INIT_DELAYED_WORK(&new_kmod_req->delete_work, kmod_dup_request_delete); | |
136 | init_completion(&new_kmod_req->first_req_done); | |
137 | ||
138 | mutex_lock(&kmod_dup_mutex); | |
139 | ||
140 | kmod_req = kmod_dup_request_lookup(module_name); | |
141 | if (!kmod_req) { | |
142 | /* | |
143 | * If the first request that came through for a module | |
144 | * was with request_module_nowait() we cannot wait for it | |
145 | * and share its return value with other users which may | |
146 | * have used request_module() and need a proper return value | |
147 | * so just skip using them as an anchor. | |
148 | * | |
149 | * If a prior request to this one came through with | |
150 | * request_module() though, then a request_module_nowait() | |
151 | * would benefit from duplicate detection. | |
152 | */ | |
153 | if (!wait) { | |
154 | kfree(new_kmod_req); | |
155 | pr_debug("New request_module_nowait() for %s -- cannot track duplicates for this request\n", module_name); | |
156 | mutex_unlock(&kmod_dup_mutex); | |
157 | return false; | |
158 | } | |
159 | ||
160 | /* | |
161 | * There was no duplicate, just add the request so we can | |
162 | * keep tab on duplicates later. | |
163 | */ | |
164 | pr_debug("New request_module() for %s\n", module_name); | |
165 | list_add_rcu(&new_kmod_req->list, &dup_kmod_reqs); | |
166 | mutex_unlock(&kmod_dup_mutex); | |
167 | return false; | |
168 | } | |
169 | mutex_unlock(&kmod_dup_mutex); | |
170 | ||
171 | /* We are dealing with a duplicate request now */ | |
172 | kfree(new_kmod_req); | |
173 | ||
174 | /* | |
175 | * To fix these try to use try_then_request_module() instead as that | |
176 | * will check if the component you are looking for is present or not. | |
177 | * You could also just queue a single request to load the module once, | |
178 | * instead of having each and everything you need try to request for | |
179 | * the module. | |
180 | * | |
181 | * Duplicate request_module() calls can cause quite a bit of wasted | |
182 | * vmalloc() space when racing with userspace. | |
183 | */ | |
184 | if (enable_dups_trace) | |
185 | WARN(1, "module-autoload: duplicate request for module %s\n", module_name); | |
186 | else | |
187 | pr_warn("module-autoload: duplicate request for module %s\n", module_name); | |
188 | ||
189 | if (!wait) { | |
190 | /* | |
191 | * If request_module_nowait() was used then the user just | |
192 | * wanted to issue the request and if another module request | |
193 | * was already its way with the same name we don't care for | |
194 | * the return value either. Let duplicate request_module_nowait() | |
195 | * calls bail out right away. | |
196 | */ | |
197 | *dup_ret = 0; | |
198 | return true; | |
199 | } | |
200 | ||
201 | /* | |
202 | * If a duplicate request_module() was used they *may* care for | |
203 | * the return value, so we have no other option but to wait for | |
204 | * the first caller to complete. If the first caller used | |
205 | * the request_module_nowait() call, subsquent callers will | |
206 | * deal with the comprmise of getting a successful call with this | |
207 | * optimization enabled ... | |
208 | */ | |
209 | ret = wait_for_completion_state(&kmod_req->first_req_done, | |
210 | TASK_UNINTERRUPTIBLE | TASK_KILLABLE); | |
211 | if (ret) { | |
212 | *dup_ret = ret; | |
213 | return true; | |
214 | } | |
215 | ||
216 | /* Now the duplicate request has the same exact return value as the first request */ | |
217 | *dup_ret = kmod_req->dup_ret; | |
218 | ||
219 | return true; | |
220 | } | |
221 | ||
222 | void kmod_dup_request_announce(char *module_name, int ret) | |
223 | { | |
224 | struct kmod_dup_req *kmod_req; | |
225 | ||
226 | mutex_lock(&kmod_dup_mutex); | |
227 | ||
228 | kmod_req = kmod_dup_request_lookup(module_name); | |
229 | if (!kmod_req) | |
230 | goto out; | |
231 | ||
232 | kmod_req->dup_ret = ret; | |
233 | ||
234 | /* | |
235 | * If we complete() here we may allow duplicate threads | |
236 | * to continue before the first one that submitted the | |
237 | * request. We're in no rush also, given that each and | |
238 | * every bounce back to userspace is slow we avoid that | |
239 | * with a slight delay here. So queueue up the completion | |
240 | * and let duplicates suffer, just wait a tad bit longer. | |
241 | * There is no rush. But we also don't want to hold the | |
242 | * caller up forever or introduce any boot delays. | |
243 | */ | |
244 | queue_work(system_wq, &kmod_req->complete_work); | |
245 | ||
246 | out: | |
247 | mutex_unlock(&kmod_dup_mutex); | |
248 | } |