Commit 980f8f8f authored by Linus Torvalds's avatar Linus Torvalds
Browse files
Pull sysctl updates from Joel Granados:
 "sysctl ctl_table constification:

   - Constifying ctl_table structs prevents the modification of
     proc_handler function pointers. All ctl_table struct arguments are
     const qualified in the sysctl API in such a way that the ctl_table
     arrays being defined elsewhere and passed through sysctl can be
     constified one-by-one.

     We kick the constification off by qualifying user_table in
     kernel/ucount.c and expect all the ctl_tables to be constified in
     the coming releases.

  Misc fixes:

   - Adjust comments in two places to better reflect the code

   - Remove superfluous dput calls

   - Remove Luis from sysctl maintainership

   - Replace comments about holding a lock with calls to
     lockdep_assert_held"

* tag 'sysctl-6.13-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/sysctl/sysctl:
  sysctl: Reduce dput(child) calls in proc_sys_fill_cache()
  sysctl: Reorganize kerneldoc parameter names
  ucounts: constify sysctl table user_table
  sysctl: update comments to new registration APIs
  MAINTAINERS: remove me from sysctl
  sysctl: Convert locking comments to lockdep assertions
  const_structs.checkpatch: add ctl_table
  sysctl: make internal ctl_tables const
  sysctl: allow registration of const struct ctl_table
  sysctl: move internal interfaces to const struct ctl_table
  bpf: Constify ctl_table argument of filter function
