Orange Pi5 kernel

Deprecated Linux kernel 5.10.110 for OrangePi 5/5B/5+ boards

3 Commits   0 Branches   0 Tags
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300    1) // SPDX-License-Identifier: GPL-2.0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300    2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300    3)  * /proc/sys support
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300    4)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300    5) #include <linux/init.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300    6) #include <linux/sysctl.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300    7) #include <linux/poll.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300    8) #include <linux/proc_fs.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300    9) #include <linux/printk.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   10) #include <linux/security.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   11) #include <linux/sched.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   12) #include <linux/cred.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   13) #include <linux/namei.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   14) #include <linux/mm.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   15) #include <linux/uio.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   16) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   17) #include <linux/bpf-cgroup.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   18) #include <linux/mount.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   19) #include "internal.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   20) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   21) static const struct dentry_operations proc_sys_dentry_operations;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   22) static const struct file_operations proc_sys_file_operations;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   23) static const struct inode_operations proc_sys_inode_operations;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   24) static const struct file_operations proc_sys_dir_file_operations;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   25) static const struct inode_operations proc_sys_dir_operations;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   26) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   27) /* shared constants to be used in various sysctls */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   28) const int sysctl_vals[] = { 0, 1, INT_MAX };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   29) EXPORT_SYMBOL(sysctl_vals);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   30) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   31) /* Support for permanently empty directories */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   32) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   33) struct ctl_table sysctl_mount_point[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   34) 	{ }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   35) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   36) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   37) static bool is_empty_dir(struct ctl_table_header *head)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   38) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   39) 	return head->ctl_table[0].child == sysctl_mount_point;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   40) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   41) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   42) static void set_empty_dir(struct ctl_dir *dir)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   43) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   44) 	dir->header.ctl_table[0].child = sysctl_mount_point;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   45) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   46) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   47) static void clear_empty_dir(struct ctl_dir *dir)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   48) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   49) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   50) 	dir->header.ctl_table[0].child = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   51) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   52) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   53) void proc_sys_poll_notify(struct ctl_table_poll *poll)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   54) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   55) 	if (!poll)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   56) 		return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   57) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   58) 	atomic_inc(&poll->event);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   59) 	wake_up_interruptible(&poll->wait);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   60) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   61) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   62) static struct ctl_table root_table[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   63) 	{
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   64) 		.procname = "",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   65) 		.mode = S_IFDIR|S_IRUGO|S_IXUGO,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   66) 	},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   67) 	{ }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   68) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   69) static struct ctl_table_root sysctl_table_root = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   70) 	.default_set.dir.header = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   71) 		{{.count = 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   72) 		  .nreg = 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   73) 		  .ctl_table = root_table }},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   74) 		.ctl_table_arg = root_table,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   75) 		.root = &sysctl_table_root,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   76) 		.set = &sysctl_table_root.default_set,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   77) 	},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   78) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   79) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   80) static DEFINE_SPINLOCK(sysctl_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   81) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   82) static void drop_sysctl_table(struct ctl_table_header *header);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   83) static int sysctl_follow_link(struct ctl_table_header **phead,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   84) 	struct ctl_table **pentry);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   85) static int insert_links(struct ctl_table_header *head);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   86) static void put_links(struct ctl_table_header *header);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   87) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   88) static void sysctl_print_dir(struct ctl_dir *dir)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   89) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   90) 	if (dir->header.parent)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   91) 		sysctl_print_dir(dir->header.parent);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   92) 	pr_cont("%s/", dir->header.ctl_table[0].procname);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   93) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   94) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   95) static int namecmp(const char *name1, int len1, const char *name2, int len2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   96) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   97) 	int minlen;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   98) 	int cmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   99) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  100) 	minlen = len1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  101) 	if (minlen > len2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  102) 		minlen = len2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  103) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  104) 	cmp = memcmp(name1, name2, minlen);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  105) 	if (cmp == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  106) 		cmp = len1 - len2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  107) 	return cmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  108) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  109) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  110) /* Called under sysctl_lock */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  111) static struct ctl_table *find_entry(struct ctl_table_header **phead,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  112) 	struct ctl_dir *dir, const char *name, int namelen)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  113) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  114) 	struct ctl_table_header *head;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  115) 	struct ctl_table *entry;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  116) 	struct rb_node *node = dir->root.rb_node;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  117) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  118) 	while (node)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  119) 	{
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  120) 		struct ctl_node *ctl_node;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  121) 		const char *procname;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  122) 		int cmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  123) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  124) 		ctl_node = rb_entry(node, struct ctl_node, node);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  125) 		head = ctl_node->header;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  126) 		entry = &head->ctl_table[ctl_node - head->node];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  127) 		procname = entry->procname;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  128) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  129) 		cmp = namecmp(name, namelen, procname, strlen(procname));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  130) 		if (cmp < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  131) 			node = node->rb_left;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  132) 		else if (cmp > 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  133) 			node = node->rb_right;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  134) 		else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  135) 			*phead = head;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  136) 			return entry;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  137) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  138) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  139) 	return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  140) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  141) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  142) static int insert_entry(struct ctl_table_header *head, struct ctl_table *entry)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  143) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  144) 	struct rb_node *node = &head->node[entry - head->ctl_table].node;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  145) 	struct rb_node **p = &head->parent->root.rb_node;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  146) 	struct rb_node *parent = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  147) 	const char *name = entry->procname;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  148) 	int namelen = strlen(name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  149) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  150) 	while (*p) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  151) 		struct ctl_table_header *parent_head;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  152) 		struct ctl_table *parent_entry;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  153) 		struct ctl_node *parent_node;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  154) 		const char *parent_name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  155) 		int cmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  156) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  157) 		parent = *p;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  158) 		parent_node = rb_entry(parent, struct ctl_node, node);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  159) 		parent_head = parent_node->header;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  160) 		parent_entry = &parent_head->ctl_table[parent_node - parent_head->node];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  161) 		parent_name = parent_entry->procname;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  162) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  163) 		cmp = namecmp(name, namelen, parent_name, strlen(parent_name));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  164) 		if (cmp < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  165) 			p = &(*p)->rb_left;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  166) 		else if (cmp > 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  167) 			p = &(*p)->rb_right;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  168) 		else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  169) 			pr_err("sysctl duplicate entry: ");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  170) 			sysctl_print_dir(head->parent);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  171) 			pr_cont("/%s\n", entry->procname);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  172) 			return -EEXIST;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  173) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  174) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  175) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  176) 	rb_link_node(node, parent, p);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  177) 	rb_insert_color(node, &head->parent->root);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  178) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  179) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  180) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  181) static void erase_entry(struct ctl_table_header *head, struct ctl_table *entry)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  182) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  183) 	struct rb_node *node = &head->node[entry - head->ctl_table].node;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  184) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  185) 	rb_erase(node, &head->parent->root);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  186) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  187) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  188) static void init_header(struct ctl_table_header *head,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  189) 	struct ctl_table_root *root, struct ctl_table_set *set,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  190) 	struct ctl_node *node, struct ctl_table *table)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  191) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  192) 	head->ctl_table = table;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  193) 	head->ctl_table_arg = table;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  194) 	head->used = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  195) 	head->count = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  196) 	head->nreg = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  197) 	head->unregistering = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  198) 	head->root = root;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  199) 	head->set = set;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  200) 	head->parent = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  201) 	head->node = node;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  202) 	INIT_HLIST_HEAD(&head->inodes);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  203) 	if (node) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  204) 		struct ctl_table *entry;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  205) 		for (entry = table; entry->procname; entry++, node++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  206) 			node->header = head;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  207) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  208) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  209) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  210) static void erase_header(struct ctl_table_header *head)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  211) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  212) 	struct ctl_table *entry;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  213) 	for (entry = head->ctl_table; entry->procname; entry++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  214) 		erase_entry(head, entry);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  215) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  216) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  217) static int insert_header(struct ctl_dir *dir, struct ctl_table_header *header)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  218) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  219) 	struct ctl_table *entry;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  220) 	int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  221) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  222) 	/* Is this a permanently empty directory? */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  223) 	if (is_empty_dir(&dir->header))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  224) 		return -EROFS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  225) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  226) 	/* Am I creating a permanently empty directory? */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  227) 	if (header->ctl_table == sysctl_mount_point) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  228) 		if (!RB_EMPTY_ROOT(&dir->root))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  229) 			return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  230) 		set_empty_dir(dir);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  231) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  232) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  233) 	dir->header.nreg++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  234) 	header->parent = dir;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  235) 	err = insert_links(header);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  236) 	if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  237) 		goto fail_links;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  238) 	for (entry = header->ctl_table; entry->procname; entry++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  239) 		err = insert_entry(header, entry);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  240) 		if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  241) 			goto fail;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  242) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  243) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  244) fail:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  245) 	erase_header(header);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  246) 	put_links(header);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  247) fail_links:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  248) 	if (header->ctl_table == sysctl_mount_point)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  249) 		clear_empty_dir(dir);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  250) 	header->parent = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  251) 	drop_sysctl_table(&dir->header);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  252) 	return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  253) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  254) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  255) /* called under sysctl_lock */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  256) static int use_table(struct ctl_table_header *p)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  257) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  258) 	if (unlikely(p->unregistering))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  259) 		return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  260) 	p->used++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  261) 	return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  262) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  263) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  264) /* called under sysctl_lock */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  265) static void unuse_table(struct ctl_table_header *p)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  266) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  267) 	if (!--p->used)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  268) 		if (unlikely(p->unregistering))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  269) 			complete(p->unregistering);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  270) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  271) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  272) static void proc_sys_invalidate_dcache(struct ctl_table_header *head)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  273) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  274) 	proc_invalidate_siblings_dcache(&head->inodes, &sysctl_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  275) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  276) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  277) /* called under sysctl_lock, will reacquire if has to wait */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  278) static void start_unregistering(struct ctl_table_header *p)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  279) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  280) 	/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  281) 	 * if p->used is 0, nobody will ever touch that entry again;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  282) 	 * we'll eliminate all paths to it before dropping sysctl_lock
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  283) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  284) 	if (unlikely(p->used)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  285) 		struct completion wait;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  286) 		init_completion(&wait);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  287) 		p->unregistering = &wait;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  288) 		spin_unlock(&sysctl_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  289) 		wait_for_completion(&wait);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  290) 	} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  291) 		/* anything non-NULL; we'll never dereference it */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  292) 		p->unregistering = ERR_PTR(-EINVAL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  293) 		spin_unlock(&sysctl_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  294) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  295) 	/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  296) 	 * Invalidate dentries for unregistered sysctls: namespaced sysctls
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  297) 	 * can have duplicate names and contaminate dcache very badly.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  298) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  299) 	proc_sys_invalidate_dcache(p);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  300) 	/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  301) 	 * do not remove from the list until nobody holds it; walking the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  302) 	 * list in do_sysctl() relies on that.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  303) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  304) 	spin_lock(&sysctl_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  305) 	erase_header(p);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  306) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  307) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  308) static struct ctl_table_header *sysctl_head_grab(struct ctl_table_header *head)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  309) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  310) 	BUG_ON(!head);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  311) 	spin_lock(&sysctl_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  312) 	if (!use_table(head))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  313) 		head = ERR_PTR(-ENOENT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  314) 	spin_unlock(&sysctl_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  315) 	return head;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  316) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  317) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  318) static void sysctl_head_finish(struct ctl_table_header *head)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  319) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  320) 	if (!head)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  321) 		return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  322) 	spin_lock(&sysctl_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  323) 	unuse_table(head);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  324) 	spin_unlock(&sysctl_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  325) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  326) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  327) static struct ctl_table_set *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  328) lookup_header_set(struct ctl_table_root *root)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  329) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  330) 	struct ctl_table_set *set = &root->default_set;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  331) 	if (root->lookup)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  332) 		set = root->lookup(root);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  333) 	return set;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  334) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  335) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  336) static struct ctl_table *lookup_entry(struct ctl_table_header **phead,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  337) 				      struct ctl_dir *dir,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  338) 				      const char *name, int namelen)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  339) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  340) 	struct ctl_table_header *head;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  341) 	struct ctl_table *entry;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  342) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  343) 	spin_lock(&sysctl_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  344) 	entry = find_entry(&head, dir, name, namelen);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  345) 	if (entry && use_table(head))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  346) 		*phead = head;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  347) 	else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  348) 		entry = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  349) 	spin_unlock(&sysctl_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  350) 	return entry;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  351) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  352) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  353) static struct ctl_node *first_usable_entry(struct rb_node *node)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  354) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  355) 	struct ctl_node *ctl_node;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  356) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  357) 	for (;node; node = rb_next(node)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  358) 		ctl_node = rb_entry(node, struct ctl_node, node);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  359) 		if (use_table(ctl_node->header))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  360) 			return ctl_node;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  361) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  362) 	return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  363) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  364) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  365) static void first_entry(struct ctl_dir *dir,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  366) 	struct ctl_table_header **phead, struct ctl_table **pentry)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  367) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  368) 	struct ctl_table_header *head = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  369) 	struct ctl_table *entry = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  370) 	struct ctl_node *ctl_node;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  371) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  372) 	spin_lock(&sysctl_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  373) 	ctl_node = first_usable_entry(rb_first(&dir->root));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  374) 	spin_unlock(&sysctl_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  375) 	if (ctl_node) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  376) 		head = ctl_node->header;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  377) 		entry = &head->ctl_table[ctl_node - head->node];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  378) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  379) 	*phead = head;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  380) 	*pentry = entry;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  381) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  382) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  383) static void next_entry(struct ctl_table_header **phead, struct ctl_table **pentry)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  384) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  385) 	struct ctl_table_header *head = *phead;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  386) 	struct ctl_table *entry = *pentry;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  387) 	struct ctl_node *ctl_node = &head->node[entry - head->ctl_table];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  388) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  389) 	spin_lock(&sysctl_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  390) 	unuse_table(head);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  391) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  392) 	ctl_node = first_usable_entry(rb_next(&ctl_node->node));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  393) 	spin_unlock(&sysctl_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  394) 	head = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  395) 	if (ctl_node) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  396) 		head = ctl_node->header;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  397) 		entry = &head->ctl_table[ctl_node - head->node];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  398) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  399) 	*phead = head;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  400) 	*pentry = entry;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  401) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  402) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  403) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  404)  * sysctl_perm does NOT grant the superuser all rights automatically, because
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  405)  * some sysctl variables are readonly even to root.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  406)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  407) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  408) static int test_perm(int mode, int op)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  409) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  410) 	if (uid_eq(current_euid(), GLOBAL_ROOT_UID))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  411) 		mode >>= 6;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  412) 	else if (in_egroup_p(GLOBAL_ROOT_GID))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  413) 		mode >>= 3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  414) 	if ((op & ~mode & (MAY_READ|MAY_WRITE|MAY_EXEC)) == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  415) 		return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  416) 	return -EACCES;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  417) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  418) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  419) static int sysctl_perm(struct ctl_table_header *head, struct ctl_table *table, int op)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  420) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  421) 	struct ctl_table_root *root = head->root;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  422) 	int mode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  423) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  424) 	if (root->permissions)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  425) 		mode = root->permissions(head, table);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  426) 	else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  427) 		mode = table->mode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  428) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  429) 	return test_perm(mode, op);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  430) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  431) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  432) static struct inode *proc_sys_make_inode(struct super_block *sb,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  433) 		struct ctl_table_header *head, struct ctl_table *table)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  434) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  435) 	struct ctl_table_root *root = head->root;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  436) 	struct inode *inode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  437) 	struct proc_inode *ei;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  438) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  439) 	inode = new_inode(sb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  440) 	if (!inode)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  441) 		return ERR_PTR(-ENOMEM);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  442) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  443) 	inode->i_ino = get_next_ino();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  444) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  445) 	ei = PROC_I(inode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  446) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  447) 	spin_lock(&sysctl_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  448) 	if (unlikely(head->unregistering)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  449) 		spin_unlock(&sysctl_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  450) 		iput(inode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  451) 		return ERR_PTR(-ENOENT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  452) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  453) 	ei->sysctl = head;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  454) 	ei->sysctl_entry = table;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  455) 	hlist_add_head_rcu(&ei->sibling_inodes, &head->inodes);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  456) 	head->count++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  457) 	spin_unlock(&sysctl_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  458) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  459) 	inode->i_mtime = inode->i_atime = inode->i_ctime = current_time(inode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  460) 	inode->i_mode = table->mode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  461) 	if (!S_ISDIR(table->mode)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  462) 		inode->i_mode |= S_IFREG;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  463) 		inode->i_op = &proc_sys_inode_operations;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  464) 		inode->i_fop = &proc_sys_file_operations;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  465) 	} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  466) 		inode->i_mode |= S_IFDIR;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  467) 		inode->i_op = &proc_sys_dir_operations;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  468) 		inode->i_fop = &proc_sys_dir_file_operations;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  469) 		if (is_empty_dir(head))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  470) 			make_empty_dir_inode(inode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  471) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  472) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  473) 	if (root->set_ownership)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  474) 		root->set_ownership(head, table, &inode->i_uid, &inode->i_gid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  475) 	else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  476) 		inode->i_uid = GLOBAL_ROOT_UID;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  477) 		inode->i_gid = GLOBAL_ROOT_GID;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  478) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  479) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  480) 	return inode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  481) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  482) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  483) void proc_sys_evict_inode(struct inode *inode, struct ctl_table_header *head)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  484) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  485) 	spin_lock(&sysctl_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  486) 	hlist_del_init_rcu(&PROC_I(inode)->sibling_inodes);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  487) 	if (!--head->count)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  488) 		kfree_rcu(head, rcu);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  489) 	spin_unlock(&sysctl_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  490) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  491) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  492) static struct ctl_table_header *grab_header(struct inode *inode)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  493) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  494) 	struct ctl_table_header *head = PROC_I(inode)->sysctl;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  495) 	if (!head)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  496) 		head = &sysctl_table_root.default_set.dir.header;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  497) 	return sysctl_head_grab(head);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  498) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  499) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  500) static struct dentry *proc_sys_lookup(struct inode *dir, struct dentry *dentry,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  501) 					unsigned int flags)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  502) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  503) 	struct ctl_table_header *head = grab_header(dir);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  504) 	struct ctl_table_header *h = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  505) 	const struct qstr *name = &dentry->d_name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  506) 	struct ctl_table *p;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  507) 	struct inode *inode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  508) 	struct dentry *err = ERR_PTR(-ENOENT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  509) 	struct ctl_dir *ctl_dir;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  510) 	int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  511) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  512) 	if (IS_ERR(head))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  513) 		return ERR_CAST(head);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  514) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  515) 	ctl_dir = container_of(head, struct ctl_dir, header);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  516) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  517) 	p = lookup_entry(&h, ctl_dir, name->name, name->len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  518) 	if (!p)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  519) 		goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  520) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  521) 	if (S_ISLNK(p->mode)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  522) 		ret = sysctl_follow_link(&h, &p);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  523) 		err = ERR_PTR(ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  524) 		if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  525) 			goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  526) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  527) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  528) 	inode = proc_sys_make_inode(dir->i_sb, h ? h : head, p);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  529) 	if (IS_ERR(inode)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  530) 		err = ERR_CAST(inode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  531) 		goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  532) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  533) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  534) 	d_set_d_op(dentry, &proc_sys_dentry_operations);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  535) 	err = d_splice_alias(inode, dentry);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  536) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  537) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  538) 	if (h)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  539) 		sysctl_head_finish(h);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  540) 	sysctl_head_finish(head);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  541) 	return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  542) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  543) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  544) static ssize_t proc_sys_call_handler(struct kiocb *iocb, struct iov_iter *iter,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  545) 		int write)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  546) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  547) 	struct inode *inode = file_inode(iocb->ki_filp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  548) 	struct ctl_table_header *head = grab_header(inode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  549) 	struct ctl_table *table = PROC_I(inode)->sysctl_entry;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  550) 	size_t count = iov_iter_count(iter);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  551) 	char *kbuf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  552) 	ssize_t error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  553) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  554) 	if (IS_ERR(head))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  555) 		return PTR_ERR(head);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  556) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  557) 	/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  558) 	 * At this point we know that the sysctl was not unregistered
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  559) 	 * and won't be until we finish.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  560) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  561) 	error = -EPERM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  562) 	if (sysctl_perm(head, table, write ? MAY_WRITE : MAY_READ))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  563) 		goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  564) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  565) 	/* if that can happen at all, it should be -EINVAL, not -EISDIR */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  566) 	error = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  567) 	if (!table->proc_handler)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  568) 		goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  569) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  570) 	/* don't even try if the size is too large */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  571) 	error = -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  572) 	if (count >= KMALLOC_MAX_SIZE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  573) 		goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  574) 	kbuf = kvzalloc(count + 1, GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  575) 	if (!kbuf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  576) 		goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  577) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  578) 	if (write) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  579) 		error = -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  580) 		if (!copy_from_iter_full(kbuf, count, iter))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  581) 			goto out_free_buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  582) 		kbuf[count] = '\0';
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  583) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  584) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  585) 	error = BPF_CGROUP_RUN_PROG_SYSCTL(head, table, write, &kbuf, &count,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  586) 					   &iocb->ki_pos);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  587) 	if (error)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  588) 		goto out_free_buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  589) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  590) 	/* careful: calling conventions are nasty here */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  591) 	error = table->proc_handler(table, write, kbuf, &count, &iocb->ki_pos);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  592) 	if (error)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  593) 		goto out_free_buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  594) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  595) 	if (!write) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  596) 		error = -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  597) 		if (copy_to_iter(kbuf, count, iter) < count)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  598) 			goto out_free_buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  599) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  600) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  601) 	error = count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  602) out_free_buf:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  603) 	kvfree(kbuf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  604) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  605) 	sysctl_head_finish(head);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  606) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  607) 	return error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  608) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  609) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  610) static ssize_t proc_sys_read(struct kiocb *iocb, struct iov_iter *iter)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  611) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  612) 	return proc_sys_call_handler(iocb, iter, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  613) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  614) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  615) static ssize_t proc_sys_write(struct kiocb *iocb, struct iov_iter *iter)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  616) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  617) 	return proc_sys_call_handler(iocb, iter, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  618) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  619) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  620) static int proc_sys_open(struct inode *inode, struct file *filp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  621) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  622) 	struct ctl_table_header *head = grab_header(inode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  623) 	struct ctl_table *table = PROC_I(inode)->sysctl_entry;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  624) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  625) 	/* sysctl was unregistered */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  626) 	if (IS_ERR(head))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  627) 		return PTR_ERR(head);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  628) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  629) 	if (table->poll)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  630) 		filp->private_data = proc_sys_poll_event(table->poll);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  631) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  632) 	sysctl_head_finish(head);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  633) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  634) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  635) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  636) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  637) static __poll_t proc_sys_poll(struct file *filp, poll_table *wait)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  638) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  639) 	struct inode *inode = file_inode(filp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  640) 	struct ctl_table_header *head = grab_header(inode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  641) 	struct ctl_table *table = PROC_I(inode)->sysctl_entry;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  642) 	__poll_t ret = DEFAULT_POLLMASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  643) 	unsigned long event;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  644) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  645) 	/* sysctl was unregistered */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  646) 	if (IS_ERR(head))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  647) 		return EPOLLERR | EPOLLHUP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  648) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  649) 	if (!table->proc_handler)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  650) 		goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  651) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  652) 	if (!table->poll)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  653) 		goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  654) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  655) 	event = (unsigned long)filp->private_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  656) 	poll_wait(filp, &table->poll->wait, wait);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  657) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  658) 	if (event != atomic_read(&table->poll->event)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  659) 		filp->private_data = proc_sys_poll_event(table->poll);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  660) 		ret = EPOLLIN | EPOLLRDNORM | EPOLLERR | EPOLLPRI;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  661) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  662) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  663) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  664) 	sysctl_head_finish(head);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  665) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  666) 	return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  667) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  668) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  669) static bool proc_sys_fill_cache(struct file *file,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  670) 				struct dir_context *ctx,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  671) 				struct ctl_table_header *head,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  672) 				struct ctl_table *table)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  673) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  674) 	struct dentry *child, *dir = file->f_path.dentry;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  675) 	struct inode *inode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  676) 	struct qstr qname;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  677) 	ino_t ino = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  678) 	unsigned type = DT_UNKNOWN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  679) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  680) 	qname.name = table->procname;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  681) 	qname.len  = strlen(table->procname);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  682) 	qname.hash = full_name_hash(dir, qname.name, qname.len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  683) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  684) 	child = d_lookup(dir, &qname);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  685) 	if (!child) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  686) 		DECLARE_WAIT_QUEUE_HEAD_ONSTACK(wq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  687) 		child = d_alloc_parallel(dir, &qname, &wq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  688) 		if (IS_ERR(child))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  689) 			return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  690) 		if (d_in_lookup(child)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  691) 			struct dentry *res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  692) 			inode = proc_sys_make_inode(dir->d_sb, head, table);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  693) 			if (IS_ERR(inode)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  694) 				d_lookup_done(child);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  695) 				dput(child);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  696) 				return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  697) 			}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  698) 			d_set_d_op(child, &proc_sys_dentry_operations);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  699) 			res = d_splice_alias(inode, child);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  700) 			d_lookup_done(child);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  701) 			if (unlikely(res)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  702) 				if (IS_ERR(res)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  703) 					dput(child);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  704) 					return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  705) 				}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  706) 				dput(child);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  707) 				child = res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  708) 			}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  709) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  710) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  711) 	inode = d_inode(child);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  712) 	ino  = inode->i_ino;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  713) 	type = inode->i_mode >> 12;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  714) 	dput(child);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  715) 	return dir_emit(ctx, qname.name, qname.len, ino, type);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  716) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  717) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  718) static bool proc_sys_link_fill_cache(struct file *file,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  719) 				    struct dir_context *ctx,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  720) 				    struct ctl_table_header *head,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  721) 				    struct ctl_table *table)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  722) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  723) 	bool ret = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  724) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  725) 	head = sysctl_head_grab(head);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  726) 	if (IS_ERR(head))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  727) 		return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  728) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  729) 	/* It is not an error if we can not follow the link ignore it */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  730) 	if (sysctl_follow_link(&head, &table))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  731) 		goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  732) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  733) 	ret = proc_sys_fill_cache(file, ctx, head, table);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  734) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  735) 	sysctl_head_finish(head);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  736) 	return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  737) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  738) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  739) static int scan(struct ctl_table_header *head, struct ctl_table *table,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  740) 		unsigned long *pos, struct file *file,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  741) 		struct dir_context *ctx)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  742) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  743) 	bool res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  744) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  745) 	if ((*pos)++ < ctx->pos)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  746) 		return true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  747) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  748) 	if (unlikely(S_ISLNK(table->mode)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  749) 		res = proc_sys_link_fill_cache(file, ctx, head, table);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  750) 	else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  751) 		res = proc_sys_fill_cache(file, ctx, head, table);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  752) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  753) 	if (res)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  754) 		ctx->pos = *pos;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  755) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  756) 	return res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  757) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  758) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  759) static int proc_sys_readdir(struct file *file, struct dir_context *ctx)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  760) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  761) 	struct ctl_table_header *head = grab_header(file_inode(file));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  762) 	struct ctl_table_header *h = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  763) 	struct ctl_table *entry;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  764) 	struct ctl_dir *ctl_dir;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  765) 	unsigned long pos;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  766) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  767) 	if (IS_ERR(head))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  768) 		return PTR_ERR(head);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  769) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  770) 	ctl_dir = container_of(head, struct ctl_dir, header);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  771) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  772) 	if (!dir_emit_dots(file, ctx))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  773) 		goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  774) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  775) 	pos = 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  776) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  777) 	for (first_entry(ctl_dir, &h, &entry); h; next_entry(&h, &entry)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  778) 		if (!scan(h, entry, &pos, file, ctx)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  779) 			sysctl_head_finish(h);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  780) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  781) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  782) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  783) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  784) 	sysctl_head_finish(head);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  785) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  786) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  787) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  788) static int proc_sys_permission(struct inode *inode, int mask)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  789) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  790) 	/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  791) 	 * sysctl entries that are not writeable,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  792) 	 * are _NOT_ writeable, capabilities or not.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  793) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  794) 	struct ctl_table_header *head;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  795) 	struct ctl_table *table;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  796) 	int error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  797) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  798) 	/* Executable files are not allowed under /proc/sys/ */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  799) 	if ((mask & MAY_EXEC) && S_ISREG(inode->i_mode))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  800) 		return -EACCES;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  801) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  802) 	head = grab_header(inode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  803) 	if (IS_ERR(head))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  804) 		return PTR_ERR(head);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  805) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  806) 	table = PROC_I(inode)->sysctl_entry;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  807) 	if (!table) /* global root - r-xr-xr-x */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  808) 		error = mask & MAY_WRITE ? -EACCES : 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  809) 	else /* Use the permissions on the sysctl table entry */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  810) 		error = sysctl_perm(head, table, mask & ~MAY_NOT_BLOCK);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  811) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  812) 	sysctl_head_finish(head);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  813) 	return error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  814) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  815) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  816) static int proc_sys_setattr(struct dentry *dentry, struct iattr *attr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  817) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  818) 	struct inode *inode = d_inode(dentry);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  819) 	int error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  820) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  821) 	if (attr->ia_valid & (ATTR_MODE | ATTR_UID | ATTR_GID))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  822) 		return -EPERM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  823) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  824) 	error = setattr_prepare(dentry, attr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  825) 	if (error)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  826) 		return error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  827) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  828) 	setattr_copy(inode, attr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  829) 	mark_inode_dirty(inode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  830) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  831) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  832) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  833) static int proc_sys_getattr(const struct path *path, struct kstat *stat,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  834) 			    u32 request_mask, unsigned int query_flags)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  835) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  836) 	struct inode *inode = d_inode(path->dentry);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  837) 	struct ctl_table_header *head = grab_header(inode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  838) 	struct ctl_table *table = PROC_I(inode)->sysctl_entry;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  839) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  840) 	if (IS_ERR(head))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  841) 		return PTR_ERR(head);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  842) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  843) 	generic_fillattr(inode, stat);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  844) 	if (table)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  845) 		stat->mode = (stat->mode & S_IFMT) | table->mode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  846) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  847) 	sysctl_head_finish(head);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  848) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  849) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  850) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  851) static const struct file_operations proc_sys_file_operations = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  852) 	.open		= proc_sys_open,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  853) 	.poll		= proc_sys_poll,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  854) 	.read_iter	= proc_sys_read,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  855) 	.write_iter	= proc_sys_write,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  856) 	.splice_read	= generic_file_splice_read,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  857) 	.splice_write	= iter_file_splice_write,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  858) 	.llseek		= default_llseek,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  859) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  860) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  861) static const struct file_operations proc_sys_dir_file_operations = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  862) 	.read		= generic_read_dir,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  863) 	.iterate_shared	= proc_sys_readdir,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  864) 	.llseek		= generic_file_llseek,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  865) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  866) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  867) static const struct inode_operations proc_sys_inode_operations = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  868) 	.permission	= proc_sys_permission,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  869) 	.setattr	= proc_sys_setattr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  870) 	.getattr	= proc_sys_getattr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  871) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  872) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  873) static const struct inode_operations proc_sys_dir_operations = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  874) 	.lookup		= proc_sys_lookup,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  875) 	.permission	= proc_sys_permission,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  876) 	.setattr	= proc_sys_setattr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  877) 	.getattr	= proc_sys_getattr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  878) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  879) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  880) static int proc_sys_revalidate(struct dentry *dentry, unsigned int flags)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  881) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  882) 	if (flags & LOOKUP_RCU)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  883) 		return -ECHILD;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  884) 	return !PROC_I(d_inode(dentry))->sysctl->unregistering;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  885) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  886) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  887) static int proc_sys_delete(const struct dentry *dentry)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  888) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  889) 	return !!PROC_I(d_inode(dentry))->sysctl->unregistering;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  890) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  891) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  892) static int sysctl_is_seen(struct ctl_table_header *p)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  893) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  894) 	struct ctl_table_set *set = p->set;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  895) 	int res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  896) 	spin_lock(&sysctl_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  897) 	if (p->unregistering)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  898) 		res = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  899) 	else if (!set->is_seen)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  900) 		res = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  901) 	else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  902) 		res = set->is_seen(set);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  903) 	spin_unlock(&sysctl_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  904) 	return res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  905) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  906) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  907) static int proc_sys_compare(const struct dentry *dentry,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  908) 		unsigned int len, const char *str, const struct qstr *name)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  909) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  910) 	struct ctl_table_header *head;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  911) 	struct inode *inode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  912) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  913) 	/* Although proc doesn't have negative dentries, rcu-walk means
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  914) 	 * that inode here can be NULL */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  915) 	/* AV: can it, indeed? */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  916) 	inode = d_inode_rcu(dentry);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  917) 	if (!inode)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  918) 		return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  919) 	if (name->len != len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  920) 		return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  921) 	if (memcmp(name->name, str, len))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  922) 		return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  923) 	head = rcu_dereference(PROC_I(inode)->sysctl);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  924) 	return !head || !sysctl_is_seen(head);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  925) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  926) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  927) static const struct dentry_operations proc_sys_dentry_operations = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  928) 	.d_revalidate	= proc_sys_revalidate,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  929) 	.d_delete	= proc_sys_delete,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  930) 	.d_compare	= proc_sys_compare,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  931) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  932) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  933) static struct ctl_dir *find_subdir(struct ctl_dir *dir,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  934) 				   const char *name, int namelen)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  935) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  936) 	struct ctl_table_header *head;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  937) 	struct ctl_table *entry;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  938) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  939) 	entry = find_entry(&head, dir, name, namelen);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  940) 	if (!entry)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  941) 		return ERR_PTR(-ENOENT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  942) 	if (!S_ISDIR(entry->mode))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  943) 		return ERR_PTR(-ENOTDIR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  944) 	return container_of(head, struct ctl_dir, header);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  945) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  946) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  947) static struct ctl_dir *new_dir(struct ctl_table_set *set,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  948) 			       const char *name, int namelen)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  949) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  950) 	struct ctl_table *table;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  951) 	struct ctl_dir *new;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  952) 	struct ctl_node *node;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  953) 	char *new_name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  954) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  955) 	new = kzalloc(sizeof(*new) + sizeof(struct ctl_node) +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  956) 		      sizeof(struct ctl_table)*2 +  namelen + 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  957) 		      GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  958) 	if (!new)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  959) 		return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  960) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  961) 	node = (struct ctl_node *)(new + 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  962) 	table = (struct ctl_table *)(node + 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  963) 	new_name = (char *)(table + 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  964) 	memcpy(new_name, name, namelen);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  965) 	new_name[namelen] = '\0';
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  966) 	table[0].procname = new_name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  967) 	table[0].mode = S_IFDIR|S_IRUGO|S_IXUGO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  968) 	init_header(&new->header, set->dir.header.root, set, node, table);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  969) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  970) 	return new;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  971) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  972) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  973) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  974)  * get_subdir - find or create a subdir with the specified name.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  975)  * @dir:  Directory to create the subdirectory in
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  976)  * @name: The name of the subdirectory to find or create
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  977)  * @namelen: The length of name
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  978)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  979)  * Takes a directory with an elevated reference count so we know that
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  980)  * if we drop the lock the directory will not go away.  Upon success
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  981)  * the reference is moved from @dir to the returned subdirectory.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  982)  * Upon error an error code is returned and the reference on @dir is
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  983)  * simply dropped.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  984)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  985) static struct ctl_dir *get_subdir(struct ctl_dir *dir,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  986) 				  const char *name, int namelen)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  987) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  988) 	struct ctl_table_set *set = dir->header.set;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  989) 	struct ctl_dir *subdir, *new = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  990) 	int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  991) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  992) 	spin_lock(&sysctl_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  993) 	subdir = find_subdir(dir, name, namelen);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  994) 	if (!IS_ERR(subdir))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  995) 		goto found;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  996) 	if (PTR_ERR(subdir) != -ENOENT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  997) 		goto failed;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  998) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  999) 	spin_unlock(&sysctl_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1000) 	new = new_dir(set, name, namelen);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1001) 	spin_lock(&sysctl_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1002) 	subdir = ERR_PTR(-ENOMEM);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1003) 	if (!new)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1004) 		goto failed;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1005) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1006) 	/* Was the subdir added while we dropped the lock? */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1007) 	subdir = find_subdir(dir, name, namelen);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1008) 	if (!IS_ERR(subdir))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1009) 		goto found;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1010) 	if (PTR_ERR(subdir) != -ENOENT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1011) 		goto failed;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1012) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1013) 	/* Nope.  Use the our freshly made directory entry. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1014) 	err = insert_header(dir, &new->header);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1015) 	subdir = ERR_PTR(err);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1016) 	if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1017) 		goto failed;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1018) 	subdir = new;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1019) found:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1020) 	subdir->header.nreg++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1021) failed:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1022) 	if (IS_ERR(subdir)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1023) 		pr_err("sysctl could not get directory: ");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1024) 		sysctl_print_dir(dir);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1025) 		pr_cont("/%*.*s %ld\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1026) 			namelen, namelen, name, PTR_ERR(subdir));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1027) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1028) 	drop_sysctl_table(&dir->header);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1029) 	if (new)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1030) 		drop_sysctl_table(&new->header);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1031) 	spin_unlock(&sysctl_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1032) 	return subdir;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1033) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1034) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1035) static struct ctl_dir *xlate_dir(struct ctl_table_set *set, struct ctl_dir *dir)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1036) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1037) 	struct ctl_dir *parent;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1038) 	const char *procname;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1039) 	if (!dir->header.parent)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1040) 		return &set->dir;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1041) 	parent = xlate_dir(set, dir->header.parent);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1042) 	if (IS_ERR(parent))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1043) 		return parent;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1044) 	procname = dir->header.ctl_table[0].procname;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1045) 	return find_subdir(parent, procname, strlen(procname));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1046) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1047) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1048) static int sysctl_follow_link(struct ctl_table_header **phead,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1049) 	struct ctl_table **pentry)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1050) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1051) 	struct ctl_table_header *head;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1052) 	struct ctl_table_root *root;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1053) 	struct ctl_table_set *set;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1054) 	struct ctl_table *entry;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1055) 	struct ctl_dir *dir;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1056) 	int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1057) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1058) 	ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1059) 	spin_lock(&sysctl_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1060) 	root = (*pentry)->data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1061) 	set = lookup_header_set(root);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1062) 	dir = xlate_dir(set, (*phead)->parent);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1063) 	if (IS_ERR(dir))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1064) 		ret = PTR_ERR(dir);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1065) 	else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1066) 		const char *procname = (*pentry)->procname;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1067) 		head = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1068) 		entry = find_entry(&head, dir, procname, strlen(procname));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1069) 		ret = -ENOENT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1070) 		if (entry && use_table(head)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1071) 			unuse_table(*phead);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1072) 			*phead = head;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1073) 			*pentry = entry;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1074) 			ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1075) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1076) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1077) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1078) 	spin_unlock(&sysctl_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1079) 	return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1080) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1081) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1082) static int sysctl_err(const char *path, struct ctl_table *table, char *fmt, ...)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1083) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1084) 	struct va_format vaf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1085) 	va_list args;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1086) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1087) 	va_start(args, fmt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1088) 	vaf.fmt = fmt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1089) 	vaf.va = &args;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1090) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1091) 	pr_err("sysctl table check failed: %s/%s %pV\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1092) 	       path, table->procname, &vaf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1093) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1094) 	va_end(args);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1095) 	return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1096) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1097) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1098) static int sysctl_check_table_array(const char *path, struct ctl_table *table)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1099) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1100) 	int err = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1101) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1102) 	if ((table->proc_handler == proc_douintvec) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1103) 	    (table->proc_handler == proc_douintvec_minmax)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1104) 		if (table->maxlen != sizeof(unsigned int))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1105) 			err |= sysctl_err(path, table, "array not allowed");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1106) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1107) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1108) 	return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1109) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1110) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1111) static int sysctl_check_table(const char *path, struct ctl_table *table)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1112) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1113) 	int err = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1114) 	for (; table->procname; table++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1115) 		if (table->child)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1116) 			err |= sysctl_err(path, table, "Not a file");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1117) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1118) 		if ((table->proc_handler == proc_dostring) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1119) 		    (table->proc_handler == proc_dointvec) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1120) 		    (table->proc_handler == proc_douintvec) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1121) 		    (table->proc_handler == proc_douintvec_minmax) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1122) 		    (table->proc_handler == proc_dointvec_minmax) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1123) 		    (table->proc_handler == proc_dointvec_jiffies) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1124) 		    (table->proc_handler == proc_dointvec_userhz_jiffies) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1125) 		    (table->proc_handler == proc_dointvec_ms_jiffies) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1126) 		    (table->proc_handler == proc_doulongvec_minmax) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1127) 		    (table->proc_handler == proc_doulongvec_ms_jiffies_minmax)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1128) 			if (!table->data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1129) 				err |= sysctl_err(path, table, "No data");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1130) 			if (!table->maxlen)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1131) 				err |= sysctl_err(path, table, "No maxlen");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1132) 			else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1133) 				err |= sysctl_check_table_array(path, table);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1134) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1135) 		if (!table->proc_handler)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1136) 			err |= sysctl_err(path, table, "No proc_handler");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1137) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1138) 		if ((table->mode & (S_IRUGO|S_IWUGO)) != table->mode)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1139) 			err |= sysctl_err(path, table, "bogus .mode 0%o",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1140) 				table->mode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1141) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1142) 	return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1143) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1144) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1145) static struct ctl_table_header *new_links(struct ctl_dir *dir, struct ctl_table *table,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1146) 	struct ctl_table_root *link_root)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1147) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1148) 	struct ctl_table *link_table, *entry, *link;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1149) 	struct ctl_table_header *links;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1150) 	struct ctl_node *node;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1151) 	char *link_name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1152) 	int nr_entries, name_bytes;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1153) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1154) 	name_bytes = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1155) 	nr_entries = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1156) 	for (entry = table; entry->procname; entry++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1157) 		nr_entries++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1158) 		name_bytes += strlen(entry->procname) + 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1159) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1160) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1161) 	links = kzalloc(sizeof(struct ctl_table_header) +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1162) 			sizeof(struct ctl_node)*nr_entries +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1163) 			sizeof(struct ctl_table)*(nr_entries + 1) +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1164) 			name_bytes,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1165) 			GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1166) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1167) 	if (!links)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1168) 		return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1169) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1170) 	node = (struct ctl_node *)(links + 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1171) 	link_table = (struct ctl_table *)(node + nr_entries);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1172) 	link_name = (char *)&link_table[nr_entries + 1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1173) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1174) 	for (link = link_table, entry = table; entry->procname; link++, entry++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1175) 		int len = strlen(entry->procname) + 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1176) 		memcpy(link_name, entry->procname, len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1177) 		link->procname = link_name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1178) 		link->mode = S_IFLNK|S_IRWXUGO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1179) 		link->data = link_root;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1180) 		link_name += len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1181) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1182) 	init_header(links, dir->header.root, dir->header.set, node, link_table);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1183) 	links->nreg = nr_entries;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1184) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1185) 	return links;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1186) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1187) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1188) static bool get_links(struct ctl_dir *dir,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1189) 	struct ctl_table *table, struct ctl_table_root *link_root)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1190) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1191) 	struct ctl_table_header *head;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1192) 	struct ctl_table *entry, *link;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1193) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1194) 	/* Are there links available for every entry in table? */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1195) 	for (entry = table; entry->procname; entry++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1196) 		const char *procname = entry->procname;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1197) 		link = find_entry(&head, dir, procname, strlen(procname));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1198) 		if (!link)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1199) 			return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1200) 		if (S_ISDIR(link->mode) && S_ISDIR(entry->mode))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1201) 			continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1202) 		if (S_ISLNK(link->mode) && (link->data == link_root))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1203) 			continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1204) 		return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1205) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1206) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1207) 	/* The checks passed.  Increase the registration count on the links */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1208) 	for (entry = table; entry->procname; entry++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1209) 		const char *procname = entry->procname;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1210) 		link = find_entry(&head, dir, procname, strlen(procname));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1211) 		head->nreg++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1212) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1213) 	return true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1214) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1215) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1216) static int insert_links(struct ctl_table_header *head)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1217) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1218) 	struct ctl_table_set *root_set = &sysctl_table_root.default_set;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1219) 	struct ctl_dir *core_parent = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1220) 	struct ctl_table_header *links;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1221) 	int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1222) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1223) 	if (head->set == root_set)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1224) 		return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1225) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1226) 	core_parent = xlate_dir(root_set, head->parent);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1227) 	if (IS_ERR(core_parent))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1228) 		return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1229) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1230) 	if (get_links(core_parent, head->ctl_table, head->root))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1231) 		return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1232) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1233) 	core_parent->header.nreg++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1234) 	spin_unlock(&sysctl_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1235) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1236) 	links = new_links(core_parent, head->ctl_table, head->root);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1237) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1238) 	spin_lock(&sysctl_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1239) 	err = -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1240) 	if (!links)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1241) 		goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1242) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1243) 	err = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1244) 	if (get_links(core_parent, head->ctl_table, head->root)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1245) 		kfree(links);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1246) 		goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1247) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1248) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1249) 	err = insert_header(core_parent, links);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1250) 	if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1251) 		kfree(links);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1252) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1253) 	drop_sysctl_table(&core_parent->header);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1254) 	return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1255) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1256) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1257) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1258)  * __register_sysctl_table - register a leaf sysctl table
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1259)  * @set: Sysctl tree to register on
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1260)  * @path: The path to the directory the sysctl table is in.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1261)  * @table: the top-level table structure
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1262)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1263)  * Register a sysctl table hierarchy. @table should be a filled in ctl_table
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1264)  * array. A completely 0 filled entry terminates the table.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1265)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1266)  * The members of the &struct ctl_table structure are used as follows:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1267)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1268)  * procname - the name of the sysctl file under /proc/sys. Set to %NULL to not
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1269)  *            enter a sysctl file
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1270)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1271)  * data - a pointer to data for use by proc_handler
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1272)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1273)  * maxlen - the maximum size in bytes of the data
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1274)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1275)  * mode - the file permissions for the /proc/sys file
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1276)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1277)  * child - must be %NULL.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1278)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1279)  * proc_handler - the text handler routine (described below)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1280)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1281)  * extra1, extra2 - extra pointers usable by the proc handler routines
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1282)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1283)  * Leaf nodes in the sysctl tree will be represented by a single file
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1284)  * under /proc; non-leaf nodes will be represented by directories.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1285)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1286)  * There must be a proc_handler routine for any terminal nodes.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1287)  * Several default handlers are available to cover common cases -
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1288)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1289)  * proc_dostring(), proc_dointvec(), proc_dointvec_jiffies(),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1290)  * proc_dointvec_userhz_jiffies(), proc_dointvec_minmax(),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1291)  * proc_doulongvec_ms_jiffies_minmax(), proc_doulongvec_minmax()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1292)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1293)  * It is the handler's job to read the input buffer from user memory
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1294)  * and process it. The handler should return 0 on success.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1295)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1296)  * This routine returns %NULL on a failure to register, and a pointer
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1297)  * to the table header on success.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1298)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1299) struct ctl_table_header *__register_sysctl_table(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1300) 	struct ctl_table_set *set,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1301) 	const char *path, struct ctl_table *table)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1302) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1303) 	struct ctl_table_root *root = set->dir.header.root;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1304) 	struct ctl_table_header *header;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1305) 	const char *name, *nextname;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1306) 	struct ctl_dir *dir;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1307) 	struct ctl_table *entry;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1308) 	struct ctl_node *node;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1309) 	int nr_entries = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1310) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1311) 	for (entry = table; entry->procname; entry++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1312) 		nr_entries++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1313) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1314) 	header = kzalloc(sizeof(struct ctl_table_header) +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1315) 			 sizeof(struct ctl_node)*nr_entries, GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1316) 	if (!header)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1317) 		return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1318) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1319) 	node = (struct ctl_node *)(header + 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1320) 	init_header(header, root, set, node, table);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1321) 	if (sysctl_check_table(path, table))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1322) 		goto fail;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1323) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1324) 	spin_lock(&sysctl_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1325) 	dir = &set->dir;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1326) 	/* Reference moved down the diretory tree get_subdir */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1327) 	dir->header.nreg++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1328) 	spin_unlock(&sysctl_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1329) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1330) 	/* Find the directory for the ctl_table */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1331) 	for (name = path; name; name = nextname) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1332) 		int namelen;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1333) 		nextname = strchr(name, '/');
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1334) 		if (nextname) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1335) 			namelen = nextname - name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1336) 			nextname++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1337) 		} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1338) 			namelen = strlen(name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1339) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1340) 		if (namelen == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1341) 			continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1342) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1343) 		dir = get_subdir(dir, name, namelen);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1344) 		if (IS_ERR(dir))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1345) 			goto fail;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1346) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1347) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1348) 	spin_lock(&sysctl_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1349) 	if (insert_header(dir, header))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1350) 		goto fail_put_dir_locked;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1351) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1352) 	drop_sysctl_table(&dir->header);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1353) 	spin_unlock(&sysctl_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1354) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1355) 	return header;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1356) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1357) fail_put_dir_locked:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1358) 	drop_sysctl_table(&dir->header);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1359) 	spin_unlock(&sysctl_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1360) fail:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1361) 	kfree(header);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1362) 	dump_stack();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1363) 	return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1364) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1365) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1366) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1367)  * register_sysctl - register a sysctl table
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1368)  * @path: The path to the directory the sysctl table is in.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1369)  * @table: the table structure
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1370)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1371)  * Register a sysctl table. @table should be a filled in ctl_table
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1372)  * array. A completely 0 filled entry terminates the table.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1373)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1374)  * See __register_sysctl_table for more details.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1375)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1376) struct ctl_table_header *register_sysctl(const char *path, struct ctl_table *table)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1377) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1378) 	return __register_sysctl_table(&sysctl_table_root.default_set,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1379) 					path, table);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1380) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1381) EXPORT_SYMBOL(register_sysctl);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1382) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1383) static char *append_path(const char *path, char *pos, const char *name)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1384) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1385) 	int namelen;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1386) 	namelen = strlen(name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1387) 	if (((pos - path) + namelen + 2) >= PATH_MAX)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1388) 		return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1389) 	memcpy(pos, name, namelen);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1390) 	pos[namelen] = '/';
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1391) 	pos[namelen + 1] = '\0';
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1392) 	pos += namelen + 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1393) 	return pos;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1394) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1395) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1396) static int count_subheaders(struct ctl_table *table)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1397) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1398) 	int has_files = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1399) 	int nr_subheaders = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1400) 	struct ctl_table *entry;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1401) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1402) 	/* special case: no directory and empty directory */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1403) 	if (!table || !table->procname)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1404) 		return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1405) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1406) 	for (entry = table; entry->procname; entry++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1407) 		if (entry->child)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1408) 			nr_subheaders += count_subheaders(entry->child);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1409) 		else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1410) 			has_files = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1411) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1412) 	return nr_subheaders + has_files;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1413) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1414) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1415) static int register_leaf_sysctl_tables(const char *path, char *pos,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1416) 	struct ctl_table_header ***subheader, struct ctl_table_set *set,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1417) 	struct ctl_table *table)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1418) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1419) 	struct ctl_table *ctl_table_arg = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1420) 	struct ctl_table *entry, *files;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1421) 	int nr_files = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1422) 	int nr_dirs = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1423) 	int err = -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1424) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1425) 	for (entry = table; entry->procname; entry++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1426) 		if (entry->child)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1427) 			nr_dirs++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1428) 		else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1429) 			nr_files++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1430) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1431) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1432) 	files = table;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1433) 	/* If there are mixed files and directories we need a new table */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1434) 	if (nr_dirs && nr_files) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1435) 		struct ctl_table *new;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1436) 		files = kcalloc(nr_files + 1, sizeof(struct ctl_table),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1437) 				GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1438) 		if (!files)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1439) 			goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1440) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1441) 		ctl_table_arg = files;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1442) 		for (new = files, entry = table; entry->procname; entry++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1443) 			if (entry->child)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1444) 				continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1445) 			*new = *entry;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1446) 			new++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1447) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1448) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1449) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1450) 	/* Register everything except a directory full of subdirectories */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1451) 	if (nr_files || !nr_dirs) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1452) 		struct ctl_table_header *header;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1453) 		header = __register_sysctl_table(set, path, files);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1454) 		if (!header) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1455) 			kfree(ctl_table_arg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1456) 			goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1457) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1458) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1459) 		/* Remember if we need to free the file table */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1460) 		header->ctl_table_arg = ctl_table_arg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1461) 		**subheader = header;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1462) 		(*subheader)++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1463) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1464) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1465) 	/* Recurse into the subdirectories. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1466) 	for (entry = table; entry->procname; entry++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1467) 		char *child_pos;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1468) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1469) 		if (!entry->child)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1470) 			continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1471) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1472) 		err = -ENAMETOOLONG;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1473) 		child_pos = append_path(path, pos, entry->procname);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1474) 		if (!child_pos)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1475) 			goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1476) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1477) 		err = register_leaf_sysctl_tables(path, child_pos, subheader,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1478) 						  set, entry->child);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1479) 		pos[0] = '\0';
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1480) 		if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1481) 			goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1482) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1483) 	err = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1484) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1485) 	/* On failure our caller will unregister all registered subheaders */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1486) 	return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1487) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1488) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1489) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1490)  * __register_sysctl_paths - register a sysctl table hierarchy
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1491)  * @set: Sysctl tree to register on
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1492)  * @path: The path to the directory the sysctl table is in.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1493)  * @table: the top-level table structure
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1494)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1495)  * Register a sysctl table hierarchy. @table should be a filled in ctl_table
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1496)  * array. A completely 0 filled entry terminates the table.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1497)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1498)  * See __register_sysctl_table for more details.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1499)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1500) struct ctl_table_header *__register_sysctl_paths(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1501) 	struct ctl_table_set *set,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1502) 	const struct ctl_path *path, struct ctl_table *table)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1503) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1504) 	struct ctl_table *ctl_table_arg = table;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1505) 	int nr_subheaders = count_subheaders(table);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1506) 	struct ctl_table_header *header = NULL, **subheaders, **subheader;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1507) 	const struct ctl_path *component;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1508) 	char *new_path, *pos;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1509) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1510) 	pos = new_path = kmalloc(PATH_MAX, GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1511) 	if (!new_path)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1512) 		return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1513) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1514) 	pos[0] = '\0';
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1515) 	for (component = path; component->procname; component++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1516) 		pos = append_path(new_path, pos, component->procname);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1517) 		if (!pos)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1518) 			goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1519) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1520) 	while (table->procname && table->child && !table[1].procname) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1521) 		pos = append_path(new_path, pos, table->procname);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1522) 		if (!pos)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1523) 			goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1524) 		table = table->child;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1525) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1526) 	if (nr_subheaders == 1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1527) 		header = __register_sysctl_table(set, new_path, table);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1528) 		if (header)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1529) 			header->ctl_table_arg = ctl_table_arg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1530) 	} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1531) 		header = kzalloc(sizeof(*header) +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1532) 				 sizeof(*subheaders)*nr_subheaders, GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1533) 		if (!header)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1534) 			goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1535) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1536) 		subheaders = (struct ctl_table_header **) (header + 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1537) 		subheader = subheaders;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1538) 		header->ctl_table_arg = ctl_table_arg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1539) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1540) 		if (register_leaf_sysctl_tables(new_path, pos, &subheader,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1541) 						set, table))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1542) 			goto err_register_leaves;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1543) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1544) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1545) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1546) 	kfree(new_path);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1547) 	return header;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1548) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1549) err_register_leaves:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1550) 	while (subheader > subheaders) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1551) 		struct ctl_table_header *subh = *(--subheader);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1552) 		struct ctl_table *table = subh->ctl_table_arg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1553) 		unregister_sysctl_table(subh);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1554) 		kfree(table);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1555) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1556) 	kfree(header);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1557) 	header = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1558) 	goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1559) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1560) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1561) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1562)  * register_sysctl_table_path - register a sysctl table hierarchy
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1563)  * @path: The path to the directory the sysctl table is in.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1564)  * @table: the top-level table structure
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1565)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1566)  * Register a sysctl table hierarchy. @table should be a filled in ctl_table
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1567)  * array. A completely 0 filled entry terminates the table.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1568)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1569)  * See __register_sysctl_paths for more details.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1570)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1571) struct ctl_table_header *register_sysctl_paths(const struct ctl_path *path,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1572) 						struct ctl_table *table)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1573) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1574) 	return __register_sysctl_paths(&sysctl_table_root.default_set,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1575) 					path, table);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1576) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1577) EXPORT_SYMBOL(register_sysctl_paths);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1578) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1579) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1580)  * register_sysctl_table - register a sysctl table hierarchy
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1581)  * @table: the top-level table structure
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1582)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1583)  * Register a sysctl table hierarchy. @table should be a filled in ctl_table
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1584)  * array. A completely 0 filled entry terminates the table.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1585)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1586)  * See register_sysctl_paths for more details.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1587)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1588) struct ctl_table_header *register_sysctl_table(struct ctl_table *table)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1589) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1590) 	static const struct ctl_path null_path[] = { {} };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1591) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1592) 	return register_sysctl_paths(null_path, table);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1593) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1594) EXPORT_SYMBOL(register_sysctl_table);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1595) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1596) static void put_links(struct ctl_table_header *header)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1597) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1598) 	struct ctl_table_set *root_set = &sysctl_table_root.default_set;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1599) 	struct ctl_table_root *root = header->root;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1600) 	struct ctl_dir *parent = header->parent;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1601) 	struct ctl_dir *core_parent;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1602) 	struct ctl_table *entry;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1603) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1604) 	if (header->set == root_set)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1605) 		return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1606) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1607) 	core_parent = xlate_dir(root_set, parent);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1608) 	if (IS_ERR(core_parent))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1609) 		return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1610) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1611) 	for (entry = header->ctl_table; entry->procname; entry++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1612) 		struct ctl_table_header *link_head;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1613) 		struct ctl_table *link;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1614) 		const char *name = entry->procname;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1615) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1616) 		link = find_entry(&link_head, core_parent, name, strlen(name));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1617) 		if (link &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1618) 		    ((S_ISDIR(link->mode) && S_ISDIR(entry->mode)) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1619) 		     (S_ISLNK(link->mode) && (link->data == root)))) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1620) 			drop_sysctl_table(link_head);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1621) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1622) 		else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1623) 			pr_err("sysctl link missing during unregister: ");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1624) 			sysctl_print_dir(parent);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1625) 			pr_cont("/%s\n", name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1626) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1627) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1628) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1629) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1630) static void drop_sysctl_table(struct ctl_table_header *header)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1631) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1632) 	struct ctl_dir *parent = header->parent;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1633) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1634) 	if (--header->nreg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1635) 		return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1636) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1637) 	if (parent) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1638) 		put_links(header);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1639) 		start_unregistering(header);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1640) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1641) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1642) 	if (!--header->count)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1643) 		kfree_rcu(header, rcu);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1644) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1645) 	if (parent)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1646) 		drop_sysctl_table(&parent->header);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1647) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1648) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1649) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1650)  * unregister_sysctl_table - unregister a sysctl table hierarchy
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1651)  * @header: the header returned from register_sysctl_table
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1652)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1653)  * Unregisters the sysctl table and all children. proc entries may not
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1654)  * actually be removed until they are no longer used by anyone.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1655)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1656) void unregister_sysctl_table(struct ctl_table_header * header)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1657) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1658) 	int nr_subheaders;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1659) 	might_sleep();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1660) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1661) 	if (header == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1662) 		return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1663) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1664) 	nr_subheaders = count_subheaders(header->ctl_table_arg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1665) 	if (unlikely(nr_subheaders > 1)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1666) 		struct ctl_table_header **subheaders;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1667) 		int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1668) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1669) 		subheaders = (struct ctl_table_header **)(header + 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1670) 		for (i = nr_subheaders -1; i >= 0; i--) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1671) 			struct ctl_table_header *subh = subheaders[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1672) 			struct ctl_table *table = subh->ctl_table_arg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1673) 			unregister_sysctl_table(subh);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1674) 			kfree(table);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1675) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1676) 		kfree(header);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1677) 		return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1678) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1679) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1680) 	spin_lock(&sysctl_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1681) 	drop_sysctl_table(header);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1682) 	spin_unlock(&sysctl_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1683) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1684) EXPORT_SYMBOL(unregister_sysctl_table);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1685) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1686) void setup_sysctl_set(struct ctl_table_set *set,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1687) 	struct ctl_table_root *root,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1688) 	int (*is_seen)(struct ctl_table_set *))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1689) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1690) 	memset(set, 0, sizeof(*set));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1691) 	set->is_seen = is_seen;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1692) 	init_header(&set->dir.header, root, set, NULL, root_table);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1693) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1694) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1695) void retire_sysctl_set(struct ctl_table_set *set)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1696) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1697) 	WARN_ON(!RB_EMPTY_ROOT(&set->dir.root));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1698) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1699) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1700) int __init proc_sys_init(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1701) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1702) 	struct proc_dir_entry *proc_sys_root;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1703) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1704) 	proc_sys_root = proc_mkdir("sys", NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1705) 	proc_sys_root->proc_iops = &proc_sys_dir_operations;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1706) 	proc_sys_root->proc_dir_ops = &proc_sys_dir_file_operations;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1707) 	proc_sys_root->nlink = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1708) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1709) 	return sysctl_init();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1710) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1711) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1712) struct sysctl_alias {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1713) 	const char *kernel_param;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1714) 	const char *sysctl_param;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1715) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1716) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1717) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1718)  * Historically some settings had both sysctl and a command line parameter.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1719)  * With the generic sysctl. parameter support, we can handle them at a single
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1720)  * place and only keep the historical name for compatibility. This is not meant
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1721)  * to add brand new aliases. When adding existing aliases, consider whether
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1722)  * the possibly different moment of changing the value (e.g. from early_param
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1723)  * to the moment do_sysctl_args() is called) is an issue for the specific
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1724)  * parameter.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1725)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1726) static const struct sysctl_alias sysctl_aliases[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1727) 	{"hardlockup_all_cpu_backtrace",	"kernel.hardlockup_all_cpu_backtrace" },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1728) 	{"hung_task_panic",			"kernel.hung_task_panic" },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1729) 	{"numa_zonelist_order",			"vm.numa_zonelist_order" },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1730) 	{"softlockup_all_cpu_backtrace",	"kernel.softlockup_all_cpu_backtrace" },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1731) 	{"softlockup_panic",			"kernel.softlockup_panic" },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1732) 	{ }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1733) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1734) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1735) static const char *sysctl_find_alias(char *param)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1736) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1737) 	const struct sysctl_alias *alias;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1738) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1739) 	for (alias = &sysctl_aliases[0]; alias->kernel_param != NULL; alias++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1740) 		if (strcmp(alias->kernel_param, param) == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1741) 			return alias->sysctl_param;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1742) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1743) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1744) 	return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1745) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1746) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1747) /* Set sysctl value passed on kernel command line. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1748) static int process_sysctl_arg(char *param, char *val,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1749) 			       const char *unused, void *arg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1750) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1751) 	char *path;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1752) 	struct vfsmount **proc_mnt = arg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1753) 	struct file_system_type *proc_fs_type;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1754) 	struct file *file;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1755) 	int len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1756) 	int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1757) 	loff_t pos = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1758) 	ssize_t wret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1759) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1760) 	if (strncmp(param, "sysctl", sizeof("sysctl") - 1) == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1761) 		param += sizeof("sysctl") - 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1762) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1763) 		if (param[0] != '/' && param[0] != '.')
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1764) 			return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1765) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1766) 		param++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1767) 	} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1768) 		param = (char *) sysctl_find_alias(param);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1769) 		if (!param)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1770) 			return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1771) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1772) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1773) 	if (!val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1774) 		return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1775) 	len = strlen(val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1776) 	if (len == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1777) 		return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1778) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1779) 	/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1780) 	 * To set sysctl options, we use a temporary mount of proc, look up the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1781) 	 * respective sys/ file and write to it. To avoid mounting it when no
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1782) 	 * options were given, we mount it only when the first sysctl option is
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1783) 	 * found. Why not a persistent mount? There are problems with a
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1784) 	 * persistent mount of proc in that it forces userspace not to use any
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1785) 	 * proc mount options.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1786) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1787) 	if (!*proc_mnt) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1788) 		proc_fs_type = get_fs_type("proc");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1789) 		if (!proc_fs_type) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1790) 			pr_err("Failed to find procfs to set sysctl from command line\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1791) 			return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1792) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1793) 		*proc_mnt = kern_mount(proc_fs_type);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1794) 		put_filesystem(proc_fs_type);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1795) 		if (IS_ERR(*proc_mnt)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1796) 			pr_err("Failed to mount procfs to set sysctl from command line\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1797) 			return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1798) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1799) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1800) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1801) 	path = kasprintf(GFP_KERNEL, "sys/%s", param);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1802) 	if (!path)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1803) 		panic("%s: Failed to allocate path for %s\n", __func__, param);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1804) 	strreplace(path, '.', '/');
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1805) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1806) 	file = file_open_root((*proc_mnt)->mnt_root, *proc_mnt, path, O_WRONLY, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1807) 	if (IS_ERR(file)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1808) 		err = PTR_ERR(file);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1809) 		if (err == -ENOENT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1810) 			pr_err("Failed to set sysctl parameter '%s=%s': parameter not found\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1811) 				param, val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1812) 		else if (err == -EACCES)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1813) 			pr_err("Failed to set sysctl parameter '%s=%s': permission denied (read-only?)\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1814) 				param, val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1815) 		else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1816) 			pr_err("Error %pe opening proc file to set sysctl parameter '%s=%s'\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1817) 				file, param, val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1818) 		goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1819) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1820) 	wret = kernel_write(file, val, len, &pos);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1821) 	if (wret < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1822) 		err = wret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1823) 		if (err == -EINVAL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1824) 			pr_err("Failed to set sysctl parameter '%s=%s': invalid value\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1825) 				param, val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1826) 		else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1827) 			pr_err("Error %pe writing to proc file to set sysctl parameter '%s=%s'\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1828) 				ERR_PTR(err), param, val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1829) 	} else if (wret != len) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1830) 		pr_err("Wrote only %zd bytes of %d writing to proc file %s to set sysctl parameter '%s=%s\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1831) 			wret, len, path, param, val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1832) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1833) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1834) 	err = filp_close(file, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1835) 	if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1836) 		pr_err("Error %pe closing proc file to set sysctl parameter '%s=%s\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1837) 			ERR_PTR(err), param, val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1838) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1839) 	kfree(path);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1840) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1841) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1842) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1843) void do_sysctl_args(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1844) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1845) 	char *command_line;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1846) 	struct vfsmount *proc_mnt = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1847) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1848) 	command_line = kstrdup(saved_command_line, GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1849) 	if (!command_line)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1850) 		panic("%s: Failed to allocate copy of command line\n", __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1851) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1852) 	parse_args("Setting sysctl args", command_line,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1853) 		   NULL, 0, -1, -1, &proc_mnt, process_sysctl_arg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1854) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1855) 	if (proc_mnt)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1856) 		kern_unmount(proc_mnt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1857) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1858) 	kfree(command_line);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1859) }