Skip to content

Commit 0ffc40f

Browse files
Aaron Tomlinmcgrof
authored andcommitted
module: Move procfs support into a separate file
No functional change. This patch migrates code that allows one to generate a list of loaded/or linked modules via /proc when procfs support is enabled into kernel/module/procfs.c. Reviewed-by: Christophe Leroy <christophe.leroy@csgroup.eu> Signed-off-by: Aaron Tomlin <atomlin@redhat.com> Signed-off-by: Luis Chamberlain <mcgrof@kernel.org>
1 parent 08126db commit 0ffc40f

4 files changed

Lines changed: 145 additions & 130 deletions

File tree

kernel/module/Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,3 +15,4 @@ obj-$(CONFIG_MODULES_TREE_LOOKUP) += tree_lookup.o
1515
obj-$(CONFIG_STRICT_MODULE_RWX) += strict_rwx.o
1616
obj-$(CONFIG_DEBUG_KMEMLEAK) += debug_kmemleak.o
1717
obj-$(CONFIG_KALLSYMS) += kallsyms.o
18+
obj-$(CONFIG_PROC_FS) += procfs.o

kernel/module/internal.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,7 @@ struct module *find_module_all(const char *name, size_t len, bool even_unformed)
7272
int cmp_name(const void *name, const void *sym);
7373
long module_get_offset(struct module *mod, unsigned int *size, Elf_Shdr *sechdr,
7474
unsigned int section);
75+
char *module_flags(struct module *mod, char *buf);
7576