parents 2a163a4c 9c738dae
Loading
Loading
Loading
Loading
+0 −1
Original line number Diff line number Diff line
@@ -18641,7 +18641,6 @@ F: include/linux/proc_fs.h
F:	tools/testing/selftests/proc/
PROC SYSCTL
M:	Luis Chamberlain <mcgrof@kernel.org>
M:	Kees Cook <kees@kernel.org>
M:	Joel Granados <joel.granados@kernel.org>
L:	linux-kernel@vger.kernel.org
+1 −1
Original line number Diff line number Diff line
@@ -102,7 +102,7 @@ struct proc_inode {
	union proc_op op;
	struct proc_dir_entry *pde;
	struct ctl_table_header *sysctl;
	struct ctl_table *sysctl_entry;
	const struct ctl_table *sysctl_entry;
	struct hlist_node sibling_inodes;
	const struct proc_ns_operations *ns_ops;
	struct inode vfs_inode;
+60 −53
Original line number Diff line number Diff line
@@ -17,6 +17,7 @@
#include <linux/bpf-cgroup.h>
#include <linux/mount.h>
#include <linux/kmemleak.h>
#include <linux/lockdep.h>
#include "internal.h"

#define list_for_each_table_entry(entry, header)	\
@@ -33,7 +34,7 @@ static const struct inode_operations proc_sys_dir_operations;
 * Support for permanently empty directories.
 * Must be non-empty to avoid sharing an address with other tables.
 */
static struct ctl_table sysctl_mount_point[] = {
static const struct ctl_table sysctl_mount_point[] = {
	{ }
};

@@ -67,7 +68,7 @@ void proc_sys_poll_notify(struct ctl_table_poll *poll)
	wake_up_interruptible(&poll->wait);
}

static struct ctl_table root_table[] = {
static const struct ctl_table root_table[] = {
	{
		.procname = "",
		.mode = S_IFDIR|S_IRUGO|S_IXUGO,
@@ -88,7 +89,7 @@ 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);
	const struct ctl_table **pentry);
static int insert_links(struct ctl_table_header *head);
static void put_links(struct ctl_table_header *header);

@@ -109,14 +110,15 @@ static int namecmp(const char *name1, int len1, const char *name2, int len2)
	return cmp;
}

/* Called under sysctl_lock */
static struct ctl_table *find_entry(struct ctl_table_header **phead,
static const struct ctl_table *find_entry(struct ctl_table_header **phead,
	struct ctl_dir *dir, const char *name, int namelen)
{
	struct ctl_table_header *head;
	struct ctl_table *entry;
	const struct ctl_table *entry;
	struct rb_node *node = dir->root.rb_node;

	lockdep_assert_held(&sysctl_lock);

	while (node)
	{
		struct ctl_node *ctl_node;
@@ -141,7 +143,7 @@ static struct ctl_table *find_entry(struct ctl_table_header **phead,
	return NULL;
}

static int insert_entry(struct ctl_table_header *head, struct ctl_table *entry)
static int insert_entry(struct ctl_table_header *head, const struct ctl_table *entry)
{
	struct rb_node *node = &head->node[entry - head->ctl_table].node;
	struct rb_node **p = &head->parent->root.rb_node;
@@ -151,7 +153,7 @@ static int insert_entry(struct ctl_table_header *head, struct ctl_table *entry)

	while (*p) {
		struct ctl_table_header *parent_head;
		struct ctl_table *parent_entry;
		const struct ctl_table *parent_entry;
		struct ctl_node *parent_node;
		const char *parent_name;
		int cmp;
@@ -180,7 +182,7 @@ static int insert_entry(struct ctl_table_header *head, struct ctl_table *entry)
	return 0;
}

static void erase_entry(struct ctl_table_header *head, struct ctl_table *entry)
static void erase_entry(struct ctl_table_header *head, const struct ctl_table *entry)
{
	struct rb_node *node = &head->node[entry - head->ctl_table].node;

@@ -189,7 +191,7 @@ 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)
	struct ctl_node *node, const struct ctl_table *table, size_t table_size)
{
	head->ctl_table = table;
	head->ctl_table_size = table_size;
@@ -204,7 +206,7 @@ static void init_header(struct ctl_table_header *head,
	head->node = node;
	INIT_HLIST_HEAD(&head->inodes);
	if (node) {
		struct ctl_table *entry;
		const struct ctl_table *entry;

		list_for_each_table_entry(entry, head) {
			node->header = head;
@@ -217,7 +219,7 @@ static void init_header(struct ctl_table_header *head,

static void erase_header(struct ctl_table_header *head)
{
	struct ctl_table *entry;
	const struct ctl_table *entry;

	list_for_each_table_entry(entry, head)
		erase_entry(head, entry);
@@ -225,7 +227,7 @@ static void erase_header(struct ctl_table_header *head)

static int insert_header(struct ctl_dir *dir, struct ctl_table_header *header)
{
	struct ctl_table *entry;
	const struct ctl_table *entry;
	struct ctl_table_header *dir_h = &dir->header;
	int err;

@@ -263,18 +265,20 @@ static int insert_header(struct ctl_dir *dir, struct ctl_table_header *header)
	return err;
}

/* called under sysctl_lock */
static int use_table(struct ctl_table_header *p)
{
	lockdep_assert_held(&sysctl_lock);

	if (unlikely(p->unregistering))
		return 0;
	p->used++;
	return 1;
}

/* called under sysctl_lock */
static void unuse_table(struct ctl_table_header *p)
{
	lockdep_assert_held(&sysctl_lock);

	if (!--p->used)
		if (unlikely(p->unregistering))
			complete(p->unregistering);
@@ -285,9 +289,11 @@ static void proc_sys_invalidate_dcache(struct ctl_table_header *head)
	proc_invalidate_siblings_dcache(&head->inodes, &sysctl_lock);
}

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

	/*
	 * if p->used is 0, nobody will ever touch that entry again;
	 * we'll eliminate all paths to it before dropping sysctl_lock
@@ -344,12 +350,12 @@ lookup_header_set(struct ctl_table_root *root)
	return set;
}

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

	spin_lock(&sysctl_lock);
	entry = find_entry(&head, dir, name, namelen);
@@ -374,10 +380,10 @@ 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)
	struct ctl_table_header **phead, const struct ctl_table **pentry)
{
	struct ctl_table_header *head = NULL;
	struct ctl_table *entry = NULL;
	const struct ctl_table *entry = NULL;
	struct ctl_node *ctl_node;

	spin_lock(&sysctl_lock);
@@ -391,10 +397,10 @@ static void first_entry(struct ctl_dir *dir,
	*pentry = entry;
}

static void next_entry(struct ctl_table_header **phead, struct ctl_table **pentry)
static void next_entry(struct ctl_table_header **phead, const struct ctl_table **pentry)
{
	struct ctl_table_header *head = *phead;
	struct ctl_table *entry = *pentry;
	const struct ctl_table *entry = *pentry;
	struct ctl_node *ctl_node = &head->node[entry - head->ctl_table];

	spin_lock(&sysctl_lock);
@@ -427,7 +433,7 @@ static int test_perm(int mode, int op)
	return -EACCES;
}

static int sysctl_perm(struct ctl_table_header *head, struct ctl_table *table, int op)
static int sysctl_perm(struct ctl_table_header *head, const struct ctl_table *table, int op)
{
	struct ctl_table_root *root = head->root;
	int mode;
@@ -441,7 +447,7 @@ static int sysctl_perm(struct ctl_table_header *head, struct ctl_table *table, i
}

static struct inode *proc_sys_make_inode(struct super_block *sb,
		struct ctl_table_header *head, struct ctl_table *table)
		struct ctl_table_header *head, const struct ctl_table *table)
{
	struct ctl_table_root *root = head->root;
	struct inode *inode;
@@ -512,7 +518,7 @@ static struct dentry *proc_sys_lookup(struct inode *dir, struct dentry *dentry,
	struct ctl_table_header *head = grab_header(dir);
	struct ctl_table_header *h = NULL;
	const struct qstr *name = &dentry->d_name;
	struct ctl_table *p;
	const struct ctl_table *p;
	struct inode *inode;
	struct dentry *err = ERR_PTR(-ENOENT);
	struct ctl_dir *ctl_dir;
@@ -550,7 +556,7 @@ static ssize_t proc_sys_call_handler(struct kiocb *iocb, struct iov_iter *iter,
{
	struct inode *inode = file_inode(iocb->ki_filp);
	struct ctl_table_header *head = grab_header(inode);
	struct ctl_table *table = PROC_I(inode)->sysctl_entry;
	const struct ctl_table *table = PROC_I(inode)->sysctl_entry;
	size_t count = iov_iter_count(iter);
	char *kbuf;
	ssize_t error;
@@ -624,7 +630,7 @@ static ssize_t proc_sys_write(struct kiocb *iocb, struct iov_iter *iter)
static int proc_sys_open(struct inode *inode, struct file *filp)
{
	struct ctl_table_header *head = grab_header(inode);
	struct ctl_table *table = PROC_I(inode)->sysctl_entry;
	const struct ctl_table *table = PROC_I(inode)->sysctl_entry;

	/* sysctl was unregistered */
	if (IS_ERR(head))
@@ -642,7 +648,7 @@ static __poll_t proc_sys_poll(struct file *filp, poll_table *wait)
{
	struct inode *inode = file_inode(filp);
	struct ctl_table_header *head = grab_header(inode);
	struct ctl_table *table = PROC_I(inode)->sysctl_entry;
	const struct ctl_table *table = PROC_I(inode)->sysctl_entry;
	__poll_t ret = DEFAULT_POLLMASK;
	unsigned long event;

@@ -673,7 +679,7 @@ 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)
				const struct ctl_table *table)
{
	struct dentry *child, *dir = file->f_path.dentry;
	struct inode *inode;
@@ -698,11 +704,11 @@ static bool proc_sys_fill_cache(struct file *file,
			res = d_splice_alias(inode, child);
			d_lookup_done(child);
			if (unlikely(res)) {
				if (IS_ERR(res)) {
				dput(child);

				if (IS_ERR(res))
					return false;
				}
				dput(child);

				child = res;
			}
		}
@@ -717,7 +723,7 @@ static bool proc_sys_fill_cache(struct file *file,
static bool proc_sys_link_fill_cache(struct file *file,
				    struct dir_context *ctx,
				    struct ctl_table_header *head,
				    struct ctl_table *table)
				    const struct ctl_table *table)
{
	bool ret = true;

@@ -735,7 +741,7 @@ static bool proc_sys_link_fill_cache(struct file *file,
	return ret;
}

static int scan(struct ctl_table_header *head, struct ctl_table *table,
static int scan(struct ctl_table_header *head, const struct ctl_table *table,
		unsigned long *pos, struct file *file,
		struct dir_context *ctx)
{
@@ -759,7 +765,7 @@ static int proc_sys_readdir(struct file *file, struct dir_context *ctx)
{
	struct ctl_table_header *head = grab_header(file_inode(file));
	struct ctl_table_header *h = NULL;
	struct ctl_table *entry;
	const struct ctl_table *entry;
	struct ctl_dir *ctl_dir;
	unsigned long pos;

@@ -792,7 +798,7 @@ static int proc_sys_permission(struct mnt_idmap *idmap,
	 * are _NOT_ writeable, capabilities or not.
	 */
	struct ctl_table_header *head;
	struct ctl_table *table;
	const struct ctl_table *table;
	int error;

	/* Executable files are not allowed under /proc/sys/ */
@@ -836,7 +842,7 @@ static int proc_sys_getattr(struct mnt_idmap *idmap,
{
	struct inode *inode = d_inode(path->dentry);
	struct ctl_table_header *head = grab_header(inode);
	struct ctl_table *table = PROC_I(inode)->sysctl_entry;
	const struct ctl_table *table = PROC_I(inode)->sysctl_entry;

	if (IS_ERR(head))
		return PTR_ERR(head);
@@ -935,7 +941,7 @@ static struct ctl_dir *find_subdir(struct ctl_dir *dir,
				   const char *name, int namelen)
{
	struct ctl_table_header *head;
	struct ctl_table *entry;
	const struct ctl_table *entry;

	entry = find_entry(&head, dir, name, namelen);
	if (!entry)
@@ -1046,12 +1052,12 @@ 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)
	const struct ctl_table **pentry)
{
	struct ctl_table_header *head;
	const struct ctl_table *entry;
	struct ctl_table_root *root;
	struct ctl_table_set *set;
	struct ctl_table *entry;
	struct ctl_dir *dir;
	int ret;

@@ -1078,7 +1084,7 @@ static int sysctl_follow_link(struct ctl_table_header **phead,
	return ret;
}

static int sysctl_err(const char *path, struct ctl_table *table, char *fmt, ...)
static int sysctl_err(const char *path, const struct ctl_table *table, char *fmt, ...)
{
	struct va_format vaf;
	va_list args;
@@ -1094,7 +1100,7 @@ static int sysctl_err(const char *path, struct ctl_table *table, char *fmt, ...)
	return -EINVAL;
}

static int sysctl_check_table_array(const char *path, struct ctl_table *table)
static int sysctl_check_table_array(const char *path, const struct ctl_table *table)
{
	unsigned int extra;
	int err = 0;
@@ -1133,7 +1139,7 @@ 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)
{
	struct ctl_table *entry;
	const struct ctl_table *entry;
	int err = 0;
	list_for_each_table_entry(entry, header) {
		if (!entry->procname)
@@ -1169,8 +1175,9 @@ 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)
{
	struct ctl_table *link_table, *entry, *link;
	struct ctl_table *link_table, *link;
	struct ctl_table_header *links;
	const struct ctl_table *entry;
	struct ctl_node *node;
	char *link_name;
	int name_bytes;
@@ -1215,7 +1222,7 @@ static bool get_links(struct ctl_dir *dir,
		      struct ctl_table_root *link_root)
{
	struct ctl_table_header *tmp_head;
	struct ctl_table *entry, *link;
	const struct ctl_table *entry, *link;

	if (header->ctl_table_size == 0 ||
	    sysctl_is_perm_empty_ctl_header(header))
@@ -1358,7 +1365,7 @@ static struct ctl_dir *sysctl_mkdir_p(struct ctl_dir *dir, const char *path)
 */
struct ctl_table_header *__register_sysctl_table(
	struct ctl_table_set *set,
	const char *path, struct ctl_table *table, size_t table_size)
	const char *path, const struct ctl_table *table, size_t table_size)
{
	struct ctl_table_root *root = set->dir.header.root;
	struct ctl_table_header *header;
@@ -1419,7 +1426,7 @@ struct ctl_table_header *__register_sysctl_table(
 *
 * See __register_sysctl_table for more details.
 */
struct ctl_table_header *register_sysctl_sz(const char *path, struct ctl_table *table,
struct ctl_table_header *register_sysctl_sz(const char *path, const struct ctl_table *table,
					    size_t table_size)
{
	return __register_sysctl_table(&sysctl_table_root.default_set,
@@ -1448,7 +1455,7 @@ EXPORT_SYMBOL(register_sysctl_sz);
 *
 * 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,
void __init __register_sysctl_init(const char *path, const struct ctl_table *table,
				 const char *table_name, size_t table_size)
{
	struct ctl_table_header *hdr = register_sysctl_sz(path, table, table_size);
@@ -1466,7 +1473,7 @@ static void put_links(struct ctl_table_header *header)
	struct ctl_table_root *root = header->root;
	struct ctl_dir *parent = header->parent;
	struct ctl_dir *core_parent;
	struct ctl_table *entry;
	const struct ctl_table *entry;

	if (header->set == root_set)
		return;
@@ -1477,7 +1484,7 @@ static void put_links(struct ctl_table_header *header)

	list_for_each_table_entry(entry, header) {
		struct ctl_table_header *link_head;
		struct ctl_table *link;
		const struct ctl_table *link;
		const char *name = entry->procname;

		link = find_entry(&link_head, core_parent, name, strlen(name));
+1 −1
Original line number Diff line number Diff line
@@ -138,7 +138,7 @@ int __cgroup_bpf_check_dev_permission(short dev_type, u32 major, u32 minor,
				      short access, enum cgroup_bpf_attach_type atype);

int __cgroup_bpf_run_filter_sysctl(struct ctl_table_header *head,
				   struct ctl_table *table, int write,
				   const struct ctl_table *table, int write,
				   char **buf, size_t *pcount, loff_t *ppos,
				   enum cgroup_bpf_attach_type atype);

+8 −10
Original line number Diff line number Diff line
@@ -90,9 +90,7 @@ int proc_do_static_key(const struct ctl_table *table, int write, void *buffer,

/*
 * Register a set of sysctl names by calling register_sysctl
 * with an initialised array of struct ctl_table's.  An entry with 
 * NULL procname terminates the table.  table->de will be
 * set up by the registration and need not be initialised in advance.
 * with an initialised array of struct ctl_table's.
 *
 * sysctl names can be mirrored automatically under /proc/sys.  The
 * procname supplied controls /proc naming.
@@ -133,7 +131,7 @@ static inline void *proc_sys_poll_event(struct ctl_table_poll *poll)

/* A sysctl table is an array of struct ctl_table: */
struct ctl_table {
	const char *procname;		/* Text ID for /proc/sys, or zero */
	const char *procname;		/* Text ID for /proc/sys */
	void *data;
	int maxlen;
	umode_t mode;
@@ -162,7 +160,7 @@ struct ctl_node {
struct ctl_table_header {
	union {
		struct {
			struct ctl_table *ctl_table;
			const struct ctl_table *ctl_table;
			int ctl_table_size;
			int used;
			int count;
@@ -223,13 +221,13 @@ extern void retire_sysctl_set(struct ctl_table_set *set);

struct ctl_table_header *__register_sysctl_table(
	struct ctl_table_set *set,
	const char *path, struct ctl_table *table, size_t table_size);
struct ctl_table_header *register_sysctl_sz(const char *path, struct ctl_table *table,
	const char *path, const struct ctl_table *table, size_t table_size);
struct ctl_table_header *register_sysctl_sz(const char *path, const struct ctl_table *table,
					    size_t table_size);
void unregister_sysctl_table(struct ctl_table_header * table);

extern int sysctl_init_bases(void);
extern void __register_sysctl_init(const char *path, struct ctl_table *table,
extern void __register_sysctl_init(const char *path, const struct ctl_table *table,
				 const char *table_name, size_t table_size);
#define register_sysctl_init(path, table)	\
	__register_sysctl_init(path, table, #table, ARRAY_SIZE(table))
@@ -251,7 +249,7 @@ extern int no_unaligned_warning;

#else /* CONFIG_SYSCTL */

static inline void register_sysctl_init(const char *path, struct ctl_table *table)
static inline void register_sysctl_init(const char *path, const struct ctl_table *table)
{
}

@@ -261,7 +259,7 @@ static inline struct ctl_table_header *register_sysctl_mount_point(const char *p
}

static inline struct ctl_table_header *register_sysctl_sz(const char *path,
							  struct ctl_table *table,
							  const struct ctl_table *table,
							  size_t table_size)
{
	return NULL;
Loading