]> git.proxmox.com Git - mirror_ubuntu-bionic-kernel.git/blobdiff - fs/pipe.c
pipe: avoid round_pipe_size() nr_pages overflow on 32-bit
[mirror_ubuntu-bionic-kernel.git] / fs / pipe.c
index 3909c55ed389bbfb7c86c1560278a00d63fc64d6..f0f4ab36c444d42d91ffeb0a2cc144387219b62f 100644 (file)
--- a/fs/pipe.c
+++ b/fs/pipe.c
@@ -1018,13 +1018,19 @@ const struct file_operations pipefifo_fops = {
 
 /*
  * Currently we rely on the pipe array holding a power-of-2 number
- * of pages.
+ * of pages. Returns 0 on error.
  */
 static inline unsigned int round_pipe_size(unsigned int size)
 {
        unsigned long nr_pages;
 
+       if (size < pipe_min_size)
+               size = pipe_min_size;
+
        nr_pages = (size + PAGE_SIZE - 1) >> PAGE_SHIFT;
+       if (nr_pages == 0)
+               return 0;
+
        return roundup_pow_of_two(nr_pages) << PAGE_SHIFT;
 }
 
@@ -1040,6 +1046,8 @@ static long pipe_set_size(struct pipe_inode_info *pipe, unsigned long arg)
        long ret = 0;
 
        size = round_pipe_size(arg);
+       if (size == 0)
+               return -EINVAL;
        nr_pages = size >> PAGE_SHIFT;
 
        if (!nr_pages)
@@ -1123,13 +1131,18 @@ out_revert_acct:
 int pipe_proc_fn(struct ctl_table *table, int write, void __user *buf,
                 size_t *lenp, loff_t *ppos)
 {
+       unsigned int rounded_pipe_max_size;
        int ret;
 
        ret = proc_douintvec_minmax(table, write, buf, lenp, ppos);
        if (ret < 0 || !write)
                return ret;
 
-       pipe_max_size = round_pipe_size(pipe_max_size);
+       rounded_pipe_max_size = round_pipe_size(pipe_max_size);
+       if (rounded_pipe_max_size == 0)
+               return -EINVAL;
+
+       pipe_max_size = rounded_pipe_max_size;
        return ret;
 }