^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0-only
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * proc/fs/generic.c --- generic routines for the proc-fs
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * This file contains generic proc-fs routines for handling
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) * directories and files.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) * Copyright (C) 1991, 1992 Linus Torvalds.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) * Copyright (C) 1997 Theodore Ts'o
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) #include <linux/cache.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) #include <linux/errno.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) #include <linux/time.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) #include <linux/proc_fs.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) #include <linux/stat.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) #include <linux/mm.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) #include <linux/namei.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) #include <linux/slab.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) #include <linux/printk.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) #include <linux/mount.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) #include <linux/init.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) #include <linux/idr.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) #include <linux/bitops.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) #include <linux/spinlock.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) #include <linux/completion.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) #include <linux/uaccess.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) #include <linux/seq_file.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) #include "internal.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) static DEFINE_RWLOCK(proc_subdir_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) struct kmem_cache *proc_dir_entry_cache __ro_after_init;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) void pde_free(struct proc_dir_entry *pde)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) if (S_ISLNK(pde->mode))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) kfree(pde->data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) if (pde->name != pde->inline_name)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) kfree(pde->name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) kmem_cache_free(proc_dir_entry_cache, pde);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) static int proc_match(const char *name, struct proc_dir_entry *de, unsigned int len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) if (len < de->namelen)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) if (len > de->namelen)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) return memcmp(name, de->name, len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) static struct proc_dir_entry *pde_subdir_first(struct proc_dir_entry *dir)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) return rb_entry_safe(rb_first(&dir->subdir), struct proc_dir_entry,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) subdir_node);
^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 proc_dir_entry *pde_subdir_next(struct proc_dir_entry *dir)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) return rb_entry_safe(rb_next(&dir->subdir_node), struct proc_dir_entry,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) subdir_node);
^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) static struct proc_dir_entry *pde_subdir_find(struct proc_dir_entry *dir,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) const char *name,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) unsigned int len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) struct rb_node *node = dir->subdir.rb_node;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) while (node) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) struct proc_dir_entry *de = rb_entry(node,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) struct proc_dir_entry,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) subdir_node);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) int result = proc_match(name, de, len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) if (result < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) node = node->rb_left;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) else if (result > 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) node = node->rb_right;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) return de;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) static bool pde_subdir_insert(struct proc_dir_entry *dir,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) struct proc_dir_entry *de)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) struct rb_root *root = &dir->subdir;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) struct rb_node **new = &root->rb_node, *parent = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) /* Figure out where to put new node */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) while (*new) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) struct proc_dir_entry *this = rb_entry(*new,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) struct proc_dir_entry,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) subdir_node);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) int result = proc_match(de->name, this, de->namelen);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) parent = *new;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) if (result < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) new = &(*new)->rb_left;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) else if (result > 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) new = &(*new)->rb_right;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) /* Add new node and rebalance tree. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) rb_link_node(&de->subdir_node, parent, new);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) rb_insert_color(&de->subdir_node, root);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) return true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) static int proc_notify_change(struct dentry *dentry, struct iattr *iattr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) struct inode *inode = d_inode(dentry);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) struct proc_dir_entry *de = PDE(inode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) int error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) error = setattr_prepare(dentry, iattr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) if (error)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) return error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) setattr_copy(inode, iattr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) mark_inode_dirty(inode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) proc_set_user(de, inode->i_uid, inode->i_gid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) de->mode = inode->i_mode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) static int proc_getattr(const struct path *path, struct kstat *stat,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) u32 request_mask, unsigned int query_flags)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) struct inode *inode = d_inode(path->dentry);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) struct proc_dir_entry *de = PDE(inode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) if (de) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) nlink_t nlink = READ_ONCE(de->nlink);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) if (nlink > 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) set_nlink(inode, nlink);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) generic_fillattr(inode, stat);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) static const struct inode_operations proc_file_inode_operations = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) .setattr = proc_notify_change,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) * This function parses a name such as "tty/driver/serial", and
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) * returns the struct proc_dir_entry for "/proc/tty/driver", and
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) * returns "serial" in residual.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) static int __xlate_proc_name(const char *name, struct proc_dir_entry **ret,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) const char **residual)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) const char *cp = name, *next;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) struct proc_dir_entry *de;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) de = *ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) if (!de)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) de = &proc_root;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) while (1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) next = strchr(cp, '/');
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) if (!next)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) de = pde_subdir_find(de, cp, next - cp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) if (!de) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) WARN(1, "name '%s'\n", name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) return -ENOENT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) cp = next + 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) *residual = cp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) *ret = de;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) return 0;
^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 int xlate_proc_name(const char *name, struct proc_dir_entry **ret,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) const char **residual)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) int rv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) read_lock(&proc_subdir_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) rv = __xlate_proc_name(name, ret, residual);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) read_unlock(&proc_subdir_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) return rv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) static DEFINE_IDA(proc_inum_ida);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) #define PROC_DYNAMIC_FIRST 0xF0000000U
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) * Return an inode number between PROC_DYNAMIC_FIRST and
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) * 0xffffffff, or zero on failure.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) int proc_alloc_inum(unsigned int *inum)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) i = ida_simple_get(&proc_inum_ida, 0, UINT_MAX - PROC_DYNAMIC_FIRST + 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) if (i < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) return i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) *inum = PROC_DYNAMIC_FIRST + (unsigned int)i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) void proc_free_inum(unsigned int inum)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) ida_simple_remove(&proc_inum_ida, inum - PROC_DYNAMIC_FIRST);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) static int proc_misc_d_revalidate(struct dentry *dentry, unsigned int flags)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) if (flags & LOOKUP_RCU)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) return -ECHILD;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) if (atomic_read(&PDE(d_inode(dentry))->in_use) < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) return 0; /* revalidate */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) static int proc_misc_d_delete(const struct dentry *dentry)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) return atomic_read(&PDE(d_inode(dentry))->in_use) < 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) static const struct dentry_operations proc_misc_dentry_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) .d_revalidate = proc_misc_d_revalidate,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) .d_delete = proc_misc_d_delete,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) * Don't create negative dentries here, return -ENOENT by hand
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) * instead.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) struct dentry *proc_lookup_de(struct inode *dir, struct dentry *dentry,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) struct proc_dir_entry *de)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) struct inode *inode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) read_lock(&proc_subdir_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) de = pde_subdir_find(de, dentry->d_name.name, dentry->d_name.len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) if (de) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) pde_get(de);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) read_unlock(&proc_subdir_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) inode = proc_get_inode(dir->i_sb, de);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) if (!inode)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) return ERR_PTR(-ENOMEM);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) d_set_d_op(dentry, de->proc_dops);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) return d_splice_alias(inode, dentry);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) read_unlock(&proc_subdir_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) return ERR_PTR(-ENOENT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) struct dentry *proc_lookup(struct inode *dir, struct dentry *dentry,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) unsigned int flags)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) struct proc_fs_info *fs_info = proc_sb_info(dir->i_sb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) if (fs_info->pidonly == PROC_PIDONLY_ON)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) return ERR_PTR(-ENOENT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) return proc_lookup_de(dir, dentry, PDE(dir));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) }
^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) * This returns non-zero if at EOF, so that the /proc
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) * root directory can use this and check if it should
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) * continue with the <pid> entries..
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) * Note that the VFS-layer doesn't care about the return
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) * value of the readdir() call, as long as it's non-negative
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) * for success..
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) int proc_readdir_de(struct file *file, struct dir_context *ctx,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) struct proc_dir_entry *de)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) if (!dir_emit_dots(file, ctx))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) i = ctx->pos - 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) read_lock(&proc_subdir_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) de = pde_subdir_first(de);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) for (;;) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) if (!de) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) read_unlock(&proc_subdir_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) if (!i)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) de = pde_subdir_next(de);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) i--;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) do {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) struct proc_dir_entry *next;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) pde_get(de);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) read_unlock(&proc_subdir_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) if (!dir_emit(ctx, de->name, de->namelen,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) de->low_ino, de->mode >> 12)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) pde_put(de);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) ctx->pos++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) read_lock(&proc_subdir_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) next = pde_subdir_next(de);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) pde_put(de);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) de = next;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) } while (de);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) read_unlock(&proc_subdir_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) int proc_readdir(struct file *file, struct dir_context *ctx)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) struct inode *inode = file_inode(file);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) struct proc_fs_info *fs_info = proc_sb_info(inode->i_sb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) if (fs_info->pidonly == PROC_PIDONLY_ON)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) return proc_readdir_de(file, ctx, PDE(inode));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) * These are the generic /proc directory operations. They
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) * use the in-memory "struct proc_dir_entry" tree to parse
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) * the /proc directory.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) static const struct file_operations proc_dir_operations = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) .llseek = generic_file_llseek,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) .read = generic_read_dir,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) .iterate_shared = proc_readdir,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) static int proc_net_d_revalidate(struct dentry *dentry, unsigned int flags)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) const struct dentry_operations proc_net_dentry_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) .d_revalidate = proc_net_d_revalidate,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) .d_delete = always_delete_dentry,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) * proc directories can do almost nothing..
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) static const struct inode_operations proc_dir_inode_operations = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) .lookup = proc_lookup,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) .getattr = proc_getattr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) .setattr = proc_notify_change,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) /* returns the registered entry, or frees dp and returns NULL on failure */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) struct proc_dir_entry *proc_register(struct proc_dir_entry *dir,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) struct proc_dir_entry *dp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) if (proc_alloc_inum(&dp->low_ino))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) goto out_free_entry;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) write_lock(&proc_subdir_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) dp->parent = dir;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) if (pde_subdir_insert(dir, dp) == false) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) WARN(1, "proc_dir_entry '%s/%s' already registered\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) dir->name, dp->name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) write_unlock(&proc_subdir_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) goto out_free_inum;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) dir->nlink++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) write_unlock(&proc_subdir_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) return dp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) out_free_inum:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) proc_free_inum(dp->low_ino);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) out_free_entry:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) pde_free(dp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) static struct proc_dir_entry *__proc_create(struct proc_dir_entry **parent,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) const char *name,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) umode_t mode,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) nlink_t nlink)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) struct proc_dir_entry *ent = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) const char *fn;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) struct qstr qstr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) if (xlate_proc_name(name, parent, &fn) != 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) qstr.name = fn;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) qstr.len = strlen(fn);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) if (qstr.len == 0 || qstr.len >= 256) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) WARN(1, "name len %u\n", qstr.len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) if (qstr.len == 1 && fn[0] == '.') {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) WARN(1, "name '.'\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) if (qstr.len == 2 && fn[0] == '.' && fn[1] == '.') {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) WARN(1, "name '..'\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422) if (*parent == &proc_root && name_to_int(&qstr) != ~0U) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423) WARN(1, "create '/proc/%s' by hand\n", qstr.name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426) if (is_empty_pde(*parent)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427) WARN(1, "attempt to add to permanently empty directory");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431) ent = kmem_cache_zalloc(proc_dir_entry_cache, GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432) if (!ent)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435) if (qstr.len + 1 <= SIZEOF_PDE_INLINE_NAME) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436) ent->name = ent->inline_name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438) ent->name = kmalloc(qstr.len + 1, GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) if (!ent->name) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440) pde_free(ent);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445) memcpy(ent->name, fn, qstr.len + 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446) ent->namelen = qstr.len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447) ent->mode = mode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448) ent->nlink = nlink;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449) ent->subdir = RB_ROOT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450) refcount_set(&ent->refcnt, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451) spin_lock_init(&ent->pde_unload_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452) INIT_LIST_HEAD(&ent->pde_openers);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453) proc_set_user(ent, (*parent)->uid, (*parent)->gid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455) ent->proc_dops = &proc_misc_dentry_ops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458) return ent;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461) struct proc_dir_entry *proc_symlink(const char *name,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462) struct proc_dir_entry *parent, const char *dest)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464) struct proc_dir_entry *ent;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466) ent = __proc_create(&parent, name,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467) (S_IFLNK | S_IRUGO | S_IWUGO | S_IXUGO),1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469) if (ent) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470) ent->data = kmalloc((ent->size=strlen(dest))+1, GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471) if (ent->data) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472) strcpy((char*)ent->data,dest);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473) ent->proc_iops = &proc_link_inode_operations;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474) ent = proc_register(parent, ent);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476) pde_free(ent);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477) ent = NULL;
^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 ent;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482) EXPORT_SYMBOL(proc_symlink);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484) struct proc_dir_entry *_proc_mkdir(const char *name, umode_t mode,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485) struct proc_dir_entry *parent, void *data, bool force_lookup)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487) struct proc_dir_entry *ent;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489) if (mode == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490) mode = S_IRUGO | S_IXUGO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492) ent = __proc_create(&parent, name, S_IFDIR | mode, 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493) if (ent) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494) ent->data = data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495) ent->proc_dir_ops = &proc_dir_operations;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496) ent->proc_iops = &proc_dir_inode_operations;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497) if (force_lookup) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498) pde_force_lookup(ent);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500) ent = proc_register(parent, ent);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502) return ent;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504) EXPORT_SYMBOL_GPL(_proc_mkdir);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506) struct proc_dir_entry *proc_mkdir_data(const char *name, umode_t mode,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507) struct proc_dir_entry *parent, void *data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509) return _proc_mkdir(name, mode, parent, data, false);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511) EXPORT_SYMBOL_GPL(proc_mkdir_data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513) struct proc_dir_entry *proc_mkdir_mode(const char *name, umode_t mode,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514) struct proc_dir_entry *parent)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516) return proc_mkdir_data(name, mode, parent, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518) EXPORT_SYMBOL(proc_mkdir_mode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520) struct proc_dir_entry *proc_mkdir(const char *name,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521) struct proc_dir_entry *parent)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523) return proc_mkdir_data(name, 0, parent, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525) EXPORT_SYMBOL(proc_mkdir);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527) struct proc_dir_entry *proc_create_mount_point(const char *name)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529) umode_t mode = S_IFDIR | S_IRUGO | S_IXUGO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530) struct proc_dir_entry *ent, *parent = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 532) ent = __proc_create(&parent, name, mode, 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 533) if (ent) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 534) ent->data = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 535) ent->proc_dir_ops = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 536) ent->proc_iops = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 537) ent = proc_register(parent, ent);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 538) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 539) return ent;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 540) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 541) EXPORT_SYMBOL(proc_create_mount_point);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 542)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 543) struct proc_dir_entry *proc_create_reg(const char *name, umode_t mode,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 544) struct proc_dir_entry **parent, void *data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 545) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 546) struct proc_dir_entry *p;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 547)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 548) if ((mode & S_IFMT) == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 549) mode |= S_IFREG;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 550) if ((mode & S_IALLUGO) == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 551) mode |= S_IRUGO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 552) if (WARN_ON_ONCE(!S_ISREG(mode)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 553) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 554)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 555) p = __proc_create(parent, name, mode, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 556) if (p) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 557) p->proc_iops = &proc_file_inode_operations;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 558) p->data = data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 559) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 560) return p;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 561) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 562)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 563) static inline void pde_set_flags(struct proc_dir_entry *pde)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 564) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 565) if (pde->proc_ops->proc_flags & PROC_ENTRY_PERMANENT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 566) pde->flags |= PROC_ENTRY_PERMANENT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 567) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 568)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 569) struct proc_dir_entry *proc_create_data(const char *name, umode_t mode,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 570) struct proc_dir_entry *parent,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 571) const struct proc_ops *proc_ops, void *data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 572) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 573) struct proc_dir_entry *p;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 574)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 575) p = proc_create_reg(name, mode, &parent, data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 576) if (!p)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 577) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 578) p->proc_ops = proc_ops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 579) pde_set_flags(p);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 580) return proc_register(parent, p);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 581) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 582) EXPORT_SYMBOL(proc_create_data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 583)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 584) struct proc_dir_entry *proc_create(const char *name, umode_t mode,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 585) struct proc_dir_entry *parent,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 586) const struct proc_ops *proc_ops)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 587) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 588) return proc_create_data(name, mode, parent, proc_ops, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 589) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 590) EXPORT_SYMBOL(proc_create);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 591)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 592) static int proc_seq_open(struct inode *inode, struct file *file)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 593) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 594) struct proc_dir_entry *de = PDE(inode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 595)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 596) if (de->state_size)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 597) return seq_open_private(file, de->seq_ops, de->state_size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 598) return seq_open(file, de->seq_ops);
^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) static int proc_seq_release(struct inode *inode, struct file *file)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 602) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 603) struct proc_dir_entry *de = PDE(inode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 604)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 605) if (de->state_size)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 606) return seq_release_private(inode, file);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 607) return seq_release(inode, file);
^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 const struct proc_ops proc_seq_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 611) /* not permanent -- can call into arbitrary seq_operations */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 612) .proc_open = proc_seq_open,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 613) .proc_read_iter = seq_read_iter,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 614) .proc_lseek = seq_lseek,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 615) .proc_release = proc_seq_release,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 616) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 617)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 618) struct proc_dir_entry *proc_create_seq_private(const char *name, umode_t mode,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 619) struct proc_dir_entry *parent, const struct seq_operations *ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 620) unsigned int state_size, void *data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 621) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 622) struct proc_dir_entry *p;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 623)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 624) p = proc_create_reg(name, mode, &parent, data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 625) if (!p)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 626) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 627) p->proc_ops = &proc_seq_ops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 628) p->seq_ops = ops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 629) p->state_size = state_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 630) return proc_register(parent, p);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 631) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 632) EXPORT_SYMBOL(proc_create_seq_private);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 633)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 634) static int proc_single_open(struct inode *inode, struct file *file)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 635) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 636) struct proc_dir_entry *de = PDE(inode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 637)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 638) return single_open(file, de->single_show, de->data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 639) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 640)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 641) static const struct proc_ops proc_single_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 642) /* not permanent -- can call into arbitrary ->single_show */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 643) .proc_open = proc_single_open,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 644) .proc_read_iter = seq_read_iter,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 645) .proc_lseek = seq_lseek,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 646) .proc_release = single_release,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 647) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 648)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 649) struct proc_dir_entry *proc_create_single_data(const char *name, umode_t mode,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 650) struct proc_dir_entry *parent,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 651) int (*show)(struct seq_file *, void *), void *data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 652) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 653) struct proc_dir_entry *p;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 654)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 655) p = proc_create_reg(name, mode, &parent, data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 656) if (!p)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 657) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 658) p->proc_ops = &proc_single_ops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 659) p->single_show = show;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 660) return proc_register(parent, p);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 661) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 662) EXPORT_SYMBOL(proc_create_single_data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 663)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 664) void proc_set_size(struct proc_dir_entry *de, loff_t size)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 665) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 666) de->size = size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 667) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 668) EXPORT_SYMBOL(proc_set_size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 669)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 670) void proc_set_user(struct proc_dir_entry *de, kuid_t uid, kgid_t gid)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 671) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 672) de->uid = uid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 673) de->gid = gid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 674) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 675) EXPORT_SYMBOL(proc_set_user);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 676)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 677) void pde_put(struct proc_dir_entry *pde)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 678) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 679) if (refcount_dec_and_test(&pde->refcnt)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 680) proc_free_inum(pde->low_ino);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 681) pde_free(pde);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 682) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 683) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 684)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 685) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 686) * Remove a /proc entry and free it if it's not currently in use.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 687) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 688) void remove_proc_entry(const char *name, struct proc_dir_entry *parent)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 689) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 690) struct proc_dir_entry *de = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 691) const char *fn = name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 692) unsigned int len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 693)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 694) write_lock(&proc_subdir_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 695) if (__xlate_proc_name(name, &parent, &fn) != 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 696) write_unlock(&proc_subdir_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 697) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 698) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 699) len = strlen(fn);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 700)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 701) de = pde_subdir_find(parent, fn, len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 702) if (de) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 703) if (unlikely(pde_is_permanent(de))) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 704) WARN(1, "removing permanent /proc entry '%s'", de->name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 705) de = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 706) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 707) rb_erase(&de->subdir_node, &parent->subdir);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 708) if (S_ISDIR(de->mode))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 709) parent->nlink--;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 710) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 711) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 712) write_unlock(&proc_subdir_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 713) if (!de) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 714) WARN(1, "name '%s'\n", name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 715) return;
^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) proc_entry_rundown(de);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 719)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 720) WARN(pde_subdir_first(de),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 721) "%s: removing non-empty directory '%s/%s', leaking at least '%s'\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 722) __func__, de->parent->name, de->name, pde_subdir_first(de)->name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 723) pde_put(de);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 724) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 725) EXPORT_SYMBOL(remove_proc_entry);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 726)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 727) int remove_proc_subtree(const char *name, struct proc_dir_entry *parent)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 728) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 729) struct proc_dir_entry *root = NULL, *de, *next;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 730) const char *fn = name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 731) unsigned int len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 732)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 733) write_lock(&proc_subdir_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 734) if (__xlate_proc_name(name, &parent, &fn) != 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 735) write_unlock(&proc_subdir_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 736) return -ENOENT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 737) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 738) len = strlen(fn);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 739)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 740) root = pde_subdir_find(parent, fn, len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 741) if (!root) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 742) write_unlock(&proc_subdir_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 743) return -ENOENT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 744) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 745) if (unlikely(pde_is_permanent(root))) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 746) write_unlock(&proc_subdir_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 747) WARN(1, "removing permanent /proc entry '%s/%s'",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 748) root->parent->name, root->name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 749) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 750) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 751) rb_erase(&root->subdir_node, &parent->subdir);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 752)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 753) de = root;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 754) while (1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 755) next = pde_subdir_first(de);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 756) if (next) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 757) if (unlikely(pde_is_permanent(next))) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 758) write_unlock(&proc_subdir_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 759) WARN(1, "removing permanent /proc entry '%s/%s'",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 760) next->parent->name, next->name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 761) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 762) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 763) rb_erase(&next->subdir_node, &de->subdir);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 764) de = next;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 765) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 766) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 767) next = de->parent;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 768) if (S_ISDIR(de->mode))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 769) next->nlink--;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 770) write_unlock(&proc_subdir_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 771)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 772) proc_entry_rundown(de);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 773) if (de == root)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 774) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 775) pde_put(de);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 776)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 777) write_lock(&proc_subdir_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 778) de = next;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 779) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 780) pde_put(root);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 781) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 782) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 783) EXPORT_SYMBOL(remove_proc_subtree);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 784)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 785) void *proc_get_parent_data(const struct inode *inode)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 786) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 787) struct proc_dir_entry *de = PDE(inode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 788) return de->parent->data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 789) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 790) EXPORT_SYMBOL_GPL(proc_get_parent_data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 791)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 792) void proc_remove(struct proc_dir_entry *de)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 793) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 794) if (de)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 795) remove_proc_subtree(de->name, de->parent);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 796) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 797) EXPORT_SYMBOL(proc_remove);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 798)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 799) void *PDE_DATA(const struct inode *inode)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 800) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 801) return __PDE_DATA(inode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 802) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 803) EXPORT_SYMBOL(PDE_DATA);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 804)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 805) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 806) * Pull a user buffer into memory and pass it to the file's write handler if
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 807) * one is supplied. The ->write() method is permitted to modify the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 808) * kernel-side buffer.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 809) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 810) ssize_t proc_simple_write(struct file *f, const char __user *ubuf, size_t size,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 811) loff_t *_pos)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 812) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 813) struct proc_dir_entry *pde = PDE(file_inode(f));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 814) char *buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 815) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 816)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 817) if (!pde->write)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 818) return -EACCES;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 819) if (size == 0 || size > PAGE_SIZE - 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 820) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 821) buf = memdup_user_nul(ubuf, size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 822) if (IS_ERR(buf))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 823) return PTR_ERR(buf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 824) ret = pde->write(f, buf, size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 825) kfree(buf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 826) return ret == 0 ? size : ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 827) }