mail archive of the barebox mailing list
 help / color / mirror / Atom feed
* [PATCH master 1/3] include: linux/overflow.h: sync with upstream
@ 2023-10-20  7:23 Ahmad Fatoum
  2023-10-20  7:23 ` [PATCH master 2/3] include: import Linux string_is_terminated helper Ahmad Fatoum
                   ` (2 more replies)
  0 siblings, 3 replies; 4+ messages in thread
From: Ahmad Fatoum @ 2023-10-20  7:23 UTC (permalink / raw)
  To: barebox; +Cc: Ahmad Fatoum

Newer versions of the header add a size_add macro for doing saturating
addition, which will be used in a follow-up fix, so sync the header with
Linux to make it available.

Signed-off-by: Ahmad Fatoum <a.fatoum@pengutronix.de>
---
 include/linux/overflow.h | 436 +++++++++++++++++++--------------------
 1 file changed, 214 insertions(+), 222 deletions(-)

diff --git a/include/linux/overflow.h b/include/linux/overflow.h
index 50c93ca0c3d6..f9b60313eaea 100644
--- a/include/linux/overflow.h
+++ b/include/linux/overflow.h
@@ -4,14 +4,12 @@
 
 #include <linux/compiler.h>
 #include <linux/limits.h>
+#include <linux/const.h>
 
 /*
- * In the fallback code below, we need to compute the minimum and
- * maximum values representable in a given type. These macros may also
- * be useful elsewhere, so we provide them outside the
- * COMPILER_HAS_GENERIC_BUILTIN_OVERFLOW block.
- *
- * It would seem more obvious to do something like
+ * We need to compute the minimum and maximum values representable in a given
+ * type. These macros may also be useful elsewhere. It would seem more obvious
+ * to do something like:
  *
  * #define type_min(T) (T)(is_signed_type(T) ? (T)1 << (8*sizeof(T)-1) : 0)
  * #define type_max(T) (T)(is_signed_type(T) ? ((T)1 << (8*sizeof(T)-1)) - 1 : ~(T)0)
@@ -32,7 +30,6 @@
  * https://mail-index.netbsd.org/tech-misc/2007/02/05/0000.html -
  * credit to Christian Biere.
  */
-#define is_signed_type(type)       (((type)(-1)) < (type)1)
 #define __type_half_max(type) ((type)1 << (8*sizeof(type) - 1 - is_signed_type(type)))
 #define type_max(T) ((T)((__type_half_max(T) - 1) + __type_half_max(T)))
 #define type_min(T) ((T)((T)-type_max(T)-(T)1))
@@ -44,191 +41,82 @@
 #define is_non_negative(a) ((a) > 0 || (a) == 0)
 #define is_negative(a) (!(is_non_negative(a)))
 
-#ifdef COMPILER_HAS_GENERIC_BUILTIN_OVERFLOW
 /*
- * For simplicity and code hygiene, the fallback code below insists on
- * a, b and *d having the same type (similar to the min() and max()
- * macros), whereas gcc's type-generic overflow checkers accept
- * different types. Hence we don't just make check_add_overflow an
- * alias for __builtin_add_overflow, but add type checks similar to
- * below.
+ * Allows for effectively applying __must_check to a macro so we can have
+ * both the type-agnostic benefits of the macros while also being able to
+ * enforce that the return value is, in fact, checked.
  */
-#define check_add_overflow(a, b, d) ({		\
-	typeof(a) __a = (a);			\
-	typeof(b) __b = (b);			\
-	typeof(d) __d = (d);			\
-	(void) (&__a == &__b);			\
-	(void) (&__a == __d);			\
-	__builtin_add_overflow(__a, __b, __d);	\
-})
+static inline bool __must_check __must_check_overflow(bool overflow)
+{
+	return unlikely(overflow);
+}
 
