^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) }