diff options
Diffstat (limited to 'fs/proc/base.c')
-rw-r--r-- | fs/proc/base.c | 70 |
1 files changed, 37 insertions, 33 deletions
diff --git a/fs/proc/base.c b/fs/proc/base.c index 03c8d747be48..b9760628e1fd 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 = |
@@ -1819,6 +1824,7 @@ static int proc_map_files_get_link(struct dentry *dentry, struct path *path) | |||
1819 | if (rc) | 1824 | if (rc) |
1820 | goto out_mmput; | 1825 | goto out_mmput; |
1821 | 1826 | ||
1827 | rc = -ENOENT; | ||
1822 | down_read(&mm->mmap_sem); | 1828 | down_read(&mm->mmap_sem); |
1823 | vma = find_exact_vma(mm, vm_start, vm_end); | 1829 | vma = find_exact_vma(mm, vm_start, vm_end); |
1824 | if (vma && vma->vm_file) { | 1830 | if (vma && vma->vm_file) { |
@@ -3092,34 +3098,42 @@ out_no_task: | |||
3092 | * In the case of a seek we start with the leader and walk nr | 3098 | * In the case of a seek we start with the leader and walk nr |
3093 | * threads past it. | 3099 | * threads past it. |
3094 | */ | 3100 | */ |
3095 | static struct task_struct *first_tid(struct task_struct *leader, | 3101 | static struct task_struct *first_tid(struct pid *pid, int tid, loff_t f_pos, |
3096 | int tid, int nr, struct pid_namespace *ns) | 3102 | struct pid_namespace *ns) |
3097 | { | 3103 | { |
3098 | struct task_struct *pos; | 3104 | struct task_struct *pos, *task; |
3105 | unsigned long nr = f_pos; | ||
3106 | |||
3107 | if (nr != f_pos) /* 32bit overflow? */ | ||
3108 | return NULL; | ||
3099 | 3109 | ||
3100 | rcu_read_lock(); | 3110 | rcu_read_lock(); |
3101 | /* Attempt to start with the pid of a thread */ | 3111 | task = pid_task(pid, PIDTYPE_PID); |
3102 | if (tid && (nr > 0)) { | 3112 | if (!task) |
3113 | goto fail; | ||
3114 | |||
3115 | /* Attempt to start with the tid of a thread */ | ||
3116 | if (tid && nr) { | ||
3103 | pos = find_task_by_pid_ns(tid, ns); | 3117 | pos = find_task_by_pid_ns(tid, ns); |
3104 | if (pos && (pos->group_leader == leader)) | 3118 | if (pos && same_thread_group(pos, task)) |
3105 | goto found; | 3119 | goto found; |
3106 | } | 3120 | } |
3107 | 3121 | ||
3108 | /* If nr exceeds the number of threads there is nothing todo */ | 3122 | /* If nr exceeds the number of threads there is nothing todo */ |
3109 | pos = NULL; | 3123 | if (nr >= get_nr_threads(task)) |
3110 | if (nr && nr >= get_nr_threads(leader)) | 3124 | goto fail; |
3111 | goto out; | ||
3112 | 3125 | ||
3113 | /* If we haven't found our starting place yet start | 3126 | /* If we haven't found our starting place yet start |
3114 | * with the leader and walk nr threads forward. | 3127 | * with the leader and walk nr threads forward. |
3115 | */ | 3128 | */ |
3116 | for (pos = leader; nr > 0; --nr) { | 3129 | pos = task = task->group_leader; |
3117 | pos = next_thread(pos); | 3130 | do { |
3118 | if (pos == leader) { | 3131 | if (!nr--) |
3119 | pos = NULL; | 3132 | goto found; |
3120 | goto out; | 3133 | } while_each_thread(task, pos); |
3121 | } | 3134 | fail: |
3122 | } | 3135 | pos = NULL; |
3136 | goto out; | ||
3123 | found: | 3137 | found: |
3124 | get_task_struct(pos); | 3138 | get_task_struct(pos); |
3125 | out: | 3139 | out: |
@@ -3152,25 +3166,16 @@ static struct task_struct *next_tid(struct task_struct *start) | |||
3152 | /* for the /proc/TGID/task/ directories */ | 3166 | /* for the /proc/TGID/task/ directories */ |
3153 | static int proc_task_readdir(struct file *file, struct dir_context *ctx) | 3167 | static int proc_task_readdir(struct file *file, struct dir_context *ctx) |
3154 | { | 3168 | { |
3155 | struct task_struct *leader = NULL; | 3169 | struct inode *inode = file_inode(file); |
3156 | struct task_struct *task = get_proc_task(file_inode(file)); | 3170 | struct task_struct *task; |
3157 | struct pid_namespace *ns; | 3171 | struct pid_namespace *ns; |
3158 | int tid; | 3172 | int tid; |
3159 | 3173 | ||
3160 | if (!task) | 3174 | if (proc_inode_is_dead(inode)) |
3161 | return -ENOENT; | ||
3162 | rcu_read_lock(); | ||
3163 | if (pid_alive(task)) { | ||
3164 | leader = task->group_leader; | ||
3165 | get_task_struct(leader); | ||
3166 | } | ||
3167 | rcu_read_unlock(); | ||
3168 | put_task_struct(task); | ||
3169 | if (!leader) | ||
3170 | return -ENOENT; | 3175 | return -ENOENT; |
3171 | 3176 | ||
3172 | if (!dir_emit_dots(file, ctx)) | 3177 | if (!dir_emit_dots(file, ctx)) |
3173 | goto out; | 3178 | return 0; |
3174 | 3179 | ||
3175 | /* f_version caches the tgid value that the last readdir call couldn't | 3180 | /* f_version caches the tgid value that the last readdir call couldn't |
3176 | * return. lseek aka telldir automagically resets f_version to 0. | 3181 | * return. lseek aka telldir automagically resets f_version to 0. |
@@ -3178,7 +3183,7 @@ static int proc_task_readdir(struct file *file, struct dir_context *ctx) | |||
3178 | ns = file->f_dentry->d_sb->s_fs_info; | 3183 | ns = file->f_dentry->d_sb->s_fs_info; |
3179 | tid = (int)file->f_version; | 3184 | tid = (int)file->f_version; |
3180 | file->f_version = 0; | 3185 | file->f_version = 0; |
3181 | for (task = first_tid(leader, tid, ctx->pos - 2, ns); | 3186 | for (task = first_tid(proc_pid(inode), tid, ctx->pos - 2, ns); |
3182 | task; | 3187 | task; |
3183 | task = next_tid(task), ctx->pos++) { | 3188 | task = next_tid(task), ctx->pos++) { |
3184 | char name[PROC_NUMBUF]; | 3189 | char name[PROC_NUMBUF]; |
@@ -3194,8 +3199,7 @@ static int proc_task_readdir(struct file *file, struct dir_context *ctx) | |||
3194 | break; | 3199 | break; |
3195 | } | 3200 | } |
3196 | } | 3201 | } |
3197 | out: | 3202 | |
3198 | put_task_struct(leader); | ||
3199 | return 0; | 3203 | return 0; |
3200 | } | 3204 | } |
3201 | 3205 | ||