]> git.proxmox.com Git - mirror_ubuntu-eoan-kernel.git/blobdiff - fs/proc/base.c
proc: simpler iterations for /proc/*/cmdline
[mirror_ubuntu-eoan-kernel.git] / fs / proc / base.c
index 33ed1746927a82ff4e39f57a65fb822561a9079c..3fcca77d45f1e758cf3a9b14c801beb22a2a2f63 100644 (file)
@@ -215,8 +215,9 @@ static ssize_t proc_pid_cmdline_read(struct file *file, char __user *buf,
        unsigned long arg_start, arg_end, env_start, env_end;
        unsigned long len1, len2, len;
        unsigned long p;
+       char __user *buf0 = buf;
        char c;
-       ssize_t rv;
+       int rv;
 
        BUG_ON(*pos < 0);
 
@@ -239,12 +240,12 @@ static ssize_t proc_pid_cmdline_read(struct file *file, char __user *buf,
                goto out_mmput;
        }
 
-       down_read(&mm->mmap_sem);
+       spin_lock(&mm->arg_lock);
        arg_start = mm->arg_start;
        arg_end = mm->arg_end;
        env_start = mm->env_start;
        env_end = mm->env_end;
-       up_read(&mm->mmap_sem);
+       spin_unlock(&mm->arg_lock);
 
        BUG_ON(arg_start > arg_end);
        BUG_ON(env_start > env_end);
@@ -253,37 +254,30 @@ static ssize_t proc_pid_cmdline_read(struct file *file, char __user *buf,
        len2 = env_end - env_start;
 
        /* Empty ARGV. */
-       if (len1 == 0) {
-               rv = 0;
-               goto out_free_page;
-       }
+       if (len1 == 0)
+               goto end;
+
        /*
         * Inherently racy -- command line shares address space
         * with code and data.
         */
-       rv = access_remote_vm(mm, arg_end - 1, &c, 1, FOLL_ANON);
-       if (rv <= 0)
-               goto out_free_page;
-
-       rv = 0;
+       if (access_remote_vm(mm, arg_end - 1, &c, 1, FOLL_ANON) != 1)
+               goto end;
 
        if (c == '\0') {
                /* Command line (set of strings) occupies whole ARGV. */
                if (len1 <= *pos)
-                       goto out_free_page;
+                       goto end;
 
                p = arg_start + *pos;
                len = len1 - *pos;
                while (count > 0 && len > 0) {
-                       unsigned int _count;
-                       int nr_read;
-
-                       _count = min3(count, len, PAGE_SIZE);
-                       nr_read = access_remote_vm(mm, p, page, _count, FOLL_ANON);
-                       if (nr_read < 0)
-                               rv = nr_read;
-                       if (nr_read <= 0)
-                               goto out_free_page;
+                       unsigned int nr_read;
+
+                       nr_read = min3(count, len, PAGE_SIZE);
+                       nr_read = access_remote_vm(mm, p, page, nr_read, FOLL_ANON);
+                       if (nr_read == 0)
+                               goto end;
 
                        if (copy_to_user(buf, page, nr_read)) {
                                rv = -EFAULT;
@@ -294,7 +288,6 @@ static ssize_t proc_pid_cmdline_read(struct file *file, char __user *buf,
                        len     -= nr_read;
                        buf     += nr_read;
                        count   -= nr_read;
-                       rv      += nr_read;
                }
        } else {
                /*
@@ -320,41 +313,31 @@ static ssize_t proc_pid_cmdline_read(struct file *file, char __user *buf,
                        p = cmdline[i].p + pos1;
                        len = cmdline[i].len - pos1;
                        while (count > 0 && len > 0) {
-                               unsigned int _count, l;
-                               int nr_read;
-                               bool final;
-
-                               _count = min3(count, len, PAGE_SIZE);
-                               nr_read = access_remote_vm(mm, p, page, _count, FOLL_ANON);
-                               if (nr_read < 0)
-                                       rv = nr_read;
-                               if (nr_read <= 0)
-                                       goto out_free_page;
+                               unsigned int nr_read, nr_write;
+
+                               nr_read = min3(count, len, PAGE_SIZE);
+                               nr_read = access_remote_vm(mm, p, page, nr_read, FOLL_ANON);
+                               if (nr_read == 0)
+                                       goto end;
 
                                /*
                                 * Command line can be shorter than whole ARGV
                                 * even if last "marker" byte says it is not.
                                 */
-                               final = false;
-                               l = strnlen(page, nr_read);
-                               if (l < nr_read) {
-                                       nr_read = l;
-                                       final = true;
-                               }
+                               nr_write = strnlen(page, nr_read);
 
-                               if (copy_to_user(buf, page, nr_read)) {
+                               if (copy_to_user(buf, page, nr_write)) {
                                        rv = -EFAULT;
                                        goto out_free_page;
                                }
 
-                               p       += nr_read;
-                               len     -= nr_read;
-                               buf     += nr_read;
-                               count   -= nr_read;
-                               rv      += nr_read;
+                               p       += nr_write;
+                               len     -= nr_write;
+                               buf     += nr_write;
+                               count   -= nr_write;
 
-                               if (final)
-                                       goto out_free_page;
+                               if (nr_write < nr_read)
+                                       goto end;
                        }
 
                        /* Only first chunk can be read partially. */
@@ -363,12 +346,13 @@ static ssize_t proc_pid_cmdline_read(struct file *file, char __user *buf,
                }
        }
 
+end:
+       *pos += buf - buf0;
+       rv = buf - buf0;
 out_free_page:
        free_page((unsigned long)page);
 out_mmput:
        mmput(mm);
-       if (rv > 0)
-               *pos += rv;
        return rv;
 }
 
@@ -927,10 +911,10 @@ static ssize_t environ_read(struct file *file, char __user *buf,
        if (!mmget_not_zero(mm))
                goto free;
 
-       down_read(&mm->mmap_sem);
+       spin_lock(&mm->arg_lock);
        env_start = mm->env_start;
        env_end = mm->env_end;
-       up_read(&mm->mmap_sem);
+       spin_unlock(&mm->arg_lock);
 
        while (count > 0) {
                size_t this_len, max_len;
@@ -1563,9 +1547,8 @@ static int comm_show(struct seq_file *m, void *v)
        if (!p)
                return -ESRCH;
 
-       task_lock(p);
-       seq_printf(m, "%s\n", p->comm);
-       task_unlock(p);
+       proc_task_name(m, p, false);
+       seq_putc(m, '\n');
 
        put_task_struct(p);