1 // SPDX-License-Identifier: GPL-2.0-or-later
5 * Copyright (C) 2008 Alexey Dobriyan
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>
15 #ifdef CONFIG_MODULE_UNLOAD
16 static inline void print_unload_info(struct seq_file
*m
, struct module
*mod
)
18 struct module_use
*use
;
19 int printed_something
= 0;
21 seq_printf(m
, " %i ", module_refcount(mod
));
24 * Always include a trailing , so userspace can differentiate
25 * between this and the old multi-field proc format.
27 list_for_each_entry(use
, &mod
->source_list
, source_list
) {
28 printed_something
= 1;
29 seq_printf(m
, "%s,", use
->source
->name
);
32 if (mod
->init
&& !mod
->exit
) {
33 printed_something
= 1;
34 seq_puts(m
, "[permanent],");
37 if (!printed_something
)
40 #else /* !CONFIG_MODULE_UNLOAD */
41 static inline void print_unload_info(struct seq_file
*m
, struct module
*mod
)
43 /* We don't know the usage count, or what modules are using. */
46 #endif /* CONFIG_MODULE_UNLOAD */
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
)
51 mutex_lock(&module_mutex
);
52 return seq_list_start(&modules
, *pos
);
55 static void *m_next(struct seq_file
*m
, void *p
, loff_t
*pos
)
57 return seq_list_next(p
, &modules
, pos
);
60 static void m_stop(struct seq_file
*m
, void *p
)
62 mutex_unlock(&module_mutex
);
65 static unsigned int module_total_size(struct module
*mod
)
69 for_each_mod_mem_type(type
)
70 size
+= mod
->mem
[type
].size
;
74 static int m_show(struct seq_file
*m
, void *p
)
76 struct module
*mod
= list_entry(p
, struct module
, list
);
77 char buf
[MODULE_FLAGS_BUF_SIZE
];
81 /* We always ignore unformed modules. */
82 if (mod
->state
== MODULE_STATE_UNFORMED
)
85 size
= module_total_size(mod
);
86 seq_printf(m
, "%s %u", mod
->name
, size
);
87 print_unload_info(m
, mod
);
89 /* Informative for users. */
91 mod
->state
== MODULE_STATE_GOING
? "Unloading" :
92 mod
->state
== MODULE_STATE_COMING
? "Loading" :
94 /* Used by oprofile and other similar tools. */
95 value
= m
->private ? NULL
: mod
->mem
[MOD_TEXT
].base
;
96 seq_printf(m
, " 0x%px", value
);
100 seq_printf(m
, " %s", module_flags(mod
, buf
, true));
107 * Format: modulename size refcount deps address
109 * Where refcount is a number or -, and deps is a comma-separated list
112 static const struct seq_operations modules_op
= {
120 * This also sets the "private" pointer to non-NULL if the
121 * kernel pointers should be hidden (so you can just test
122 * "m->private" to see if you should keep the values private).
124 * We use the same logic as for /proc/kallsyms.
126 static int modules_open(struct inode
*inode
, struct file
*file
)
128 int err
= seq_open(file
, &modules_op
);
131 struct seq_file
*m
= file
->private_data
;
133 m
->private = kallsyms_show_value(file
->f_cred
) ? NULL
: (void *)8ul;
139 static const struct proc_ops modules_proc_ops
= {
140 .proc_flags
= PROC_ENTRY_PERMANENT
,
141 .proc_open
= modules_open
,
142 .proc_read
= seq_read
,
143 .proc_lseek
= seq_lseek
,
144 .proc_release
= seq_release
,
147 static int __init
proc_modules_init(void)
149 proc_create("modules", 0, NULL
, &modules_proc_ops
);
152 module_init(proc_modules_init
);