-#define check_sub_overflow(a, b, d) ({		\
-	typeof(a) __a = (a);			\
-	typeof(b) __b = (b);			\
-	typeof(d) __d = (d);			\
-	(void) (&__a == &__b);			\
-	(void) (&__a == __d);			\
-	__builtin_sub_overflow(__a, __b, __d);	\
-})
-
-#define check_mul_overflow(a, b, d) ({		\
-	typeof(a) __a = (a);			\
-	typeof(b) __b = (b);			\
-	typeof(d) __d = (d);			\
-	(void) (&__a == &__b);			\
-	(void) (&__a == __d);			\
-	__builtin_mul_overflow(__a, __b, __d);	\
-})
-
-#else
-
-
-/* Checking for unsigned overflow is relatively easy without causing UB. */
-#define __unsigned_add_overflow(a, b, d) ({	\
-	typeof(a) __a = (a);			\
-	typeof(b) __b = (b);			\
-	typeof(d) __d = (d);			\
-	(void) (&__a == &__b);			\
-	(void) (&__a == __d);			\
-	*__d = __a + __b;			\
-	*__d < __a;				\
-})
-#define __unsigned_sub_overflow(a, b, d) ({	\
-	typeof(a) __a = (a);			\
-	typeof(b) __b = (b);			\
-	typeof(d) __d = (d);			\
-	(void) (&__a == &__b);			\
-	(void) (&__a == __d);			\
-	*__d = __a - __b;			\
-	__a < __b;				\
-})
-/*
- * If one of a or b is a compile-time constant, this avoids a division.
- */
-#define __unsigned_mul_overflow(a, b, d) ({		\
-	typeof(a) __a = (a);				\
-	typeof(b) __b = (b);				\
-	typeof(d) __d = (d);				\
-	(void) (&__a == &__b);				\
-	(void) (&__a == __d);				\
-	*__d = __a * __b;				\
-	__builtin_constant_p(__b) ?			\
-	  __b > 0 && __a > type_max(typeof(__a)) / __b : \
-	  __a > 0 && __b > type_max(typeof(__b)) / __a;	 \
-})
-
-/*
- * For signed types, detecting overflow is much harder, especially if
- * we want to avoid UB. But the interface of these macros is such that
- * we must provide a result in *d, and in fact we must produce the
- * result promised by gcc's builtins, which is simply the possibly
- * wrapped-around value. Fortunately, we can just formally do the
- * operations in the widest relevant unsigned type (u64) and then
- * truncate the result - gcc is smart enough to generate the same code
- * with and without the (u64) casts.
- */
-
-/*
- * Adding two signed integers can overflow only if they have the same
- * sign, and overflow has happened iff the result has the opposite
- * sign.
- */
-#define __signed_add_overflow(a, b, d) ({	\
-	typeof(a) __a = (a);			\
-	typeof(b) __b = (b);			\
-	typeof(d) __d = (d);			\
-	(void) (&__a == &__b);			\
-	(void) (&__a == __d);			\
-	*__d = (u64)__a + (u64)__b;		\
-	(((~(__a ^ __b)) & (*__d ^ __a))	\
-		& type_min(typeof(__a))) != 0;	\
-})
-
-/*
- * Subtraction is similar, except that overflow can now happen only
- * when the signs are opposite. In this case, overflow has happened if
- * the result has the opposite sign of a.
- */
-#define __signed_sub_overflow(a, b, d) ({	\
-	typeof(a) __a = (a);			\
-	typeof(b) __b = (b);			\
-	typeof(d) __d = (d);			\
-	(void) (&__a == &__b);			\
-	(void) (&__a == __d);			\
-	*__d = (u64)__a - (u64)__b;		\
-	((((__a ^ __b)) & (*__d ^ __a))		\
-		& type_min(typeof(__a))) != 0;	\
-})
-
-/*
- * Signed multiplication is rather hard. gcc always follows C99, so
- * division is truncated towards 0. This means that we can write the
- * overflow check like this:
+/**
+ * check_add_overflow() - Calculate addition with overflow checking
+ * @a: first addend
+ * @b: second addend
+ * @d: pointer to store sum
  *
- * (a > 0 && (b > MAX/a || b < MIN/a)) ||
- * (a < -1 && (b > MIN/a || b < MAX/a) ||
- * (a == -1 && b == MIN)
+ * Returns 0 on success.
  *
- * The redundant casts of -1 are to silence an annoying -Wtype-limits
- * (included in -Wextra) warning: When the type is u8 or u16, the
- * __b_c_e in check_mul_overflow obviously selects
- * __unsigned_mul_overflow, but unfortunately gcc still parses this
- * code and warns about the limited range of __b.
+ * *@d holds the results of the attempted addition, but is not considered
+ * "safe for use" on a non-zero return value, which indicates that the
+ * sum has overflowed or been truncated.
  */
+#define check_add_overflow(a, b, d)	\
+	__must_check_overflow(__builtin_add_overflow(a, b, d))
 
-#define __signed_mul_overflow(a, b, d) ({				\
-	typeof(a) __a = (a);						\
-	typeof(b) __b = (b);						\
-	typeof(d) __d = (d);						\
-	typeof(a) __tmax = type_max(typeof(a));				\
-	typeof(a) __tmin = type_min(typeof(a));				\
-	(void) (&__a == &__b);						\
-	(void) (&__a == __d);						\
-	*__d = (u64)__a * (u64)__b;					\
-	(__b > 0   && (__a > __tmax/__b || __a < __tmin/__b)) ||	\
-	(__b < (typeof(__b))-1  && (__a > __tmin/__b || __a < __tmax/__b)) || \
-	(__b == (typeof(__b))-1 && __a == __tmin);			\
-})
-
-
-#define check_add_overflow(a, b, d)					\
-	__builtin_choose_expr(is_signed_type(typeof(a)),		\
-			__signed_add_overflow(a, b, d),			\
-			__unsigned_add_overflow(a, b, d))
-
-#define check_sub_overflow(a, b, d)					\
-	__builtin_choose_expr(is_signed_type(typeof(a)),		\
-			__signed_sub_overflow(a, b, d),			\
-			__unsigned_sub_overflow(a, b, d))
-
-#define check_mul_overflow(a, b, d)					\
-	__builtin_choose_expr(is_signed_type(typeof(a)),		\
-			__signed_mul_overflow(a, b, d),			\
-			__unsigned_mul_overflow(a, b, d))
-
-
-#endif /* COMPILER_HAS_GENERIC_BUILTIN_OVERFLOW */
-
-/** check_shl_overflow() - Calculate a left-shifted value and check overflow
+/**
+ * check_sub_overflow() - Calculate subtraction with overflow checking
+ * @a: minuend; value to subtract from
+ * @b: subtrahend; value to subtract from @a
+ * @d: pointer to store difference
  *
+ * Returns 0 on success.
+ *
+ * *@d holds the results of the attempted subtraction, but is not considered
+ * "safe for use" on a non-zero return value, which indicates that the
+ * difference has underflowed or been truncated.
+ */
+#define check_sub_overflow(a, b, d)	\
+	__must_check_overflow(__builtin_sub_overflow(a, b, d))
+
+/**
+ * check_mul_overflow() - Calculate multiplication with overflow checking
+ * @a: first factor
+ * @b: second factor
+ * @d: pointer to store product
+ *
+ * Returns 0 on success.
+ *
+ * *@d holds the results of the attempted multiplication, but is not
+ * considered "safe for use" on a non-zero return value, which indicates
+ * that the product has overflowed or been truncated.
+ */
+#define check_mul_overflow(a, b, d)	\
+	__must_check_overflow(__builtin_mul_overflow(a, b, d))
+
+/**
+ * check_shl_overflow() - Calculate a left-shifted value and check overflow
  * @a: Value to be shifted
  * @s: How many bits left to shift
  * @d: Pointer to where to store the result
  *
  * Computes *@d = (@a << @s)
  *
- * Returns true if '*d' cannot hold the result or when 'a << s' doesn't
+ * Returns true if '*@d' cannot hold the result or when '@a << @s' doesn't
  * make sense. Example conditions:
- * - 'a << s' causes bits to be lost when stored in *d.
- * - 's' is garbage (e.g. negative) or so large that the result of
- *   'a << s' is guaranteed to be 0.
- * - 'a' is negative.
- * - 'a << s' sets the sign bit, if any, in '*d'.
  *
- * '*d' will hold the results of the attempted shift, but is not
- * considered "safe for use" if false is returned.
+ * - '@a << @s' causes bits to be lost when stored in *@d.
+ * - '@s' is garbage (e.g. negative) or so large that the result of
+ *   '@a << @s' is guaranteed to be 0.
+ * - '@a' is negative.
+ * - '@a << @s' sets the sign bit, if any, in '*@d'.
+ *
+ * '*@d' will hold the results of the attempted shift, but is not
+ * considered "safe for use" if true is returned.
  */
