mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/next/linux-next.git
synced 2025-01-15 02:05:33 +00:00
Merge branch 'modules-next' of git://git.kernel.org/pub/scm/linux/kernel/git/modules/linux.git
This commit is contained in:
commit
33db36712a
@ -57,10 +57,10 @@ static inline void *dereference_symbol_descriptor(void *ptr)
|
|||||||
|
|
||||||
preempt_disable();
|
preempt_disable();
|
||||||
mod = __module_address((unsigned long)ptr);
|
mod = __module_address((unsigned long)ptr);
|
||||||
preempt_enable();
|
|
||||||
|
|
||||||
if (mod)
|
if (mod)
|
||||||
ptr = dereference_module_function_descriptor(mod, ptr);
|
ptr = dereference_module_function_descriptor(mod, ptr);
|
||||||
|
preempt_enable();
|
||||||
#endif
|
#endif
|
||||||
return ptr;
|
return ptr;
|
||||||
}
|
}
|
||||||
|
@ -52,9 +52,9 @@ struct module_kobject {
|
|||||||
|
|
||||||
struct module_attribute {
|
struct module_attribute {
|
||||||
struct attribute attr;
|
struct attribute attr;
|
||||||
ssize_t (*show)(struct module_attribute *, struct module_kobject *,
|
ssize_t (*show)(const struct module_attribute *, struct module_kobject *,
|
||||||
char *);
|
char *);
|
||||||
ssize_t (*store)(struct module_attribute *, struct module_kobject *,
|
ssize_t (*store)(const struct module_attribute *, struct module_kobject *,
|
||||||
const char *, size_t count);
|
const char *, size_t count);
|
||||||
void (*setup)(struct module *, const char *);
|
void (*setup)(struct module *, const char *);
|
||||||
int (*test)(struct module *);
|
int (*test)(struct module *);
|
||||||
@ -67,10 +67,10 @@ struct module_version_attribute {
|
|||||||
const char *version;
|
const char *version;
|
||||||
};
|
};
|
||||||
|
|
||||||
extern ssize_t __modver_version_show(struct module_attribute *,
|
extern ssize_t __modver_version_show(const struct module_attribute *,
|
||||||
struct module_kobject *, char *);
|
struct module_kobject *, char *);
|
||||||
|
|
||||||
extern struct module_attribute module_uevent;
|
extern const struct module_attribute module_uevent;
|
||||||
|
|
||||||
/* These are either module local, or the kernel's dummy ones. */
|
/* These are either module local, or the kernel's dummy ones. */
|
||||||
extern int init_module(void);
|
extern int init_module(void);
|
||||||
@ -275,7 +275,7 @@ extern typeof(name) __mod_device_table__##type##__##name \
|
|||||||
#else
|
#else
|
||||||
#define MODULE_VERSION(_version) \
|
#define MODULE_VERSION(_version) \
|
||||||
MODULE_INFO(version, _version); \
|
MODULE_INFO(version, _version); \
|
||||||
static struct module_version_attribute __modver_attr \
|
static const struct module_version_attribute __modver_attr \
|
||||||
__used __section("__modver") \
|
__used __section("__modver") \
|
||||||
__aligned(__alignof__(struct module_version_attribute)) \
|
__aligned(__alignof__(struct module_version_attribute)) \
|
||||||
= { \
|
= { \
|
||||||
|
@ -286,6 +286,7 @@ comment "Do not forget to sign required modules with scripts/sign-file"
|
|||||||
choice
|
choice
|
||||||
prompt "Hash algorithm to sign modules"
|
prompt "Hash algorithm to sign modules"
|
||||||
depends on MODULE_SIG || IMA_APPRAISE_MODSIG
|
depends on MODULE_SIG || IMA_APPRAISE_MODSIG
|
||||||
|
default MODULE_SIG_SHA512
|
||||||
help
|
help
|
||||||
This determines which sort of hashing algorithm will be used during
|
This determines which sort of hashing algorithm will be used during
|
||||||
signature generation. This algorithm _must_ be built into the kernel
|
signature generation. This algorithm _must_ be built into the kernel
|
||||||
|
@ -47,8 +47,8 @@ struct kernel_symbol {
|
|||||||
extern struct mutex module_mutex;
|
extern struct mutex module_mutex;
|
||||||
extern struct list_head modules;
|
extern struct list_head modules;
|
||||||
|
|
||||||
extern struct module_attribute *modinfo_attrs[];
|
extern const struct module_attribute *const modinfo_attrs[];
|
||||||
extern size_t modinfo_attrs_count;
|
extern const size_t modinfo_attrs_count;
|
||||||
|
|
||||||
/* Provided by the linker */
|
/* Provided by the linker */
|
||||||
extern const struct kernel_symbol __start___ksymtab[];
|
extern const struct kernel_symbol __start___ksymtab[];
|
||||||
@ -329,7 +329,8 @@ static inline struct module *mod_find(unsigned long addr, struct mod_tree_root *
|
|||||||
}
|
}
|
||||||
#endif /* CONFIG_MODULES_TREE_LOOKUP */
|
#endif /* CONFIG_MODULES_TREE_LOOKUP */
|
||||||
|
|
||||||
int module_enable_rodata_ro(const struct module *mod, bool after_init);
|
int module_enable_rodata_ro(const struct module *mod);
|
||||||
|
int module_enable_rodata_ro_after_init(const struct module *mod);
|
||||||
int module_enable_data_nx(const struct module *mod);
|
int module_enable_data_nx(const struct module *mod);
|
||||||
int module_enable_text_rox(const struct module *mod);
|
int module_enable_text_rox(const struct module *mod);
|
||||||
int module_enforce_rwx_sections(Elf_Ehdr *hdr, Elf_Shdr *sechdrs,
|
int module_enforce_rwx_sections(Elf_Ehdr *hdr, Elf_Shdr *sechdrs,
|
||||||
|
@ -538,7 +538,7 @@ static void setup_modinfo_##field(struct module *mod, const char *s) \
|
|||||||
{ \
|
{ \
|
||||||
mod->field = kstrdup(s, GFP_KERNEL); \
|
mod->field = kstrdup(s, GFP_KERNEL); \
|
||||||
} \
|
} \
|
||||||
static ssize_t show_modinfo_##field(struct module_attribute *mattr, \
|
static ssize_t show_modinfo_##field(const struct module_attribute *mattr, \
|
||||||
struct module_kobject *mk, char *buffer) \
|
struct module_kobject *mk, char *buffer) \
|
||||||
{ \
|
{ \
|
||||||
return scnprintf(buffer, PAGE_SIZE, "%s\n", mk->mod->field); \
|
return scnprintf(buffer, PAGE_SIZE, "%s\n", mk->mod->field); \
|
||||||
@ -552,7 +552,7 @@ static void free_modinfo_##field(struct module *mod) \
|
|||||||
kfree(mod->field); \
|
kfree(mod->field); \
|
||||||
mod->field = NULL; \
|
mod->field = NULL; \
|
||||||
} \
|
} \
|
||||||
static struct module_attribute modinfo_##field = { \
|
static const struct module_attribute modinfo_##field = { \
|
||||||
.attr = { .name = __stringify(field), .mode = 0444 }, \
|
.attr = { .name = __stringify(field), .mode = 0444 }, \
|
||||||
.show = show_modinfo_##field, \
|
.show = show_modinfo_##field, \
|
||||||
.setup = setup_modinfo_##field, \
|
.setup = setup_modinfo_##field, \
|
||||||
@ -842,13 +842,13 @@ void symbol_put_addr(void *addr)
|
|||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(symbol_put_addr);
|
EXPORT_SYMBOL_GPL(symbol_put_addr);
|
||||||
|
|
||||||
static ssize_t show_refcnt(struct module_attribute *mattr,
|
static ssize_t show_refcnt(const struct module_attribute *mattr,
|
||||||
struct module_kobject *mk, char *buffer)
|
struct module_kobject *mk, char *buffer)
|
||||||
{
|
{
|
||||||
return sprintf(buffer, "%i\n", module_refcount(mk->mod));
|
return sprintf(buffer, "%i\n", module_refcount(mk->mod));
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct module_attribute modinfo_refcnt =
|
static const struct module_attribute modinfo_refcnt =
|
||||||
__ATTR(refcnt, 0444, show_refcnt, NULL);
|
__ATTR(refcnt, 0444, show_refcnt, NULL);
|
||||||
|
|
||||||
void __module_get(struct module *module)
|
void __module_get(struct module *module)
|
||||||
@ -917,7 +917,7 @@ size_t module_flags_taint(unsigned long taints, char *buf)
|
|||||||
return l;
|
return l;
|
||||||
}
|
}
|
||||||
|
|
||||||
static ssize_t show_initstate(struct module_attribute *mattr,
|
static ssize_t show_initstate(const struct module_attribute *mattr,
|
||||||
struct module_kobject *mk, char *buffer)
|
struct module_kobject *mk, char *buffer)
|
||||||
{
|
{
|
||||||
const char *state = "unknown";
|
const char *state = "unknown";
|
||||||
@ -938,10 +938,10 @@ static ssize_t show_initstate(struct module_attribute *mattr,
|
|||||||
return sprintf(buffer, "%s\n", state);
|
return sprintf(buffer, "%s\n", state);
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct module_attribute modinfo_initstate =
|
static const struct module_attribute modinfo_initstate =
|
||||||
__ATTR(initstate, 0444, show_initstate, NULL);
|
__ATTR(initstate, 0444, show_initstate, NULL);
|
||||||
|
|
||||||
static ssize_t store_uevent(struct module_attribute *mattr,
|
static ssize_t store_uevent(const struct module_attribute *mattr,
|
||||||
struct module_kobject *mk,
|
struct module_kobject *mk,
|
||||||
const char *buffer, size_t count)
|
const char *buffer, size_t count)
|
||||||
{
|
{
|
||||||
@ -951,10 +951,10 @@ static ssize_t store_uevent(struct module_attribute *mattr,
|
|||||||
return rc ? rc : count;
|
return rc ? rc : count;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct module_attribute module_uevent =
|
const struct module_attribute module_uevent =
|
||||||
__ATTR(uevent, 0200, NULL, store_uevent);
|
__ATTR(uevent, 0200, NULL, store_uevent);
|
||||||
|
|
||||||
static ssize_t show_coresize(struct module_attribute *mattr,
|
static ssize_t show_coresize(const struct module_attribute *mattr,
|
||||||
struct module_kobject *mk, char *buffer)
|
struct module_kobject *mk, char *buffer)
|
||||||
{
|
{
|
||||||
unsigned int size = mk->mod->mem[MOD_TEXT].size;
|
unsigned int size = mk->mod->mem[MOD_TEXT].size;
|
||||||
@ -966,11 +966,11 @@ static ssize_t show_coresize(struct module_attribute *mattr,
|
|||||||
return sprintf(buffer, "%u\n", size);
|
return sprintf(buffer, "%u\n", size);
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct module_attribute modinfo_coresize =
|
static const struct module_attribute modinfo_coresize =
|
||||||
__ATTR(coresize, 0444, show_coresize, NULL);
|
__ATTR(coresize, 0444, show_coresize, NULL);
|
||||||
|
|
||||||
#ifdef CONFIG_ARCH_WANTS_MODULES_DATA_IN_VMALLOC
|
#ifdef CONFIG_ARCH_WANTS_MODULES_DATA_IN_VMALLOC
|
||||||
static ssize_t show_datasize(struct module_attribute *mattr,
|
static ssize_t show_datasize(const struct module_attribute *mattr,
|
||||||
struct module_kobject *mk, char *buffer)
|
struct module_kobject *mk, char *buffer)
|
||||||
{
|
{
|
||||||
unsigned int size = 0;
|
unsigned int size = 0;
|
||||||
@ -980,11 +980,11 @@ static ssize_t show_datasize(struct module_attribute *mattr,
|
|||||||
return sprintf(buffer, "%u\n", size);
|
return sprintf(buffer, "%u\n", size);
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct module_attribute modinfo_datasize =
|
static const struct module_attribute modinfo_datasize =
|
||||||
__ATTR(datasize, 0444, show_datasize, NULL);
|
__ATTR(datasize, 0444, show_datasize, NULL);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static ssize_t show_initsize(struct module_attribute *mattr,
|
static ssize_t show_initsize(const struct module_attribute *mattr,
|
||||||
struct module_kobject *mk, char *buffer)
|
struct module_kobject *mk, char *buffer)
|
||||||
{
|
{
|
||||||
unsigned int size = 0;
|
unsigned int size = 0;
|
||||||
@ -994,10 +994,10 @@ static ssize_t show_initsize(struct module_attribute *mattr,
|
|||||||
return sprintf(buffer, "%u\n", size);
|
return sprintf(buffer, "%u\n", size);
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct module_attribute modinfo_initsize =
|
static const struct module_attribute modinfo_initsize =
|
||||||
__ATTR(initsize, 0444, show_initsize, NULL);
|
__ATTR(initsize, 0444, show_initsize, NULL);
|
||||||
|
|
||||||
static ssize_t show_taint(struct module_attribute *mattr,
|
static ssize_t show_taint(const struct module_attribute *mattr,
|
||||||
struct module_kobject *mk, char *buffer)
|
struct module_kobject *mk, char *buffer)
|
||||||
{
|
{
|
||||||
size_t l;
|
size_t l;
|
||||||
@ -1007,10 +1007,10 @@ static ssize_t show_taint(struct module_attribute *mattr,
|
|||||||
return l;
|
return l;
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct module_attribute modinfo_taint =
|
static const struct module_attribute modinfo_taint =
|
||||||
__ATTR(taint, 0444, show_taint, NULL);
|
__ATTR(taint, 0444, show_taint, NULL);
|
||||||
|
|
||||||
struct module_attribute *modinfo_attrs[] = {
|
const struct module_attribute *const modinfo_attrs[] = {
|
||||||
&module_uevent,
|
&module_uevent,
|
||||||
&modinfo_version,
|
&modinfo_version,
|
||||||
&modinfo_srcversion,
|
&modinfo_srcversion,
|
||||||
@ -1027,7 +1027,7 @@ struct module_attribute *modinfo_attrs[] = {
|
|||||||
NULL,
|
NULL,
|
||||||
};
|
};
|
||||||
|
|
||||||
size_t modinfo_attrs_count = ARRAY_SIZE(modinfo_attrs);
|
const size_t modinfo_attrs_count = ARRAY_SIZE(modinfo_attrs);
|
||||||
|
|
||||||
static const char vermagic[] = VERMAGIC_STRING;
|
static const char vermagic[] = VERMAGIC_STRING;
|
||||||
|
|
||||||
@ -1681,7 +1681,7 @@ static void module_license_taint_check(struct module *mod, const char *license)
|
|||||||
|
|
||||||
static void setup_modinfo(struct module *mod, struct load_info *info)
|
static void setup_modinfo(struct module *mod, struct load_info *info)
|
||||||
{
|
{
|
||||||
struct module_attribute *attr;
|
const struct module_attribute *attr;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
for (i = 0; (attr = modinfo_attrs[i]); i++) {
|
for (i = 0; (attr = modinfo_attrs[i]); i++) {
|
||||||
@ -1692,7 +1692,7 @@ static void setup_modinfo(struct module *mod, struct load_info *info)
|
|||||||
|
|
||||||
static void free_modinfo(struct module *mod)
|
static void free_modinfo(struct module *mod)
|
||||||
{
|
{
|
||||||
struct module_attribute *attr;
|
const struct module_attribute *attr;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
for (i = 0; (attr = modinfo_attrs[i]); i++) {
|
for (i = 0; (attr = modinfo_attrs[i]); i++) {
|
||||||
@ -2408,11 +2408,20 @@ static int rewrite_section_headers(struct load_info *info, int flags)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static const char *const module_license_offenders[] = {
|
||||||
|
/* driverloader was caught wrongly pretending to be under GPL */
|
||||||
|
"driverloader",
|
||||||
|
|
||||||
|
/* lve claims to be GPL but upstream won't provide source */
|
||||||
|
"lve",
|
||||||
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* These calls taint the kernel depending certain module circumstances */
|
* These calls taint the kernel depending certain module circumstances */
|
||||||
static void module_augment_kernel_taints(struct module *mod, struct load_info *info)
|
static void module_augment_kernel_taints(struct module *mod, struct load_info *info)
|
||||||
{
|
{
|
||||||
int prev_taint = test_taint(TAINT_PROPRIETARY_MODULE);
|
int prev_taint = test_taint(TAINT_PROPRIETARY_MODULE);
|
||||||
|
size_t i;
|
||||||
|
|
||||||
if (!get_modinfo(info, "intree")) {
|
if (!get_modinfo(info, "intree")) {
|
||||||
if (!test_taint(TAINT_OOT_MODULE))
|
if (!test_taint(TAINT_OOT_MODULE))
|
||||||
@ -2461,15 +2470,11 @@ static void module_augment_kernel_taints(struct module *mod, struct load_info *i
|
|||||||
if (strcmp(mod->name, "ndiswrapper") == 0)
|
if (strcmp(mod->name, "ndiswrapper") == 0)
|
||||||
add_taint(TAINT_PROPRIETARY_MODULE, LOCKDEP_NOW_UNRELIABLE);
|
add_taint(TAINT_PROPRIETARY_MODULE, LOCKDEP_NOW_UNRELIABLE);
|
||||||
|
|
||||||
/* driverloader was caught wrongly pretending to be under GPL */
|
for (i = 0; i < ARRAY_SIZE(module_license_offenders); ++i) {
|
||||||
if (strcmp(mod->name, "driverloader") == 0)
|
if (strcmp(mod->name, module_license_offenders[i]) == 0)
|
||||||
add_taint_module(mod, TAINT_PROPRIETARY_MODULE,
|
add_taint_module(mod, TAINT_PROPRIETARY_MODULE,
|
||||||
LOCKDEP_NOW_UNRELIABLE);
|
LOCKDEP_NOW_UNRELIABLE);
|
||||||
|
}
|
||||||
/* lve claims to be GPL but upstream won't provide source */
|
|
||||||
if (strcmp(mod->name, "lve") == 0)
|
|
||||||
add_taint_module(mod, TAINT_PROPRIETARY_MODULE,
|
|
||||||
LOCKDEP_NOW_UNRELIABLE);
|
|
||||||
|
|
||||||
if (!prev_taint && test_taint(TAINT_PROPRIETARY_MODULE))
|
if (!prev_taint && test_taint(TAINT_PROPRIETARY_MODULE))
|
||||||
pr_warn("%s: module license taints kernel.\n", mod->name);
|
pr_warn("%s: module license taints kernel.\n", mod->name);
|
||||||
@ -3024,9 +3029,12 @@ static noinline int do_init_module(struct module *mod)
|
|||||||
/* Switch to core kallsyms now init is done: kallsyms may be walking! */
|
/* Switch to core kallsyms now init is done: kallsyms may be walking! */
|
||||||
rcu_assign_pointer(mod->kallsyms, &mod->core_kallsyms);
|
rcu_assign_pointer(mod->kallsyms, &mod->core_kallsyms);
|
||||||
#endif
|
#endif
|
||||||
ret = module_enable_rodata_ro(mod, true);
|
ret = module_enable_rodata_ro_after_init(mod);
|
||||||
if (ret)
|
if (ret)
|
||||||
goto fail_mutex_unlock;
|
pr_warn("%s: module_enable_rodata_ro_after_init() returned %d, "
|
||||||
|
"ro_after_init data might still be writable\n",
|
||||||
|
mod->name, ret);
|
||||||
|
|
||||||
mod_tree_remove_init(mod);
|
mod_tree_remove_init(mod);
|
||||||
module_arch_freeing_init(mod);
|
module_arch_freeing_init(mod);
|
||||||
for_class_mod_mem_type(type, init) {
|
for_class_mod_mem_type(type, init) {
|
||||||
@ -3065,8 +3073,6 @@ static noinline int do_init_module(struct module *mod)
|
|||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
fail_mutex_unlock:
|
|
||||||
mutex_unlock(&module_mutex);
|
|
||||||
fail_free_freeinit:
|
fail_free_freeinit:
|
||||||
kfree(freeinit);
|
kfree(freeinit);
|
||||||
fail:
|
fail:
|
||||||
@ -3194,7 +3200,7 @@ static int complete_formation(struct module *mod, struct load_info *info)
|
|||||||
module_bug_finalize(info->hdr, info->sechdrs, mod);
|
module_bug_finalize(info->hdr, info->sechdrs, mod);
|
||||||
module_cfi_finalize(info->hdr, info->sechdrs, mod);
|
module_cfi_finalize(info->hdr, info->sechdrs, mod);
|
||||||
|
|
||||||
err = module_enable_rodata_ro(mod, false);
|
err = module_enable_rodata_ro(mod);
|
||||||
if (err)
|
if (err)
|
||||||
goto out_strict_rwx;
|
goto out_strict_rwx;
|
||||||
err = module_enable_data_nx(mod);
|
err = module_enable_data_nx(mod);
|
||||||
|
@ -47,7 +47,7 @@ int module_enable_text_rox(const struct module *mod)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int module_enable_rodata_ro(const struct module *mod, bool after_init)
|
int module_enable_rodata_ro(const struct module *mod)
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
@ -61,12 +61,17 @@ int module_enable_rodata_ro(const struct module *mod, bool after_init)
|
|||||||
if (ret)
|
if (ret)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
if (after_init)
|
|
||||||
return module_set_memory(mod, MOD_RO_AFTER_INIT, set_memory_ro);
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int module_enable_rodata_ro_after_init(const struct module *mod)
|
||||||
|
{
|
||||||
|
if (!IS_ENABLED(CONFIG_STRICT_MODULE_RWX) || !rodata_enabled)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
return module_set_memory(mod, MOD_RO_AFTER_INIT, set_memory_ro);
|
||||||
|
}
|
||||||
|
|
||||||
int module_enable_data_nx(const struct module *mod)
|
int module_enable_data_nx(const struct module *mod)
|
||||||
{
|
{
|
||||||
if (!IS_ENABLED(CONFIG_STRICT_MODULE_RWX))
|
if (!IS_ENABLED(CONFIG_STRICT_MODULE_RWX))
|
||||||
|
@ -19,24 +19,16 @@
|
|||||||
* J. Corbet <corbet@lwn.net>
|
* J. Corbet <corbet@lwn.net>
|
||||||
*/
|
*/
|
||||||
#ifdef CONFIG_KALLSYMS
|
#ifdef CONFIG_KALLSYMS
|
||||||
struct module_sect_attr {
|
|
||||||
struct bin_attribute battr;
|
|
||||||
unsigned long address;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct module_sect_attrs {
|
struct module_sect_attrs {
|
||||||
struct attribute_group grp;
|
struct attribute_group grp;
|
||||||
unsigned int nsections;
|
struct bin_attribute attrs[];
|
||||||
struct module_sect_attr attrs[];
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#define MODULE_SECT_READ_SIZE (3 /* "0x", "\n" */ + (BITS_PER_LONG / 4))
|
#define MODULE_SECT_READ_SIZE (3 /* "0x", "\n" */ + (BITS_PER_LONG / 4))
|
||||||
static ssize_t module_sect_read(struct file *file, struct kobject *kobj,
|
static ssize_t module_sect_read(struct file *file, struct kobject *kobj,
|
||||||
struct bin_attribute *battr,
|
const struct bin_attribute *battr,
|
||||||
char *buf, loff_t pos, size_t count)
|
char *buf, loff_t pos, size_t count)
|
||||||
{
|
{
|
||||||
struct module_sect_attr *sattr =
|
|
||||||
container_of(battr, struct module_sect_attr, battr);
|
|
||||||
char bounce[MODULE_SECT_READ_SIZE + 1];
|
char bounce[MODULE_SECT_READ_SIZE + 1];
|
||||||
size_t wrote;
|
size_t wrote;
|
||||||
|
|
||||||
@ -53,7 +45,7 @@ static ssize_t module_sect_read(struct file *file, struct kobject *kobj,
|
|||||||
*/
|
*/
|
||||||
wrote = scnprintf(bounce, sizeof(bounce), "0x%px\n",
|
wrote = scnprintf(bounce, sizeof(bounce), "0x%px\n",
|
||||||
kallsyms_show_value(file->f_cred)
|
kallsyms_show_value(file->f_cred)
|
||||||
? (void *)sattr->address : NULL);
|
? battr->private : NULL);
|
||||||
count = min(count, wrote);
|
count = min(count, wrote);
|
||||||
memcpy(buf, bounce, count);
|
memcpy(buf, bounce, count);
|
||||||
|
|
||||||
@ -62,59 +54,59 @@ static ssize_t module_sect_read(struct file *file, struct kobject *kobj,
|
|||||||
|
|
||||||
static void free_sect_attrs(struct module_sect_attrs *sect_attrs)
|
static void free_sect_attrs(struct module_sect_attrs *sect_attrs)
|
||||||
{
|
{
|
||||||
unsigned int section;
|
const struct bin_attribute *const *bin_attr;
|
||||||
|
|
||||||
for (section = 0; section < sect_attrs->nsections; section++)
|
for (bin_attr = sect_attrs->grp.bin_attrs_new; *bin_attr; bin_attr++)
|
||||||
kfree(sect_attrs->attrs[section].battr.attr.name);
|
kfree((*bin_attr)->attr.name);
|
||||||
|
kfree(sect_attrs->grp.bin_attrs_new);
|
||||||
kfree(sect_attrs);
|
kfree(sect_attrs);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int add_sect_attrs(struct module *mod, const struct load_info *info)
|
static int add_sect_attrs(struct module *mod, const struct load_info *info)
|
||||||
{
|
{
|
||||||
unsigned int nloaded = 0, i, size[2];
|
|
||||||
struct module_sect_attrs *sect_attrs;
|
struct module_sect_attrs *sect_attrs;
|
||||||
struct module_sect_attr *sattr;
|
const struct bin_attribute **gattr;
|
||||||
struct bin_attribute **gattr;
|
struct bin_attribute *sattr;
|
||||||
|
unsigned int nloaded = 0, i;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
/* Count loaded sections and allocate structures */
|
/* Count loaded sections and allocate structures */
|
||||||
for (i = 0; i < info->hdr->e_shnum; i++)
|
for (i = 0; i < info->hdr->e_shnum; i++)
|
||||||
if (!sect_empty(&info->sechdrs[i]))
|
if (!sect_empty(&info->sechdrs[i]))
|
||||||
nloaded++;
|
nloaded++;
|
||||||
size[0] = ALIGN(struct_size(sect_attrs, attrs, nloaded),
|
sect_attrs = kzalloc(struct_size(sect_attrs, attrs, nloaded), GFP_KERNEL);
|
||||||
sizeof(sect_attrs->grp.bin_attrs[0]));
|
|
||||||
size[1] = (nloaded + 1) * sizeof(sect_attrs->grp.bin_attrs[0]);
|
|
||||||
sect_attrs = kzalloc(size[0] + size[1], GFP_KERNEL);
|
|
||||||
if (!sect_attrs)
|
if (!sect_attrs)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
|
gattr = kcalloc(nloaded + 1, sizeof(*gattr), GFP_KERNEL);
|
||||||
|
if (!gattr) {
|
||||||
|
kfree(sect_attrs);
|
||||||
|
return -ENOMEM;
|
||||||
|
}
|
||||||
|
|
||||||
/* Setup section attributes. */
|
/* Setup section attributes. */
|
||||||
sect_attrs->grp.name = "sections";
|
sect_attrs->grp.name = "sections";
|
||||||
sect_attrs->grp.bin_attrs = (void *)sect_attrs + size[0];
|
sect_attrs->grp.bin_attrs_new = gattr;
|
||||||
|
|
||||||
sect_attrs->nsections = 0;
|
|
||||||
sattr = §_attrs->attrs[0];
|
sattr = §_attrs->attrs[0];
|
||||||
gattr = §_attrs->grp.bin_attrs[0];
|
|
||||||
for (i = 0; i < info->hdr->e_shnum; i++) {
|
for (i = 0; i < info->hdr->e_shnum; i++) {
|
||||||
Elf_Shdr *sec = &info->sechdrs[i];
|
Elf_Shdr *sec = &info->sechdrs[i];
|
||||||
|
|
||||||
if (sect_empty(sec))
|
if (sect_empty(sec))
|
||||||
continue;
|
continue;
|
||||||
sysfs_bin_attr_init(&sattr->battr);
|
sysfs_bin_attr_init(sattr);
|
||||||
sattr->address = sec->sh_addr;
|
sattr->attr.name =
|
||||||
sattr->battr.attr.name =
|
|
||||||
kstrdup(info->secstrings + sec->sh_name, GFP_KERNEL);
|
kstrdup(info->secstrings + sec->sh_name, GFP_KERNEL);
|
||||||
if (!sattr->battr.attr.name) {
|
if (!sattr->attr.name) {
|
||||||
ret = -ENOMEM;
|
ret = -ENOMEM;
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
sect_attrs->nsections++;
|
sattr->read_new = module_sect_read;
|
||||||
sattr->battr.read = module_sect_read;
|
sattr->private = (void *)sec->sh_addr;
|
||||||
sattr->battr.size = MODULE_SECT_READ_SIZE;
|
sattr->size = MODULE_SECT_READ_SIZE;
|
||||||
sattr->battr.attr.mode = 0400;
|
sattr->attr.mode = 0400;
|
||||||
*(gattr++) = &(sattr++)->battr;
|
*(gattr++) = sattr++;
|
||||||
}
|
}
|
||||||
*gattr = NULL;
|
|
||||||
|
|
||||||
ret = sysfs_create_group(&mod->mkobj.kobj, §_attrs->grp);
|
ret = sysfs_create_group(&mod->mkobj.kobj, §_attrs->grp);
|
||||||
if (ret)
|
if (ret)
|
||||||
@ -146,20 +138,13 @@ static void remove_sect_attrs(struct module *mod)
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
struct module_notes_attrs {
|
struct module_notes_attrs {
|
||||||
struct kobject *dir;
|
struct attribute_group grp;
|
||||||
unsigned int notes;
|
struct bin_attribute attrs[];
|
||||||
struct bin_attribute attrs[] __counted_by(notes);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
static void free_notes_attrs(struct module_notes_attrs *notes_attrs,
|
static void free_notes_attrs(struct module_notes_attrs *notes_attrs)
|
||||||
unsigned int i)
|
|
||||||
{
|
{
|
||||||
if (notes_attrs->dir) {
|
kfree(notes_attrs->grp.bin_attrs_new);
|
||||||
while (i-- > 0)
|
|
||||||
sysfs_remove_bin_file(notes_attrs->dir,
|
|
||||||
¬es_attrs->attrs[i]);
|
|
||||||
kobject_put(notes_attrs->dir);
|
|
||||||
}
|
|
||||||
kfree(notes_attrs);
|
kfree(notes_attrs);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -167,6 +152,7 @@ static int add_notes_attrs(struct module *mod, const struct load_info *info)
|
|||||||
{
|
{
|
||||||
unsigned int notes, loaded, i;
|
unsigned int notes, loaded, i;
|
||||||
struct module_notes_attrs *notes_attrs;
|
struct module_notes_attrs *notes_attrs;
|
||||||
|
const struct bin_attribute **gattr;
|
||||||
struct bin_attribute *nattr;
|
struct bin_attribute *nattr;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
@ -185,47 +171,55 @@ static int add_notes_attrs(struct module *mod, const struct load_info *info)
|
|||||||
if (!notes_attrs)
|
if (!notes_attrs)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
notes_attrs->notes = notes;
|
gattr = kcalloc(notes + 1, sizeof(*gattr), GFP_KERNEL);
|
||||||
|
if (!gattr) {
|
||||||
|
kfree(notes_attrs);
|
||||||
|
return -ENOMEM;
|
||||||
|
}
|
||||||
|
|
||||||
|
notes_attrs->grp.name = "notes";
|
||||||
|
notes_attrs->grp.bin_attrs_new = gattr;
|
||||||
|
|
||||||
nattr = ¬es_attrs->attrs[0];
|
nattr = ¬es_attrs->attrs[0];
|
||||||
for (loaded = i = 0; i < info->hdr->e_shnum; ++i) {
|
for (loaded = i = 0; i < info->hdr->e_shnum; ++i) {
|
||||||
if (sect_empty(&info->sechdrs[i]))
|
if (sect_empty(&info->sechdrs[i]))
|
||||||
continue;
|
continue;
|
||||||
if (info->sechdrs[i].sh_type == SHT_NOTE) {
|
if (info->sechdrs[i].sh_type == SHT_NOTE) {
|
||||||
sysfs_bin_attr_init(nattr);
|
sysfs_bin_attr_init(nattr);
|
||||||
nattr->attr.name = mod->sect_attrs->attrs[loaded].battr.attr.name;
|
nattr->attr.name = mod->sect_attrs->attrs[loaded].attr.name;
|
||||||
nattr->attr.mode = 0444;
|
nattr->attr.mode = 0444;
|
||||||
nattr->size = info->sechdrs[i].sh_size;
|
nattr->size = info->sechdrs[i].sh_size;
|
||||||
nattr->private = (void *)info->sechdrs[i].sh_addr;
|
nattr->private = (void *)info->sechdrs[i].sh_addr;
|
||||||
nattr->read = sysfs_bin_attr_simple_read;
|
nattr->read = sysfs_bin_attr_simple_read;
|
||||||
++nattr;
|
*(gattr++) = nattr++;
|
||||||
}
|
}
|
||||||
++loaded;
|
++loaded;
|
||||||
}
|
}
|
||||||
|
|
||||||
notes_attrs->dir = kobject_create_and_add("notes", &mod->mkobj.kobj);
|
ret = sysfs_create_group(&mod->mkobj.kobj, ¬es_attrs->grp);
|
||||||
if (!notes_attrs->dir) {
|
if (ret)
|
||||||
ret = -ENOMEM;
|
|
||||||
goto out;
|
goto out;
|
||||||
}
|
|
||||||
|
|
||||||
for (i = 0; i < notes; ++i) {
|
|
||||||
ret = sysfs_create_bin_file(notes_attrs->dir, ¬es_attrs->attrs[i]);
|
|
||||||
if (ret)
|
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
|
|
||||||
mod->notes_attrs = notes_attrs;
|
mod->notes_attrs = notes_attrs;
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
out:
|
out:
|
||||||
free_notes_attrs(notes_attrs, i);
|
free_notes_attrs(notes_attrs);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void remove_notes_attrs(struct module *mod)
|
static void remove_notes_attrs(struct module *mod)
|
||||||
{
|
{
|
||||||
if (mod->notes_attrs)
|
if (mod->notes_attrs) {
|
||||||
free_notes_attrs(mod->notes_attrs, mod->notes_attrs->notes);
|
sysfs_remove_group(&mod->mkobj.kobj,
|
||||||
|
&mod->notes_attrs->grp);
|
||||||
|
/*
|
||||||
|
* We are positive that no one is using any notes attrs
|
||||||
|
* at this point. Deallocate immediately.
|
||||||
|
*/
|
||||||
|
free_notes_attrs(mod->notes_attrs);
|
||||||
|
mod->notes_attrs = NULL;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#else /* !CONFIG_KALLSYMS */
|
#else /* !CONFIG_KALLSYMS */
|
||||||
@ -275,7 +269,7 @@ static int add_usage_links(struct module *mod)
|
|||||||
|
|
||||||
static void module_remove_modinfo_attrs(struct module *mod, int end)
|
static void module_remove_modinfo_attrs(struct module *mod, int end)
|
||||||
{
|
{
|
||||||
struct module_attribute *attr;
|
const struct module_attribute *attr;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
for (i = 0; (attr = &mod->modinfo_attrs[i]); i++) {
|
for (i = 0; (attr = &mod->modinfo_attrs[i]); i++) {
|
||||||
@ -293,7 +287,7 @@ static void module_remove_modinfo_attrs(struct module *mod, int end)
|
|||||||
|
|
||||||
static int module_add_modinfo_attrs(struct module *mod)
|
static int module_add_modinfo_attrs(struct module *mod)
|
||||||
{
|
{
|
||||||
struct module_attribute *attr;
|
const struct module_attribute *attr;
|
||||||
struct module_attribute *temp_attr;
|
struct module_attribute *temp_attr;
|
||||||
int error = 0;
|
int error = 0;
|
||||||
int i;
|
int i;
|
||||||
|
@ -538,7 +538,7 @@ const struct kernel_param_ops param_ops_string = {
|
|||||||
EXPORT_SYMBOL(param_ops_string);
|
EXPORT_SYMBOL(param_ops_string);
|
||||||
|
|
||||||
/* sysfs output in /sys/modules/XYZ/parameters/ */
|
/* sysfs output in /sys/modules/XYZ/parameters/ */
|
||||||
#define to_module_attr(n) container_of(n, struct module_attribute, attr)
|
#define to_module_attr(n) container_of_const(n, struct module_attribute, attr)
|
||||||
#define to_module_kobject(n) container_of(n, struct module_kobject, kobj)
|
#define to_module_kobject(n) container_of(n, struct module_kobject, kobj)
|
||||||
|
|
||||||
struct param_attribute
|
struct param_attribute
|
||||||
@ -555,13 +555,13 @@ struct module_param_attrs
|
|||||||
};
|
};
|
||||||
|
|
||||||
#ifdef CONFIG_SYSFS
|
#ifdef CONFIG_SYSFS
|
||||||
#define to_param_attr(n) container_of(n, struct param_attribute, mattr)
|
#define to_param_attr(n) container_of_const(n, struct param_attribute, mattr)
|
||||||
|
|
||||||
static ssize_t param_attr_show(struct module_attribute *mattr,
|
static ssize_t param_attr_show(const struct module_attribute *mattr,
|
||||||
struct module_kobject *mk, char *buf)
|
struct module_kobject *mk, char *buf)
|
||||||
{
|
{
|
||||||
int count;
|
int count;
|
||||||
struct param_attribute *attribute = to_param_attr(mattr);
|
const struct param_attribute *attribute = to_param_attr(mattr);
|
||||||
|
|
||||||
if (!attribute->param->ops->get)
|
if (!attribute->param->ops->get)
|
||||||
return -EPERM;
|
return -EPERM;
|
||||||
@ -573,12 +573,12 @@ static ssize_t param_attr_show(struct module_attribute *mattr,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* sysfs always hands a nul-terminated string in buf. We rely on that. */
|
/* sysfs always hands a nul-terminated string in buf. We rely on that. */
|
||||||
static ssize_t param_attr_store(struct module_attribute *mattr,
|
static ssize_t param_attr_store(const struct module_attribute *mattr,
|
||||||
struct module_kobject *mk,
|
struct module_kobject *mk,
|
||||||
const char *buf, size_t len)
|
const char *buf, size_t len)
|
||||||
{
|
{
|
||||||
int err;
|
int err;
|
||||||
struct param_attribute *attribute = to_param_attr(mattr);
|
const struct param_attribute *attribute = to_param_attr(mattr);
|
||||||
|
|
||||||
if (!attribute->param->ops->set)
|
if (!attribute->param->ops->set)
|
||||||
return -EPERM;
|
return -EPERM;
|
||||||
@ -857,11 +857,11 @@ static void __init param_sysfs_builtin(void)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ssize_t __modver_version_show(struct module_attribute *mattr,
|
ssize_t __modver_version_show(const struct module_attribute *mattr,
|
||||||
struct module_kobject *mk, char *buf)
|
struct module_kobject *mk, char *buf)
|
||||||
{
|
{
|
||||||
struct module_version_attribute *vattr =
|
const struct module_version_attribute *vattr =
|
||||||
container_of(mattr, struct module_version_attribute, mattr);
|
container_of_const(mattr, struct module_version_attribute, mattr);
|
||||||
|
|
||||||
return scnprintf(buf, PAGE_SIZE, "%s\n", vattr->version);
|
return scnprintf(buf, PAGE_SIZE, "%s\n", vattr->version);
|
||||||
}
|
}
|
||||||
@ -892,7 +892,7 @@ static ssize_t module_attr_show(struct kobject *kobj,
|
|||||||
struct attribute *attr,
|
struct attribute *attr,
|
||||||
char *buf)
|
char *buf)
|
||||||
{
|
{
|
||||||
struct module_attribute *attribute;
|
const struct module_attribute *attribute;
|
||||||
struct module_kobject *mk;
|
struct module_kobject *mk;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
@ -911,7 +911,7 @@ static ssize_t module_attr_store(struct kobject *kobj,
|
|||||||
struct attribute *attr,
|
struct attribute *attr,
|
||||||
const char *buf, size_t len)
|
const char *buf, size_t len)
|
||||||
{
|
{
|
||||||
struct module_attribute *attribute;
|
const struct module_attribute *attribute;
|
||||||
struct module_kobject *mk;
|
struct module_kobject *mk;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user