xref: /openbmc/linux/fs/proc/self.c (revision e656d8a6)
1e656d8a6SEric W. Biederman #include <linux/proc_fs.h>
2e656d8a6SEric W. Biederman #include <linux/sched.h>
3e656d8a6SEric W. Biederman #include <linux/namei.h>
4e656d8a6SEric W. Biederman 
5e656d8a6SEric W. Biederman /*
6e656d8a6SEric W. Biederman  * /proc/self:
7e656d8a6SEric W. Biederman  */
8e656d8a6SEric W. Biederman static int proc_self_readlink(struct dentry *dentry, char __user *buffer,
9e656d8a6SEric W. Biederman 			      int buflen)
10e656d8a6SEric W. Biederman {
11e656d8a6SEric W. Biederman 	struct pid_namespace *ns = dentry->d_sb->s_fs_info;
12e656d8a6SEric W. Biederman 	pid_t tgid = task_tgid_nr_ns(current, ns);
13e656d8a6SEric W. Biederman 	char tmp[PROC_NUMBUF];
14e656d8a6SEric W. Biederman 	if (!tgid)
15e656d8a6SEric W. Biederman 		return -ENOENT;
16e656d8a6SEric W. Biederman 	sprintf(tmp, "%d", tgid);
17e656d8a6SEric W. Biederman 	return vfs_readlink(dentry,buffer,buflen,tmp);
18e656d8a6SEric W. Biederman }
19e656d8a6SEric W. Biederman 
20e656d8a6SEric W. Biederman static void *proc_self_follow_link(struct dentry *dentry, struct nameidata *nd)
21e656d8a6SEric W. Biederman {
22e656d8a6SEric W. Biederman 	struct pid_namespace *ns = dentry->d_sb->s_fs_info;
23e656d8a6SEric W. Biederman 	pid_t tgid = task_tgid_nr_ns(current, ns);
24e656d8a6SEric W. Biederman 	char *name = ERR_PTR(-ENOENT);
25e656d8a6SEric W. Biederman 	if (tgid) {
26e656d8a6SEric W. Biederman 		/* 11 for max length of signed int in decimal + NULL term */
27e656d8a6SEric W. Biederman 		name = kmalloc(12, GFP_KERNEL);
28e656d8a6SEric W. Biederman 		if (!name)
29e656d8a6SEric W. Biederman 			name = ERR_PTR(-ENOMEM);
30e656d8a6SEric W. Biederman 		else
31e656d8a6SEric W. Biederman 			sprintf(name, "%d", tgid);
32e656d8a6SEric W. Biederman 	}
33e656d8a6SEric W. Biederman 	nd_set_link(nd, name);
34e656d8a6SEric W. Biederman 	return NULL;
35e656d8a6SEric W. Biederman }
36e656d8a6SEric W. Biederman 
37e656d8a6SEric W. Biederman static void proc_self_put_link(struct dentry *dentry, struct nameidata *nd,
38e656d8a6SEric W. Biederman 				void *cookie)
39e656d8a6SEric W. Biederman {
40e656d8a6SEric W. Biederman 	char *s = nd_get_link(nd);
41e656d8a6SEric W. Biederman 	if (!IS_ERR(s))
42e656d8a6SEric W. Biederman 		kfree(s);
43e656d8a6SEric W. Biederman }
44e656d8a6SEric W. Biederman 
45e656d8a6SEric W. Biederman static const struct inode_operations proc_self_inode_operations = {
46e656d8a6SEric W. Biederman 	.readlink	= proc_self_readlink,
47e656d8a6SEric W. Biederman 	.follow_link	= proc_self_follow_link,
48e656d8a6SEric W. Biederman 	.put_link	= proc_self_put_link,
49e656d8a6SEric W. Biederman };
50e656d8a6SEric W. Biederman 
51e656d8a6SEric W. Biederman void __init proc_self_init(void)
52e656d8a6SEric W. Biederman {
53e656d8a6SEric W. Biederman 	struct proc_dir_entry *proc_self_symlink;
54e656d8a6SEric W. Biederman 	mode_t mode;
55e656d8a6SEric W. Biederman 
56e656d8a6SEric W. Biederman 	mode = S_IFLNK | S_IRWXUGO;
57e656d8a6SEric W. Biederman 	proc_self_symlink = proc_create("self", mode, NULL, NULL );
58e656d8a6SEric W. Biederman 	proc_self_symlink->proc_iops = &proc_self_inode_operations;
59e656d8a6SEric W. Biederman }
60