7677
static inline unsigned long kernel_symbol_value(const struct kernel_symbol *sym)
7778
{

kernel/module/main.c

Lines changed: 1 addition & 130 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,6 @@
2222
#include <linux/slab.h>
2323
#include <linux/vmalloc.h>
2424
#include <linux/elf.h>
25-
#include <linux/proc_fs.h>
2625
#include <linux/seq_file.h>
2726
#include <linux/syscalls.h>
2827
#include <linux/fcntl.h>
@@ -805,31 +804,6 @@ SYSCALL_DEFINE2(delete_module, const char __user *, name_user,
805804
return ret;
806805
}
807806

808-
static inline void print_unload_info(struct seq_file *m, struct module *mod)
809-
{
810-
struct module_use *use;
811-
int printed_something = 0;
812-
813-
seq_printf(m, " %i ", module_refcount(mod));
814-
815-
/*
816-
* Always include a trailing , so userspace can differentiate
817-
* between this and the old multi-field proc format.
818-
*/
819-
list_for_each_entry(use, &mod->source_list, source_list) {
820-
printed_something = 1;
821-
seq_printf(m, "%s,", use->source->name);
822-
}
823-
824-
if (mod->init != NULL && mod->exit == NULL) {
825-
printed_something = 1;
826-
seq_puts(m, "[permanent],");
827-
}
828-
829-
if (!printed_something)
830-
seq_puts(m, "-");
831-
}
832-
833807
void __symbol_put(const char *symbol)
834808
{
835809
struct find_symbol_arg fsa = {
@@ -919,12 +893,6 @@ void module_put(struct module *module)
919893
EXPORT_SYMBOL(module_put);
920894

921895
#else /* !CONFIG_MODULE_UNLOAD */
922-
static inline void print_unload_info(struct seq_file *m, struct module *mod)
923-
{
924-
/* We don't know the usage count, or what modules are using. */
925-
seq_puts(m, " - -");
926-
}
927-
928896
static inline void module_unload_free(struct module *mod)
929897
{
930898
}
@@ -3596,7 +3564,7 @@ static void cfi_cleanup(struct module *mod)
35963564
}
35973565

35983566
/* Keep in sync with MODULE_FLAGS_BUF_SIZE !!! */
3599-
static char *module_flags(struct module *mod, char *buf)
3567+
char *module_flags(struct module *mod, char *buf)
36003568
{
36013569
int bx = 0;
36023570

@@ -3619,103 +3587,6 @@ static char *module_flags(struct module *mod, char *buf)
36193587
return buf;
36203588
}
36213589

3622-
#ifdef CONFIG_PROC_FS
3623-
/* Called by the /proc file system to return a list of modules. */
3624-
static void *m_start(struct seq_file *m, loff_t *pos)
3625-
{
3626-
mutex_lock(&module_mutex);
3627-
return seq_list_start(&modules, *pos);
3628-
}
3629-
3630-
static void *m_next(struct seq_file *m, void *p, loff_t *pos)
3631-
{
3632-
return seq_list_next(p, &modules, pos);
3633-
}
3634-
3635-
static void m_stop(struct seq_file *m, void *p)
3636-
{
3637-
mutex_unlock(&module_mutex);
3638-
}
3639-
3640-
static int m_show(struct seq_file *m, void *p)
3641-
{
3642-
struct module *mod = list_entry(p, struct module, list);
3643-
char buf[MODULE_FLAGS_BUF_SIZE];
3644-
void *value;
3645-
3646-
/* We always ignore unformed modules. */
3647-
if (mod->state == MODULE_STATE_UNFORMED)
3648-
return 0;
3649-
3650-
seq_printf(m, "%s %u",
3651-
mod->name, mod->init_layout.size + mod->core_layout.size);
3652-
print_unload_info(m, mod);
3653-
3654-
/* Informative for users. */
3655-
seq_printf(m, " %s",
3656-
mod->state == MODULE_STATE_GOING ? "Unloading" :
3657-
mod->state == MODULE_STATE_COMING ? "Loading" :
3658-
"Live");
3659-
/* Used by oprofile and other similar tools. */
3660-
value = m->private ? NULL : mod->core_layout.base;
3661-
seq_printf(m, " 0x%px", value);
3662-
3663-
/* Taints info */
3664-
if (mod->taints)
3665-
seq_printf(m, " %s", module_flags(mod, buf));
3666-
3667-
seq_puts(m, "\n");
3668-
return 0;
3669-
}
3670-
3671-
/*
3672-
* Format: modulename size refcount deps address
3673-
*
3674-
* Where refcount is a number or -, and deps is a comma-separated list
3675-
* of depends or -.
3676-
*/
3677-
static const struct seq_operations modules_op = {
3678-
.start = m_start,
3679-
.next = m_next,
3680-
.stop = m_stop,
3681-
.show = m_show
3682-
};
3683-
3684-
/*
3685-
* This also sets the "private" pointer to non-NULL if the
3686-
* kernel pointers should be hidden (so you can just test
3687-
* "m->private" to see if you should keep the values private).
3688-
*
3689-
* We use the same logic as for /proc/kallsyms.
3690-
*/
3691-
static int modules_open(struct inode *inode, struct file *file)
3692-
{
3693-
int err = seq_open(file, &modules_op);
3694-
3695-
if (!err) {
3696-
struct seq_file *m = file->private_data;
3697-
m->private = kallsyms_show_value(file->f_cred) ? NULL : (void *)8ul;
3698-
}
3699-
3700-
return err;
3701-
}
3702-
3703-
static const struct proc_ops modules_proc_ops = {
3704-
.proc_flags = PROC_ENTRY_PERMANENT,
3705-
.proc_open = modules_open,
3706-
.proc_read = seq_read,
3707-
.proc_lseek = seq_lseek,
3708-
.proc_release = seq_release,
3709-
};
3710-
3711-
static int __init proc_modules_init(void)
3712-
{
3713-
proc_create("modules", 0, NULL, &modules_proc_ops);
3714-
return 0;
3715-
}
3716-
module_init(proc_modules_init);
3717-
#endif
3718-
37193590
/* Given an address, look for it in the module exception tables. */
37203591
const struct exception_table_entry *search_module_extables(unsigned long addr)
37213592
{

kernel/module/procfs.c

Lines changed: 142 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,142 @@
1+
// SPDX-License-Identifier: GPL-2.0-or-later
2+
/*
3+
* Module proc support
4+
*
5+
* Copyright (C) 2008 Alexey Dobriyan
6+
*/
7+
8+
#include <linux/module.h>
9+
#include <linux/kallsyms.h>
10+
#include <linux/mutex.h>
11+
#include <linux/seq_file.h>
12+
#include <linux/proc_fs.h>
13+
#include "internal.h"
14+
15+
#ifdef CONFIG_MODULE_UNLOAD
16+
static inline void print_unload_info(struct seq_file *m, struct module *mod)
17+
{
18+
struct module_use *use;
19+
int printed_something = 0;
20+
21+
seq_printf(m, " %i ", module_refcount(mod));
22+
23+
/*
24+
* Always include a trailing , so userspace can differentiate
25+
* between this and the old multi-field proc format.
26+
*/
27+
list_for_each_entry(use, &mod->source_list, source_list) {
28+
printed_something = 1;
29+
seq_printf(m, "%s,", use->source->name);
30+
}
31+
32+
if (mod->init && !mod->exit) {
33+
printed_something = 1;
34+
seq_puts(m, "[permanent],");
35+
}
36+
37+
if (!printed_something)
38+
seq_puts(m, "-");
39+
}
40+
#else /* !CONFIG_MODULE_UNLOAD */
41+
static inline void print_unload_info(struct seq_file *m, struct module *mod)
42+
{
43+
/* We don't know the usage count, or what modules are using. */
44+
seq_puts(m, " - -");
45+
}
46+
#endif /* CONFIG_MODULE_UNLOAD */
47+
48+
/* Called by the /proc file system to return a list of modules. */
49+
static void *m_start(struct seq_file *m, loff_t *pos)
50+
{
51+
mutex_lock(&module_mutex);
52+
return seq_list_start(&modules, *pos);
53+
}
54+
55+
static void *m_next(struct seq_file *m, void *p, loff_t *pos)
56+
{
57+
return seq_list_next(p, &modules, pos);
58+
}
59+
60+
static void m_stop(struct seq_file *m, void *p)
61+
{
62+
mutex_unlock(&module_mutex);
63+
}
64+
65+
static int m_show(struct seq_file *m, void *p)
66+
{
67+
struct module *mod = list_entry(p, struct module, list);
68+
char buf[MODULE_FLAGS_BUF_SIZE];
69+
void *value;
70+
71+
/* We always ignore unformed modules. */
72+
if (mod->state == MODULE_STATE_UNFORMED)
73+
return 0;
74+
75+
seq_printf(m, "%s %u",
76+
mod->name, mod->init_layout.size + mod->core_layout.size);
77+
print_unload_info(m, mod);
78+
79+
/* Informative for users. */
80+
seq_printf(m, " %s",
81+
mod->state == MODULE_STATE_GOING ? "Unloading" :
82+
mod->state == MODULE_STATE_COMING ? "Loading" :
83+
"Live");
84+
/* Used by oprofile and other similar tools. */
85+
value = m->private ? NULL : mod->core_layout.base;
86+
seq_printf(m, " 0x%px", value);
87+
88+
/* Taints info */
89+
if (mod->taints)
90+
seq_printf(m, " %s", module_flags(mod, buf));
91+
92+
seq_puts(m, "\n");
93+
return 0;
94+
}
95+
96+
/*
97+
* Format: modulename size refcount deps address
98+
*
99+
* Where refcount is a number or -, and deps is a comma-separated list
100+
* of depends or -.
101+
*/
102+
static const struct seq_operations modules_op = {
103+
.start = m_start,
104+
.next = m_next,
105+
.stop = m_stop,
106+
.show = m_show
107+
};
108+
109+
/*
110+
* This also sets the "private" pointer to non-NULL if the
111+
* kernel pointers should be hidden (so you can just test
112+
* "m->private" to see if you should keep the values private).
113+
*
114+
* We use the same logic as for /proc/kallsyms.
115+
*/
116+
static int modules_open(struct inode *inode, struct file *file)
117+
{
118+
int err = seq_open(file, &modules_op);
119+
120+
if (!err) {
121+
struct seq_file *m = file->private_data;
122+
123+
m->private = kallsyms_show_value(file->f_cred) ? NULL : (void *)8ul;
124+
}
125+
126+
return err;
127+
}
128+
129+
static const struct proc_ops modules_proc_ops = {
130+
.proc_flags = PROC_ENTRY_PERMANENT,
131+
.proc_open = modules_open,
132+
.proc_read = seq_read,
133+
.proc_lseek = seq_lseek,
134+
.proc_release = seq_release,
135+
};
136+
137+
static int __init proc_modules_init(void)
138+
{
139+
proc_create("modules", 0, NULL, &modules_proc_ops);
140+
return 0;
141+
}
142+
module_init(proc_modules_init);

0 commit comments

Comments
 (0)