From: Greg Kroah-Hartman Date: Wed, 4 Sep 2024 09:54:02 +0000 (+0200) Subject: 4.19-stable patches X-Git-Tag: v4.19.321~3 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=f0fbd1434fa81f8e10bd9cb4365e19c05de8a5c5;p=thirdparty%2Fkernel%2Fstable-queue.git 4.19-stable patches added patches: overflow-implement-size_t-saturating-arithmetic-helpers.patch overflow.h-add-flex_array_size-helper.patch --- diff --git a/queue-4.19/overflow-implement-size_t-saturating-arithmetic-helpers.patch b/queue-4.19/overflow-implement-size_t-saturating-arithmetic-helpers.patch new file mode 100644 index 00000000000..aaa0f8fd5f6 --- /dev/null +++ b/queue-4.19/overflow-implement-size_t-saturating-arithmetic-helpers.patch @@ -0,0 +1,327 @@ +From e1be43d9b5d0d1310dbd90185a8e5c7145dde40f Mon Sep 17 00:00:00 2001 +From: Kees Cook +Date: Sat, 18 Sep 2021 15:17:53 -0700 +Subject: overflow: Implement size_t saturating arithmetic helpers + +From: Kees Cook + +commit e1be43d9b5d0d1310dbd90185a8e5c7145dde40f upstream. + +In order to perform more open-coded replacements of common allocation +size arithmetic, the kernel needs saturating (SIZE_MAX) helpers for +multiplication, addition, and subtraction. For example, it is common in +allocators, especially on realloc, to add to an existing size: + + p = krealloc(map->patch, + sizeof(struct reg_sequence) * (map->patch_regs + num_regs), + GFP_KERNEL); + +There is no existing saturating replacement for this calculation, and +just leaving the addition open coded inside array_size() could +potentially overflow as well. For example, an overflow in an expression +for a size_t argument might wrap to zero: + + array_size(anything, something_at_size_max + 1) == 0 + +Introduce size_mul(), size_add(), and size_sub() helpers that +implicitly promote arguments to size_t and saturated calculations for +use in allocations. With these helpers it is also possible to redefine +array_size(), array3_size(), flex_array_size(), and struct_size() in +terms of the new helpers. + +As with the check_*_overflow() helpers, the new helpers use __must_check, +though what is really desired is a way to make sure that assignment is +only to a size_t lvalue. Without this, it's still possible to introduce +overflow/underflow via type conversion (i.e. from size_t to int). +Enforcing this will currently need to be left to static analysis or +future use of -Wconversion. + +Additionally update the overflow unit tests to force runtime evaluation +for the pathological cases. + +Cc: Rasmus Villemoes +Cc: Gustavo A. R. Silva +Cc: Nathan Chancellor +Cc: Jason Gunthorpe +Cc: Nick Desaulniers +Cc: Leon Romanovsky +Cc: Keith Busch +Cc: Len Baker +Signed-off-by: Kees Cook +Signed-off-by: Greg Kroah-Hartman +--- + include/linux/overflow.h | 108 ++++++++++++++++++++++++++++++----------------- + lib/test_overflow.c | 98 ++++++++++++++++++++++++++++++++++++++++++ + 2 files changed, 168 insertions(+), 38 deletions(-) + +--- a/include/linux/overflow.h ++++ b/include/linux/overflow.h +@@ -241,77 +241,94 @@ + }) + + /** +- * array_size() - Calculate size of 2-dimensional array. +- * +- * @a: dimension one +- * @b: dimension two ++ * size_mul() - Calculate size_t multiplication with saturation at SIZE_MAX + * +- * Calculates size of 2-dimensional array: @a * @b. ++ * @factor1: first factor ++ * @factor2: second factor + * +- * Returns: number of bytes needed to represent the array or SIZE_MAX on +- * overflow. ++ * Returns: calculate @factor1 * @factor2, both promoted to size_t, ++ * with any overflow causing the return value to be SIZE_MAX. The ++ * lvalue must be size_t to avoid implicit type conversion. + */ +-static inline __must_check size_t array_size(size_t a, size_t b) ++static inline size_t __must_check size_mul(size_t factor1, size_t factor2) + { + size_t bytes; + +- if (check_mul_overflow(a, b, &bytes)) ++ if (check_mul_overflow(factor1, factor2, &bytes)) + return SIZE_MAX; + + return bytes; + } + + /** +- * array3_size() - Calculate size of 3-dimensional array. ++ * size_add() - Calculate size_t addition with saturation at SIZE_MAX + * +- * @a: dimension one +- * @b: dimension two +- * @c: dimension three +- * +- * Calculates size of 3-dimensional array: @a * @b * @c. ++ * @addend1: first addend ++ * @addend2: second addend + * +- * Returns: number of bytes needed to represent the array or SIZE_MAX on +- * overflow. ++ * Returns: calculate @addend1 + @addend2, both promoted to size_t, ++ * with any overflow causing the return value to be SIZE_MAX. The ++ * lvalue must be size_t to avoid implicit type conversion. + */ +-static inline __must_check size_t array3_size(size_t a, size_t b, size_t c) ++static inline size_t __must_check size_add(size_t addend1, size_t addend2) + { + size_t bytes; + +- if (check_mul_overflow(a, b, &bytes)) +- return SIZE_MAX; +- if (check_mul_overflow(bytes, c, &bytes)) ++ if (check_add_overflow(addend1, addend2, &bytes)) + return SIZE_MAX; + + return bytes; + } + +-static inline __must_check size_t __ab_c_size(size_t n, size_t size, size_t c) ++/** ++ * size_sub() - Calculate size_t subtraction with saturation at SIZE_MAX ++ * ++ * @minuend: value to subtract from ++ * @subtrahend: value to subtract from @minuend ++ * ++ * Returns: calculate @minuend - @subtrahend, both promoted to size_t, ++ * with any overflow causing the return value to be SIZE_MAX. For ++ * composition with the size_add() and size_mul() helpers, neither ++ * argument may be SIZE_MAX (or the result with be forced to SIZE_MAX). ++ * The lvalue must be size_t to avoid implicit type conversion. ++ */ ++static inline size_t __must_check size_sub(size_t minuend, size_t subtrahend) + { + size_t bytes; + +- if (check_mul_overflow(n, size, &bytes)) +- return SIZE_MAX; +- if (check_add_overflow(bytes, c, &bytes)) ++ if (minuend == SIZE_MAX || subtrahend == SIZE_MAX || ++ check_sub_overflow(minuend, subtrahend, &bytes)) + return SIZE_MAX; + + return bytes; + } + + /** +- * struct_size() - Calculate size of structure with trailing array. +- * @p: Pointer to the structure. +- * @member: Name of the array member. +- * @count: Number of elements in the array. ++ * array_size() - Calculate size of 2-dimensional array. + * +- * Calculates size of memory needed for structure @p followed by an +- * array of @count number of @member elements. ++ * @a: dimension one ++ * @b: dimension two + * +- * Return: number of bytes needed or SIZE_MAX on overflow. ++ * Calculates size of 2-dimensional array: @a * @b. ++ * ++ * Returns: number of bytes needed to represent the array or SIZE_MAX on ++ * overflow. + */ +-#define struct_size(p, member, count) \ +- __ab_c_size(count, \ +- sizeof(*(p)->member) + __must_be_array((p)->member),\ +- sizeof(*(p))) ++#define array_size(a, b) size_mul(a, b) ++ ++/** ++ * array3_size() - Calculate size of 3-dimensional array. ++ * ++ * @a: dimension one ++ * @b: dimension two ++ * @c: dimension three ++ * ++ * Calculates size of 3-dimensional array: @a * @b * @c. ++ * ++ * Returns: number of bytes needed to represent the array or SIZE_MAX on ++ * overflow. ++ */ ++#define array3_size(a, b, c) size_mul(size_mul(a, b), c) + + /** + * flex_array_size() - Calculate size of a flexible array member +@@ -327,7 +344,22 @@ static inline __must_check size_t __ab_c + * Return: number of bytes needed or SIZE_MAX on overflow. + */ + #define flex_array_size(p, member, count) \ +- array_size(count, \ +- sizeof(*(p)->member) + __must_be_array((p)->member)) ++ size_mul(count, \ ++ sizeof(*(p)->member) + __must_be_array((p)->member)) ++ ++/** ++ * struct_size() - Calculate size of structure with trailing flexible array. ++ * ++ * @p: Pointer to the structure. ++ * @member: Name of the array member. ++ * @count: Number of elements in the array. ++ * ++ * Calculates size of memory needed for structure @p followed by an ++ * array of @count number of @member elements. ++ * ++ * Return: number of bytes needed or SIZE_MAX on overflow. ++ */ ++#define struct_size(p, member, count) \ ++ size_add(sizeof(*(p)), flex_array_size(p, member, count)) + + #endif /* __LINUX_OVERFLOW_H */ +--- a/lib/test_overflow.c ++++ b/lib/test_overflow.c +@@ -588,12 +588,110 @@ static int __init test_overflow_allocati + return err; + } + ++struct __test_flex_array { ++ unsigned long flags; ++ size_t count; ++ unsigned long data[]; ++}; ++ ++static int __init test_overflow_size_helpers(void) ++{ ++ struct __test_flex_array *obj; ++ int count = 0; ++ int err = 0; ++ int var; ++ ++#define check_one_size_helper(expected, func, args...) ({ \ ++ bool __failure = false; \ ++ size_t _r; \ ++ \ ++ _r = func(args); \ ++ if (_r != (expected)) { \ ++ pr_warn("expected " #func "(" #args ") " \ ++ "to return %zu but got %zu instead\n", \ ++ (size_t)(expected), _r); \ ++ __failure = true; \ ++ } \ ++ count++; \ ++ __failure; \ ++}) ++ ++ var = 4; ++ err |= check_one_size_helper(20, size_mul, var++, 5); ++ err |= check_one_size_helper(20, size_mul, 4, var++); ++ err |= check_one_size_helper(0, size_mul, 0, 3); ++ err |= check_one_size_helper(0, size_mul, 3, 0); ++ err |= check_one_size_helper(6, size_mul, 2, 3); ++ err |= check_one_size_helper(SIZE_MAX, size_mul, SIZE_MAX, 1); ++ err |= check_one_size_helper(SIZE_MAX, size_mul, SIZE_MAX, 3); ++ err |= check_one_size_helper(SIZE_MAX, size_mul, SIZE_MAX, -3); ++ ++ var = 4; ++ err |= check_one_size_helper(9, size_add, var++, 5); ++ err |= check_one_size_helper(9, size_add, 4, var++); ++ err |= check_one_size_helper(9, size_add, 9, 0); ++ err |= check_one_size_helper(9, size_add, 0, 9); ++ err |= check_one_size_helper(5, size_add, 2, 3); ++ err |= check_one_size_helper(SIZE_MAX, size_add, SIZE_MAX, 1); ++ err |= check_one_size_helper(SIZE_MAX, size_add, SIZE_MAX, 3); ++ err |= check_one_size_helper(SIZE_MAX, size_add, SIZE_MAX, -3); ++ ++ var = 4; ++ err |= check_one_size_helper(1, size_sub, var--, 3); ++ err |= check_one_size_helper(1, size_sub, 4, var--); ++ err |= check_one_size_helper(1, size_sub, 3, 2); ++ err |= check_one_size_helper(9, size_sub, 9, 0); ++ err |= check_one_size_helper(SIZE_MAX, size_sub, 9, -3); ++ err |= check_one_size_helper(SIZE_MAX, size_sub, 0, 9); ++ err |= check_one_size_helper(SIZE_MAX, size_sub, 2, 3); ++ err |= check_one_size_helper(SIZE_MAX, size_sub, SIZE_MAX, 0); ++ err |= check_one_size_helper(SIZE_MAX, size_sub, SIZE_MAX, 10); ++ err |= check_one_size_helper(SIZE_MAX, size_sub, 0, SIZE_MAX); ++ err |= check_one_size_helper(SIZE_MAX, size_sub, 14, SIZE_MAX); ++ err |= check_one_size_helper(SIZE_MAX - 2, size_sub, SIZE_MAX - 1, 1); ++ err |= check_one_size_helper(SIZE_MAX - 4, size_sub, SIZE_MAX - 1, 3); ++ err |= check_one_size_helper(1, size_sub, SIZE_MAX - 1, -3); ++ ++ var = 4; ++ err |= check_one_size_helper(4 * sizeof(*obj->data), ++ flex_array_size, obj, data, var++); ++ err |= check_one_size_helper(5 * sizeof(*obj->data), ++ flex_array_size, obj, data, var++); ++ err |= check_one_size_helper(0, flex_array_size, obj, data, 0); ++ err |= check_one_size_helper(sizeof(*obj->data), ++ flex_array_size, obj, data, 1); ++ err |= check_one_size_helper(7 * sizeof(*obj->data), ++ flex_array_size, obj, data, 7); ++ err |= check_one_size_helper(SIZE_MAX, ++ flex_array_size, obj, data, -1); ++ err |= check_one_size_helper(SIZE_MAX, ++ flex_array_size, obj, data, SIZE_MAX - 4); ++ ++ var = 4; ++ err |= check_one_size_helper(sizeof(*obj) + (4 * sizeof(*obj->data)), ++ struct_size, obj, data, var++); ++ err |= check_one_size_helper(sizeof(*obj) + (5 * sizeof(*obj->data)), ++ struct_size, obj, data, var++); ++ err |= check_one_size_helper(sizeof(*obj), struct_size, obj, data, 0); ++ err |= check_one_size_helper(sizeof(*obj) + sizeof(*obj->data), ++ struct_size, obj, data, 1); ++ err |= check_one_size_helper(SIZE_MAX, ++ struct_size, obj, data, -3); ++ err |= check_one_size_helper(SIZE_MAX, ++ struct_size, obj, data, SIZE_MAX - 3); ++ ++ pr_info("%d overflow size helper tests finished\n", count); ++ ++ return err; ++} ++ + static int __init test_module_init(void) + { + int err = 0; + + err |= test_overflow_calculation(); + err |= test_overflow_shift(); ++ err |= test_overflow_size_helpers(); + err |= test_overflow_allocation(); + + if (err) { diff --git a/queue-4.19/overflow.h-add-flex_array_size-helper.patch b/queue-4.19/overflow.h-add-flex_array_size-helper.patch new file mode 100644 index 00000000000..8c9342b9c25 --- /dev/null +++ b/queue-4.19/overflow.h-add-flex_array_size-helper.patch @@ -0,0 +1,78 @@ +From b19d57d0f3cc6f1022edf94daf1d70506a09e3c2 Mon Sep 17 00:00:00 2001 +From: "Gustavo A. R. Silva" +Date: Mon, 8 Jun 2020 20:22:33 -0500 +Subject: overflow.h: Add flex_array_size() helper + +From: Gustavo A. R. Silva + +commit b19d57d0f3cc6f1022edf94daf1d70506a09e3c2 upstream. + +Add flex_array_size() helper for the calculation of the size, in bytes, +of a flexible array member contained within an enclosing structure. + +Example of usage: + +struct something { + size_t count; + struct foo items[]; +}; + +struct something *instance; + +instance = kmalloc(struct_size(instance, items, count), GFP_KERNEL); +instance->count = count; +memcpy(instance->items, src, flex_array_size(instance, items, instance->count)); + +The helper returns SIZE_MAX on overflow instead of wrapping around. + +Additionally replaces parameter "n" with "count" in struct_size() helper +for greater clarity and unification. + +Signed-off-by: Gustavo A. R. Silva +Link: https://lore.kernel.org/r/20200609012233.GA3371@embeddedor +Signed-off-by: Kees Cook +Signed-off-by: Greg Kroah-Hartman +--- + include/linux/overflow.h | 25 +++++++++++++++++++++---- + 1 file changed, 21 insertions(+), 4 deletions(-) + +--- a/include/linux/overflow.h ++++ b/include/linux/overflow.h +@@ -301,16 +301,33 @@ static inline __must_check size_t __ab_c + * struct_size() - Calculate size of structure with trailing array. + * @p: Pointer to the structure. + * @member: Name of the array member. +- * @n: Number of elements in the array. ++ * @count: Number of elements in the array. + * + * Calculates size of memory needed for structure @p followed by an +- * array of @n @member elements. ++ * array of @count number of @member elements. + * + * Return: number of bytes needed or SIZE_MAX on overflow. + */ +-#define struct_size(p, member, n) \ +- __ab_c_size(n, \ ++#define struct_size(p, member, count) \ ++ __ab_c_size(count, \ + sizeof(*(p)->member) + __must_be_array((p)->member),\ + sizeof(*(p))) + ++/** ++ * flex_array_size() - Calculate size of a flexible array member ++ * within an enclosing structure. ++ * ++ * @p: Pointer to the structure. ++ * @member: Name of the flexible array member. ++ * @count: Number of elements in the array. ++ * ++ * Calculates size of a flexible array of @count number of @member ++ * elements, at the end of structure @p. ++ * ++ * Return: number of bytes needed or SIZE_MAX on overflow. ++ */ ++#define flex_array_size(p, member, count) \ ++ array_size(count, \ ++ sizeof(*(p)->member) + __must_be_array((p)->member)) ++ + #endif /* __LINUX_OVERFLOW_H */ diff --git a/queue-4.19/series b/queue-4.19/series index 45e51ccfdf5..1d99300c2ac 100644 --- a/queue-4.19/series +++ b/queue-4.19/series @@ -10,6 +10,8 @@ selinux-fix-potential-counting-error-in-avc_add_xperms_decision.patch drm-amdgpu-actually-check-flags-for-all-context-ops.patch memcg_write_event_control-fix-a-user-triggerable-oops.patch s390-cio-rename-bitmap_size-idset_bitmap_size.patch +overflow.h-add-flex_array_size-helper.patch +overflow-implement-size_t-saturating-arithmetic-helpers.patch btrfs-rename-bitmap_set_bits-btrfs_bitmap_set_bits.patch net-mlx5e-correctly-report-errors-for-ethtool-rx-flo.patch atm-idt77252-prevent-use-after-free-in-dequeue_rx.patch