xref: /OK3568_Linux_fs/kernel/fs/proc/self.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0
2*4882a593Smuzhiyun #include <linux/cache.h>
3*4882a593Smuzhiyun #include <linux/sched.h>
4*4882a593Smuzhiyun #include <linux/slab.h>
5*4882a593Smuzhiyun #include <linux/pid_namespace.h>
6*4882a593Smuzhiyun #include "internal.h"
7*4882a593Smuzhiyun 
8*4882a593Smuzhiyun /*
9*4882a593Smuzhiyun  * /proc/self:
10*4882a593Smuzhiyun  */
proc_self_get_link(struct dentry * dentry,struct inode * inode,struct delayed_call * done)11*4882a593Smuzhiyun static const char *proc_self_get_link(struct dentry *dentry,
12*4882a593Smuzhiyun 				      struct inode *inode,
13*4882a593Smuzhiyun 				      struct delayed_call *done)
14*4882a593Smuzhiyun {
15*4882a593Smuzhiyun 	struct pid_namespace *ns = proc_pid_ns(inode->i_sb);
16*4882a593Smuzhiyun 	pid_t tgid = task_tgid_nr_ns(current, ns);
17*4882a593Smuzhiyun 	char *name;
18*4882a593Smuzhiyun 
19*4882a593Smuzhiyun 	if (!tgid)
20*4882a593Smuzhiyun 		return ERR_PTR(-ENOENT);
21*4882a593Smuzhiyun 	/* max length of unsigned int in decimal + NULL term */
22*4882a593Smuzhiyun 	name = kmalloc(10 + 1, dentry ? GFP_KERNEL : GFP_ATOMIC);
23*4882a593Smuzhiyun 	if (unlikely(!name))
24*4882a593Smuzhiyun 		return dentry ? ERR_PTR(-ENOMEM) : ERR_PTR(-ECHILD);
25*4882a593Smuzhiyun 	sprintf(name, "%u", tgid);
26*4882a593Smuzhiyun 	set_delayed_call(done, kfree_link, name);
27*4882a593Smuzhiyun 	return name;
28*4882a593Smuzhiyun }
29*4882a593Smuzhiyun 
30*4882a593Smuzhiyun static const struct inode_operations proc_self_inode_operations = {
31*4882a593Smuzhiyun 	.get_link	= proc_self_get_link,
32*4882a593Smuzhiyun };
33*4882a593Smuzhiyun 
34*4882a593Smuzhiyun static unsigned self_inum __ro_after_init;
35*4882a593Smuzhiyun 
proc_setup_self(struct super_block * s)36*4882a593Smuzhiyun int proc_setup_self(struct super_block *s)
37*4882a593Smuzhiyun {
38*4882a593Smuzhiyun 	struct inode *root_inode = d_inode(s->s_root);
39*4882a593Smuzhiyun 	struct proc_fs_info *fs_info = proc_sb_info(s);
40*4882a593Smuzhiyun 	struct dentry *self;
41*4882a593Smuzhiyun 	int ret = -ENOMEM;
42*4882a593Smuzhiyun 
43*4882a593Smuzhiyun 	inode_lock(root_inode);
44*4882a593Smuzhiyun 	self = d_alloc_name(s->s_root, "self");
45*4882a593Smuzhiyun 	if (self) {
46*4882a593Smuzhiyun 		struct inode *inode = new_inode(s);
47*4882a593Smuzhiyun 		if (inode) {
48*4882a593Smuzhiyun 			inode->i_ino = self_inum;
49*4882a593Smuzhiyun 			inode->i_mtime = inode->i_atime = inode->i_ctime = current_time(inode);
50*4882a593Smuzhiyun 			inode->i_mode = S_IFLNK | S_IRWXUGO;
51*4882a593Smuzhiyun 			inode->i_uid = GLOBAL_ROOT_UID;
52*4882a593Smuzhiyun 			inode->i_gid = GLOBAL_ROOT_GID;
53*4882a593Smuzhiyun 			inode->i_op = &proc_self_inode_operations;
54*4882a593Smuzhiyun 			d_add(self, inode);
55*4882a593Smuzhiyun 			ret = 0;
56*4882a593Smuzhiyun 		} else {
57*4882a593Smuzhiyun 			dput(self);
58*4882a593Smuzhiyun 		}
59*4882a593Smuzhiyun 	}
60*4882a593Smuzhiyun 	inode_unlock(root_inode);
61*4882a593Smuzhiyun 
62*4882a593Smuzhiyun 	if (ret)
63*4882a593Smuzhiyun 		pr_err("proc_fill_super: can't allocate /proc/self\n");
64*4882a593Smuzhiyun 	else
65*4882a593Smuzhiyun 		fs_info->proc_self = self;
66*4882a593Smuzhiyun 
67*4882a593Smuzhiyun 	return ret;
68*4882a593Smuzhiyun }
69*4882a593Smuzhiyun 
proc_self_init(void)70*4882a593Smuzhiyun void __init proc_self_init(void)
71*4882a593Smuzhiyun {
72*4882a593Smuzhiyun 	proc_alloc_inum(&self_inum);
73*4882a593Smuzhiyun }
74