Orange Pi5 kernel

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

3 Commits   0 Branches   0 Tags
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   1) // SPDX-License-Identifier: GPL-2.0-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) }