mail archive of the barebox mailing list
 help / color / mirror / Atom feed
* [PATCH 1/2] list: rename debugging hooks
@ 2024-01-03 10:19 Ahmad Fatoum
  2024-01-03 10:19 ` [PATCH 2/2] lib: add optional linked list debugging Ahmad Fatoum
  2024-01-04  9:12 ` [PATCH 1/2] list: rename debugging hooks Sascha Hauer
  0 siblings, 2 replies; 3+ messages in thread
From: Ahmad Fatoum @ 2024-01-03 10:19 UTC (permalink / raw)
  To: barebox; +Cc: Ahmad Fatoum

Linux recently renamed the name of these helpers, so have barebox follow
suit before implementing them out of line when optional list debugging
is enabled.

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

diff --git a/include/linux/list.h b/include/linux/list.h
index 1341806b59da..60b0111f467c 100644
--- a/include/linux/list.h
+++ b/include/linux/list.h
@@ -37,18 +37,18 @@ static inline void INIT_LIST_HEAD(struct list_head *list)
 }
 
 #ifdef CONFIG_DEBUG_LIST
-extern bool __list_add_valid(struct list_head *new,
-			      struct list_head *prev,
-			      struct list_head *next);
-extern bool __list_del_entry_valid(struct list_head *entry);
+extern bool __list_add_valid_or_report(struct list_head *new,
+				       struct list_head *prev,
+				       struct list_head *next);
+extern bool __list_del_entry_valid_or_report(struct list_head *entry);
 #else
-static inline bool __list_add_valid(struct list_head *new,
-				struct list_head *prev,
-				struct list_head *next)
+static inline bool __list_add_valid_or_report(struct list_head *new,
+					      struct list_head *prev,
+					      struct list_head *next)
 {
 	return true;
 }
-static inline bool __list_del_entry_valid(struct list_head *entry)
+static inline bool __list_del_entry_valid_or_report(struct list_head *entry)
 {
 	return true;
 }
