Skip freeing module's data section if there are non-zero allocation tags because otherwise, once these allocations are freed, the access to their code tag would cause UAF.
Showing the changes to kernel/module (1 of 3 files). Show all
Unified · Split
| @@ -1211,15 +1211,19 @@ static void *module_memory_alloc(unsigned int size, enum mod_mem_type type) · 1210 unmodified lines | ||
| 1211 | 1211 | return module_alloc(size); |
| 1212 | 1212 | } |
| 1213 | 1213 | |
| 1214 | −static void module_memory_free(void *ptr, enum mod_mem_type type) | |
| 1214 | +static void module_memory_free(void *ptr, enum mod_mem_type type, | |
| 1215 | + bool unload_codetags) | |
| 1215 | 1216 | { |
| 1217 | + if (!unload_codetags && mod_mem_type_is_core_data(type)) | |
| 1218 | + return; | |
| 1219 | + | |
| 1216 | 1220 | if (mod_mem_use_vmalloc(type)) |
| 1217 | 1221 | vfree(ptr); |
| 1218 | 1222 | else |
| 1219 | 1223 | module_memfree(ptr); |
| 1220 | 1224 | } |
| 1221 | 1225 | |
| 1222 | −static void free_mod_mem(struct module *mod) | |
| 1226 | +static void free_mod_mem(struct module *mod, bool unload_codetags) | |
| 1223 | 1227 | { |
| 1224 | 1228 | for_each_mod_mem_type(type) { |
| 1225 | 1229 | struct module_memory *mod_mem = &mod->mem[type]; |
| @@ -1230,20 +1234,27 @@ static void free_mod_mem(struct module *mod) · 4 unmodified lines | ||
| 1230 | 1234 | /* Free lock-classes; relies on the preceding sync_rcu(). */ |
| 1231 | 1235 | lockdep_free_key_range(mod_mem->base, mod_mem->size); |
| 1232 | 1236 | if (mod_mem->size) |
| 1233 | − module_memory_free(mod_mem->base, type); | |
| 1237 | + module_memory_free(mod_mem->base, type, | |
| 1238 | + unload_codetags); | |
| 1234 | 1239 | } |
| 1235 | 1240 | |
| 1236 | 1241 | /* MOD_DATA hosts mod, so free it at last */ |
| 1237 | 1242 | lockdep_free_key_range(mod->mem[MOD_DATA].base, mod->mem[MOD_DATA].size); |
| 1238 | − module_memory_free(mod->mem[MOD_DATA].base, MOD_DATA); | |
| 1243 | + module_memory_free(mod->mem[MOD_DATA].base, MOD_DATA, unload_codetags); | |
| 1239 | 1244 | } |
| 1240 | 1245 | |
| 1241 | 1246 | /* Free a module, remove from lists, etc. */ |
| 1242 | 1247 | static void free_module(struct module *mod) |
| 1243 | 1248 | { |
| 1249 | + bool unload_codetags; | |
| 1250 | + | |
| 1244 | 1251 | trace_module_free(mod); |
| 1245 | 1252 | |
| 1246 | − codetag_unload_module(mod); | |
| 1253 | + unload_codetags = codetag_unload_module(mod); | |
| 1254 | + if (!unload_codetags) | |
| 1255 | + pr_warn("%s: memory allocation(s) from the module still alive, cannot unload cleanly\n", | |
| 1256 | + mod->name); | |
| 1257 | + | |
| 1247 | 1258 | mod_sysfs_teardown(mod); |
| 1248 | 1259 | |
| 1249 | 1260 | /* |
| @@ -1285,7 +1296,7 @@ static void free_module(struct module *mod) · 35 unmodified lines | ||
| 1285 | 1296 | kfree(mod->args); |
| 1286 | 1297 | percpu_modfree(mod); |
| 1287 | 1298 | |
| 1288 | − free_mod_mem(mod); | |
| 1299 | + free_mod_mem(mod, unload_codetags); | |
| 1289 | 1300 | } |
| 1290 | 1301 | |
| 1291 | 1302 | void *__symbol_get(const char *symbol) |
| @@ -2298,7 +2309,7 @@ static int move_module(struct module *mod, struct load_info *info) · 1006 unmodified lines | ||
| 2298 | 2309 | return 0; |
| 2299 | 2310 | out_enomem: |
| 2300 | 2311 | for (t--; t >= 0; t--) |
| 2301 | − module_memory_free(mod->mem[t].base, t); | |
| 2312 | + module_memory_free(mod->mem[t].base, t, true); | |
| 2302 | 2313 | return ret; |
| 2303 | 2314 | } |
| 2304 | 2315 | |
| @@ -2428,7 +2439,7 @@ static void module_deallocate(struct module *mod, struct load_info *info) · 123 unmodified lines | ||
| 2428 | 2439 | percpu_modfree(mod); |
| 2429 | 2440 | module_arch_freeing_init(mod); |
| 2430 | 2441 | |
| 2431 | − free_mod_mem(mod); | |
| 2442 | + free_mod_mem(mod, true); | |
| 2432 | 2443 | } |
| 2433 | 2444 | |
| 2434 | 2445 | int __weak module_finalize(const Elf_Ehdr *hdr, |