-#define check_shl_overflow(a, s, d) ({					\
+#define check_shl_overflow(a, s, d) __must_check_overflow(({		\
 	typeof(a) _a = a;						\
 	typeof(s) _s = s;						\
 	typeof(d) _d = d;						\
@@ -238,11 +126,117 @@
 	*_d = (_a_full << _to_shift);					\
 	(_to_shift != _s || is_negative(*_d) || is_negative(_a) ||	\
 	(*_d >> _to_shift) != _a);					\
+}))
+
+#define __overflows_type_constexpr(x, T) (			\
+	is_unsigned_type(typeof(x)) ?				\
+		(x) > type_max(typeof(T)) :			\
+	is_unsigned_type(typeof(T)) ?				\
+		(x) < 0 || (x) > type_max(typeof(T)) :		\
+	(x) < type_min(typeof(T)) || (x) > type_max(typeof(T)))
+
+#define __overflows_type(x, T)		({	\
+	typeof(T) v = 0;			\
+	check_add_overflow((x), v, &v);		\
 })
 
 /**
- * array_size() - Calculate size of 2-dimensional array.
+ * overflows_type - helper for checking the overflows between value, variables,
+ *		    or data type
  *
+ * @n: source constant value or variable to be checked
+ * @T: destination variable or data type proposed to store @x
+ *
+ * Compares the @x expression for whether or not it can safely fit in
+ * the storage of the type in @T. @x and @T can have different types.
+ * If @x is a constant expression, this will also resolve to a constant
+ * expression.
+ *
+ * Returns: true if overflow can occur, false otherwise.
+ */
+#define overflows_type(n, T)					\
+	__builtin_choose_expr(__is_constexpr(n),		\
+			      __overflows_type_constexpr(n, T),	\
+			      __overflows_type(n, T))
+
+/**
+ * castable_to_type - like __same_type(), but also allows for casted literals
+ *
+ * @n: variable or constant value
+ * @T: variable or data type
+ *
+ * Unlike the __same_type() macro, this allows a constant value as the
+ * first argument. If this value would not overflow into an assignment
+ * of the second argument's type, it returns true. Otherwise, this falls
+ * back to __same_type().
+ */
+#define castable_to_type(n, T)						\
+	__builtin_choose_expr(__is_constexpr(n),			\
+			      !__overflows_type_constexpr(n, T),	\
+			      __same_type(n, T))
+
+/**
+ * size_mul() - Calculate size_t multiplication with saturation at SIZE_MAX
+ * @factor1: first factor
+ * @factor2: second factor
+ *
+ * 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 size_t __must_check size_mul(size_t factor1, size_t factor2)
+{
+	size_t bytes;
+
+	if (check_mul_overflow(factor1, factor2, &bytes))
+		return SIZE_MAX;
+
+	return bytes;
+}
+
+/**
+ * size_add() - Calculate size_t addition with saturation at SIZE_MAX
+ * @addend1: first addend
+ * @addend2: second addend
+ *
+ * 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 size_t __must_check size_add(size_t addend1, size_t addend2)
+{
+	size_t bytes;
+
+	if (check_add_overflow(addend1, addend2, &bytes))
+		return SIZE_MAX;
+
+	return bytes;
+}
+
+/**
+ * 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 (minuend == SIZE_MAX || subtrahend == SIZE_MAX ||
+	    check_sub_overflow(minuend, subtrahend, &bytes))
+		return SIZE_MAX;
+
+	return bytes;
+}
+
+/**
+ * array_size() - Calculate size of 2-dimensional array.
  * @a: dimension one
  * @b: dimension two
  *
@@ -251,19 +245,10 @@
  * Returns: number of bytes needed to represent the array or SIZE_MAX on
  * overflow.
  */
-static inline __must_check size_t array_size(size_t a, size_t b)
-{
-	size_t bytes;
-
-	if (check_mul_overflow(a, b, &bytes))
-		return SIZE_MAX;
-
-	return bytes;
-}
+#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
@@ -273,48 +258,55 @@ static inline __must_check size_t array_size(size_t a, size_t b)
  * Returns: number of bytes needed to represent the array or SIZE_MAX on
  * overflow.
  */
