linux/fs/proc/proc_sysctl.c

// SPDX-License-Identifier: GPL-2.0
/*
 * /proc/sys support
 */
#include <linux/init.h>
#include <linux/sysctl.h>
#include <linux/poll.h>
#include <linux/proc_fs.h>
#include <linux/printk.h>
#include <linux/security.h>
#include <linux/sched.h>
#include <linux/cred.h>
#include <linux/namei.h>
#include <linux/mm.h>
#include <linux/uio.h>
#include <linux/module.h>
#include <linux/bpf-cgroup.h>
#include <linux/mount.h>
#include <linux/kmemleak.h>
#include "internal.h"

#define list_for_each_table_entry(entry, header)

static const struct dentry_operations proc_sys_dentry_operations;
static const struct file_operations proc_sys_file_operations;
static const struct inode_operations proc_sys_inode_operations;
static const struct file_operations proc_sys_dir_file_operations;
static const struct inode_operations proc_sys_dir_operations;

/* Support for permanently empty directories */
static struct ctl_table sysctl_mount_point[] =;

/**
 * register_sysctl_mount_point() - registers a sysctl mount point
 * @path: path for the mount point
 *
 * Used to create a permanently empty directory to serve as mount point.
 * There are some subtle but important permission checks this allows in the
 * case of unprivileged mounts.
 */
struct ctl_table_header *register_sysctl_mount_point(const char *path)
{}
EXPORT_SYMBOL();

#define sysctl_is_perm_empty_ctl_header(hptr)
#define sysctl_set_perm_empty_ctl_header(hptr)
#define sysctl_clear_perm_empty_ctl_header(hptr)

void proc_sys_poll_notify(struct ctl_table_poll *poll)
{}

static struct ctl_table root_table[] =;
static struct ctl_table_root sysctl_table_root =;

static DEFINE_SPINLOCK(sysctl_lock);

static void drop_sysctl_table(struct ctl_table_header *header);
static int sysctl_follow_link(struct ctl_table_header **phead,
	struct ctl_table **pentry);
static int insert_links(struct ctl_table_header *head);
static void put_links(struct ctl_table_header *header);

static void sysctl_print_dir(struct ctl_dir *dir)
{}

static int namecmp(const char *name1, int len1, const char *name2, int len2)
{}

/* Called under sysctl_lock */
static struct ctl_table *find_entry(struct ctl_table_header **phead,
	struct ctl_dir *dir, const char *name, int namelen)
{}

static int insert_entry(struct ctl_table_header *head, struct ctl_table *entry)
{}

static void erase_entry(struct ctl_table_header *head, struct ctl_table *entry)
{}

static void init_header(struct ctl_table_header *head,
	struct ctl_table_root *root, struct ctl_table_set *set,
	struct ctl_node *node, struct ctl_table *table, size_t table_size)
{}

static void erase_header(struct ctl_table_header *head)
{}

static int insert_header(struct ctl_dir *dir, struct ctl_table_header *header)
{}

/* called under sysctl_lock */
static int use_table(struct ctl_table_header *p)
{}

/* called under sysctl_lock */
static void unuse_table(struct ctl_table_header *p)
{}

static void proc_sys_invalidate_dcache(struct ctl_table_header *head)
{}

/* called under sysctl_lock, will reacquire if has to wait */
static void start_unregistering(struct ctl_table_header *p)
{}

static struct ctl_table_header *sysctl_head_grab(struct ctl_table_header *head)
{}

static void sysctl_head_finish(struct ctl_table_header *head)
{}

static struct ctl_table_set *
lookup_header_set(struct ctl_table_root *root)
{}

static struct ctl_table *lookup_entry(struct ctl_table_header **phead,
				      struct ctl_dir *dir,
				      const char *name, int namelen)
{}

static struct ctl_node *first_usable_entry(struct rb_node *node)
{}

static void first_entry(struct ctl_dir *dir,
	struct ctl_table_header **phead, struct ctl_table **pentry)
{}

static void next_entry(struct ctl_table_header **phead, struct ctl_table **pentry)
{}

/*
 * sysctl_perm does NOT grant the superuser all rights automatically, because
 * some sysctl variables are readonly even to root.
 */

static int test_perm(int mode, int op)
{}

static int sysctl_perm(struct ctl_table_header *head, struct ctl_table *table, int op)
{}

static struct inode *proc_sys_make_inode(struct super_block *sb,
		struct ctl_table_header *head, struct ctl_table *table)
{}

void proc_sys_evict_inode(struct inode *inode, struct ctl_table_header *head)
{}

static struct ctl_table_header *grab_header(struct inode *inode)
{}

static struct dentry *proc_sys_lookup(struct inode *dir, struct dentry *dentry,
					unsigned int flags)
{}

