diff options
author | Oleg Nesterov <oleg@redhat.com> | 2014-01-23 18:55:39 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2014-01-23 19:37:01 -0500 |
commit | d855a4b79f49ea07d1827fc0591490a6a324148b (patch) | |
tree | f1169b0bc68f35548a3fd05c8b5da91814c38f8b | |
parent | c986c14a6a88427946dc77d7018a81b95b3d41b6 (diff) |
proc: don't (ab)use ->group_leader in proc_task_readdir() paths
proc_task_readdir() does not really need "leader", first_tid() has to
revalidate it anyway. Just pass proc_pid(inode) to first_tid() instead,
it can do pid_task(PIDTYPE_PID) itself and read ->group_leader only if
necessary.
The patch also extracts the "inode is dead" code from
pid_delete_dentry(dentry) into the new trivial helper,
proc_inode_is_dead(inode), proc_task_readdir() uses it to return -ENOENT
if this dir was removed.
This is a bit racy, but the race is very inlikely and the getdents() after
openndir() can see the empty "." + ".." dir only once.
Signed-off-by: Oleg Nesterov <oleg@redhat.com>
Cc: "Eric W. Biederman" <ebiederm@xmission.com>
Cc: Michal Hocko <mhocko@suse.cz>
Cc: Sameer Nanda <snanda@chromium.org>
Cc: Sergey Dyasly <dserrg@gmail.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
-rw-r--r-- | fs/proc/base.c | 52 |
1 files changed, 24 insertions, 28 deletions
diff --git a/fs/proc/base.c b/fs/proc/base.c index be8e17cabfc7..9b423fec9732 100644 --- a/fs/proc/base.c +++ b/fs/proc/base.c | |||
@@ -1658,13 +1658,18 @@ int pid_revalidate(struct dentry *dentry, unsigned int flags) | |||
1658 | return 0; | 1658 | return 0; |
1659 | } | 1659 | } |
1660 | 1660 | ||
1661 | static inline bool proc_inode_is_dead(struct inode *inode) | ||
1662 | { | ||
1663 | return !proc_pid(inode)->tasks[PIDTYPE_PID].first; | ||
1664 | } | ||
1665 | |||
1661 | int pid_delete_dentry(const struct dentry *dentry) | 1666 | int pid_delete_dentry(const struct dentry *dentry) |
1662 | { | 1667 | { |
1663 | /* Is the task we represent dead? | 1668 | /* Is the task we represent dead? |
1664 | * If so, then don't put the dentry on the lru list, | 1669 | * If so, then don't put the dentry on the lru list, |
1665 | * kill it immediately. | 1670 | * kill it immediately. |
1666 | */ | 1671 | */ |
1667 | return !proc_pid(dentry->d_inode)->tasks[PIDTYPE_PID].first; | 1672 | return proc_inode_is_dead(dentry->d_inode); |
1668 | } | 1673 | } |
1669 | 1674 | ||
1670 | const struct dentry_operations pid_dentry_operations = | 1675 | const struct dentry_operations pid_dentry_operations = |
@@ -3092,34 +3097,35 @@ out_no_task: | |||
3092 | * In the case of a seek we start with the leader and walk nr | 3097 | * In the case of a seek we start with the leader and walk nr |
3093 | * threads past it. | 3098 | * threads past it. |
3094 | */ | 3099 | */ |
3095 | static struct task_struct *first_tid(struct task_struct *leader, | 3100 | static struct task_struct *first_tid(struct pid *pid, int tid, |
3096 | int tid, int nr, struct pid_namespace *ns) | 3101 | int nr, struct pid_namespace *ns) |
3097 | { | 3102 | { |
3098 | struct task_struct *pos; | 3103 | struct task_struct *pos, *task; |
3099 | 3104 | ||
3100 | rcu_read_lock(); | 3105 | rcu_read_lock(); |
3101 | /* Attempt to start with the pid of a thread */ | 3106 | task = pid_task(pid, PIDTYPE_PID); |
3107 | if (!task) | ||
3108 | goto fail; | ||
3109 | |||
3110 | /* Attempt to start with the tid of a thread */ | ||
3102 | if (tid && (nr > 0)) { | 3111 | if (tid && (nr > 0)) { |
3103 | pos = find_task_by_pid_ns(tid, ns); | 3112 | pos = find_task_by_pid_ns(tid, ns); |
3104 | if (pos && (pos->group_leader == leader)) | 3113 | if (pos && same_thread_group(pos, task)) |
3105 | goto found; | 3114 | goto found; |
3106 | } | 3115 | } |
3107 | 3116 | ||
3108 | /* If nr exceeds the number of threads there is nothing todo */ | 3117 | /* If nr exceeds the number of threads there is nothing todo */ |
3109 | if (nr && nr >= get_nr_threads(leader)) | 3118 | if (nr && nr >= get_nr_threads(task)) |
3110 | goto fail; | ||
3111 | /* It could be unhashed before we take rcu lock */ | ||
3112 | if (!pid_alive(leader)) | ||
3113 | goto fail; | 3119 | goto fail; |
3114 | 3120 | ||
3115 | /* If we haven't found our starting place yet start | 3121 | /* If we haven't found our starting place yet start |
3116 | * with the leader and walk nr threads forward. | 3122 | * with the leader and walk nr threads forward. |
3117 | */ | 3123 | */ |
3118 | pos = leader; | 3124 | pos = task = task->group_leader; |
3119 | do { | 3125 | do { |
3120 | if (nr-- <= 0) | 3126 | if (nr-- <= 0) |
3121 | goto found; | 3127 | goto found; |
3122 | } while_each_thread(leader, pos); | 3128 | } while_each_thread(task, pos); |
3123 | fail: | 3129 | fail: |
3124 | pos = NULL; | 3130 | pos = NULL; |
3125 | goto out; | 3131 | goto out; |
@@ -3155,25 +3161,16 @@ static struct task_struct *next_tid(struct task_struct *start) | |||
3155 | /* for the /proc/TGID/task/ directories */ | 3161 | /* for the /proc/TGID/task/ directories */ |
3156 | static int proc_task_readdir(struct file *file, struct dir_context *ctx) | 3162 | static int proc_task_readdir(struct file *file, struct dir_context *ctx) |
3157 | { | 3163 | { |
3158 | struct task_struct *leader = NULL; | 3164 | struct inode *inode = file_inode(file); |
3159 | struct task_struct *task = get_proc_task(file_inode(file)); | 3165 | struct task_struct *task; |
3160 | struct pid_namespace *ns; | 3166 | struct pid_namespace *ns; |
3161 | int tid; | 3167 | int tid; |
3162 | 3168 | ||
3163 | if (!task) | 3169 | if (proc_inode_is_dead(inode)) |
3164 | return -ENOENT; | ||
3165 | rcu_read_lock(); | ||
3166 | if (pid_alive(task)) { | ||
3167 | leader = task->group_leader; | ||
3168 | get_task_struct(leader); | ||
3169 | } | ||
3170 | rcu_read_unlock(); | ||
3171 | put_task_struct(task); | ||
3172 | if (!leader) | ||
3173 | return -ENOENT; | 3170 | return -ENOENT; |
3174 | 3171 | ||
3175 | if (!dir_emit_dots(file, ctx)) | 3172 | if (!dir_emit_dots(file, ctx)) |
3176 | goto out; | 3173 | return 0; |
3177 | 3174 | ||
3178 | /* f_version caches the tgid value that the last readdir call couldn't | 3175 | /* f_version caches the tgid value that the last readdir call couldn't |
3179 | * return. lseek aka telldir automagically resets f_version to 0. | 3176 | * return. lseek aka telldir automagically resets f_version to 0. |
@@ -3181,7 +3178,7 @@ static int proc_task_readdir(struct file *file, struct dir_context *ctx) | |||
3181 | ns = file->f_dentry->d_sb->s_fs_info; | 3178 | ns = file->f_dentry->d_sb->s_fs_info; |
3182 | tid = (int)file->f_version; | 3179 | tid = (int)file->f_version; |
3183 | file->f_version = 0; | 3180 | file->f_version = 0; |
3184 | for (task = first_tid(leader, tid, ctx->pos - 2, ns); | 3181 | for (task = first_tid(proc_pid(inode), tid, ctx->pos - 2, ns); |
3185 | task; | 3182 | task; |
3186 | task = next_tid(task), ctx->pos++) { | 3183 | task = next_tid(task), ctx->pos++) { |
3187 | char name[PROC_NUMBUF]; | 3184 | char name[PROC_NUMBUF]; |
@@ -3197,8 +3194,7 @@ static int proc_task_readdir(struct file *file, struct dir_context *ctx) | |||
3197 | break; | 3194 | break; |
3198 | } | 3195 | } |
3199 | } | 3196 | } |
3200 | out: | 3197 | |
3201 | put_task_struct(leader); | ||
3202 | return 0; | 3198 | return 0; |
3203 | } | 3199 | } |
3204 | 3200 | ||