2010-07-11 01:52:49 +04:00
# include <linux/sched.h>
2013-04-12 02:51:01 +04:00
# include <linux/slab.h>
2013-03-30 03:27:05 +04:00
# include <linux/pid_namespace.h>
# include "internal.h"
2010-07-11 01:52:49 +04:00
/*
* / proc / self :
*/
static int proc_self_readlink ( struct dentry * dentry , char __user * buffer ,
int buflen )
{
struct pid_namespace * ns = dentry - > d_sb - > s_fs_info ;
pid_t tgid = task_tgid_nr_ns ( current , ns ) ;
char tmp [ PROC_NUMBUF ] ;
if ( ! tgid )
return - ENOENT ;
sprintf ( tmp , " %d " , tgid ) ;
2014-03-14 21:42:45 +04:00
return readlink_copy ( buffer , buflen , tmp ) ;
2010-07-11 01:52:49 +04:00
}
2015-05-02 20:32:22 +03:00
static const char * proc_self_follow_link ( struct dentry * dentry , void * * cookie , struct nameidata * nd )
2010-07-11 01:52:49 +04:00
{
struct pid_namespace * ns = dentry - > d_sb - > s_fs_info ;
pid_t tgid = task_tgid_nr_ns ( current , ns ) ;
2015-05-02 20:32:22 +03:00
char * name ;
if ( ! tgid )
return ERR_PTR ( - ENOENT ) ;
/* 11 for max length of signed int in decimal + NULL term */
name = kmalloc ( 12 , GFP_KERNEL ) ;
if ( ! name )
return ERR_PTR ( - ENOMEM ) ;
sprintf ( name , " %d " , tgid ) ;
return * cookie = name ;
2010-07-11 01:52:49 +04:00
}
static const struct inode_operations proc_self_inode_operations = {
. readlink = proc_self_readlink ,
. follow_link = proc_self_follow_link ,
2013-09-16 18:30:04 +04:00
. put_link = kfree_put_link ,
2010-07-11 01:52:49 +04:00
} ;
2013-03-30 03:27:05 +04:00
static unsigned self_inum ;
int proc_setup_self ( struct super_block * s )
2010-07-11 01:52:49 +04:00
{
2015-03-18 01:25:59 +03:00
struct inode * root_inode = d_inode ( s - > s_root ) ;
2013-03-30 03:27:05 +04:00
struct pid_namespace * ns = s - > s_fs_info ;
struct dentry * self ;
mutex_lock ( & root_inode - > i_mutex ) ;
self = d_alloc_name ( s - > s_root , " self " ) ;
if ( self ) {
struct inode * inode = new_inode_pseudo ( s ) ;
if ( inode ) {
inode - > i_ino = self_inum ;
inode - > i_mtime = inode - > i_atime = inode - > i_ctime = CURRENT_TIME ;
inode - > i_mode = S_IFLNK | S_IRWXUGO ;
inode - > i_uid = GLOBAL_ROOT_UID ;
inode - > i_gid = GLOBAL_ROOT_GID ;
inode - > i_op = & proc_self_inode_operations ;
d_add ( self , inode ) ;
} else {
dput ( self ) ;
self = ERR_PTR ( - ENOMEM ) ;
}
} else {
self = ERR_PTR ( - ENOMEM ) ;
}
mutex_unlock ( & root_inode - > i_mutex ) ;
if ( IS_ERR ( self ) ) {
pr_err ( " proc_fill_super: can't allocate /proc/self \n " ) ;
return PTR_ERR ( self ) ;
}
ns - > proc_self = self ;
return 0 ;
}
2010-07-11 01:52:49 +04:00
2013-03-30 03:27:05 +04:00
void __init proc_self_init ( void )
{
proc_alloc_inum ( & self_inum ) ;
2010-07-11 01:52:49 +04:00
}