-static inline __must_check size_t array3_size(size_t a, size_t b, size_t c)
-{
-	size_t bytes;
-
-	if (check_mul_overflow(a, b, &bytes))
-		return SIZE_MAX;
-	if (check_mul_overflow(bytes, c, &bytes))
-		return SIZE_MAX;
-
-	return bytes;
-}
-
-/*
- * Compute a*b+c, returning SIZE_MAX on overflow. Internal helper for
- * struct_size() below.
- */
-static inline __must_check size_t __ab_c_size(size_t a, size_t b, size_t c)
-{
-	size_t bytes;
-
-	if (check_mul_overflow(a, b, &bytes))
-		return SIZE_MAX;
-	if (check_add_overflow(bytes, c, &bytes))
-		return SIZE_MAX;
-
-	return bytes;
-}
+#define array3_size(a, b, c)	size_mul(size_mul(a, b), c)
 
 /**
- * struct_size() - Calculate size of structure with trailing array.
+ * flex_array_size() - Calculate size of a flexible array member
+ *                     within an enclosing structure.
  * @p: Pointer to the structure.
- * @member: Name of the array member.
- * @n: Number of elements in the array.
+ * @member: Name of the flexible array member.
+ * @count: Number of elements in the array.
  *
- * Calculates size of memory needed for structure @p followed by an
- * array of @n @member elements.
+ * 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 struct_size(p, member, n)					\
-	__ab_c_size(n,							\
-		    sizeof(*(p)->member) + __must_be_array((p)->member),\
-		    sizeof(*(p)))
+#define flex_array_size(p, member, count)				\
+	__builtin_choose_expr(__is_constexpr(count),			\
+		(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 of @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)					\
+	__builtin_choose_expr(__is_constexpr(count),			\
+		sizeof(*(p)) + flex_array_size(p, member, count),	\
+		size_add(sizeof(*(p)), flex_array_size(p, member, count)))
+
+/**
+ * struct_size_t() - Calculate size of structure with trailing flexible array
+ * @type: structure type name.
+ * @member: Name of the array member.
+ * @count: Number of elements in the array.
+ *
+ * Calculates size of memory needed for structure @type followed by an
+ * array of @count number of @member elements. Prefer using struct_size()
+ * when possible instead, to keep calculations associated with a specific
+ * instance variable of type @type.
+ *
+ * Return: number of bytes needed or SIZE_MAX on overflow.
+ */
+#define struct_size_t(type, member, count)					\
+	struct_size((type *)NULL, member, count)
 
 #endif /* __LINUX_OVERFLOW_H */
-- 
2.39.2




^ permalink raw reply	[flat|nested] 4+ messages in thread

* [PATCH master 2/3] include: import Linux string_is_terminated helper
  2023-10-20  7:23 [PATCH master 1/3] include: linux/overflow.h: sync with upstream Ahmad Fatoum
@ 2023-10-20  7:23 ` Ahmad Fatoum
  2023-10-20  7:23 ` [PATCH master 3/3] of: fdt: fix possibles overflows during parsing of invalid DTs Ahmad Fatoum
  2023-10-23 11:41 ` [PATCH master 1/3] include: linux/overflow.h: sync with upstream Sascha Hauer
  2 siblings, 0 replies; 4+ messages in thread
From: Ahmad Fatoum @ 2023-10-20  7:23 UTC (permalink / raw)
  To: barebox; +Cc: Ahmad Fatoum

Some binary formats read by barebox feature null-terminated string.
Import the kernel's string_is_terminated() helper to verify such
strings before passing them to string API.

Signed-off-by: Ahmad Fatoum <a.fatoum@pengutronix.de>
---
 include/linux/string_helpers.h | 13 +++++++++++++
 1 file changed, 13 insertions(+)
 create mode 100644 include/linux/string_helpers.h

diff --git a/include/linux/string_helpers.h b/include/linux/string_helpers.h
new file mode 100644
index 000000000000..5a8a469be7c0
--- /dev/null
+++ b/include/linux/string_helpers.h
@@ -0,0 +1,13 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef _LINUX_STRING_HELPERS_H_
+#define _LINUX_STRING_HELPERS_H_
+
+#include <linux/string.h>
+#include <linux/types.h>
+
+static inline bool string_is_terminated(const char *s, int len)
+{
+	return memchr(s, '\0', len) ? true : false;
+}
+
+#endif
-- 
2.39.2




^ permalink raw reply	[flat|nested] 4+ messages in thread

* [PATCH master 3/3] of: fdt: fix possibles overflows during parsing of invalid DTs
  2023-10-20  7:23 [PATCH master 1/3] include: linux/overflow.h: sync with upstream Ahmad Fatoum
  2023-10-20  7:23 ` [PATCH master 2/3] include: import Linux string_is_terminated helper Ahmad Fatoum
@ 2023-10-20  7:23 ` Ahmad Fatoum
  2023-10-23 11:41 ` [PATCH master 1/3] include: linux/overflow.h: sync with upstream Sascha Hauer
  2 siblings, 0 replies; 4+ messages in thread
From: Ahmad Fatoum @ 2023-10-20  7:23 UTC (permalink / raw)
  To: barebox; +Cc: Ahmad Fatoum

barebox may end up doing out of bound accesses if certain offsets in
parsed device trees exceed the total size of the flattened device tree
being parsed. Add some checks to early abort the parsing of such
invalid device trees.

Signed-off-by: Ahmad Fatoum <a.fatoum@pengutronix.de>
---
 drivers/of/fdt.c | 48 ++++++++++++++++++++++++++++++++++++++++--------
 1 file changed, 40 insertions(+), 8 deletions(-)

diff --git a/drivers/of/fdt.c b/drivers/of/fdt.c
index 9d72fafd3669..a4b42eec1c46 100644
--- a/drivers/of/fdt.c
+++ b/drivers/of/fdt.c
@@ -14,8 +14,23 @@
 #include <memory.h>
 #include <linux/sizes.h>
 #include <linux/ctype.h>
+#include <linux/overflow.h>
+#include <linux/string_helpers.h>
 #include <linux/err.h>
 