static ssize_t proc_sys_call_handler(struct kiocb *iocb, struct iov_iter *iter,
		int write)
{}

static ssize_t proc_sys_read(struct kiocb *iocb, struct iov_iter *iter)
{}

static ssize_t proc_sys_write(struct kiocb *iocb, struct iov_iter *iter)
{}

static int proc_sys_open(struct inode *inode, struct file *filp)
{}

static __poll_t proc_sys_poll(struct file *filp, poll_table *wait)
{}

static bool proc_sys_fill_cache(struct file *file,
				struct dir_context *ctx,
				struct ctl_table_header *head,
				struct ctl_table *table)
{}

static bool proc_sys_link_fill_cache(struct file *file,
				    struct dir_context *ctx,
				    struct ctl_table_header *head,
				    struct ctl_table *table)
{}

static int scan(struct ctl_table_header *head, struct ctl_table *table,
		unsigned long *pos, struct file *file,
		struct dir_context *ctx)
{}

static int proc_sys_readdir(struct file *file, struct dir_context *ctx)
{}

static int proc_sys_permission(struct mnt_idmap *idmap,
			       struct inode *inode, int mask)
{}

static int proc_sys_setattr(struct mnt_idmap *idmap,
			    struct dentry *dentry, struct iattr *attr)
{}

static int proc_sys_getattr(struct mnt_idmap *idmap,
			    const struct path *path, struct kstat *stat,
			    u32 request_mask, unsigned int query_flags)
{}

static const struct file_operations proc_sys_file_operations =;

static const struct file_operations proc_sys_dir_file_operations =;

static const struct inode_operations proc_sys_inode_operations =;

static const struct inode_operations proc_sys_dir_operations =;

static int proc_sys_revalidate(struct dentry *dentry, unsigned int flags)
{}

static int proc_sys_delete(const struct dentry *dentry)
{}

static int sysctl_is_seen(struct ctl_table_header *p)
{}

static int proc_sys_compare(const struct dentry *dentry,
		unsigned int len, const char *str, const struct qstr *name)
{}

static const struct dentry_operations proc_sys_dentry_operations =;

static struct ctl_dir *find_subdir(struct ctl_dir *dir,
				   const char *name, int namelen)
{}

static struct ctl_dir *new_dir(struct ctl_table_set *set,
			       const char *name, int namelen)
{}

/**
 * get_subdir - find or create a subdir with the specified name.
 * @dir:  Directory to create the subdirectory in
 * @name: The name of the subdirectory to find or create
 * @namelen: The length of name
 *
 * Takes a directory with an elevated reference count so we know that
 * if we drop the lock the directory will not go away.  Upon success
 * the reference is moved from @dir to the returned subdirectory.
 * Upon error an error code is returned and the reference on @dir is
 * simply dropped.
 */
static struct ctl_dir *get_subdir(struct ctl_dir *dir,
				  const char *name, int namelen)
{}

static struct ctl_dir *xlate_dir(struct ctl_table_set *set, struct ctl_dir *dir)
{}

static int sysctl_follow_link(struct ctl_table_header **phead,
	struct ctl_table **pentry)
{}

static int sysctl_err(const char *path, struct ctl_table *table, char *fmt, ...)
{}

static int sysctl_check_table_array(const char *path, struct ctl_table *table)
{}

static int sysctl_check_table(const char *path, struct ctl_table_header *header)
{}

static struct ctl_table_header *new_links(struct ctl_dir *dir, struct ctl_table_header *head)
{}

static bool get_links(struct ctl_dir *dir,
		      struct ctl_table_header *header,
		      struct ctl_table_root *link_root)
{}

static int insert_links(struct ctl_table_header *head)
{}

/* Find the directory for the ctl_table. If one is not found create it. */
static struct ctl_dir *sysctl_mkdir_p(struct ctl_dir *dir, const char *path)
{}

/**
 * __register_sysctl_table - register a leaf sysctl table
 * @set: Sysctl tree to register on
 * @path: The path to the directory the sysctl table is in.
 *
 * @table: the top-level table structure. This table should not be free'd
 *         after registration. So it should not be used on stack. It can either
 *         be a global or dynamically allocated by the caller and free'd later
 *         after sysctl unregistration.
 * @table_size : The number of elements in table
 *
 * Register a sysctl table hierarchy. @table should be a filled in ctl_table
 * array.
 *
 * The members of the &struct ctl_table structure are used as follows:
 * procname - the name of the sysctl file under /proc/sys. Set to %NULL to not
 *            enter a sysctl file
 * data     - a pointer to data for use by proc_handler
 * maxlen   - the maximum size in bytes of the data
 * mode     - the file permissions for the /proc/sys file
 * type     - Defines the target type (described in struct definition)
 * proc_handler - the text handler routine (described below)
 *
 * extra1, extra2 - extra pointers usable by the proc handler routines
 * XXX: we should eventually modify these to use long min / max [0]
 * [0] https://lkml.kernel.org/[email protected]
 *
 * Leaf nodes in the sysctl tree will be represented by a single file
 * under /proc; non-leaf nodes are not allowed.
 *
 * There must be a proc_handler routine for any terminal nodes.
 * Several default handlers are available to cover common cases -
 *
 * proc_dostring(), proc_dointvec(), proc_dointvec_jiffies(),
 * proc_dointvec_userhz_jiffies(), proc_dointvec_minmax(),
 * proc_doulongvec_ms_jiffies_minmax(), proc_doulongvec_minmax()
 *
 * It is the handler's job to read the input buffer from user memory
 * and process it. The handler should return 0 on success.
 *
 * This routine returns %NULL on a failure to register, and a pointer
 * to the table header on success.
 */
struct ctl_table_header *__register_sysctl_table(
	struct ctl_table_set *set,
	const char *path, struct ctl_table *table, size_t table_size)
{}

/**
 * register_sysctl_sz - register a sysctl table
 * @path: The path to the directory the sysctl table is in. If the path
 * 	doesn't exist we will create it for you.
 * @table: the table structure. The calller must ensure the life of the @table
 * 	will be kept during the lifetime use of the syctl. It must not be freed
 * 	until unregister_sysctl_table() is called with the given returned table
 * 	with this registration. If your code is non modular then you don't need
 * 	to call unregister_sysctl_table() and can instead use something like
 * 	register_sysctl_init() which does not care for the result of the syctl
 * 	registration.
 * @table_size: The number of elements in table.
 *
 * Register a sysctl table. @table should be a filled in ctl_table
 * array. A completely 0 filled entry terminates the table.
 *
 * See __register_sysctl_table for more details.
 */
struct ctl_table_header *register_sysctl_sz(const char *path, struct ctl_table *table,
					    size_t table_size)
{}
EXPORT_SYMBOL();

/**
 * __register_sysctl_init() - register sysctl table to path
 * @path: path name for sysctl base. If that path doesn't exist we will create
 * 	it for you.
 * @table: This is the sysctl table that needs to be registered to the path.
 * 	The caller must ensure the life of the @table will be kept during the
 * 	lifetime use of the sysctl.
 * @table_name: The name of sysctl table, only used for log printing when
 *              registration fails
 * @table_size: The number of elements in table
 *
 * The sysctl interface is used by userspace to query or modify at runtime
 * a predefined value set on a variable. These variables however have default
 * values pre-set. Code which depends on these variables will always work even
 * if register_sysctl() fails. If register_sysctl() fails you'd just loose the
 * ability to query or modify the sysctls dynamically at run time. Chances of
 * register_sysctl() failing on init are extremely low, and so for both reasons
 * this function does not return any error as it is used by initialization code.
 *
 * Context: if your base directory does not exist it will be created for you.
 */
void __init __register_sysctl_init(const char *path, struct ctl_table *table,
				 const char *table_name, size_t table_size)
{}

static void put_links(struct ctl_table_header *header)
{}

static void drop_sysctl_table(struct ctl_table_header *header)
{}

/**
 * unregister_sysctl_table - unregister a sysctl table hierarchy
 * @header: the header returned from register_sysctl or __register_sysctl_table
 *
 * Unregisters the sysctl table and all children. proc entries may not
 * actually be removed until they are no longer used by anyone.
 */
void unregister_sysctl_table(struct ctl_table_header * header)
{}
EXPORT_SYMBOL();

void setup_sysctl_set(struct ctl_table_set *set,
	struct ctl_table_root *root,
	int (*is_seen)(struct ctl_table_set *))
{}

void retire_sysctl_set(struct ctl_table_set *set)
{}

int __init proc_sys_init(void)
{}

struct sysctl_alias {};

/*
 * Historically some settings had both sysctl and a command line parameter.
 * With the generic sysctl. parameter support, we can handle them at a single
 * place and only keep the historical name for compatibility. This is not meant
 * to add brand new aliases. When adding existing aliases, consider whether
 * the possibly different moment of changing the value (e.g. from early_param
 * to the moment do_sysctl_args() is called) is an issue for the specific
 * parameter.
 */
static const struct sysctl_alias sysctl_aliases[] =;

static const char *sysctl_find_alias(char *param)
{}

bool sysctl_is_alias(char *param)
{}

/* Set sysctl value passed on kernel command line. */
static int process_sysctl_arg(char *param, char *val,
			       const char *unused, void *arg)
{}

void do_sysctl_args(void)
{}