brintos

brintos / linux-shallow public Read only

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