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