aboutsummaryrefslogtreecommitdiffstats
path: root/fs/proc/base.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/proc/base.c')
-rw-r--r--fs/proc/base.c73
1 files changed, 27 insertions, 46 deletions
diff --git a/fs/proc/base.c b/fs/proc/base.c
index 0c9de19a1633..f71559784bfb 100644
--- a/fs/proc/base.c
+++ b/fs/proc/base.c
@@ -80,6 +80,7 @@
80#include <linux/oom.h> 80#include <linux/oom.h>
81#include <linux/elf.h> 81#include <linux/elf.h>
82#include <linux/pid_namespace.h> 82#include <linux/pid_namespace.h>
83#include <linux/fs_struct.h>
83#include "internal.h" 84#include "internal.h"
84 85
85/* NOTE: 86/* NOTE:
@@ -146,15 +147,22 @@ static unsigned int pid_entry_count_dirs(const struct pid_entry *entries,
146 return count; 147 return count;
147} 148}
148 149
149static struct fs_struct *get_fs_struct(struct task_struct *task) 150static int get_fs_path(struct task_struct *task, struct path *path, bool root)
150{ 151{
151 struct fs_struct *fs; 152 struct fs_struct *fs;
153 int result = -ENOENT;
154
152 task_lock(task); 155 task_lock(task);
153 fs = task->fs; 156 fs = task->fs;
154 if(fs) 157 if (fs) {
155 atomic_inc(&fs->count); 158 read_lock(&fs->lock);
159 *path = root ? fs->root : fs->pwd;
160 path_get(path);
161 read_unlock(&fs->lock);
162 result = 0;
163 }
156 task_unlock(task); 164 task_unlock(task);
157 return fs; 165 return result;
158} 166}
159 167
160static int get_nr_threads(struct task_struct *tsk) 168static int get_nr_threads(struct task_struct *tsk)
@@ -172,42 +180,24 @@ static int get_nr_threads(struct task_struct *tsk)
172static int proc_cwd_link(struct inode *inode, struct path *path) 180static int proc_cwd_link(struct inode *inode, struct path *path)
173{ 181{
174 struct task_struct *task = get_proc_task(inode); 182 struct task_struct *task = get_proc_task(inode);
175 struct fs_struct *fs = NULL;
176 int result = -ENOENT; 183 int result = -ENOENT;
177 184
178 if (task) { 185 if (task) {
179 fs = get_fs_struct(task); 186 result = get_fs_path(task, path, 0);
180 put_task_struct(task); 187 put_task_struct(task);
181 } 188 }
182 if (fs) {
183 read_lock(&fs->lock);
184 *path = fs->pwd;
185 path_get(&fs->pwd);
186 read_unlock(&fs->lock);
187 result = 0;
188 put_fs_struct(fs);
189 }
190 return result; 189 return result;
191} 190}
192 191
193static int proc_root_link(struct inode *inode, struct path *path) 192static int proc_root_link(struct inode *inode, struct path *path)
194{ 193{
195 struct task_struct *task = get_proc_task(inode); 194 struct task_struct *task = get_proc_task(inode);
196 struct fs_struct *fs = NULL;
197 int result = -ENOENT; 195 int result = -ENOENT;
198 196
199 if (task) { 197 if (task) {
200 fs = get_fs_struct(task); 198 result = get_fs_path(task, path, 1);
201 put_task_struct(task); 199 put_task_struct(task);
202 } 200 }
203 if (fs) {
204 read_lock(&fs->lock);
205 *path = fs->root;
206 path_get(&fs->root);
207 read_unlock(&fs->lock);
208 result = 0;
209 put_fs_struct(fs);
210 }
211 return result; 201 return result;
212} 202}
213 203
@@ -596,7 +586,6 @@ static int mounts_open_common(struct inode *inode, struct file *file,
596 struct task_struct *task = get_proc_task(inode); 586 struct task_struct *task = get_proc_task(inode);
597 struct nsproxy *nsp; 587 struct nsproxy *nsp;
598 struct mnt_namespace *ns = NULL; 588 struct mnt_namespace *ns = NULL;
599 struct fs_struct *fs = NULL;
600 struct path root; 589 struct path root;
601 struct proc_mounts *p; 590 struct proc_mounts *p;
602 int ret = -EINVAL; 591 int ret = -EINVAL;
@@ -610,22 +599,16 @@ static int mounts_open_common(struct inode *inode, struct file *file,
610 get_mnt_ns(ns); 599 get_mnt_ns(ns);
611 } 600 }
612 rcu_read_unlock(); 601 rcu_read_unlock();
613 if (ns) 602 if (ns && get_fs_path(task, &root, 1) == 0)
614 fs = get_fs_struct(task); 603 ret = 0;
615 put_task_struct(task); 604 put_task_struct(task);
616 } 605 }
617 606
618 if (!ns) 607 if (!ns)
619 goto err; 608 goto err;
620 if (!fs) 609 if (ret)
621 goto err_put_ns; 610 goto err_put_ns;
622 611
623 read_lock(&fs->lock);
624 root = fs->root;
625 path_get(&root);
626 read_unlock(&fs->lock);
627 put_fs_struct(fs);
628
629 ret = -ENOMEM; 612 ret = -ENOMEM;
630 p = kmalloc(sizeof(struct proc_mounts), GFP_KERNEL); 613 p = kmalloc(sizeof(struct proc_mounts), GFP_KERNEL);
631 if (!p) 614 if (!p)
@@ -1545,7 +1528,7 @@ static int pid_delete_dentry(struct dentry * dentry)
1545 return !proc_pid(dentry->d_inode)->tasks[PIDTYPE_PID].first; 1528 return !proc_pid(dentry->d_inode)->tasks[PIDTYPE_PID].first;
1546} 1529}
1547 1530
1548static struct dentry_operations pid_dentry_operations = 1531static const struct dentry_operations pid_dentry_operations =
1549{ 1532{
1550 .d_revalidate = pid_revalidate, 1533 .d_revalidate = pid_revalidate,
1551 .d_delete = pid_delete_dentry, 1534 .d_delete = pid_delete_dentry,
@@ -1717,7 +1700,7 @@ static int tid_fd_revalidate(struct dentry *dentry, struct nameidata *nd)
1717 return 0; 1700 return 0;
1718} 1701}
1719 1702
1720static struct dentry_operations tid_fd_dentry_operations = 1703static const struct dentry_operations tid_fd_dentry_operations =
1721{ 1704{
1722 .d_revalidate = tid_fd_revalidate, 1705 .d_revalidate = tid_fd_revalidate,
1723 .d_delete = pid_delete_dentry, 1706 .d_delete = pid_delete_dentry,
@@ -2339,7 +2322,7 @@ static int proc_base_revalidate(struct dentry *dentry, struct nameidata *nd)
2339 return 0; 2322 return 0;
2340} 2323}
2341 2324
2342static struct dentry_operations proc_base_dentry_operations = 2325static const struct dentry_operations proc_base_dentry_operations =
2343{ 2326{
2344 .d_revalidate = proc_base_revalidate, 2327 .d_revalidate = proc_base_revalidate,
2345 .d_delete = pid_delete_dentry, 2328 .d_delete = pid_delete_dentry,
@@ -3066,7 +3049,6 @@ static int proc_task_readdir(struct file * filp, void * dirent, filldir_t filldi
3066 int retval = -ENOENT; 3049 int retval = -ENOENT;
3067 ino_t ino; 3050 ino_t ino;
3068 int tid; 3051 int tid;
3069 unsigned long pos = filp->f_pos; /* avoiding "long long" filp->f_pos */
3070 struct pid_namespace *ns; 3052 struct pid_namespace *ns;
3071 3053
3072 task = get_proc_task(inode); 3054 task = get_proc_task(inode);
@@ -3083,18 +3065,18 @@ static int proc_task_readdir(struct file * filp, void * dirent, filldir_t filldi
3083 goto out_no_task; 3065 goto out_no_task;
3084 retval = 0; 3066 retval = 0;
3085 3067
3086 switch (pos) { 3068 switch ((unsigned long)filp->f_pos) {
3087 case 0: 3069 case 0:
3088 ino = inode->i_ino; 3070 ino = inode->i_ino;
3089 if (filldir(dirent, ".", 1, pos, ino, DT_DIR) < 0) 3071 if (filldir(dirent, ".", 1, filp->f_pos, ino, DT_DIR) < 0)
3090 goto out; 3072 goto out;
3091 pos++; 3073 filp->f_pos++;
3092 /* fall through */ 3074 /* fall through */
3093 case 1: 3075 case 1:
3094 ino = parent_ino(dentry); 3076 ino = parent_ino(dentry);
3095 if (filldir(dirent, "..", 2, pos, ino, DT_DIR) < 0) 3077 if (filldir(dirent, "..", 2, filp->f_pos, ino, DT_DIR) < 0)
3096 goto out; 3078 goto out;
3097 pos++; 3079 filp->f_pos++;
3098 /* fall through */ 3080 /* fall through */
3099 } 3081 }
3100 3082
@@ -3104,9 +3086,9 @@ static int proc_task_readdir(struct file * filp, void * dirent, filldir_t filldi
3104 ns = filp->f_dentry->d_sb->s_fs_info; 3086 ns = filp->f_dentry->d_sb->s_fs_info;
3105 tid = (int)filp->f_version; 3087 tid = (int)filp->f_version;
3106 filp->f_version = 0; 3088 filp->f_version = 0;
3107 for (task = first_tid(leader, tid, pos - 2, ns); 3089 for (task = first_tid(leader, tid, filp->f_pos - 2, ns);
3108 task; 3090 task;
3109 task = next_tid(task), pos++) { 3091 task = next_tid(task), filp->f_pos++) {
3110 tid = task_pid_nr_ns(task, ns); 3092 tid = task_pid_nr_ns(task, ns);
3111 if (proc_task_fill_cache(filp, dirent, filldir, task, tid) < 0) { 3093 if (proc_task_fill_cache(filp, dirent, filldir, task, tid) < 0) {
3112 /* returning this tgid failed, save it as the first 3094 /* returning this tgid failed, save it as the first
@@ -3117,7 +3099,6 @@ static int proc_task_readdir(struct file * filp, void * dirent, filldir_t filldi
3117 } 3099 }
3118 } 3100 }
3119out: 3101out:
3120 filp->f_pos = pos;
3121 put_task_struct(leader); 3102 put_task_struct(leader);
3122out_no_task: 3103out_no_task:
3123 return retval; 3104 return retval;