@@ -64,7 +64,7 @@ static inline void __list_add(struct list_head *new,
 			      struct list_head *prev,
 			      struct list_head *next)
 {
-	if (!__list_add_valid(new, prev, next))
+	if (!__list_add_valid_or_report(new, prev, next))
 		return;
 
 	next->prev = new;
@@ -129,7 +129,7 @@ static inline void __list_del_clearprev(struct list_head *entry)
 
 static inline void __list_del_entry(struct list_head *entry)
 {
-	if (!__list_del_entry_valid(entry))
+	if (!__list_del_entry_valid_or_report(entry))
 		return;
 
 	__list_del(entry->prev, entry->next);
-- 
2.39.2




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

* [PATCH 2/2] lib: add optional linked list debugging
  2024-01-03 10:19 [PATCH 1/2] list: rename debugging hooks Ahmad Fatoum
@ 2024-01-03 10:19 ` Ahmad Fatoum
  2024-01-04  9:12 ` [PATCH 1/2] list: rename debugging hooks Sascha Hauer
  1 sibling, 0 replies; 3+ messages in thread
From: Ahmad Fatoum @ 2024-01-03 10:19 UTC (permalink / raw)
  To: barebox; +Cc: Ahmad Fatoum

When enabled, this outputs messages like:

  list_del corruption, 000000005fe4a9d0->next is LIST_POISON1 (0000000000000100)

which can be useful when debugging.

Signed-off-by: Ahmad Fatoum <a.fatoum@pengutronix.de>
---
 common/Kconfig        |  8 +++++
 include/linux/bug.h   | 17 +++++++++++
 lib/Kconfig.hardening | 10 +++++++
 lib/Makefile          |  1 +
 lib/list_debug.c      | 68 +++++++++++++++++++++++++++++++++++++++++++
 5 files changed, 104 insertions(+)
 create mode 100644 lib/list_debug.c

diff --git a/common/Kconfig b/common/Kconfig
index c8c23a8e03a2..18ad01713293 100644
--- a/common/Kconfig
+++ b/common/Kconfig
@@ -1704,6 +1704,14 @@ config DMA_API_DEBUG
 
 	  If unsure, say N.
 
+config DEBUG_LIST
+	bool "Debug linked list manipulation"
+	help
+	  Enable this to turn on extended checks in the linked-list
+	  walking routines.
+
+	  If unsure, say N.
+
 config PBL_BREAK
 	bool "Execute software break on pbl start"
 	depends on ARM && (!CPU_32v4T && !ARCH_TEGRA)
diff --git a/include/linux/bug.h b/include/linux/bug.h
index d8fc328a0706..8ea5f8d1b260 100644
--- a/include/linux/bug.h
+++ b/include/linux/bug.h
@@ -6,4 +6,21 @@
 #include <asm-generic/bug.h>
 #include <linux/build_bug.h>
 
+/*
+ * Since detected data corruption should stop operation on the affected
+ * structures. Return value must be checked and sanely acted on by caller.
+ */
+static inline __must_check bool check_data_corruption(bool v) { return v; }
+#define CHECK_DATA_CORRUPTION(condition, fmt, ...)			 \
+	check_data_corruption(({					 \
+		bool corruption = unlikely(condition);			 \
+		if (corruption) {					 \
+			if (IS_ENABLED(CONFIG_BUG_ON_DATA_CORRUPTION)) { \
+				panic(fmt, ##__VA_ARGS__);		 \
+			} else						 \
+				WARN(1, fmt, ##__VA_ARGS__);		 \
+		}							 \
+		corruption;						 \
+	}))
+
 #endif	/* _LINUX_BUG_H */
diff --git a/lib/Kconfig.hardening b/lib/Kconfig.hardening
index 7f74d0d98a9c..28be42a27465 100644
--- a/lib/Kconfig.hardening
+++ b/lib/Kconfig.hardening
@@ -1,5 +1,15 @@
 menu "Hardening options"
 
+config BUG_ON_DATA_CORRUPTION
+	bool "Trigger a BUG when data corruption is detected"
+	select DEBUG_LIST
+	help
+	  Select this option if barebox should BUG when it encounters
+	  data corruption in its memory structures when they get checked
+	  for validity.
+
+	  If unsure, say N.
+
 config STACK_GUARD_PAGE
 	bool "Place guard page to catch stack overflows"
 	depends on ARM && MMU
diff --git a/lib/Makefile b/lib/Makefile
index 38204c8273e5..853d8870fe14 100644
--- a/lib/Makefile
+++ b/lib/Makefile
@@ -71,6 +71,7 @@ obj-$(CONFIG_FONTS)	+= fonts/
 obj-$(CONFIG_BAREBOX_LOGO)     += logo/
 obj-y			+= reed_solomon/
 obj-$(CONFIG_RATP)	+= ratp.o
+obj-$(CONFIG_DEBUG_LIST) += list_debug.o
 obj-y			+= list_sort.o
 obj-y			+= refcount.o
 obj-y			+= int_sqrt.o
diff --git a/lib/list_debug.c b/lib/list_debug.c
new file mode 100644
index 000000000000..7de4c709a391
--- /dev/null
+++ b/lib/list_debug.c
@@ -0,0 +1,68 @@
+/*
+ * Copyright 2006, Red Hat, Inc., Dave Jones
+ * Released under the General Public License (GPL).
+ *
+ * This file contains the linked list validation for DEBUG_LIST.
+ */
+
+#include <linux/export.h>
+#include <linux/list.h>
+#include <linux/bug.h>
+#include <linux/kernel.h>
+
+/*
+ * Check that the data structures for the list manipulations are reasonably
+ * valid. Failures here indicate memory corruption (and possibly an exploit
+ * attempt).
+ */
+
+bool __list_add_valid_or_report(struct list_head *new, struct list_head *prev,
+				struct list_head *next)
+{
+	if (CHECK_DATA_CORRUPTION(prev == NULL,
+			"list_add corruption. prev is NULL.\n") ||
+	    CHECK_DATA_CORRUPTION(next == NULL,
+			"list_add corruption. next is NULL.\n") ||
+	    CHECK_DATA_CORRUPTION(next->prev != prev,
+			"list_add corruption. next->prev should be prev (%px), but was %px. (next=%px).\n",
+			prev, next->prev, next) ||
+	    CHECK_DATA_CORRUPTION(prev->next != next,
+			"list_add corruption. prev->next should be next (%px), but was %px. (prev=%px).\n",
+			next, prev->next, prev) ||
+	    CHECK_DATA_CORRUPTION(new == prev || new == next,
+			"list_add double add: new=%px, prev=%px, next=%px.\n",
+			new, prev, next))
+		return false;
+
+	return true;
+}
+EXPORT_SYMBOL(__list_add_valid_or_report);
+
+bool __list_del_entry_valid_or_report(struct list_head *entry)
+{
+	struct list_head *prev, *next;
+
+	prev = entry->prev;
+	next = entry->next;
+
+	if (CHECK_DATA_CORRUPTION(next == NULL,
+			"list_del corruption, %px->next is NULL\n", entry) ||
+	    CHECK_DATA_CORRUPTION(prev == NULL,
+			"list_del corruption, %px->prev is NULL\n", entry) ||
+	    CHECK_DATA_CORRUPTION(next == LIST_POISON1,
+			"list_del corruption, %px->next is LIST_POISON1 (%px)\n",
+			entry, LIST_POISON1) ||
+	    CHECK_DATA_CORRUPTION(prev == LIST_POISON2,
+			"list_del corruption, %px->prev is LIST_POISON2 (%px)\n",
+			entry, LIST_POISON2) ||
+	    CHECK_DATA_CORRUPTION(prev->next != entry,
+			"list_del corruption. prev->next should be %px, but was %px. (prev=%px)\n",
+			entry, prev->next, prev) ||
+	    CHECK_DATA_CORRUPTION(next->prev != entry,
+			"list_del corruption. next->prev should be %px, but was %px. (next=%px)\n",
+			entry, next->prev, next))
+		return false;
+
+	return true;
+}
+EXPORT_SYMBOL(__list_del_entry_valid_or_report);
-- 
2.39.2




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

* Re: [PATCH 1/2] list: rename debugging hooks
  2024-01-03 10:19 [PATCH 1/2] list: rename debugging hooks Ahmad Fatoum
  2024-01-03 10:19 ` [PATCH 2/2] lib: add optional linked list debugging Ahmad Fatoum
@ 2024-01-04  9:12 ` Sascha Hauer
  1 sibling, 0 replies; 3+ messages in thread
From: Sascha Hauer @ 2024-01-04  9:12 UTC (permalink / raw)
  To: Ahmad Fatoum; +Cc: barebox

On Wed, Jan 03, 2024 at 11:19:47AM +0100, Ahmad Fatoum wrote:
> Linux recently renamed the name of these helpers, so have barebox follow
> suit before implementing them out of line when optional list debugging
> is enabled.
> 
> Signed-off-by: Ahmad Fatoum <a.fatoum@pengutronix.de>
> ---
>  include/linux/list.h | 20 ++++++++++----------
>  1 file changed, 10 insertions(+), 10 deletions(-)

Applied, thanks

Sascha

> 
> diff --git a/include/linux/list.h b/include/linux/list.h
> index 1341806b59da..60b0111f467c 100644
> --- a/include/linux/list.h
> +++ b/include/linux/list.h
> @@ -37,18 +37,18 @@ static inline void INIT_LIST_HEAD(struct list_head *list)
>  }
>  
>  #ifdef CONFIG_DEBUG_LIST
> -extern bool __list_add_valid(struct list_head *new,
> -			      struct list_head *prev,
> -			      struct list_head *next);
> -extern bool __list_del_entry_valid(struct list_head *entry);
> +extern bool __list_add_valid_or_report(struct list_head *new,
> +				       struct list_head *prev,
> +				       struct list_head *next);
> +extern bool __list_del_entry_valid_or_report(struct list_head *entry);
>  #else
> -static inline bool __list_add_valid(struct list_head *new,
> -				struct list_head *prev,
> -				struct list_head *next)
> +static inline bool __list_add_valid_or_report(struct list_head *new,
> +					      struct list_head *prev,
> +					      struct list_head *next)
>  {
>  	return true;
>  }
> -static inline bool __list_del_entry_valid(struct list_head *entry)
> +static inline bool __list_del_entry_valid_or_report(struct list_head *entry)
>  {
>  	return true;
>  }
> @@ -64,7 +64,7 @@ static inline void __list_add(struct list_head *new,
>  			      struct list_head *prev,
>  			      struct list_head *next)
>  {
> -	if (!__list_add_valid(new, prev, next))
> +	if (!__list_add_valid_or_report(new, prev, next))
>  		return;
>  
>  	next->prev = new;
> @@ -129,7 +129,7 @@ static inline void __list_del_clearprev(struct list_head *entry)
>  
>  static inline void __list_del_entry(struct list_head *entry)
>  {
> -	if (!__list_del_entry_valid(entry))
> +	if (!__list_del_entry_valid_or_report(entry))
>  		return;
>  
>  	__list_del(entry->prev, entry->next);
> -- 
> 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] 3+ messages in thread

end of thread, other threads:[~2024-01-04  9:13 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2024-01-03 10:19 [PATCH 1/2] list: rename debugging hooks Ahmad Fatoum
2024-01-03 10:19 ` [PATCH 2/2] lib: add optional linked list debugging Ahmad Fatoum
2024-01-04  9:12 ` [PATCH 1/2] list: rename debugging hooks Sascha Hauer

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