+static inline bool __dt_ptr_ok(const struct fdt_header *fdt, const void *p,
+				  unsigned elem_size, unsigned elem_align)
+{
+	if (!p || (const void *)fdt > p || !PTR_IS_ALIGNED(p, elem_align) ||
+	     p + elem_size > (const void *)fdt + be32_to_cpu(fdt->totalsize)) {
+		pr_err("unflatten: offset overflows or misaligns FDT\n");
+		return false;
+	}
+
+	return true;
+}
+#define dt_ptr_ok(fdt, p) __dt_ptr_ok(fdt, p, sizeof(*(p)), __alignof__(*(p)))
+
 static inline uint32_t dt_struct_advance(struct fdt_header *f, uint32_t dt, int size)
 {
 	dt += size;
@@ -29,27 +44,38 @@ static inline uint32_t dt_struct_advance(struct fdt_header *f, uint32_t dt, int
 
 static inline char *dt_string(struct fdt_header *f, char *strstart, uint32_t ofs)
 {
+	char *str;
+
 	if (ofs > f->size_dt_strings)
 		return NULL;
-	else
-		return strstart + ofs;
+
+	str = strstart + ofs;
+
+	return string_is_terminated(str, f->size_dt_strings - ofs) ? str : NULL;
 }
 
 static int of_reservemap_num_entries(const struct fdt_header *fdt)
 {
-	const struct fdt_reserve_entry *r;
+	/*
+	 * FDT may violate spec mandated 8-byte alignment if unflattening it out of
+	 * a FIT image property, so play it safe here.
+	 */
+	const struct fdt_reserve_entry_unaligned {
+		fdt64_t address;
+		fdt64_t size;
+	} __packed *r;
 	int n = 0;
 
 	r = (void *)fdt + be32_to_cpu(fdt->off_mem_rsvmap);
 
-	while (r->size) {
+	while (dt_ptr_ok(fdt, r) && r->size) {
 		n++;
 		r++;
 		if (n == OF_MAX_RESERVE_MAP)
 			return -EINVAL;
 	}
 
-	return n;
+	return r->size == 0 ? n : -ESPIPE;
 }
 
 /**
@@ -135,12 +161,12 @@ static struct device_node *__of_unflatten_dtb(const void *infdt, int size,
 	if (f.totalsize > size)
 		return ERR_PTR(-EINVAL);
 
-	if (f.off_dt_struct + f.size_dt_struct > f.totalsize) {
+	if (size_add(f.off_dt_struct, f.size_dt_struct) > f.totalsize) {
 		pr_err("unflatten: dt size exceeds total size\n");
 		return ERR_PTR(-ESPIPE);
 	}
 
-	if (f.off_dt_strings + f.size_dt_strings > f.totalsize) {
+	if (size_add(f.off_dt_strings, f.size_dt_strings) > f.totalsize) {
 		pr_err("unflatten: string size exceeds total size\n");
 		return ERR_PTR(-ESPIPE);
 	}
@@ -157,7 +183,13 @@ static struct device_node *__of_unflatten_dtb(const void *infdt, int size,
 		goto err;
 
 	while (1) {
-		tag = be32_to_cpu(*(uint32_t *)(infdt + dt_struct));
+		__be32 *tagp = (uint32_t *)(infdt + dt_struct);
+		if (!dt_ptr_ok(infdt, tagp)) {
+			ret = -ESPIPE;
+			goto err;
+		}
+
+		tag = be32_to_cpu(*tagp);
 
 		switch (tag) {
 		case FDT_BEGIN_NODE:
-- 
2.39.2




^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: [PATCH master 1/3] include: linux/overflow.h: sync with upstream
  2023-10-20  7:23 [PATCH master 1/3] include: linux/overflow.h: sync with upstream Ahmad Fatoum
  2023-10-20  7:23 ` [PATCH master 2/3] include: import Linux string_is_terminated helper Ahmad Fatoum
  2023-10-20  7:23 ` [PATCH master 3/3] of: fdt: fix possibles overflows during parsing of invalid DTs Ahmad Fatoum
@ 2023-10-23 11:41 ` Sascha Hauer
  2 siblings, 0 replies; 4+ messages in thread
From: Sascha Hauer @ 2023-10-23 11:41 UTC (permalink / raw)
  To: Ahmad Fatoum; +Cc: barebox

On Fri, Oct 20, 2023 at 09:23:14AM +0200, Ahmad Fatoum wrote:
> Newer versions of the header add a size_add macro for doing saturating
> addition, which will be used in a follow-up fix, so sync the header with
> Linux to make it available.
> 
> Signed-off-by: Ahmad Fatoum <a.fatoum@pengutronix.de>
> ---
>  include/linux/overflow.h | 436 +++++++++++++++++++--------------------
>  1 file changed, 214 insertions(+), 222 deletions(-)

Applied, thanks

Sascha

> 
> diff --git a/include/linux/overflow.h b/include/linux/overflow.h
> index 50c93ca0c3d6..f9b60313eaea 100644
> --- a/include/linux/overflow.h
> +++ b/include/linux/overflow.h
> @@ -4,14 +4,12 @@
>  
>  #include <linux/compiler.h>
>  #include <linux/limits.h>
> +#include <linux/const.h>
>  
>  /*
> - * In the fallback code below, we need to compute the minimum and
> - * maximum values representable in a given type. These macros may also
> - * be useful elsewhere, so we provide them outside the
> - * COMPILER_HAS_GENERIC_BUILTIN_OVERFLOW block.
> - *
> - * It would seem more obvious to do something like
> + * We need to compute the minimum and maximum values representable in a given
> + * type. These macros may also be useful elsewhere. It would seem more obvious
> + * to do something like:
>   *
>   * #define type_min(T) (T)(is_signed_type(T) ? (T)1 << (8*sizeof(T)-1) : 0)
>   * #define type_max(T) (T)(is_signed_type(T) ? ((T)1 << (8*sizeof(T)-1)) - 1 : ~(T)0)
> @@ -32,7 +30,6 @@
>   * https://mail-index.netbsd.org/tech-misc/2007/02/05/0000.html -
>   * credit to Christian Biere.
>   */
> -#define is_signed_type(type)       (((type)(-1)) < (type)1)
>  #define __type_half_max(type) ((type)1 << (8*sizeof(type) - 1 - is_signed_type(type)))
>  #define type_max(T) ((T)((__type_half_max(T) - 1) + __type_half_max(T)))
>  #define type_min(T) ((T)((T)-type_max(T)-(T)1))
> @@ -44,191 +41,82 @@
>  #define is_non_negative(a) ((a) > 0 || (a) == 0)
>  #define is_negative(a) (!(is_non_negative(a)))
>  
> -#ifdef COMPILER_HAS_GENERIC_BUILTIN_OVERFLOW
>  /*
> - * For simplicity and code hygiene, the fallback code below insists on
> - * a, b and *d having the same type (similar to the min() and max()
> - * macros), whereas gcc's type-generic overflow checkers accept
> - * different types. Hence we don't just make check_add_overflow an
> - * alias for __builtin_add_overflow, but add type checks similar to
> - * below.
> + * Allows for effectively applying __must_check to a macro so we can have
> + * both the type-agnostic benefits of the macros while also being able to
> + * enforce that the return value is, in fact, checked.
>   */
> -#define check_add_overflow(a, b, d) ({		\
> -	typeof(a) __a = (a);			\
> -	typeof(b) __b = (b);			\
> -	typeof(d) __d = (d);			\
> -	(void) (&__a == &__b);			\
> -	(void) (&__a == __d);			\
> -	__builtin_add_overflow(__a, __b, __d);	\
> -})
> +static inline bool __must_check __must_check_overflow(bool overflow)
> +{
> +	return unlikely(overflow);
> +}
>  
> -#define check_sub_overflow(a, b, d) ({		\
> -	typeof(a) __a = (a);			\
> -	typeof(b) __b = (b);			\
> -	typeof(d) __d = (d);			\
> -	(void) (&__a == &__b);			\
> -	(void) (&__a == __d);			\
> -	__builtin_sub_overflow(__a, __b, __d);	\
> -})
> -
> -#define check_mul_overflow(a, b, d) ({		\
> -	typeof(a) __a = (a);			\
> -	typeof(b) __b = (b);			\
> -	typeof(d) __d = (d);			\
> -	(void) (&__a == &__b);			\
> -	(void) (&__a == __d);			\
> -	__builtin_mul_overflow(__a, __b, __d);	\
> -})
> -
> -#else
> -
> -
> -/* Checking for unsigned overflow is relatively easy without causing UB. */
> -#define __unsigned_add_overflow(a, b, d) ({	\
> -	typeof(a) __a = (a);			\
> -	typeof(b) __b = (b);			\
> -	typeof(d) __d = (d);			\
> -	(void) (&__a == &__b);			\
> -	(void) (&__a == __d);			\
> -	*__d = __a + __b;			\
> -	*__d < __a;				\
> -})
> -#define __unsigned_sub_overflow(a, b, d) ({	\
> -	typeof(a) __a = (a);			\
> -	typeof(b) __b = (b);			\
> -	typeof(d) __d = (d);			\
> -	(void) (&__a == &__b);			\
> -	(void) (&__a == __d);			\
> -	*__d = __a - __b;			\
> -	__a < __b;				\
> -})
> -/*
> - * If one of a or b is a compile-time constant, this avoids a division.
> - */
> -#define __unsigned_mul_overflow(a, b, d) ({		\
> -	typeof(a) __a = (a);				\
> -	typeof(b) __b = (b);				\
> -	typeof(d) __d = (d);				\
> -	(void) (&__a == &__b);				\
> -	(void) (&__a == __d);				\
> -	*__d = __a * __b;				\
> -	__builtin_constant_p(__b) ?			\
> -	  __b > 0 && __a > type_max(typeof(__a)) / __b : \
> -	  __a > 0 && __b > type_max(typeof(__b)) / __a;	 \
> -})
> -
> -/*
> - * For signed types, detecting overflow is much harder, especially if
> - * we want to avoid UB. But the interface of these macros is such that
> - * we must provide a result in *d, and in fact we must produce the
> - * result promised by gcc's builtins, which is simply the possibly
> - * wrapped-around value. Fortunately, we can just formally do the
> - * operations in the widest relevant unsigned type (u64) and then
> - * truncate the result - gcc is smart enough to generate the same code
> - * with and without the (u64) casts.
> - */
> -
> -/*
> - * Adding two signed integers can overflow only if they have the same
> - * sign, and overflow has happened iff the result has the opposite
> - * sign.
> - */
> -#define __signed_add_overflow(a, b, d) ({	\
> -	typeof(a) __a = (a);			\
> -	typeof(b) __b = (b);			\
> -	typeof(d) __d = (d);			\
> -	(void) (&__a == &__b);			\
> -	(void) (&__a == __d);			\
> -	*__d = (u64)__a + (u64)__b;		\
> -	(((~(__a ^ __b)) & (*__d ^ __a))	\
> -		& type_min(typeof(__a))) != 0;	\
> -})
> -
> -/*
> - * Subtraction is similar, except that overflow can now happen only
> - * when the signs are opposite. In this case, overflow has happened if
> - * the result has the opposite sign of a.
> - */
> -#define __signed_sub_overflow(a, b, d) ({	\
> -	typeof(a) __a = (a);			\
> -	typeof(b) __b = (b);			\
> -	typeof(d) __d = (d);			\
> -	(void) (&__a == &__b);			\
> -	(void) (&__a == __d);			\
> -	*__d = (u64)__a - (u64)__b;		\
> -	((((__a ^ __b)) & (*__d ^ __a))		\
> -		& type_min(typeof(__a))) != 0;	\
> -})
> -
> -/*
> - * Signed multiplication is rather hard. gcc always follows C99, so
> - * division is truncated towards 0. This means that we can write the
> - * overflow check like this:
> +/**
> + * check_add_overflow() - Calculate addition with overflow checking
> + * @a: first addend
> + * @b: second addend
> + * @d: pointer to store sum
>   *
> - * (a > 0 && (b > MAX/a || b < MIN/a)) ||
> - * (a < -1 && (b > MIN/a || b < MAX/a) ||
> - * (a == -1 && b == MIN)
> + * Returns 0 on success.
>   *
> - * The redundant casts of -1 are to silence an annoying -Wtype-limits
> - * (included in -Wextra) warning: When the type is u8 or u16, the
> - * __b_c_e in check_mul_overflow obviously selects
> - * __unsigned_mul_overflow, but unfortunately gcc still parses this
> - * code and warns about the limited range of __b.
> + * *@d holds the results of the attempted addition, but is not considered
> + * "safe for use" on a non-zero return value, which indicates that the
> + * sum has overflowed or been truncated.
>   */
> +#define check_add_overflow(a, b, d)	\
> +	__must_check_overflow(__builtin_add_overflow(a, b, d))
>  
> -#define __signed_mul_overflow(a, b, d) ({				\
> -	typeof(a) __a = (a);						\
> -	typeof(b) __b = (b);						\
> -	typeof(d) __d = (d);						\
> -	typeof(a) __tmax = type_max(typeof(a));				\
> -	typeof(a) __tmin = type_min(typeof(a));				\
> -	(void) (&__a == &__b);						\
> -	(void) (&__a == __d);						\
> -	*__d = (u64)__a * (u64)__b;					\
> -	(__b > 0   && (__a > __tmax/__b || __a < __tmin/__b)) ||	\
> -	(__b < (typeof(__b))-1  && (__a > __tmin/__b || __a < __tmax/__b)) || \
> -	(__b == (typeof(__b))-1 && __a == __tmin);			\
> -})
> -
> -
> -#define check_add_overflow(a, b, d)					\
> -	__builtin_choose_expr(is_signed_type(typeof(a)),		\
> -			__signed_add_overflow(a, b, d),			\
> -			__unsigned_add_overflow(a, b, d))
> -
> -#define check_sub_overflow(a, b, d)					\
> -	__builtin_choose_expr(is_signed_type(typeof(a)),		\
> -			__signed_sub_overflow(a, b, d),			\
> -			__unsigned_sub_overflow(a, b, d))
> -
> -#define check_mul_overflow(a, b, d)					\
> -	__builtin_choose_expr(is_signed_type(typeof(a)),		\
> -			__signed_mul_overflow(a, b, d),			\
> -			__unsigned_mul_overflow(a, b, d))
> -
> -
> -#endif /* COMPILER_HAS_GENERIC_BUILTIN_OVERFLOW */
> -
> -/** check_shl_overflow() - Calculate a left-shifted value and check overflow
> +/**
> + * check_sub_overflow() - Calculate subtraction with overflow checking
> + * @a: minuend; value to subtract from
> + * @b: subtrahend; value to subtract from @a
> + * @d: pointer to store difference
>   *
> + * Returns 0 on success.
> + *
> + * *@d holds the results of the attempted subtraction, but is not considered
> + * "safe for use" on a non-zero return value, which indicates that the
> + * difference has underflowed or been truncated.
> + */
> +#define check_sub_overflow(a, b, d)	\
> +	__must_check_overflow(__builtin_sub_overflow(a, b, d))
> +
> +/**
> + * check_mul_overflow() - Calculate multiplication with overflow checking
> + * @a: first factor
> + * @b: second factor
> + * @d: pointer to store product
> + *
> + * Returns 0 on success.
> + *
> + * *@d holds the results of the attempted multiplication, but is not
> + * considered "safe for use" on a non-zero return value, which indicates
> + * that the product has overflowed or been truncated.
> + */
> +#define check_mul_overflow(a, b, d)	\
> +	__must_check_overflow(__builtin_mul_overflow(a, b, d))
> +
> +/**
> + * check_shl_overflow() - Calculate a left-shifted value and check overflow
>   * @a: Value to be shifted
>   * @s: How many bits left to shift
>   * @d: Pointer to where to store the result
>   *
>   * Computes *@d = (@a << @s)
>   *
> - * Returns true if '*d' cannot hold the result or when 'a << s' doesn't
> + * Returns true if '*@d' cannot hold the result or when '@a << @s' doesn't
>   * make sense. Example conditions:
> - * - 'a << s' causes bits to be lost when stored in *d.
> - * - 's' is garbage (e.g. negative) or so large that the result of
> - *   'a << s' is guaranteed to be 0.
> - * - 'a' is negative.
> - * - 'a << s' sets the sign bit, if any, in '*d'.
>   *
> - * '*d' will hold the results of the attempted shift, but is not
> - * considered "safe for use" if false is returned.
> + * - '@a << @s' causes bits to be lost when stored in *@d.
> + * - '@s' is garbage (e.g. negative) or so large that the result of
> + *   '@a << @s' is guaranteed to be 0.
> + * - '@a' is negative.
> + * - '@a << @s' sets the sign bit, if any, in '*@d'.
> + *
> + * '*@d' will hold the results of the attempted shift, but is not
> + * considered "safe for use" if true is returned.
>   */
> -#define check_shl_overflow(a, s, d) ({					\
> +#define check_shl_overflow(a, s, d) __must_check_overflow(({		\
>  	typeof(a) _a = a;						\
>  	typeof(s) _s = s;						\
>  	typeof(d) _d = d;						\
> @@ -238,11 +126,117 @@
>  	*_d = (_a_full << _to_shift);					\
>  	(_to_shift != _s || is_negative(*_d) || is_negative(_a) ||	\
>  	(*_d >> _to_shift) != _a);					\
> +}))
> +
> +#define __overflows_type_constexpr(x, T) (			\
> +	is_unsigned_type(typeof(x)) ?				\
> +		(x) > type_max(typeof(T)) :			\
> +	is_unsigned_type(typeof(T)) ?				\
> +		(x) < 0 || (x) > type_max(typeof(T)) :		\
> +	(x) < type_min(typeof(T)) || (x) > type_max(typeof(T)))
> +
> +#define __overflows_type(x, T)		({	\
> +	typeof(T) v = 0;			\
> +	check_add_overflow((x), v, &v);		\
>  })
>  
>  /**
> - * array_size() - Calculate size of 2-dimensional array.
> + * overflows_type - helper for checking the overflows between value, variables,
> + *		    or data type
>   *
> + * @n: source constant value or variable to be checked
> + * @T: destination variable or data type proposed to store @x
> + *
> + * Compares the @x expression for whether or not it can safely fit in
> + * the storage of the type in @T. @x and @T can have different types.
> + * If @x is a constant expression, this will also resolve to a constant
> + * expression.
> + *
> + * Returns: true if overflow can occur, false otherwise.
> + */
> +#define overflows_type(n, T)					\
> +	__builtin_choose_expr(__is_constexpr(n),		\
> +			      __overflows_type_constexpr(n, T),	\
> +			      __overflows_type(n, T))
> +
> +/**
> + * castable_to_type - like __same_type(), but also allows for casted literals
> + *
> + * @n: variable or constant value
> + * @T: variable or data type
> + *
> + * Unlike the __same_type() macro, this allows a constant value as the
> + * first argument. If this value would not overflow into an assignment
> + * of the second argument's type, it returns true. Otherwise, this falls
> + * back to __same_type().
> + */
> +#define castable_to_type(n, T)						\
> +	__builtin_choose_expr(__is_constexpr(n),			\
> +			      !__overflows_type_constexpr(n, T),	\
> +			      __same_type(n, T))
> +
> +/**
> + * size_mul() - Calculate size_t multiplication with saturation at SIZE_MAX
> + * @factor1: first factor
> + * @factor2: second factor
> + *
> + * 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 size_t __must_check size_mul(size_t factor1, size_t factor2)
> +{
> +	size_t bytes;
> +
> +	if (check_mul_overflow(factor1, factor2, &bytes))
> +		return SIZE_MAX;
> +
> +	return bytes;
> +}
> +
> +/**
> + * size_add() - Calculate size_t addition with saturation at SIZE_MAX
> + * @addend1: first addend
> + * @addend2: second addend
> + *
> + * 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 size_t __must_check size_add(size_t addend1, size_t addend2)
> +{
> +	size_t bytes;
> +
> +	if (check_add_overflow(addend1, addend2, &bytes))
> +		return SIZE_MAX;
> +
> +	return bytes;
> +}
> +
> +/**
> + * 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 (minuend == SIZE_MAX || subtrahend == SIZE_MAX ||
> +	    check_sub_overflow(minuend, subtrahend, &bytes))
> +		return SIZE_MAX;
> +
> +	return bytes;
> +}
> +
> +/**
> + * array_size() - Calculate size of 2-dimensional array.
>   * @a: dimension one
>   * @b: dimension two
>   *
> @@ -251,19 +245,10 @@
>   * Returns: number of bytes needed to represent the array or SIZE_MAX on
>   * overflow.
>   */
> -static inline __must_check size_t array_size(size_t a, size_t b)
> -{
> -	size_t bytes;
> -
> -	if (check_mul_overflow(a, b, &bytes))
> -		return SIZE_MAX;
> -
> -	return bytes;
> -}
> +#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
> @@ -273,48 +258,55 @@ static inline __must_check size_t array_size(size_t a, size_t b)
>   * Returns: number of bytes needed to represent the array or SIZE_MAX on
>   * overflow.
>   */
> -static inline __must_check size_t array3_size(size_t a, size_t b, size_t c)
> -{
> -	size_t bytes;
> -
> -	if (check_mul_overflow(a, b, &bytes))
> -		return SIZE_MAX;
> -	if (check_mul_overflow(bytes, c, &bytes))
> -		return SIZE_MAX;
> -
> -	return bytes;
> -}
> -
> -/*
> - * Compute a*b+c, returning SIZE_MAX on overflow. Internal helper for
> - * struct_size() below.
> - */
> -static inline __must_check size_t __ab_c_size(size_t a, size_t b, size_t c)
> -{
> -	size_t bytes;
> -
> -	if (check_mul_overflow(a, b, &bytes))
> -		return SIZE_MAX;
> -	if (check_add_overflow(bytes, c, &bytes))
> -		return SIZE_MAX;
> -
> -	return bytes;
> -}
> +#define array3_size(a, b, c)	size_mul(size_mul(a, b), c)
>  
>  /**
> - * struct_size() - Calculate size of structure with trailing array.
> + * flex_array_size() - Calculate size of a flexible array member
> + *                     within an enclosing structure.
>   * @p: Pointer to the structure.
> - * @member: Name of the array member.
> - * @n: Number of elements in the array.
> + * @member: Name of the flexible array member.
> + * @count: Number of elements in the array.
>   *
> - * Calculates size of memory needed for structure @p followed by an
> - * array of @n @member elements.
> + * 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 struct_size(p, member, n)					\
> -	__ab_c_size(n,							\
> -		    sizeof(*(p)->member) + __must_be_array((p)->member),\
> -		    sizeof(*(p)))
> +#define flex_array_size(p, member, count)				\
> +	__builtin_choose_expr(__is_constexpr(count),			\
> +		(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 of @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)					\
> +	__builtin_choose_expr(__is_constexpr(count),			\
> +		sizeof(*(p)) + flex_array_size(p, member, count),	\
> +		size_add(sizeof(*(p)), flex_array_size(p, member, count)))
> +
> +/**
> + * struct_size_t() - Calculate size of structure with trailing flexible array
> + * @type: structure type name.
> + * @member: Name of the array member.
> + * @count: Number of elements in the array.
> + *
> + * Calculates size of memory needed for structure @type followed by an
> + * array of @count number of @member elements. Prefer using struct_size()
> + * when possible instead, to keep calculations associated with a specific
> + * instance variable of type @type.
> + *
> + * Return: number of bytes needed or SIZE_MAX on overflow.
> + */
> +#define struct_size_t(type, member, count)					\
> +	struct_size((type *)NULL, member, count)
>  
>  #endif /* __LINUX_OVERFLOW_H */
> -- 
> 2.39.2
> 
> 
> 

-- 
Pengutronix e.K.                           |                             |
Steuerwalder Str. 21                       | http://www.pengutronix.de/  |
31137 Hildesheim, Germany                  | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |



^ permalink raw reply	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2023-10-23 11:43 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2023-10-20  7:23 [PATCH master 1/3] include: linux/overflow.h: sync with upstream Ahmad Fatoum
2023-10-20  7:23 ` [PATCH master 2/3] include: import Linux string_is_terminated helper Ahmad Fatoum
2023-10-20  7:23 ` [PATCH master 3/3] of: fdt: fix possibles overflows during parsing of invalid DTs Ahmad Fatoum
2023-10-23 11:41 ` [PATCH master 1/3] include: linux/overflow.h: sync with upstream Sascha Hauer

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox