1 // SPDX-License-Identifier: GPL-2.0-or-later 2 /* 3 * Module sysfs support 4 * 5 * Copyright (C) 2008 Rusty Russell 6 */ 7 8 #include <linux/module.h> 9 #include <linux/kernel.h> 10 #include <linux/fs.h> 11 #include <linux/sysfs.h> 12 #include <linux/slab.h> 13 #include <linux/kallsyms.h> 14 #include <linux/mutex.h> 15 #include "internal.h" 16 17 /* 18 * /sys/module/foo/sections stuff 19 * J. Corbet <[email protected]> 20 */ 21 #ifdef CONFIG_KALLSYMS 22 struct module_sect_attr { 23 struct bin_attribute battr; 24 unsigned long address; 25 }; 26 27 struct module_sect_attrs { 28 struct attribute_group grp; 29 struct module_sect_attr attrs[]; 30 }; 31 32 #define MODULE_SECT_READ_SIZE (3 /* "0x", "\n" */ + (BITS_PER_LONG / 4)) 33 static ssize_t module_sect_read(struct file *file, struct kobject *kobj, 34 struct bin_attribute *battr, 35 char *buf, loff_t pos, size_t count) 36 { 37 struct module_sect_attr *sattr = 38 container_of(battr, struct module_sect_attr, battr); 39 char bounce[MODULE_SECT_READ_SIZE + 1]; 40 size_t wrote; 41 42 if (pos != 0) 43 return -EINVAL; 44 45 /* 46 * Since we're a binary read handler, we must account for the 47 * trailing NUL byte that sprintf will write: if "buf" is 48 * too small to hold the NUL, or the NUL is exactly the last 49 * byte, the read will look like it got truncated by one byte. 50 * Since there is no way to ask sprintf nicely to not write 51 * the NUL, we have to use a bounce buffer. 52 */ 53 wrote = scnprintf(bounce, sizeof(bounce), "0x%px\n", 54 kallsyms_show_value(file->f_cred) 55 ? (void *)sattr->address : NULL); 56 count = min(count, wrote); 57 memcpy(buf, bounce, count); 58 59 return count; 60 } 61 62 static void free_sect_attrs(struct module_sect_attrs *sect_attrs) 63 { 64 struct bin_attribute **bin_attr; 65 66 for (bin_attr = sect_attrs->grp.bin_attrs; *bin_attr; bin_attr++) 67 kfree((*bin_attr)->attr.name); 68 kfree(sect_attrs); 69 } 70 71 static int add_sect_attrs(struct module *mod, const struct load_info *info) 72 { 73 unsigned int nloaded = 0, i, size[2]; 74 struct module_sect_attrs *sect_attrs; 75 struct module_sect_attr *sattr; 76 struct bin_attribute **gattr; 77 int ret; 78 79 /* Count loaded sections and allocate structures */ 80 for (i = 0; i < info->hdr->e_shnum; i++) 81 if (!sect_empty(&info->sechdrs[i])) 82 nloaded++; 83 size[0] = ALIGN(struct_size(sect_attrs, attrs, nloaded), 84 sizeof(sect_attrs->grp.bin_attrs[0])); 85 size[1] = (nloaded + 1) * sizeof(sect_attrs->grp.bin_attrs[0]); 86 sect_attrs = kzalloc(size[0] + size[1], GFP_KERNEL); 87 if (!sect_attrs) 88 return -ENOMEM; 89 90 /* Setup section attributes. */ 91 sect_attrs->grp.name = "sections"; 92 sect_attrs->grp.bin_attrs = (void *)sect_attrs + size[0]; 93 94 sattr = §_attrs->attrs[0]; 95 gattr = §_attrs->grp.bin_attrs[0]; 96 for (i = 0; i < info->hdr->e_shnum; i++) { 97 Elf_Shdr *sec = &info->sechdrs[i]; 98 99 if (sect_empty(sec)) 100 continue; 101 sysfs_bin_attr_init(&sattr->battr); 102 sattr->address = sec->sh_addr; 103 sattr->battr.attr.name = 104 kstrdup(info->secstrings + sec->sh_name, GFP_KERNEL); 105 if (!sattr->battr.attr.name) { 106 ret = -ENOMEM; 107 goto out; 108 } 109 sattr->battr.read = module_sect_read; 110 sattr->battr.size = MODULE_SECT_READ_SIZE; 111 sattr->battr.attr.mode = 0400; 112 *(gattr++) = &(sattr++)->battr; 113 } 114 *gattr = NULL; 115 116 ret = sysfs_create_group(&mod->mkobj.kobj, §_attrs->grp); 117 if (ret) 118 goto out; 119 120 mod->sect_attrs = sect_attrs; 121 return 0; 122 out: 123 free_sect_attrs(sect_attrs); 124 return ret; 125 } 126 127 static void remove_sect_attrs(struct module *mod) 128 { 129 if (mod->sect_attrs) { 130 sysfs_remove_group(&mod->mkobj.kobj, 131 &mod->sect_attrs->grp); 132 /* 133 * We are positive that no one is using any sect attrs 134 * at this point. Deallocate immediately. 135 */ 136 free_sect_attrs(mod->sect_attrs); 137 mod->sect_attrs = NULL; 138 } 139 } 140 141 /* 142 * /sys/module/foo/notes/.section.name gives contents of SHT_NOTE sections. 143 */ 144 145 struct module_notes_attrs { 146 struct kobject *dir; 147 unsigned int notes; 148 struct bin_attribute attrs[] __counted_by(notes); 149 }; 150 151 static void free_notes_attrs(struct module_notes_attrs *notes_attrs, 152 unsigned int i) 153 { 154 if (notes_attrs->dir) { 155 while (i-- > 0) 156 sysfs_remove_bin_file(notes_attrs->dir, 157 ¬es_attrs->attrs[i]); 158 kobject_put(notes_attrs->dir); 159 } 160 kfree(notes_attrs); 161 } 162 163 static int add_notes_attrs(struct module *mod, const struct load_info *info) 164 { 165 unsigned int notes, loaded, i; 166 struct module_notes_attrs *notes_attrs; 167 struct bin_attribute *nattr; 168 int ret; 169 170 /* Count notes sections and allocate structures. */ 171 notes = 0; 172 for (i = 0; i < info->hdr->e_shnum; i++) 173 if (!sect_empty(&info->sechdrs[i]) && 174 info->sechdrs[i].sh_type == SHT_NOTE) 175 ++notes; 176 177 if (notes == 0) 178 return 0; 179 180 notes_attrs = kzalloc(struct_size(notes_attrs, attrs, notes), 181 GFP_KERNEL); 182 if (!notes_attrs) 183 return -ENOMEM; 184 185 notes_attrs->notes = notes; 186 nattr = ¬es_attrs->attrs[0]; 187 for (loaded = i = 0; i < info->hdr->e_shnum; ++i) { 188 if (sect_empty(&info->sechdrs[i])) 189 continue; 190 if (info->sechdrs[i].sh_type == SHT_NOTE) { 191 sysfs_bin_attr_init(nattr); 192 nattr->attr.name = mod->sect_attrs->attrs[loaded].battr.attr.name; 193 nattr->attr.mode = 0444; 194 nattr->size = info->sechdrs[i].sh_size; 195 nattr->private = (void *)info->sechdrs[i].sh_addr; 196 nattr->read = sysfs_bin_attr_simple_read; 197 ++nattr; 198 } 199 ++loaded; 200 } 201 202 notes_attrs->dir = kobject_create_and_add("notes", &mod->mkobj.kobj); 203 if (!notes_attrs->dir) { 204 ret = -ENOMEM; 205 goto out; 206 } 207 208 for (i = 0; i < notes; ++i) { 209 ret = sysfs_create_bin_file(notes_attrs->dir, ¬es_attrs->attrs[i]); 210 if (ret) 211 goto out; 212 } 213 214 mod->notes_attrs = notes_attrs; 215 return 0; 216 217 out: 218 free_notes_attrs(notes_attrs, i); 219 return ret; 220 } 221 222 static void remove_notes_attrs(struct module *mod) 223 { 224 if (mod->notes_attrs) 225 free_notes_attrs(mod->notes_attrs, mod->notes_attrs->notes); 226 } 227 228 #else /* !CONFIG_KALLSYMS */ 229 static inline int add_sect_attrs(struct module *mod, const struct load_info *info) 230 { 231 return 0; 232 } 233 static inline void remove_sect_attrs(struct module *mod) { } 234 static inline int add_notes_attrs(struct module *mod, const struct load_info *info) 235 { 236 return 0; 237 } 238 static inline void remove_notes_attrs(struct module *mod) { } 239 #endif /* CONFIG_KALLSYMS */ 240 241 static void del_usage_links(struct module *mod) 242 { 243 #ifdef CONFIG_MODULE_UNLOAD 244 struct module_use *use; 245 246 mutex_lock(&module_mutex); 247 list_for_each_entry(use, &mod->target_list, target_list) 248 sysfs_remove_link(use->target->holders_dir, mod->name); 249 mutex_unlock(&module_mutex); 250 #endif 251 } 252 253 static int add_usage_links(struct module *mod) 254 { 255 int ret = 0; 256 #ifdef CONFIG_MODULE_UNLOAD 257 struct module_use *use; 258 259 mutex_lock(&module_mutex); 260 list_for_each_entry(use, &mod->target_list, target_list) { 261 ret = sysfs_create_link(use->target->holders_dir, 262 &mod->mkobj.kobj, mod->name); 263 if (ret) 264 break; 265 } 266 mutex_unlock(&module_mutex); 267 if (ret) 268 del_usage_links(mod); 269 #endif 270 return ret; 271 } 272 273 static void module_remove_modinfo_attrs(struct module *mod, int end) 274 { 275 const struct module_attribute *attr; 276 int i; 277 278 for (i = 0; (attr = &mod->modinfo_attrs[i]); i++) { 279 if (end >= 0 && i > end) 280 break; 281 /* pick a field to test for end of list */ 282 if (!attr->attr.name) 283 break; 284 sysfs_remove_file(&mod->mkobj.kobj, &attr->attr); 285 if (attr->free) 286 attr->free(mod); 287 } 288 kfree(mod->modinfo_attrs); 289 } 290 291 static int module_add_modinfo_attrs(struct module *mod) 292 { 293 const struct module_attribute *attr; 294 struct module_attribute *temp_attr; 295 int error = 0; 296 int i; 297 298 mod->modinfo_attrs = kzalloc((sizeof(struct module_attribute) * 299 (modinfo_attrs_count + 1)), 300 GFP_KERNEL); 301 if (!mod->modinfo_attrs) 302 return -ENOMEM; 303 304 temp_attr = mod->modinfo_attrs; 305 for (i = 0; (attr = modinfo_attrs[i]); i++) { 306 if (!attr->test || attr->test(mod)) { 307 memcpy(temp_attr, attr, sizeof(*temp_attr)); 308 sysfs_attr_init(&temp_attr->attr); 309 error = sysfs_create_file(&mod->mkobj.kobj, 310 &temp_attr->attr); 311 if (error) 312 goto error_out; 313 ++temp_attr; 314 } 315 } 316 317 return 0; 318 319 error_out: 320 if (i > 0) 321 module_remove_modinfo_attrs(mod, --i); 322 else 323 kfree(mod->modinfo_attrs); 324 return error; 325 } 326 327 static void mod_kobject_put(struct module *mod) 328 { 329 DECLARE_COMPLETION_ONSTACK(c); 330 331 mod->mkobj.kobj_completion = &c; 332 kobject_put(&mod->mkobj.kobj); 333 wait_for_completion(&c); 334 } 335 336 static int mod_sysfs_init(struct module *mod) 337 { 338 int err; 339 struct kobject *kobj; 340 341 if (!module_kset) { 342 pr_err("%s: module sysfs not initialized\n", mod->name); 343 err = -EINVAL; 344 goto out; 345 } 346 347 kobj = kset_find_obj(module_kset, mod->name); 348 if (kobj) { 349 pr_err("%s: module is already loaded\n", mod->name); 350 kobject_put(kobj); 351 err = -EINVAL; 352 goto out; 353 } 354 355 mod->mkobj.mod = mod; 356 357 memset(&mod->mkobj.kobj, 0, sizeof(mod->mkobj.kobj)); 358 mod->mkobj.kobj.kset = module_kset; 359 err = kobject_init_and_add(&mod->mkobj.kobj, &module_ktype, NULL, 360 "%s", mod->name); 361 if (err) 362 mod_kobject_put(mod); 363 364 out: 365 return err; 366 } 367 368 int mod_sysfs_setup(struct module *mod, 369 const struct load_info *info, 370 struct kernel_param *kparam, 371 unsigned int num_params) 372 { 373 int err; 374 375 err = mod_sysfs_init(mod); 376 if (err) 377 goto out; 378 379 mod->holders_dir = kobject_create_and_add("holders", &mod->mkobj.kobj); 380 if (!mod->holders_dir) { 381 err = -ENOMEM; 382 goto out_unreg; 383 } 384 385 err = module_param_sysfs_setup(mod, kparam, num_params); 386 if (err) 387 goto out_unreg_holders; 388 389 err = module_add_modinfo_attrs(mod); 390 if (err) 391 goto out_unreg_param; 392 393 err = add_usage_links(mod); 394 if (err) 395 goto out_unreg_modinfo_attrs; 396 397 err = add_sect_attrs(mod, info); 398 if (err) 399 goto out_del_usage_links; 400 401 err = add_notes_attrs(mod, info); 402 if (err) 403 goto out_unreg_sect_attrs; 404 405 return 0; 406 407 out_unreg_sect_attrs: 408 remove_sect_attrs(mod); 409 out_del_usage_links: 410 del_usage_links(mod); 411 out_unreg_modinfo_attrs: 412 module_remove_modinfo_attrs(mod, -1); 413 out_unreg_param: 414 module_param_sysfs_remove(mod); 415 out_unreg_holders: 416 kobject_put(mod->holders_dir); 417 out_unreg: 418 mod_kobject_put(mod); 419 out: 420 return err; 421 } 422 423 static void mod_sysfs_fini(struct module *mod) 424 { 425 remove_notes_attrs(mod); 426 remove_sect_attrs(mod); 427 mod_kobject_put(mod); 428 } 429 430 void mod_sysfs_teardown(struct module *mod) 431 { 432 del_usage_links(mod); 433 module_remove_modinfo_attrs(mod, -1); 434 module_param_sysfs_remove(mod); 435 kobject_put(mod->mkobj.drivers_dir); 436 kobject_put(mod->holders_dir); 437 mod_sysfs_fini(mod); 438 } 439 440 void init_param_lock(struct module *mod) 441 { 442 mutex_init(&mod->param_lock); 443 } 444