2014-07-31 14:10:50 +04:00
# include <linux/sched.h>
# include <linux/slab.h>
# include <linux/pid_namespace.h>
# include "internal.h"
/*
* / proc / thread_self :
*/
2015-11-17 18:20:54 +03:00
static const char * proc_thread_self_get_link ( struct dentry * dentry ,
2015-12-29 23:58:39 +03:00
struct inode * inode ,
struct delayed_call * done )
2014-07-31 14:10:50 +04:00
{
2015-11-17 18:20:54 +03:00
struct pid_namespace * ns = inode - > i_sb - > s_fs_info ;
2014-07-31 14:10:50 +04:00
pid_t tgid = task_tgid_nr_ns ( current , ns ) ;
pid_t pid = task_pid_nr_ns ( current , ns ) ;
2015-05-02 20:32:22 +03:00
char * name ;
if ( ! pid )
return ERR_PTR ( - ENOENT ) ;
2015-11-17 18:58:42 +03:00
name = kmalloc ( PROC_NUMBUF + 6 + PROC_NUMBUF ,
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/task/%d " , tgid , pid ) ;
2015-12-29 23:58:39 +03:00
set_delayed_call ( done , kfree_link , name ) ;
return name ;
2014-07-31 14:10:50 +04:00
}
static const struct inode_operations proc_thread_self_inode_operations = {
2015-11-17 18:20:54 +03:00
. get_link = proc_thread_self_get_link ,
2014-07-31 14:10:50 +04:00
} ;
static unsigned thread_self_inum ;
int proc_setup_thread_self ( struct super_block * s )
{
2015-03-18 01:25:59 +03:00
struct inode * root_inode = d_inode ( s - > s_root ) ;
2014-07-31 14:10:50 +04:00
struct pid_namespace * ns = s - > s_fs_info ;
struct dentry * thread_self ;
2016-01-22 23:40:57 +03:00
inode_lock ( root_inode ) ;
2014-07-31 14:10:50 +04:00
thread_self = d_alloc_name ( s - > s_root , " thread-self " ) ;
if ( thread_self ) {
struct inode * inode = new_inode_pseudo ( s ) ;
if ( inode ) {
inode - > i_ino = thread_self_inum ;
2016-09-14 17:48:04 +03:00
inode - > i_mtime = inode - > i_atime = inode - > i_ctime = current_time ( inode ) ;
2014-07-31 14:10:50 +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_thread_self_inode_operations ;
d_add ( thread_self , inode ) ;
} else {
dput ( thread_self ) ;
thread_self = ERR_PTR ( - ENOMEM ) ;
}
} else {
thread_self = ERR_PTR ( - ENOMEM ) ;
}
2016-01-22 23:40:57 +03:00
inode_unlock ( root_inode ) ;
2014-07-31 14:10:50 +04:00
if ( IS_ERR ( thread_self ) ) {
pr_err ( " proc_fill_super: can't allocate /proc/thread_self \n " ) ;
return PTR_ERR ( thread_self ) ;
}
ns - > proc_thread_self = thread_self ;
return 0 ;
}
void __init proc_thread_self_init ( void )
{
proc_alloc_inum ( & thread_self_inum ) ;
}