Merge branch 'for-4.18' of git://git.kernel.org/pub/scm/linux/kernel/git/tj/wq
[muen/linux.git] / fs / proc / base.c
index bb192a699bce1a1025501314fe4d9711318ae479..af128b37414308025819ad8038507ad622ac3e94 100644 (file)
@@ -261,7 +261,7 @@ static ssize_t proc_pid_cmdline_read(struct file *file, char __user *buf,
         * Inherently racy -- command line shares address space
         * with code and data.
         */
-       rv = access_remote_vm(mm, arg_end - 1, &c, 1, 0);
+       rv = access_remote_vm(mm, arg_end - 1, &c, 1, FOLL_ANON);
        if (rv <= 0)
                goto out_free_page;
 
@@ -279,7 +279,7 @@ static ssize_t proc_pid_cmdline_read(struct file *file, char __user *buf,
                        int nr_read;
 
                        _count = min3(count, len, PAGE_SIZE);
-                       nr_read = access_remote_vm(mm, p, page, _count, 0);
+                       nr_read = access_remote_vm(mm, p, page, _count, FOLL_ANON);
                        if (nr_read < 0)
                                rv = nr_read;
                        if (nr_read <= 0)
@@ -325,7 +325,7 @@ static ssize_t proc_pid_cmdline_read(struct file *file, char __user *buf,
                                bool final;
 
                                _count = min3(count, len, PAGE_SIZE);
-                               nr_read = access_remote_vm(mm, p, page, _count, 0);
+                               nr_read = access_remote_vm(mm, p, page, _count, FOLL_ANON);
                                if (nr_read < 0)
                                        rv = nr_read;
                                if (nr_read <= 0)
@@ -698,7 +698,7 @@ static bool has_pid_permissions(struct pid_namespace *pid,
 
 static int proc_pid_permission(struct inode *inode, int mask)
 {
-       struct pid_namespace *pid = inode->i_sb->s_fs_info;
+       struct pid_namespace *pid = proc_pid_ns(inode);
        struct task_struct *task;
        bool has_perms;
 
@@ -733,13 +733,11 @@ static const struct inode_operations proc_def_inode_operations = {
 static int proc_single_show(struct seq_file *m, void *v)
 {
        struct inode *inode = m->private;
-       struct pid_namespace *ns;
-       struct pid *pid;
+       struct pid_namespace *ns = proc_pid_ns(inode);
+       struct pid *pid = proc_pid(inode);
        struct task_struct *task;
        int ret;
 
-       ns = inode->i_sb->s_fs_info;
-       pid = proc_pid(inode);
        task = get_pid_task(pid, PIDTYPE_PID);
        if (!task)
                return -ESRCH;
@@ -946,7 +944,7 @@ static ssize_t environ_read(struct file *file, char __user *buf,
                max_len = min_t(size_t, PAGE_SIZE, count);
                this_len = min(max_len, this_len);
 
-               retval = access_remote_vm(mm, (env_start + src), page, this_len, 0);
+               retval = access_remote_vm(mm, (env_start + src), page, this_len, FOLL_ANON);
 
                if (retval <= 0) {
                        ret = retval;
@@ -1410,7 +1408,7 @@ static const struct file_operations proc_fail_nth_operations = {
 static int sched_show(struct seq_file *m, void *v)
 {
        struct inode *inode = m->private;
-       struct pid_namespace *ns = inode->i_sb->s_fs_info;
+       struct pid_namespace *ns = proc_pid_ns(inode);
        struct task_struct *p;
 
        p = get_proc_task(inode);
@@ -1781,8 +1779,8 @@ int pid_getattr(const struct path *path, struct kstat *stat,
                u32 request_mask, unsigned int query_flags)
 {
        struct inode *inode = d_inode(path->dentry);
+       struct pid_namespace *pid = proc_pid_ns(inode);
        struct task_struct *task;
-       struct pid_namespace *pid = path->dentry->d_sb->s_fs_info;
 
        generic_fillattr(inode, stat);
 
@@ -1808,15 +1806,22 @@ int pid_getattr(const struct path *path, struct kstat *stat,
 /* dentry stuff */
 
 /*
- *     Exceptional case: normally we are not allowed to unhash a busy
- * directory. In this case, however, we can do it - no aliasing problems
- * due to the way we treat inodes.
- *
+ * Set <pid>/... inode ownership (can change due to setuid(), etc.)
+ */
+void pid_update_inode(struct task_struct *task, struct inode *inode)
+{
+       task_dump_owner(task, inode->i_mode, &inode->i_uid, &inode->i_gid);
+
+       inode->i_mode &= ~(S_ISUID | S_ISGID);
+       security_task_to_inode(task, inode);
+}
+
+/*
  * Rewrite the inode's ownerships here because the owning task may have
  * performed a setuid(), etc.
  *
  */
-int pid_revalidate(struct dentry *dentry, unsigned int flags)
+static int pid_revalidate(struct dentry *dentry, unsigned int flags)
 {
        struct inode *inode;
        struct task_struct *task;
@@ -1828,10 +1833,7 @@ int pid_revalidate(struct dentry *dentry, unsigned int flags)
        task = get_proc_task(inode);
 
        if (task) {
-               task_dump_owner(task, inode->i_mode, &inode->i_uid, &inode->i_gid);
-
-               inode->i_mode &= ~(S_ISUID | S_ISGID);
-               security_task_to_inode(task, inode);
+               pid_update_inode(task, inode);
                put_task_struct(task);
                return 1;
        }
@@ -1879,8 +1881,8 @@ bool proc_fill_cache(struct file *file, struct dir_context *ctx,
        struct dentry *child, *dir = file->f_path.dentry;
        struct qstr qname = QSTR_INIT(name, len);
        struct inode *inode;
-       unsigned type;
-       ino_t ino;
+       unsigned type = DT_UNKNOWN;
+       ino_t ino = 1;
 
        child = d_hash_and_lookup(dir, &qname);
        if (!child) {
@@ -1889,22 +1891,23 @@ bool proc_fill_cache(struct file *file, struct dir_context *ctx,
                if (IS_ERR(child))
                        goto end_instantiate;
                if (d_in_lookup(child)) {
-                       int err = instantiate(d_inode(dir), child, task, ptr);
+                       struct dentry *res;
+                       res = instantiate(child, task, ptr);
                        d_lookup_done(child);
-                       if (err < 0) {
-                               dput(child);
+                       if (IS_ERR(res))
                                goto end_instantiate;
+                       if (unlikely(res)) {
+                               dput(child);
+                               child = res;
                        }
                }
        }
        inode = d_inode(child);
        ino = inode->i_ino;
        type = inode->i_mode >> 12;
+end_instantiate:
        dput(child);
        return dir_emit(ctx, name, len, ino, type);
-
-end_instantiate:
-       return dir_emit(ctx, name, len, 1, DT_UNKNOWN);
 }
 
 /*
@@ -2066,19 +2069,19 @@ static const struct inode_operations proc_map_files_link_inode_operations = {
        .setattr        = proc_setattr,
 };
 
-static int
-proc_map_files_instantiate(struct inode *dir, struct dentry *dentry,
+static struct dentry *
+proc_map_files_instantiate(struct dentry *dentry,
                           struct task_struct *task, const void *ptr)
 {
        fmode_t mode = (fmode_t)(unsigned long)ptr;
        struct proc_inode *ei;
        struct inode *inode;
 
-       inode = proc_pid_make_inode(dir->i_sb, task, S_IFLNK |
+       inode = proc_pid_make_inode(dentry->d_sb, task, S_IFLNK |
                                    ((mode & FMODE_READ ) ? S_IRUSR : 0) |
                                    ((mode & FMODE_WRITE) ? S_IWUSR : 0));
        if (!inode)
-               return -ENOENT;
+               return ERR_PTR(-ENOENT);
 
        ei = PROC_I(inode);
        ei->op.proc_get_link = map_files_get_link;
@@ -2087,9 +2090,7 @@ proc_map_files_instantiate(struct inode *dir, struct dentry *dentry,
        inode->i_size = 64;
 
        d_set_d_op(dentry, &tid_map_files_dentry_operations);
-       d_add(dentry, inode);
-
-       return 0;
+       return d_splice_alias(inode, dentry);
 }
 
 static struct dentry *proc_map_files_lookup(struct inode *dir,
@@ -2098,19 +2099,19 @@ static struct dentry *proc_map_files_lookup(struct inode *dir,
        unsigned long vm_start, vm_end;
        struct vm_area_struct *vma;
        struct task_struct *task;
-       int result;
+       struct dentry *result;
        struct mm_struct *mm;
 
-       result = -ENOENT;
+       result = ERR_PTR(-ENOENT);
        task = get_proc_task(dir);
        if (!task)
                goto out;
 
-       result = -EACCES;
+       result = ERR_PTR(-EACCES);
        if (!ptrace_may_access(task, PTRACE_MODE_READ_FSCREDS))
                goto out_put_task;
 
-       result = -ENOENT;
+       result = ERR_PTR(-ENOENT);
        if (dname_to_vma_addr(dentry, &vm_start, &vm_end))
                goto out_put_task;
 
@@ -2124,7 +2125,7 @@ static struct dentry *proc_map_files_lookup(struct inode *dir,
                goto out_no_vma;
 
        if (vma->vm_file)
-               result = proc_map_files_instantiate(dir, dentry, task,
+               result = proc_map_files_instantiate(dentry, task,
                                (void *)(unsigned long)vma->vm_file->f_mode);
 
 out_no_vma:
@@ -2133,7 +2134,7 @@ out_no_vma:
 out_put_task:
        put_task_struct(task);
 out:
-       return ERR_PTR(result);
+       return result;
 }
 
 static const struct inode_operations proc_map_files_inode_operations = {
@@ -2336,7 +2337,7 @@ static int proc_timers_open(struct inode *inode, struct file *file)
                return -ENOMEM;
 
        tp->pid = proc_pid(inode);
-       tp->ns = inode->i_sb->s_fs_info;
+       tp->ns = proc_pid_ns(inode);
        return 0;
 }
 
@@ -2434,16 +2435,16 @@ static const struct file_operations proc_pid_set_timerslack_ns_operations = {
        .release        = single_release,
 };
 
-static int proc_pident_instantiate(struct inode *dir,
-       struct dentry *dentry, struct task_struct *task, const void *ptr)
+static struct dentry *proc_pident_instantiate(struct dentry *dentry,
+       struct task_struct *task, const void *ptr)
 {
        const struct pid_entry *p = ptr;
        struct inode *inode;
        struct proc_inode *ei;
 
-       inode = proc_pid_make_inode(dir->i_sb, task, p->mode);
+       inode = proc_pid_make_inode(dentry->d_sb, task, p->mode);
        if (!inode)
-               goto out;
+               return ERR_PTR(-ENOENT);
 
        ei = PROC_I(inode);
        if (S_ISDIR(inode->i_mode))
@@ -2453,13 +2454,9 @@ static int proc_pident_instantiate(struct inode *dir,
        if (p->fop)
                inode->i_fop = p->fop;
        ei->op = p->op;
+       pid_update_inode(task, inode);
        d_set_d_op(dentry, &pid_dentry_operations);
-       d_add(dentry, inode);
-       /* Close the race of the process dying before we return the dentry */
-       if (pid_revalidate(dentry, 0))
-               return 0;
-out:
-       return -ENOENT;
+       return d_splice_alias(inode, dentry);
 }
 
 static struct dentry *proc_pident_lookup(struct inode *dir, 
@@ -2467,11 +2464,9 @@ static struct dentry *proc_pident_lookup(struct inode *dir,
                                         const struct pid_entry *ents,
                                         unsigned int nents)
 {
-       int error;
        struct task_struct *task = get_proc_task(dir);
        const struct pid_entry *p, *last;
-
-       error = -ENOENT;
+       struct dentry *res = ERR_PTR(-ENOENT);
 
        if (!task)
                goto out_no_task;
@@ -2490,11 +2485,11 @@ static struct dentry *proc_pident_lookup(struct inode *dir,
        if (p >= last)
                goto out;
 
-       error = proc_pident_instantiate(dir, dentry, task, p);
+       res = proc_pident_instantiate(dentry, task, p);
 out:
        put_task_struct(task);
 out_no_task:
-       return ERR_PTR(error);
+       return res;
 }
 
 static int proc_pident_readdir(struct file *file, struct dir_context *ctx,
@@ -3137,38 +3132,32 @@ void proc_flush_task(struct task_struct *task)
        }
 }
 
-static int proc_pid_instantiate(struct inode *dir,
-                                  struct dentry * dentry,
+static struct dentry *proc_pid_instantiate(struct dentry * dentry,
                                   struct task_struct *task, const void *ptr)
 {
        struct inode *inode;
 
-       inode = proc_pid_make_inode(dir->i_sb, task, S_IFDIR | S_IRUGO | S_IXUGO);
+       inode = proc_pid_make_inode(dentry->d_sb, task, S_IFDIR | S_IRUGO | S_IXUGO);
        if (!inode)
-               goto out;
+               return ERR_PTR(-ENOENT);
 
        inode->i_op = &proc_tgid_base_inode_operations;
        inode->i_fop = &proc_tgid_base_operations;
        inode->i_flags|=S_IMMUTABLE;
 
        set_nlink(inode, nlink_tgid);
+       pid_update_inode(task, inode);
 
        d_set_d_op(dentry, &pid_dentry_operations);
-
-       d_add(dentry, inode);
-       /* Close the race of the process dying before we return the dentry */
-       if (pid_revalidate(dentry, 0))
-               return 0;
-out:
-       return -ENOENT;
+       return d_splice_alias(inode, dentry);
 }
 
 struct dentry *proc_pid_lookup(struct inode *dir, struct dentry * dentry, unsigned int flags)
 {
-       int result = -ENOENT;
        struct task_struct *task;
        unsigned tgid;
        struct pid_namespace *ns;
+       struct dentry *result = ERR_PTR(-ENOENT);
 
        tgid = name_to_int(&dentry->d_name);
        if (tgid == ~0U)
@@ -3183,10 +3172,10 @@ struct dentry *proc_pid_lookup(struct inode *dir, struct dentry * dentry, unsign
        if (!task)
                goto out;
 
-       result = proc_pid_instantiate(dir, dentry, task, NULL);
+       result = proc_pid_instantiate(dentry, task, NULL);
        put_task_struct(task);
 out:
-       return ERR_PTR(result);
+       return result;
 }
 
 /*
@@ -3238,7 +3227,7 @@ retry:
 int proc_pid_readdir(struct file *file, struct dir_context *ctx)
 {
        struct tgid_iter iter;
-       struct pid_namespace *ns = file_inode(file)->i_sb->s_fs_info;
+       struct pid_namespace *ns = proc_pid_ns(file_inode(file));
        loff_t pos = ctx->pos;
 
        if (pos >= PID_MAX_LIMIT + TGID_OFFSET)
@@ -3434,37 +3423,32 @@ static const struct inode_operations proc_tid_base_inode_operations = {
        .setattr        = proc_setattr,
 };
 
-static int proc_task_instantiate(struct inode *dir,
-       struct dentry *dentry, struct task_struct *task, const void *ptr)
+static struct dentry *proc_task_instantiate(struct dentry *dentry,
+       struct task_struct *task, const void *ptr)
 {
        struct inode *inode;
-       inode = proc_pid_make_inode(dir->i_sb, task, S_IFDIR | S_IRUGO | S_IXUGO);
-
+       inode = proc_pid_make_inode(dentry->d_sb, task, S_IFDIR | S_IRUGO | S_IXUGO);
        if (!inode)
-               goto out;
+               return ERR_PTR(-ENOENT);
+
        inode->i_op = &proc_tid_base_inode_operations;
        inode->i_fop = &proc_tid_base_operations;
-       inode->i_flags|=S_IMMUTABLE;
+       inode->i_flags |= S_IMMUTABLE;
 
        set_nlink(inode, nlink_tid);
+       pid_update_inode(task, inode);
 
        d_set_d_op(dentry, &pid_dentry_operations);
-
-       d_add(dentry, inode);
-       /* Close the race of the process dying before we return the dentry */
-       if (pid_revalidate(dentry, 0))
-               return 0;
-out:
-       return -ENOENT;
+       return d_splice_alias(inode, dentry);
 }
 
 static struct dentry *proc_task_lookup(struct inode *dir, struct dentry * dentry, unsigned int flags)
 {
-       int result = -ENOENT;
        struct task_struct *task;
        struct task_struct *leader = get_proc_task(dir);
        unsigned tid;
        struct pid_namespace *ns;
+       struct dentry *result = ERR_PTR(-ENOENT);
 
        if (!leader)
                goto out_no_task;
@@ -3484,13 +3468,13 @@ static struct dentry *proc_task_lookup(struct inode *dir, struct dentry * dentry
        if (!same_thread_group(leader, task))
                goto out_drop_task;
 
-       result = proc_task_instantiate(dir, dentry, task, NULL);
+       result = proc_task_instantiate(dentry, task, NULL);
 out_drop_task:
        put_task_struct(task);
 out:
        put_task_struct(leader);
 out_no_task:
-       return ERR_PTR(result);
+       return result;
 }
 
 /*
@@ -3587,7 +3571,7 @@ static int proc_task_readdir(struct file *file, struct dir_context *ctx)
        /* f_version caches the tgid value that the last readdir call couldn't
         * return. lseek aka telldir automagically resets f_version to 0.
         */
-       ns = inode->i_sb->s_fs_info;
+       ns = proc_pid_ns(inode);
        tid = (int)file->f_version;
        file->f_version = 0;
        for (task = first_tid(proc_pid(inode), tid, ctx->pos - 2, ns);