Like reading /proc/*/cmdline, it is possible to be blocked for long time
when reading /proc/*/environ when manipulating large mapping at the mean
time. The environ reading process will be waiting for mmap_sem become
available for a long time then it may cause the reading task hung.

Convert down_read() and access_remote_vm() to killable version.

Signed-off-by: Yang Shi <yang....@linux.alibaba.com>
Suggested-by: Alexey Dobriyan <adobri...@gmail.com>
---
 fs/proc/base.c | 9 +++++++--
 1 file changed, 7 insertions(+), 2 deletions(-)

diff --git a/fs/proc/base.c b/fs/proc/base.c
index 9bdb84b..d87d9ab 100644
--- a/fs/proc/base.c
+++ b/fs/proc/base.c
@@ -933,7 +933,9 @@ static ssize_t environ_read(struct file *file, char __user 
*buf,
        if (!mmget_not_zero(mm))
                goto free;
 
-       down_read(&mm->mmap_sem);
+       ret = down_read_killable(&mm->mmap_sem);
+       if (ret)
+               goto out_mmput;
        env_start = mm->env_start;
        env_end = mm->env_end;
        up_read(&mm->mmap_sem);
@@ -950,7 +952,8 @@ 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_killable(mm, (env_start + src),
+                                               page, this_len, 0);
 
                if (retval <= 0) {
                        ret = retval;
@@ -968,6 +971,8 @@ static ssize_t environ_read(struct file *file, char __user 
*buf,
                count -= retval;
        }
        *ppos = src;
+
+out_mmput:
        mmput(mm);
 
 free:
-- 
1.8.3.1

Reply via email to