Branch data Line data Source code
1 : : #include <linux/sched.h>
2 : : #include <linux/namei.h>
3 : : #include <linux/slab.h>
4 : : #include <linux/pid_namespace.h>
5 : : #include "internal.h"
6 : :
7 : : /*
8 : : * /proc/self:
9 : : */
10 : 0 : static int proc_self_readlink(struct dentry *dentry, char __user *buffer,
11 : : int buflen)
12 : : {
13 : 0 : struct pid_namespace *ns = dentry->d_sb->s_fs_info;
14 : 0 : pid_t tgid = task_tgid_nr_ns(current, ns);
15 : : char tmp[PROC_NUMBUF];
16 [ # # ]: 0 : if (!tgid)
17 : : return -ENOENT;
18 : 0 : sprintf(tmp, "%d", tgid);
19 : 0 : return vfs_readlink(dentry,buffer,buflen,tmp);
20 : : }
21 : :
22 : 0 : static void *proc_self_follow_link(struct dentry *dentry, struct nameidata *nd)
23 : : {
24 : 4057 : struct pid_namespace *ns = dentry->d_sb->s_fs_info;
25 : 4057 : pid_t tgid = task_tgid_nr_ns(current, ns);
26 : : char *name = ERR_PTR(-ENOENT);
27 [ + - ]: 4057 : if (tgid) {
28 : : /* 11 for max length of signed int in decimal + NULL term */
29 : : name = kmalloc(12, GFP_KERNEL);
30 [ + - ]: 4057 : if (!name)
31 : : name = ERR_PTR(-ENOMEM);
32 : : else
33 : 4057 : sprintf(name, "%d", tgid);
34 : : }
35 : : nd_set_link(nd, name);
36 : 0 : return NULL;
37 : : }
38 : :
39 : : static const struct inode_operations proc_self_inode_operations = {
40 : : .readlink = proc_self_readlink,
41 : : .follow_link = proc_self_follow_link,
42 : : .put_link = kfree_put_link,
43 : : };
44 : :
45 : : static unsigned self_inum;
46 : :
47 : 0 : int proc_setup_self(struct super_block *s)
48 : : {
49 : 0 : struct inode *root_inode = s->s_root->d_inode;
50 : 0 : struct pid_namespace *ns = s->s_fs_info;
51 : : struct dentry *self;
52 : :
53 : 0 : mutex_lock(&root_inode->i_mutex);
54 : 0 : self = d_alloc_name(s->s_root, "self");
55 [ # # ]: 0 : if (self) {
56 : 0 : struct inode *inode = new_inode_pseudo(s);
57 [ # # ]: 0 : if (inode) {
58 : 0 : inode->i_ino = self_inum;
59 : 0 : inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME;
60 : 0 : inode->i_mode = S_IFLNK | S_IRWXUGO;
61 : 0 : inode->i_uid = GLOBAL_ROOT_UID;
62 : 0 : inode->i_gid = GLOBAL_ROOT_GID;
63 : 0 : inode->i_op = &proc_self_inode_operations;
64 : : d_add(self, inode);
65 : : } else {
66 : 0 : dput(self);
67 : : self = ERR_PTR(-ENOMEM);
68 : : }
69 : : } else {
70 : : self = ERR_PTR(-ENOMEM);
71 : : }
72 : 0 : mutex_unlock(&root_inode->i_mutex);
73 [ # # ]: 0 : if (IS_ERR(self)) {
74 : 0 : pr_err("proc_fill_super: can't allocate /proc/self\n");
75 : 0 : return PTR_ERR(self);
76 : : }
77 : 0 : ns->proc_self = self;
78 : 0 : return 0;
79 : : }
80 : :
81 : 0 : void __init proc_self_init(void)
82 : : {
83 : 0 : proc_alloc_inum(&self_inum);
84 : 0 : }
|