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