cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

procfs.c (3523B)


      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
     16static 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 */
     41static 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. */
     49static 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
     55static void *m_next(struct seq_file *m, void *p, loff_t *pos)
     56{
     57	return seq_list_next(p, &modules, pos);
     58}
     59
     60static void m_stop(struct seq_file *m, void *p)
     61{
     62	mutex_unlock(&module_mutex);
     63}
     64
     65static 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	unsigned int size;
     71
     72	/* We always ignore unformed modules. */
     73	if (mod->state == MODULE_STATE_UNFORMED)
     74		return 0;
     75
     76	size = mod->init_layout.size + mod->core_layout.size;
     77#ifdef CONFIG_ARCH_WANTS_MODULES_DATA_IN_VMALLOC
     78	size += mod->data_layout.size;
     79#endif
     80	seq_printf(m, "%s %u", mod->name, size);
     81	print_unload_info(m, mod);
     82
     83	/* Informative for users. */
     84	seq_printf(m, " %s",
     85		   mod->state == MODULE_STATE_GOING ? "Unloading" :
     86		   mod->state == MODULE_STATE_COMING ? "Loading" :
     87		   "Live");
     88	/* Used by oprofile and other similar tools. */
     89	value = m->private ? NULL : mod->core_layout.base;
     90	seq_printf(m, " 0x%px", value);
     91
     92	/* Taints info */
     93	if (mod->taints)
     94		seq_printf(m, " %s", module_flags(mod, buf));
     95
     96	seq_puts(m, "\n");
     97	return 0;
     98}
     99
    100/*
    101 * Format: modulename size refcount deps address
    102 *
    103 * Where refcount is a number or -, and deps is a comma-separated list
    104 * of depends or -.
    105 */
    106static const struct seq_operations modules_op = {
    107	.start	= m_start,
    108	.next	= m_next,
    109	.stop	= m_stop,
    110	.show	= m_show
    111};
    112
    113/*
    114 * This also sets the "private" pointer to non-NULL if the
    115 * kernel pointers should be hidden (so you can just test
    116 * "m->private" to see if you should keep the values private).
    117 *
    118 * We use the same logic as for /proc/kallsyms.
    119 */
    120static int modules_open(struct inode *inode, struct file *file)
    121{
    122	int err = seq_open(file, &modules_op);
    123
    124	if (!err) {
    125		struct seq_file *m = file->private_data;
    126
    127		m->private = kallsyms_show_value(file->f_cred) ? NULL : (void *)8ul;
    128	}
    129
    130	return err;
    131}
    132
    133static const struct proc_ops modules_proc_ops = {
    134	.proc_flags	= PROC_ENTRY_PERMANENT,
    135	.proc_open	= modules_open,
    136	.proc_read	= seq_read,
    137	.proc_lseek	= seq_lseek,
    138	.proc_release	= seq_release,
    139};
    140
    141static int __init proc_modules_init(void)
    142{
    143	proc_create("modules", 0, NULL, &modules_proc_ops);
    144	return 0;
    145}
    146module_init(proc_modules_init);