diff options
Diffstat (limited to 'fs')
| -rw-r--r-- | fs/proc/base.c | 16 | ||||
| -rw-r--r-- | fs/proc/inode.c | 2 | ||||
| -rw-r--r-- | fs/proc/internal.h | 1 | ||||
| -rw-r--r-- | fs/proc/root.c | 2 | ||||
| -rw-r--r-- | fs/proc/self.c | 46 |
5 files changed, 55 insertions, 12 deletions
diff --git a/fs/proc/base.c b/fs/proc/base.c index 69078c7cef1f..593e7c5ddb49 100644 --- a/fs/proc/base.c +++ b/fs/proc/base.c | |||
| @@ -2794,7 +2794,7 @@ retry: | |||
| 2794 | return iter; | 2794 | return iter; |
| 2795 | } | 2795 | } |
| 2796 | 2796 | ||
| 2797 | #define TGID_OFFSET (FIRST_PROCESS_ENTRY) | 2797 | #define TGID_OFFSET (FIRST_PROCESS_ENTRY + 1) |
| 2798 | 2798 | ||
| 2799 | static int proc_pid_fill_cache(struct file *filp, void *dirent, filldir_t filldir, | 2799 | static int proc_pid_fill_cache(struct file *filp, void *dirent, filldir_t filldir, |
| 2800 | struct tgid_iter iter) | 2800 | struct tgid_iter iter) |
| @@ -2817,13 +2817,21 @@ int proc_pid_readdir(struct file * filp, void * dirent, filldir_t filldir) | |||
| 2817 | struct tgid_iter iter; | 2817 | struct tgid_iter iter; |
| 2818 | struct pid_namespace *ns; | 2818 | struct pid_namespace *ns; |
| 2819 | filldir_t __filldir; | 2819 | filldir_t __filldir; |
| 2820 | loff_t pos = filp->f_pos; | ||
| 2820 | 2821 | ||
| 2821 | if (filp->f_pos >= PID_MAX_LIMIT + TGID_OFFSET) | 2822 | if (pos >= PID_MAX_LIMIT + TGID_OFFSET) |
| 2822 | goto out; | 2823 | goto out; |
| 2823 | 2824 | ||
| 2824 | ns = filp->f_dentry->d_sb->s_fs_info; | 2825 | if (pos == TGID_OFFSET - 1) { |
| 2826 | if (proc_fill_cache(filp, dirent, filldir, "self", 4, | ||
| 2827 | NULL, NULL, NULL) < 0) | ||
| 2828 | goto out; | ||
| 2829 | iter.tgid = 0; | ||
| 2830 | } else { | ||
| 2831 | iter.tgid = pos - TGID_OFFSET; | ||
| 2832 | } | ||
| 2825 | iter.task = NULL; | 2833 | iter.task = NULL; |
| 2826 | iter.tgid = filp->f_pos - TGID_OFFSET; | 2834 | ns = filp->f_dentry->d_sb->s_fs_info; |
| 2827 | for (iter = next_tgid(ns, iter); | 2835 | for (iter = next_tgid(ns, iter); |
| 2828 | iter.task; | 2836 | iter.task; |
| 2829 | iter.tgid += 1, iter = next_tgid(ns, iter)) { | 2837 | iter.tgid += 1, iter = next_tgid(ns, iter)) { |
diff --git a/fs/proc/inode.c b/fs/proc/inode.c index 869116c2afbe..908e97457319 100644 --- a/fs/proc/inode.c +++ b/fs/proc/inode.c | |||
| @@ -506,5 +506,5 @@ int proc_fill_super(struct super_block *s) | |||
| 506 | return -ENOMEM; | 506 | return -ENOMEM; |
| 507 | } | 507 | } |
| 508 | 508 | ||
| 509 | return 0; | 509 | return proc_setup_self(s); |
| 510 | } | 510 | } |
diff --git a/fs/proc/internal.h b/fs/proc/internal.h index 85ff3a4598b3..9c93a53f371d 100644 --- a/fs/proc/internal.h +++ b/fs/proc/internal.h | |||
| @@ -205,3 +205,4 @@ int proc_setattr(struct dentry *dentry, struct iattr *attr); | |||
| 205 | extern const struct inode_operations proc_ns_dir_inode_operations; | 205 | extern const struct inode_operations proc_ns_dir_inode_operations; |
| 206 | extern const struct file_operations proc_ns_dir_operations; | 206 | extern const struct file_operations proc_ns_dir_operations; |
| 207 | 207 | ||
| 208 | extern int proc_setup_self(struct super_block *); | ||
diff --git a/fs/proc/root.c b/fs/proc/root.c index c6e9fac26bac..20834b3c8ea3 100644 --- a/fs/proc/root.c +++ b/fs/proc/root.c | |||
| @@ -137,6 +137,8 @@ static void proc_kill_sb(struct super_block *sb) | |||
| 137 | struct pid_namespace *ns; | 137 | struct pid_namespace *ns; |
| 138 | 138 | ||
| 139 | ns = (struct pid_namespace *)sb->s_fs_info; | 139 | ns = (struct pid_namespace *)sb->s_fs_info; |
| 140 | if (ns->proc_self) | ||
| 141 | dput(ns->proc_self); | ||
| 140 | kill_anon_super(sb); | 142 | kill_anon_super(sb); |
| 141 | put_pid_ns(ns); | 143 | put_pid_ns(ns); |
| 142 | } | 144 | } |
diff --git a/fs/proc/self.c b/fs/proc/self.c index d8a025296613..21940d89977e 100644 --- a/fs/proc/self.c +++ b/fs/proc/self.c | |||
| @@ -1,6 +1,7 @@ | |||
| 1 | #include <linux/proc_fs.h> | ||
| 2 | #include <linux/sched.h> | 1 | #include <linux/sched.h> |
| 3 | #include <linux/namei.h> | 2 | #include <linux/namei.h> |
| 3 | #include <linux/pid_namespace.h> | ||
| 4 | #include "internal.h" | ||
| 4 | 5 | ||
| 5 | /* | 6 | /* |
| 6 | * /proc/self: | 7 | * /proc/self: |
| @@ -48,12 +49,43 @@ static const struct inode_operations proc_self_inode_operations = { | |||
| 48 | .put_link = proc_self_put_link, | 49 | .put_link = proc_self_put_link, |
| 49 | }; | 50 | }; |
| 50 | 51 | ||
| 51 | void __init proc_self_init(void) | 52 | static unsigned self_inum; |
| 53 | |||
| 54 | int proc_setup_self(struct super_block *s) | ||
| 52 | { | 55 | { |
| 53 | struct proc_dir_entry *proc_self_symlink; | 56 | struct inode *root_inode = s->s_root->d_inode; |
| 54 | umode_t mode; | 57 | struct pid_namespace *ns = s->s_fs_info; |
| 58 | struct dentry *self; | ||
| 59 | |||
| 60 | mutex_lock(&root_inode->i_mutex); | ||
| 61 | self = d_alloc_name(s->s_root, "self"); | ||
| 62 | if (self) { | ||
| 63 | struct inode *inode = new_inode_pseudo(s); | ||
| 64 | if (inode) { | ||
| 65 | inode->i_ino = self_inum; | ||
| 66 | inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME; | ||
| 67 | inode->i_mode = S_IFLNK | S_IRWXUGO; | ||
| 68 | inode->i_uid = GLOBAL_ROOT_UID; | ||
| 69 | inode->i_gid = GLOBAL_ROOT_GID; | ||
| 70 | inode->i_op = &proc_self_inode_operations; | ||
| 71 | d_add(self, inode); | ||
| 72 | } else { | ||
| 73 | dput(self); | ||
| 74 | self = ERR_PTR(-ENOMEM); | ||
| 75 | } | ||
| 76 | } else { | ||
| 77 | self = ERR_PTR(-ENOMEM); | ||
| 78 | } | ||
| 79 | mutex_unlock(&root_inode->i_mutex); | ||
| 80 | if (IS_ERR(self)) { | ||
| 81 | pr_err("proc_fill_super: can't allocate /proc/self\n"); | ||
| 82 | return PTR_ERR(self); | ||
| 83 | } | ||
| 84 | ns->proc_self = self; | ||
| 85 | return 0; | ||
| 86 | } | ||
| 55 | 87 | ||
| 56 | mode = S_IFLNK | S_IRWXUGO; | 88 | void __init proc_self_init(void) |
| 57 | proc_self_symlink = proc_create("self", mode, NULL, NULL ); | 89 | { |
| 58 | proc_self_symlink->proc_iops = &proc_self_inode_operations; | 90 | proc_alloc_inum(&self_inum); |
| 59 | } | 91 | } |
