From c0b475173f1f399904b56f5cdee9b45d6acd2b94 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Fri, 19 Jan 2018 14:38:10 +0100 Subject: [PATCH] 4.4-stable patches added patches: pipe-avoid-round_pipe_size-nr_pages-overflow-on-32-bit.patch --- ...ipe_size-nr_pages-overflow-on-32-bit.patch | 115 ++++++++++++++++++ queue-4.4/series | 1 + 2 files changed, 116 insertions(+) create mode 100644 queue-4.4/pipe-avoid-round_pipe_size-nr_pages-overflow-on-32-bit.patch diff --git a/queue-4.4/pipe-avoid-round_pipe_size-nr_pages-overflow-on-32-bit.patch b/queue-4.4/pipe-avoid-round_pipe_size-nr_pages-overflow-on-32-bit.patch new file mode 100644 index 00000000000..110713b4ad4 --- /dev/null +++ b/queue-4.4/pipe-avoid-round_pipe_size-nr_pages-overflow-on-32-bit.patch @@ -0,0 +1,115 @@ +From d3f14c485867cfb2e0c48aa88c41d0ef4bf5209c Mon Sep 17 00:00:00 2001 +From: Joe Lawrence +Date: Fri, 17 Nov 2017 15:29:21 -0800 +Subject: pipe: avoid round_pipe_size() nr_pages overflow on 32-bit + +From: Joe Lawrence + +commit d3f14c485867cfb2e0c48aa88c41d0ef4bf5209c upstream. + +round_pipe_size() contains a right-bit-shift expression which may +overflow, which would cause undefined results in a subsequent +roundup_pow_of_two() call. + + static inline unsigned int round_pipe_size(unsigned int size) + { + unsigned long nr_pages; + + nr_pages = (size + PAGE_SIZE - 1) >> PAGE_SHIFT; + return roundup_pow_of_two(nr_pages) << PAGE_SHIFT; + } + +PAGE_SIZE is defined as (1UL << PAGE_SHIFT), so: + - 4 bytes wide on 32-bit (0 to 0xffffffff) + - 8 bytes wide on 64-bit (0 to 0xffffffffffffffff) + +That means that 32-bit round_pipe_size(), nr_pages may overflow to 0: + + size=0x00000000 nr_pages=0x0 + size=0x00000001 nr_pages=0x1 + size=0xfffff000 nr_pages=0xfffff + size=0xfffff001 nr_pages=0x0 << ! + size=0xffffffff nr_pages=0x0 << ! + +This is bad because roundup_pow_of_two(n) is undefined when n == 0! + +64-bit is not a problem as the unsigned int size is 4 bytes wide +(similar to 32-bit) and the larger, 8 byte wide unsigned long, is +sufficient to handle the largest value of the bit shift expression: + + size=0xffffffff nr_pages=100000 + +Modify round_pipe_size() to return 0 if n == 0 and updates its callers to +handle accordingly. + +Link: http://lkml.kernel.org/r/1507658689-11669-3-git-send-email-joe.lawrence@redhat.com +Signed-off-by: Joe Lawrence +Reported-by: Mikulas Patocka +Reviewed-by: Mikulas Patocka +Cc: Al Viro +Cc: Jens Axboe +Cc: Michael Kerrisk +Cc: Randy Dunlap +Cc: Josh Poimboeuf +Signed-off-by: Andrew Morton +Signed-off-by: Linus Torvalds +Signed-off-by: Dong Jinguang +Signed-off-by: Greg Kroah-Hartman + +--- + fs/pipe.c | 18 ++++++++++++++++-- + 1 file changed, 16 insertions(+), 2 deletions(-) + +--- a/fs/pipe.c ++++ b/fs/pipe.c +@@ -1001,6 +1001,9 @@ static long pipe_set_size(struct pipe_in + { + struct pipe_buffer *bufs; + ++ if (!nr_pages) ++ return -EINVAL; ++ + /* + * We can shrink the pipe, if arg >= pipe->nrbufs. Since we don't + * expect a lot of shrink+grow operations, just free and allocate +@@ -1045,13 +1048,19 @@ static long pipe_set_size(struct pipe_in + + /* + * 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; + } + +@@ -1062,13 +1071,18 @@ static inline unsigned int round_pipe_si + 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_dointvec_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; + } + diff --git a/queue-4.4/series b/queue-4.4/series index 9a3a20cee94..843d58319f9 100644 --- a/queue-4.4/series +++ b/queue-4.4/series @@ -29,3 +29,4 @@ scsi-hpsa-fix-volume-offline-state.patch sched-deadline-zero-out-positive-runtime-after-throttling-constrained-tasks.patch x86-retpoline-add-lfence-to-the-retpoline-rsb-filling-rsb-macros.patch module-add-retpoline-tag-to-vermagic.patch +pipe-avoid-round_pipe_size-nr_pages-overflow-on-32-bit.patch -- 2.47.3