From: Greg Kroah-Hartman Date: Wed, 4 Sep 2024 09:54:17 +0000 (+0200) Subject: 5.4-stable patches X-Git-Tag: v4.19.321~2 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=1e2a3cbd7555e100a35dbd4f07b55c0b9d7e49b8;p=thirdparty%2Fkernel%2Fstable-queue.git 5.4-stable patches added patches: overflow-implement-size_t-saturating-arithmetic-helpers.patch overflow.h-add-flex_array_size-helper.patch --- diff --git a/queue-5.4/overflow-implement-size_t-saturating-arithmetic-helpers.patch b/queue-5.4/overflow-implement-size_t-saturating-arithmetic-helpers.patch new file mode 100644 index 00000000000..b89989114d2 --- /dev/null +++ b/queue-5.4/overflow-implement-size_t-saturating-arithmetic-helpers.patch @@ -0,0 +1,367 @@ +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 +--- + Documentation/process/deprecated.rst | 20 +++++- + include/linux/overflow.h | 110 +++++++++++++++++++++-------------- + lib/test_overflow.c | 98 +++++++++++++++++++++++++++++++ + 3 files changed, 184 insertions(+), 44 deletions(-) + +--- a/Documentation/process/deprecated.rst ++++ b/Documentation/process/deprecated.rst +@@ -48,6 +48,9 @@ Instead, the 2-factor form of the alloca + + foo = kmalloc_array(count, size, GFP_KERNEL); + ++Specifically, kmalloc() can be replaced with kmalloc_array(), and ++kzalloc() can be replaced with kcalloc(). ++ + If no 2-factor form is available, the saturate-on-overflow helpers should + be used:: + +@@ -63,9 +66,20 @@ Instead, use the helper:: + + header = kzalloc(struct_size(header, item, count), GFP_KERNEL); + +-See :c:func:`array_size`, :c:func:`array3_size`, and :c:func:`struct_size`, +-for more details as well as the related :c:func:`check_add_overflow` and +-:c:func:`check_mul_overflow` family of functions. ++For other calculations, please compose the use of the size_mul(), ++size_add(), and size_sub() helpers. For example, in the case of:: ++ ++ foo = krealloc(current_size + chunk_size * (count - 3), GFP_KERNEL); ++ ++Instead, use the helpers:: ++ ++ foo = krealloc(size_add(current_size, ++ size_mul(chunk_size, ++ size_sub(count, 3))), GFP_KERNEL); ++ ++For more details, also see array3_size() and flex_array_size(), ++as well as the related check_mul_overflow(), check_add_overflow(), ++check_sub_overflow(), and check_shl_overflow() family of functions. + + simple_strtol(), simple_strtoll(), simple_strtoul(), simple_strtoull() + ---------------------------------------------------------------------- +--- a/include/linux/overflow.h ++++ b/include/linux/overflow.h +@@ -241,81 +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 ++ * @addend1: first addend ++ * @addend2: second addend + * +- * Calculates size of 3-dimensional array: @a * @b * @c. +- * +- * 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; + } + +-/* +- * Compute a*b+c, returning SIZE_MAX on overflow. Internal helper for +- * struct_size() below. ++/** ++ * 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 __must_check size_t __ab_c_size(size_t a, size_t b, size_t c) ++static inline size_t __must_check size_sub(size_t minuend, size_t subtrahend) + { + size_t bytes; + +- if (check_mul_overflow(a, b, &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 +@@ -331,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-5.4/overflow.h-add-flex_array_size-helper.patch b/queue-5.4/overflow.h-add-flex_array_size-helper.patch new file mode 100644 index 00000000000..0f4890ea187 --- /dev/null +++ b/queue-5.4/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 +@@ -305,16 +305,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-5.4/series b/queue-5.4/series index c92c0eef52d..93793a5d973 100644 --- a/queue-5.4/series +++ b/queue-5.4/series @@ -11,6 +11,8 @@ fix-bitmap-corruption-on-close_range-with-close_range_unshare.patch 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 +overflow.h-add-flex_array_size-helper.patch +overflow-implement-size_t-saturating-arithmetic-helpers.patch s390-cio-rename-bitmap_size-idset_bitmap_size.patch btrfs-rename-bitmap_set_bits-btrfs_bitmap_set_bits.patch s390-uv-panic-for-set-and-remove-shared-access-uvc-e.patch