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 35 #include "internal.h" 36 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 } 249