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 :
*/
2015-11-17 18:20:54 +03:00
static const char * proc_self_get_link ( struct dentry * dentry ,
2015-12-29 23:58:39 +03:00
struct inode * inode ,
struct delayed_call * done )
2010-07-11 01:52:49 +04:00
{
2015-11-17 18:20:54 +03:00
struct pid_namespace * ns = inode - > i_sb - > s_fs_info ;
2010-07-11 01:52:49 +04:00
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 */
2015-11-17 18:58:42 +03:00
name = kmalloc ( 12 , dentry ? GFP_KERNEL : GFP_ATOMIC ) ;
if ( unlikely ( ! name ) )
return dentry ? ERR_PTR ( - ENOMEM ) : ERR_PTR ( - ECHILD ) ;
2015-05-02 20:32:22 +03:00
sprintf ( name , " %d " , tgid ) ;
2015-12-29 23:58:39 +03:00
set_delayed_call ( done , kfree_link , name ) ;
return name ;
2010-07-11 01:52:49 +04:00
}
static const struct inode_operations proc_self_inode_operations = {
2015-11-17 18:20:54 +03:00
. get_link = proc_self_get_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 ;
2016-01-22 23:40:57 +03:00
inode_lock ( root_inode ) ;
2013-03-30 03:27:05 +04:00
self = d_alloc_name ( s - > s_root , " self " ) ;
if ( self ) {
struct inode * inode = new_inode_pseudo ( s ) ;
if ( inode ) {
inode - > i_ino = self_inum ;
2016-09-14 17:48:04 +03:00
inode - > i_mtime = inode - > i_atime = inode - > i_ctime = current_time ( inode ) ;
2013-03-30 03:27:05 +04:00
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 ) ;
}
2016-01-22 23:40:57 +03:00
inode_unlock ( root_inode ) ;
2013-03-30 03:27:05 +04:00
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
}