All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 00/11] Fuzzing and ASAN for sandbox
@ 2022-04-07  9:41 Andrew Scull
  2022-04-07  9:41 ` [PATCH 01/11] sandbox: Set the EFI symbols in linker script Andrew Scull
                   ` (10 more replies)
  0 siblings, 11 replies; 30+ messages in thread
From: Andrew Scull @ 2022-04-07  9:41 UTC (permalink / raw)
  To: u-boot; +Cc: sjg, seanga2, Andrew Scull

This series sets up a basic fuzzing infrastructure that works with
sandbox. The example fuzz test towards the end of the series will find
something pretty quickly (that something is fixed by
"virtio_ring: Maintain a shadow copy of descriptors" from another
series).

There is some refactoring to stop using '.' prefixed sections that elf
defines as being for system use and clang's ASAN instrumentation happily
adds redzones between, but that's not what we want for things like
linker lists where the linker script has carefully placed the sections
contiguously.

It may require patches from the "Fix misc ASAN reports" series to be
applied as I've already dealt with the first set of ASAN reports from
running the tests.

Andrew Scull (11):
  sandbox: Set the EFI symbols in linker script
  sandbox: Migrate getopt section to linker list
  linker_lists: Rename sections to remove . prefix
  sandbox: Add support for Address Sanitizer
  fuzzing_engine: Add fuzzing engine uclass
  test: fuzz: Add framework for fuzzing
  sandbox: Decouple program entry from sandbox init
  sandbox: Add libfuzzer integration
  sandbox: Implement fuzzing engine driver
  fuzz: virtio: Add fuzzer for vring
  RFC: Hack dlmalloc to poison memory

 Kconfig                                       |  15 +
 arch/Kconfig                                  |   2 +
 arch/arc/cpu/u-boot.lds                       |   4 +-
 arch/arm/config.mk                            |   4 +-
 arch/arm/cpu/arm926ejs/sunxi/u-boot-spl.lds   |   4 +-
 arch/arm/cpu/armv7/sunxi/u-boot-spl.lds       |   4 +-
 arch/arm/cpu/armv8/u-boot-spl.lds             |   4 +-
 arch/arm/cpu/armv8/u-boot.lds                 |   4 +-
 arch/arm/cpu/u-boot-spl.lds                   |   4 +-
 arch/arm/cpu/u-boot.lds                       |   6 +-
 arch/arm/mach-at91/arm926ejs/u-boot-spl.lds   |   2 +-
 arch/arm/mach-at91/armv7/u-boot-spl.lds       |   2 +-
 arch/arm/mach-omap2/u-boot-spl.lds            |   4 +-
 arch/arm/mach-orion5x/u-boot-spl.lds          |   4 +-
 arch/arm/mach-rockchip/u-boot-tpl-v8.lds      |   4 +-
 arch/arm/mach-zynq/u-boot-spl.lds             |   4 +-
 arch/arm/mach-zynq/u-boot.lds                 |   4 +-
 arch/m68k/cpu/u-boot.lds                      |   4 +-
 arch/microblaze/cpu/u-boot-spl.lds            |   4 +-
 arch/microblaze/cpu/u-boot.lds                |   4 +-
 arch/mips/config.mk                           |   2 +-
 arch/mips/cpu/u-boot-spl.lds                  |   4 +-
 arch/mips/cpu/u-boot.lds                      |   4 +-
 arch/nds32/cpu/n1213/u-boot.lds               |   4 +-
 arch/nios2/cpu/u-boot.lds                     |   4 +-
 arch/powerpc/cpu/mpc83xx/u-boot.lds           |   4 +-
 arch/powerpc/cpu/mpc85xx/u-boot-nand.lds      |   4 +-
 arch/powerpc/cpu/mpc85xx/u-boot-nand_spl.lds  |   4 +-
 arch/powerpc/cpu/mpc85xx/u-boot-spl.lds       |   4 +-
 arch/powerpc/cpu/mpc85xx/u-boot.lds           |   4 +-
 arch/riscv/cpu/u-boot-spl.lds                 |   4 +-
 arch/riscv/cpu/u-boot.lds                     |   4 +-
 arch/sandbox/config.mk                        |  15 +-
 arch/sandbox/cpu/os.c                         |  97 +++++-
 arch/sandbox/cpu/start.c                      |  12 +-
 arch/sandbox/cpu/u-boot-spl.lds               |  10 +-
 arch/sandbox/cpu/u-boot.lds                   |  42 +--
 arch/sandbox/dts/test.dts                     |   4 +
 arch/sandbox/include/asm/fuzzing_engine.h     |  25 ++
 arch/sandbox/include/asm/getopt.h             |  19 +-
 arch/sandbox/include/asm/main.h               |  18 ++
 arch/sandbox/include/asm/sections.h           |  25 --
 arch/sandbox/lib/Makefile                     |   2 +-
 arch/sandbox/lib/sections.c                   |  13 -
 arch/sh/cpu/u-boot.lds                        |   4 +-
 arch/x86/cpu/u-boot-64.lds                    |   6 +-
 arch/x86/cpu/u-boot-spl.lds                   |   6 +-
 arch/x86/cpu/u-boot.lds                       |   6 +-
 arch/x86/lib/elf_ia32_efi.lds                 |   4 +-
 arch/x86/lib/elf_x86_64_efi.lds               |   4 +-
 arch/xtensa/cpu/u-boot.lds                    |   2 +-
 arch/xtensa/include/asm/ldscript.h            |   4 +-
 board/compulab/cm_t335/u-boot.lds             |   4 +-
 board/cssi/MCR3000/u-boot.lds                 |   4 +-
 .../davinci/da8xxevm/u-boot-spl-da850evm.lds  |   2 +-
 board/qualcomm/dragonboard820c/u-boot.lds     |   4 +-
 board/samsung/common/exynos-uboot-spl.lds     |   4 +-
 board/synopsys/iot_devkit/u-boot.lds          |   4 +-
 board/ti/am335x/u-boot.lds                    |   4 +-
 board/vscom/baltos/u-boot.lds                 |   4 +-
 common/dlmalloc.c                             | 284 +++++++++++++++---
 configs/sandbox_defconfig                     |   1 +
 doc/api/linker_lists.rst                      |  22 +-
 doc/develop/commands.rst                      |   4 +-
 doc/develop/driver-model/of-plat.rst          |   4 +-
 drivers/Kconfig                               |   2 +
 drivers/Makefile                              |   1 +
 drivers/fuzzing_engine/Kconfig                |  17 ++
 drivers/fuzzing_engine/Makefile               |   8 +
 .../fuzzing_engine/fuzzing_engine-uclass.c    |  28 ++
 .../fuzzing_engine/sandbox_fuzzing_engine.c   |  35 +++
 include/compiler.h                            |   1 +
 include/dm/uclass-id.h                        |   1 +
 include/fuzzing_engine.h                      |  51 ++++
 include/linker_lists.h                        |  18 +-
 include/linux/types.h                         |   1 +
 include/test/fuzz.h                           |  51 ++++
 test/Makefile                                 |   1 +
 test/fuzz/Makefile                            |   8 +
 test/fuzz/cmd_fuzz.c                          |  82 +++++
 test/fuzz/virtio.c                            |  72 +++++
 81 files changed, 909 insertions(+), 264 deletions(-)
 create mode 100644 arch/sandbox/include/asm/fuzzing_engine.h
 create mode 100644 arch/sandbox/include/asm/main.h
 delete mode 100644 arch/sandbox/lib/sections.c
 create mode 100644 drivers/fuzzing_engine/Kconfig
 create mode 100644 drivers/fuzzing_engine/Makefile
 create mode 100644 drivers/fuzzing_engine/fuzzing_engine-uclass.c
 create mode 100644 drivers/fuzzing_engine/sandbox_fuzzing_engine.c
 create mode 100644 include/fuzzing_engine.h
 create mode 100644 include/test/fuzz.h
 create mode 100644 test/fuzz/Makefile
 create mode 100644 test/fuzz/cmd_fuzz.c
 create mode 100644 test/fuzz/virtio.c

-- 
2.35.1.1094.g7c7d902a7c-goog


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

* [PATCH 01/11] sandbox: Set the EFI symbols in linker script
  2022-04-07  9:41 [PATCH 00/11] Fuzzing and ASAN for sandbox Andrew Scull
@ 2022-04-07  9:41 ` Andrew Scull
  2022-04-11 18:35   ` Simon Glass
  2022-04-11 22:15   ` Heinrich Schuchardt
  2022-04-07  9:41 ` [PATCH 02/11] sandbox: Migrate getopt section to linker list Andrew Scull
                   ` (9 subsequent siblings)
  10 siblings, 2 replies; 30+ messages in thread
From: Andrew Scull @ 2022-04-07  9:41 UTC (permalink / raw)
  To: u-boot; +Cc: sjg, seanga2, Andrew Scull

The sandbox doesn't populate the EFI lists so explicitly set the list
start and end symbols to indicate that the lists are empty. This
simplifies the linker scripts, removed references to non-existant
sections and removes '.' prefixed sections that conflicted with clang's
ASAN.

Signed-off-by: Andrew Scull <ascull@google.com>
---
 arch/sandbox/cpu/u-boot.lds | 32 +++++---------------------------
 arch/sandbox/lib/Makefile   |  2 +-
 arch/sandbox/lib/sections.c | 13 -------------
 3 files changed, 6 insertions(+), 41 deletions(-)
 delete mode 100644 arch/sandbox/lib/sections.c

diff --git a/arch/sandbox/cpu/u-boot.lds b/arch/sandbox/cpu/u-boot.lds
index 6d710618f5..dd675cc3d2 100644
--- a/arch/sandbox/cpu/u-boot.lds
+++ b/arch/sandbox/cpu/u-boot.lds
@@ -19,33 +19,11 @@ SECTIONS
 		*(.u_boot_sandbox_getopt_end)
 	}
 
-	.__efi_runtime_start : {
-		*(.__efi_runtime_start)
-	}
-
-	.efi_runtime : {
-		*(efi_runtime_text)
-		*(efi_runtime_data)
-	}
-
-	.__efi_runtime_stop : {
-		*(.__efi_runtime_stop)
-	}
-
-	.efi_runtime_rel_start :
-	{
-		*(.__efi_runtime_rel_start)
-	}
-
-	.efi_runtime_rel : {
-		*(.relefi_runtime_text)
-		*(.relefi_runtime_data)
-	}
-
-	.efi_runtime_rel_stop :
-	{
-		*(.__efi_runtime_rel_stop)
-	}
+	/* Sandbox has empty EFI runtime lists. */
+	__efi_runtime_start = .;
+	__efi_runtime_stop = __efi_runtime_start;
+	__efi_runtime_rel_start = .;
+	__efi_runtime_rel_stop = __efi_runtime_rel_start;
 
 	.dynsym :
 	{
diff --git a/arch/sandbox/lib/Makefile b/arch/sandbox/lib/Makefile
index a2bc5a7ee6..05f06180f8 100644
--- a/arch/sandbox/lib/Makefile
+++ b/arch/sandbox/lib/Makefile
@@ -5,7 +5,7 @@
 # (C) Copyright 2002-2006
 # Wolfgang Denk, DENX Software Engineering, wd@denx.de.
 
-obj-y	+= fdt_fixup.o interrupts.o sections.o
+obj-y	+= fdt_fixup.o interrupts.o
 obj-$(CONFIG_PCI)	+= pci_io.o
 obj-$(CONFIG_CMD_BOOTM) += bootm.o
 obj-$(CONFIG_CMD_BOOTZ) += bootm.o
diff --git a/arch/sandbox/lib/sections.c b/arch/sandbox/lib/sections.c
deleted file mode 100644
index 2559eeea38..0000000000
--- a/arch/sandbox/lib/sections.c
+++ /dev/null
@@ -1,13 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0+
-/*
- * Copyright 2013 Albert ARIBAUD <albert.u.boot@aribaud.net>
- *
- */
-#include <linux/compiler.h>
-
-char __efi_runtime_start[0] __section(".__efi_runtime_start");
-char __efi_runtime_stop[0] __section(".__efi_runtime_stop");
-char __efi_runtime_rel_start[0]
-		__section(".__efi_runtime_rel_start");
-char __efi_runtime_rel_stop[0]
-		__section(".__efi_runtime_rel_stop");
-- 
2.35.1.1094.g7c7d902a7c-goog


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

* [PATCH 02/11] sandbox: Migrate getopt section to linker list
  2022-04-07  9:41 [PATCH 00/11] Fuzzing and ASAN for sandbox Andrew Scull
  2022-04-07  9:41 ` [PATCH 01/11] sandbox: Set the EFI symbols in linker script Andrew Scull
@ 2022-04-07  9:41 ` Andrew Scull
  2022-04-11 18:35   ` Simon Glass
  2022-04-07  9:41 ` [PATCH 03/11] linker_lists: Rename sections to remove . prefix Andrew Scull
                   ` (8 subsequent siblings)
  10 siblings, 1 reply; 30+ messages in thread
From: Andrew Scull @ 2022-04-07  9:41 UTC (permalink / raw)
  To: u-boot; +Cc: sjg, seanga2, Andrew Scull

Use the common infrastructure to create a linker list of the sandbox
command line flags rather than using a custom method.

The list is changed from containing pointers to containing structs and
the uses are updated accordingly.

Signed-off-by: Andrew Scull <ascull@google.com>
---
 arch/sandbox/cpu/os.c               | 21 ++++++++++-----------
 arch/sandbox/cpu/start.c            | 10 +++++-----
 arch/sandbox/cpu/u-boot-spl.lds     |  6 ------
 arch/sandbox/cpu/u-boot.lds         |  6 ------
 arch/sandbox/include/asm/getopt.h   | 19 ++++++++++++-------
 arch/sandbox/include/asm/sections.h | 25 -------------------------
 6 files changed, 27 insertions(+), 60 deletions(-)

diff --git a/arch/sandbox/cpu/os.c b/arch/sandbox/cpu/os.c
index d83c862182..72a72029f2 100644
--- a/arch/sandbox/cpu/os.c
+++ b/arch/sandbox/cpu/os.c
@@ -424,9 +424,8 @@ static struct option *long_opts;
 
 int os_parse_args(struct sandbox_state *state, int argc, char *argv[])
 {
-	struct sandbox_cmdline_option **sb_opt =
-		__u_boot_sandbox_option_start();
-	size_t num_options = __u_boot_sandbox_option_count();
+	struct sandbox_cmdline_option *sb_opt = SANDBOX_CMDLINE_OPT_START();
+	size_t num_options = SANDBOX_CMDLINE_OPT_COUNT();
 	size_t i;
 
 	int hidden_short_opt;
@@ -455,17 +454,17 @@ int os_parse_args(struct sandbox_state *state, int argc, char *argv[])
 	hidden_short_opt = 0x100;
 	si = 0;
 	for (i = 0; i < num_options; ++i) {
-		long_opts[i].name = sb_opt[i]->flag;
-		long_opts[i].has_arg = sb_opt[i]->has_arg ?
+		long_opts[i].name = sb_opt[i].flag;
+		long_opts[i].has_arg = sb_opt[i].has_arg ?
 			required_argument : no_argument;
 		long_opts[i].flag = NULL;
 
-		if (sb_opt[i]->flag_short) {
-			short_opts[si++] = long_opts[i].val = sb_opt[i]->flag_short;
+		if (sb_opt[i].flag_short) {
+			short_opts[si++] = long_opts[i].val = sb_opt[i].flag_short;
 			if (long_opts[i].has_arg == required_argument)
 				short_opts[si++] = ':';
 		} else
-			long_opts[i].val = sb_opt[i]->flag_short = hidden_short_opt++;
+			long_opts[i].val = sb_opt[i].flag_short = hidden_short_opt++;
 	}
 	short_opts[si] = '\0';
 
@@ -480,9 +479,9 @@ int os_parse_args(struct sandbox_state *state, int argc, char *argv[])
 	 */
 	while ((c = getopt_long(argc, argv, short_opts, long_opts, NULL)) != -1) {
 		for (i = 0; i < num_options; ++i) {
-			if (sb_opt[i]->flag_short == c) {
-				if (sb_opt[i]->callback(state, optarg)) {
-					state->parse_err = sb_opt[i]->flag;
+			if (sb_opt[i].flag_short == c) {
+				if (sb_opt[i].callback(state, optarg)) {
+					state->parse_err = sb_opt[i].flag;
 					return 0;
 				}
 				break;
diff --git a/arch/sandbox/cpu/start.c b/arch/sandbox/cpu/start.c
index 13b0731ec3..5cb47e1156 100644
--- a/arch/sandbox/cpu/start.c
+++ b/arch/sandbox/cpu/start.c
@@ -58,9 +58,8 @@ static int h_compare_opt(const void *p1, const void *p2)
 int sandbox_early_getopt_check(void)
 {
 	struct sandbox_state *state = state_get_current();
-	struct sandbox_cmdline_option **sb_opt =
-		__u_boot_sandbox_option_start();
-	size_t num_options = __u_boot_sandbox_option_count();
+	struct sandbox_cmdline_option *sb_opt = SANDBOX_CMDLINE_OPT_START();
+	size_t num_options = SANDBOX_CMDLINE_OPT_COUNT();
 	size_t i;
 	int max_arg_len, max_noarg_len;
 	struct sandbox_cmdline_option **sorted_opt;
@@ -84,7 +83,7 @@ int sandbox_early_getopt_check(void)
 
 	max_arg_len = 0;
 	for (i = 0; i < num_options; ++i)
-		max_arg_len = max((int)strlen(sb_opt[i]->flag), max_arg_len);
+		max_arg_len = max((int)strlen(sb_opt[i].flag), max_arg_len);
 	max_noarg_len = max_arg_len + 7;
 
 	/* Sort the options */
@@ -94,7 +93,8 @@ int sandbox_early_getopt_check(void)
 		printf("No memory to sort options\n");
 		os_exit(1);
 	}
-	memcpy(sorted_opt, sb_opt, size);
+	for (i = 0; i < num_options; ++i)
+		sorted_opt[i] = &sb_opt[i];
 	qsort(sorted_opt, num_options, sizeof(*sorted_opt), h_compare_opt);
 
 	for (i = 0; i < num_options; ++i) {
diff --git a/arch/sandbox/cpu/u-boot-spl.lds b/arch/sandbox/cpu/u-boot-spl.lds
index 6754f4ef6c..5c19d090cb 100644
--- a/arch/sandbox/cpu/u-boot-spl.lds
+++ b/arch/sandbox/cpu/u-boot-spl.lds
@@ -20,12 +20,6 @@ SECTIONS
 		*(SORT_BY_ALIGNMENT(SORT_BY_NAME(.priv_data*)))
 		__priv_data_end = .;
 	}
-
-	_u_boot_sandbox_getopt : {
-		*(.u_boot_sandbox_getopt_start)
-		KEEP(*(.u_boot_sandbox_getopt))
-		*(.u_boot_sandbox_getopt_end)
-	}
 }
 
 INSERT AFTER .data;
diff --git a/arch/sandbox/cpu/u-boot.lds b/arch/sandbox/cpu/u-boot.lds
index dd675cc3d2..c3fc67a15b 100644
--- a/arch/sandbox/cpu/u-boot.lds
+++ b/arch/sandbox/cpu/u-boot.lds
@@ -13,12 +13,6 @@ SECTIONS
 		KEEP(*(SORT(.u_boot_list*)));
 	}
 
-	_u_boot_sandbox_getopt : {
-		*(.u_boot_sandbox_getopt_start)
-		*(.u_boot_sandbox_getopt)
-		*(.u_boot_sandbox_getopt_end)
-	}
-
 	/* Sandbox has empty EFI runtime lists. */
 	__efi_runtime_start = .;
 	__efi_runtime_stop = __efi_runtime_start;
diff --git a/arch/sandbox/include/asm/getopt.h b/arch/sandbox/include/asm/getopt.h
index d2145ad6e2..a4b510bd20 100644
--- a/arch/sandbox/include/asm/getopt.h
+++ b/arch/sandbox/include/asm/getopt.h
@@ -9,6 +9,8 @@
 #ifndef __SANDBOX_GETOPT_H
 #define __SANDBOX_GETOPT_H
 
+#include <linker_lists.h>
+
 struct sandbox_state;
 
 /*
@@ -36,18 +38,13 @@ struct sandbox_cmdline_option {
  * magic junk that makes this all work.
  */
 #define _SANDBOX_CMDLINE_OPT(f, s, ha, h) \
-	static struct sandbox_cmdline_option sandbox_cmdline_option_##f = { \
+	ll_entry_declare(struct sandbox_cmdline_option, f, sandbox_getopt) = { \
 		.flag = #f, \
 		.flag_short = s, \
 		.help = h, \
 		.has_arg = ha, \
 		.callback = sandbox_cmdline_cb_##f, \
-	}; \
-	/* Ppointer to the struct in a special section for the linker script */ \
-	static __used __section(".u_boot_sandbox_getopt") \
-		struct sandbox_cmdline_option \
-			*sandbox_cmdline_option_##f##_ptr = \
-			&sandbox_cmdline_option_##f
+	}
 
 /**
  * Macros for end code to declare new command line flags.
@@ -69,4 +66,12 @@ struct sandbox_cmdline_option {
  */
 #define SANDBOX_CMDLINE_OPT_SHORT(f, s, ha, h) _SANDBOX_CMDLINE_OPT(f, s, ha, h)
 
+/** Get the start of the list of command line flags. */
+#define SANDBOX_CMDLINE_OPT_START() \
+	ll_entry_start(struct sandbox_cmdline_option, sandbox_getopt)
+
+/** Get the number of entries in the command line flags list. */
+#define SANDBOX_CMDLINE_OPT_COUNT() \
+	ll_entry_count(struct sandbox_cmdline_option, sandbox_getopt)
+
 #endif
diff --git a/arch/sandbox/include/asm/sections.h b/arch/sandbox/include/asm/sections.h
index f4351ae7db..c335cb2061 100644
--- a/arch/sandbox/include/asm/sections.h
+++ b/arch/sandbox/include/asm/sections.h
@@ -11,29 +11,4 @@
 
 #include <asm-generic/sections.h>
 
-struct sandbox_cmdline_option;
-
-static inline struct sandbox_cmdline_option **
-__u_boot_sandbox_option_start(void)
-{
-	static char start[0] __aligned(4) __attribute__((unused))
-		__section(".u_boot_sandbox_getopt_start");
-
-	return (struct sandbox_cmdline_option **)&start;
-}
-
-static inline struct sandbox_cmdline_option **
-__u_boot_sandbox_option_end(void)
-{
-	static char end[0] __aligned(4) __attribute__((unused))
-		__section(".u_boot_sandbox_getopt_end");
-
-	return (struct sandbox_cmdline_option **)&end;
-}
-
-static inline size_t __u_boot_sandbox_option_count(void)
-{
-	return __u_boot_sandbox_option_end() - __u_boot_sandbox_option_start();
-}
-
 #endif
-- 
2.35.1.1094.g7c7d902a7c-goog


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

* [PATCH 03/11] linker_lists: Rename sections to remove . prefix
  2022-04-07  9:41 [PATCH 00/11] Fuzzing and ASAN for sandbox Andrew Scull
  2022-04-07  9:41 ` [PATCH 01/11] sandbox: Set the EFI symbols in linker script Andrew Scull
  2022-04-07  9:41 ` [PATCH 02/11] sandbox: Migrate getopt section to linker list Andrew Scull
@ 2022-04-07  9:41 ` Andrew Scull
  2022-04-11 18:35   ` Simon Glass
  2022-04-07  9:41 ` [PATCH 04/11] sandbox: Add support for Address Sanitizer Andrew Scull
                   ` (7 subsequent siblings)
  10 siblings, 1 reply; 30+ messages in thread
From: Andrew Scull @ 2022-04-07  9:41 UTC (permalink / raw)
  To: u-boot; +Cc: sjg, seanga2, Andrew Scull

Rename the sections used to implement linker lists so they begin with
'__u_boot_list' rather than '.u_boot_list'. The double underscore at the
start is still distinct from the single underscore used by the symbol
names.

Having a '.' in the section names conflicts with clang's ASAN
instrumentation which tries to add redzones between the linker list
elements, causing expected accesses to fail. However, clang doesn't try
to add redzones to user sections, which are names with all alphanumeric
and underscore characters.

Signed-off-by: Andrew Scull <ascull@google.com>
---
 arch/arc/cpu/u-boot.lds                       |  4 ++--
 arch/arm/config.mk                            |  4 ++--
 arch/arm/cpu/arm926ejs/sunxi/u-boot-spl.lds   |  4 ++--
 arch/arm/cpu/armv7/sunxi/u-boot-spl.lds       |  4 ++--
 arch/arm/cpu/armv8/u-boot-spl.lds             |  4 ++--
 arch/arm/cpu/armv8/u-boot.lds                 |  4 ++--
 arch/arm/cpu/u-boot-spl.lds                   |  4 ++--
 arch/arm/cpu/u-boot.lds                       |  6 ++---
 arch/arm/mach-at91/arm926ejs/u-boot-spl.lds   |  2 +-
 arch/arm/mach-at91/armv7/u-boot-spl.lds       |  2 +-
 arch/arm/mach-omap2/u-boot-spl.lds            |  4 ++--
 arch/arm/mach-orion5x/u-boot-spl.lds          |  4 ++--
 arch/arm/mach-rockchip/u-boot-tpl-v8.lds      |  4 ++--
 arch/arm/mach-zynq/u-boot-spl.lds             |  4 ++--
 arch/arm/mach-zynq/u-boot.lds                 |  4 ++--
 arch/m68k/cpu/u-boot.lds                      |  4 ++--
 arch/microblaze/cpu/u-boot-spl.lds            |  4 ++--
 arch/microblaze/cpu/u-boot.lds                |  4 ++--
 arch/mips/config.mk                           |  2 +-
 arch/mips/cpu/u-boot-spl.lds                  |  4 ++--
 arch/mips/cpu/u-boot.lds                      |  4 ++--
 arch/nds32/cpu/n1213/u-boot.lds               |  4 ++--
 arch/nios2/cpu/u-boot.lds                     |  4 ++--
 arch/powerpc/cpu/mpc83xx/u-boot.lds           |  4 ++--
 arch/powerpc/cpu/mpc85xx/u-boot-nand.lds      |  4 ++--
 arch/powerpc/cpu/mpc85xx/u-boot-nand_spl.lds  |  4 ++--
 arch/powerpc/cpu/mpc85xx/u-boot-spl.lds       |  4 ++--
 arch/powerpc/cpu/mpc85xx/u-boot.lds           |  4 ++--
 arch/riscv/cpu/u-boot-spl.lds                 |  4 ++--
 arch/riscv/cpu/u-boot.lds                     |  4 ++--
 arch/sandbox/config.mk                        |  4 ++--
 arch/sandbox/cpu/u-boot-spl.lds               |  4 ++--
 arch/sandbox/cpu/u-boot.lds                   |  4 ++--
 arch/sh/cpu/u-boot.lds                        |  4 ++--
 arch/x86/cpu/u-boot-64.lds                    |  6 ++---
 arch/x86/cpu/u-boot-spl.lds                   |  6 ++---
 arch/x86/cpu/u-boot.lds                       |  6 ++---
 arch/x86/lib/elf_ia32_efi.lds                 |  4 ++--
 arch/x86/lib/elf_x86_64_efi.lds               |  4 ++--
 arch/xtensa/cpu/u-boot.lds                    |  2 +-
 arch/xtensa/include/asm/ldscript.h            |  4 ++--
 board/compulab/cm_t335/u-boot.lds             |  4 ++--
 board/cssi/MCR3000/u-boot.lds                 |  4 ++--
 .../davinci/da8xxevm/u-boot-spl-da850evm.lds  |  2 +-
 board/qualcomm/dragonboard820c/u-boot.lds     |  4 ++--
 board/samsung/common/exynos-uboot-spl.lds     |  4 ++--
 board/synopsys/iot_devkit/u-boot.lds          |  4 ++--
 board/ti/am335x/u-boot.lds                    |  4 ++--
 board/vscom/baltos/u-boot.lds                 |  4 ++--
 doc/api/linker_lists.rst                      | 22 +++++++++----------
 doc/develop/commands.rst                      |  4 ++--
 doc/develop/driver-model/of-plat.rst          |  4 ++--
 include/linker_lists.h                        | 18 +++++++--------
 53 files changed, 121 insertions(+), 121 deletions(-)

diff --git a/arch/arc/cpu/u-boot.lds b/arch/arc/cpu/u-boot.lds
index e12145c768..9f2973da65 100644
--- a/arch/arc/cpu/u-boot.lds
+++ b/arch/arc/cpu/u-boot.lds
@@ -39,8 +39,8 @@ SECTIONS
 	}
 
 	. = ALIGN(4);
-	.u_boot_list : {
-		KEEP(*(SORT(.u_boot_list*)));
+	__u_boot_list : {
+		KEEP(*(SORT(__u_boot_list*)));
 	}
 
 	. = ALIGN(4);
diff --git a/arch/arm/config.mk b/arch/arm/config.mk
index b107b1af27..b3548ce243 100644
--- a/arch/arm/config.mk
+++ b/arch/arm/config.mk
@@ -141,11 +141,11 @@ endif
 # limit ourselves to the sections we want in the .bin.
 ifdef CONFIG_ARM64
 OBJCOPYFLAGS += -j .text -j .secure_text -j .secure_data -j .rodata -j .data \
-		-j .u_boot_list -j .rela.dyn -j .got -j .got.plt \
+		-j __u_boot_list -j .rela.dyn -j .got -j .got.plt \
 		-j .binman_sym_table -j .text_rest
 else
 OBJCOPYFLAGS += -j .text -j .secure_text -j .secure_data -j .rodata -j .hash \
-		-j .data -j .got -j .got.plt -j .u_boot_list -j .rel.dyn \
+		-j .data -j .got -j .got.plt -j __u_boot_list -j .rel.dyn \
 		-j .binman_sym_table -j .text_rest
 endif
 
diff --git a/arch/arm/cpu/arm926ejs/sunxi/u-boot-spl.lds b/arch/arm/cpu/arm926ejs/sunxi/u-boot-spl.lds
index 9a000ac5d3..c108736811 100644
--- a/arch/arm/cpu/arm926ejs/sunxi/u-boot-spl.lds
+++ b/arch/arm/cpu/arm926ejs/sunxi/u-boot-spl.lds
@@ -29,8 +29,8 @@ SECTIONS
 	.data : { *(SORT_BY_ALIGNMENT(.data*)) } >.sram
 
 	. = ALIGN(4);
-	.u_boot_list : {
-		KEEP(*(SORT(.u_boot_list*)));
+	__u_boot_list : {
+		KEEP(*(SORT(__u_boot_list*)));
 	} > .sram
 
 	. = ALIGN(4);
diff --git a/arch/arm/cpu/armv7/sunxi/u-boot-spl.lds b/arch/arm/cpu/armv7/sunxi/u-boot-spl.lds
index 942c29fc95..306a4ddf3c 100644
--- a/arch/arm/cpu/armv7/sunxi/u-boot-spl.lds
+++ b/arch/arm/cpu/armv7/sunxi/u-boot-spl.lds
@@ -38,8 +38,8 @@ SECTIONS
 	.data : { *(SORT_BY_ALIGNMENT(.data*)) } >.sram
 
 	. = ALIGN(4);
-	.u_boot_list : {
-		KEEP(*(SORT(.u_boot_list*)));
+	__u_boot_list : {
+		KEEP(*(SORT(__u_boot_list*)));
 	} > .sram
 
 	. = ALIGN(4);
diff --git a/arch/arm/cpu/armv8/u-boot-spl.lds b/arch/arm/cpu/armv8/u-boot-spl.lds
index 730eb93dbc..d02b788e60 100644
--- a/arch/arm/cpu/armv8/u-boot-spl.lds
+++ b/arch/arm/cpu/armv8/u-boot-spl.lds
@@ -46,9 +46,9 @@ SECTIONS
 	} >.sram
 #endif
 
-	.u_boot_list : {
+	__u_boot_list : {
 		. = ALIGN(8);
-		KEEP(*(SORT(.u_boot_list*)));
+		KEEP(*(SORT(__u_boot_list*)));
 	} >.sram
 
 	.image_copy_end : {
diff --git a/arch/arm/cpu/armv8/u-boot.lds b/arch/arm/cpu/armv8/u-boot.lds
index 2554980595..8fe4682dd2 100644
--- a/arch/arm/cpu/armv8/u-boot.lds
+++ b/arch/arm/cpu/armv8/u-boot.lds
@@ -109,8 +109,8 @@ SECTIONS
 	. = .;
 
 	. = ALIGN(8);
-	.u_boot_list : {
-		KEEP(*(SORT(.u_boot_list*)));
+	__u_boot_list : {
+		KEEP(*(SORT(__u_boot_list*)));
 	}
 
 	. = ALIGN(8);
diff --git a/arch/arm/cpu/u-boot-spl.lds b/arch/arm/cpu/u-boot-spl.lds
index 97899a567f..fb2189d50d 100644
--- a/arch/arm/cpu/u-boot-spl.lds
+++ b/arch/arm/cpu/u-boot-spl.lds
@@ -32,8 +32,8 @@ SECTIONS
 	}
 
 	. = ALIGN(4);
-	.u_boot_list : {
-		KEEP(*(SORT(.u_boot_list*)));
+	__u_boot_list : {
+		KEEP(*(SORT(__u_boot_list*)));
 	}
 
 	. = ALIGN(4);
diff --git a/arch/arm/cpu/u-boot.lds b/arch/arm/cpu/u-boot.lds
index 0eb164d2e6..f25f72b2e0 100644
--- a/arch/arm/cpu/u-boot.lds
+++ b/arch/arm/cpu/u-boot.lds
@@ -15,7 +15,7 @@ ENTRY(_start)
 SECTIONS
 {
 #ifndef CONFIG_CMDLINE
-	/DISCARD/ : { *(.u_boot_list_2_cmd_*) }
+	/DISCARD/ : { *(__u_boot_list_2_cmd_*) }
 #endif
 #if defined(CONFIG_ARMV7_SECURE_BASE) && defined(CONFIG_ARMV7_NONSEC)
 	/*
@@ -149,8 +149,8 @@ SECTIONS
 	. = .;
 
 	. = ALIGN(4);
-	.u_boot_list : {
-		KEEP(*(SORT(.u_boot_list*)));
+	__u_boot_list : {
+		KEEP(*(SORT(__u_boot_list*)));
 	}
 
 	. = ALIGN(4);
diff --git a/arch/arm/mach-at91/arm926ejs/u-boot-spl.lds b/arch/arm/mach-at91/arm926ejs/u-boot-spl.lds
index 74f6355229..1a8bf94dee 100644
--- a/arch/arm/mach-at91/arm926ejs/u-boot-spl.lds
+++ b/arch/arm/mach-at91/arm926ejs/u-boot-spl.lds
@@ -29,7 +29,7 @@ SECTIONS
 	.data : { *(SORT_BY_ALIGNMENT(.data*)) } >.sram
 
 	. = ALIGN(4);
-	.u_boot_list : { KEEP(*(SORT(.u_boot_list*))) } > .sram
+	__u_boot_list : { KEEP(*(SORT(__u_boot_list*))) } > .sram
 
 	. = ALIGN(4);
 	__image_copy_end = .;
diff --git a/arch/arm/mach-at91/armv7/u-boot-spl.lds b/arch/arm/mach-at91/armv7/u-boot-spl.lds
index 950ea55d7c..6ca725fc4c 100644
--- a/arch/arm/mach-at91/armv7/u-boot-spl.lds
+++ b/arch/arm/mach-at91/armv7/u-boot-spl.lds
@@ -36,7 +36,7 @@ SECTIONS
 	.data : { *(SORT_BY_ALIGNMENT(.data*)) } >.sram
 
 	. = ALIGN(4);
-	.u_boot_list : { KEEP(*(SORT(.u_boot_list*))) } > .sram
+	__u_boot_list : { KEEP(*(SORT(__u_boot_list*))) } > .sram
 
 	. = ALIGN(4);
 	__image_copy_end = .;
diff --git a/arch/arm/mach-omap2/u-boot-spl.lds b/arch/arm/mach-omap2/u-boot-spl.lds
index 88d81f9b98..1d6e5d45b4 100644
--- a/arch/arm/mach-omap2/u-boot-spl.lds
+++ b/arch/arm/mach-omap2/u-boot-spl.lds
@@ -33,8 +33,8 @@ SECTIONS
 	.data : { *(SORT_BY_ALIGNMENT(.data*)) } >.sram
 
 	. = ALIGN(4);
-	.u_boot_list : {
-		KEEP(*(SORT(.u_boot_list*)));
+	__u_boot_list : {
+		KEEP(*(SORT(__u_boot_list*)));
 	} >.sram
 
 	. = ALIGN(4);
diff --git a/arch/arm/mach-orion5x/u-boot-spl.lds b/arch/arm/mach-orion5x/u-boot-spl.lds
index a537fe0295..154bb12060 100644
--- a/arch/arm/mach-orion5x/u-boot-spl.lds
+++ b/arch/arm/mach-orion5x/u-boot-spl.lds
@@ -41,8 +41,8 @@ SECTIONS
 	.data : { *(SORT_BY_ALIGNMENT(.data*)) } >.nor
 
 	. = ALIGN(4);
-	.u_boot_list : {
-		KEEP(*(SORT(.u_boot_list*)));
+	__u_boot_list : {
+		KEEP(*(SORT(__u_boot_list*)));
 	} > .nor
 
 	. = ALIGN(4);
diff --git a/arch/arm/mach-rockchip/u-boot-tpl-v8.lds b/arch/arm/mach-rockchip/u-boot-tpl-v8.lds
index 9869972e22..74618eba59 100644
--- a/arch/arm/mach-rockchip/u-boot-tpl-v8.lds
+++ b/arch/arm/mach-rockchip/u-boot-tpl-v8.lds
@@ -39,9 +39,9 @@ SECTIONS
 		*(.data*)
 	}
 
-	.u_boot_list : {
+	__u_boot_list : {
 		. = ALIGN(8);
-		KEEP(*(SORT(.u_boot_list*)));
+		KEEP(*(SORT(__u_boot_list*)));
 	}
 
 	.image_copy_end : {
diff --git a/arch/arm/mach-zynq/u-boot-spl.lds b/arch/arm/mach-zynq/u-boot-spl.lds
index 106d2e390b..8c18d3f91f 100644
--- a/arch/arm/mach-zynq/u-boot-spl.lds
+++ b/arch/arm/mach-zynq/u-boot-spl.lds
@@ -37,8 +37,8 @@ SECTIONS
 	} > .sram
 
 	. = ALIGN(4);
-	.u_boot_list : {
-		KEEP(*(SORT(.u_boot_list*)));
+	__u_boot_list : {
+		KEEP(*(SORT(__u_boot_list*)));
 	} > .sram
 
 	. = ALIGN(4);
diff --git a/arch/arm/mach-zynq/u-boot.lds b/arch/arm/mach-zynq/u-boot.lds
index 91c32e89e8..a5169fd915 100644
--- a/arch/arm/mach-zynq/u-boot.lds
+++ b/arch/arm/mach-zynq/u-boot.lds
@@ -54,8 +54,8 @@ SECTIONS
 	. = .;
 
 	. = ALIGN(4);
-	.u_boot_list : {
-		KEEP(*(SORT(.u_boot_list*)));
+	__u_boot_list : {
+		KEEP(*(SORT(__u_boot_list*)));
 	}
 
 	. = ALIGN(4);
diff --git a/arch/m68k/cpu/u-boot.lds b/arch/m68k/cpu/u-boot.lds
index affb2d9374..133f79150b 100644
--- a/arch/m68k/cpu/u-boot.lds
+++ b/arch/m68k/cpu/u-boot.lds
@@ -60,8 +60,8 @@ SECTIONS
 	. = .;
 
 	. = ALIGN(4);
-	.u_boot_list : {
-		KEEP(*(SORT(.u_boot_list*)));
+	__u_boot_list : {
+		KEEP(*(SORT(__u_boot_list*)));
 	}
 
 	. = .;
diff --git a/arch/microblaze/cpu/u-boot-spl.lds b/arch/microblaze/cpu/u-boot-spl.lds
index 7883a64b15..4ac5a21524 100644
--- a/arch/microblaze/cpu/u-boot-spl.lds
+++ b/arch/microblaze/cpu/u-boot-spl.lds
@@ -37,8 +37,8 @@ SECTIONS
 	}
 
 	. = ALIGN(4);
-	.u_boot_list : {
-		KEEP(*(SORT(.u_boot_list*)));
+	__u_boot_list : {
+		KEEP(*(SORT(__u_boot_list*)));
 	}
 	__init_end = . ;
 
diff --git a/arch/microblaze/cpu/u-boot.lds b/arch/microblaze/cpu/u-boot.lds
index 2b316cc7f5..8bd515b099 100644
--- a/arch/microblaze/cpu/u-boot.lds
+++ b/arch/microblaze/cpu/u-boot.lds
@@ -41,8 +41,8 @@ SECTIONS
 	}
 
 	. = ALIGN(4);
-	.u_boot_list : {
-		KEEP(*(SORT(.u_boot_list*)));
+	__u_boot_list : {
+		KEEP(*(SORT(__u_boot_list*)));
 	}
 	__init_end = . ;
 
diff --git a/arch/mips/config.mk b/arch/mips/config.mk
index faf4129ac1..04f3627805 100644
--- a/arch/mips/config.mk
+++ b/arch/mips/config.mk
@@ -65,6 +65,6 @@ PLATFORM_CPPFLAGS		+= -msoft-float
 KBUILD_LDFLAGS			+= -G 0 -static -n -nostdlib
 PLATFORM_RELFLAGS		+= -ffunction-sections -fdata-sections
 LDFLAGS_FINAL			+= --gc-sections
-OBJCOPYFLAGS			+= -j .text -j .rodata -j .data -j .u_boot_list
+OBJCOPYFLAGS			+= -j .text -j .rodata -j .data -j __u_boot_list
 
 LDFLAGS_STANDALONE		+= --gc-sections
diff --git a/arch/mips/cpu/u-boot-spl.lds b/arch/mips/cpu/u-boot-spl.lds
index 28ea4f2a48..194398be85 100644
--- a/arch/mips/cpu/u-boot-spl.lds
+++ b/arch/mips/cpu/u-boot-spl.lds
@@ -29,8 +29,8 @@ SECTIONS
 
 #if defined(CONFIG_SPL_DM) || defined(CONFIG_SPL_LOADER_SUPPORT)
 	. = ALIGN(4);
-	.u_boot_list : {
-		KEEP(*(SORT(.u_boot_list*)));
+	__u_boot_list : {
+		KEEP(*(SORT(__u_boot_list*)));
 	} > .spl_mem
 #endif
 
diff --git a/arch/mips/cpu/u-boot.lds b/arch/mips/cpu/u-boot.lds
index 86496737d3..9a4ebcd151 100644
--- a/arch/mips/cpu/u-boot.lds
+++ b/arch/mips/cpu/u-boot.lds
@@ -33,8 +33,8 @@ SECTIONS
 	}
 
 	. = ALIGN(4);
-	.u_boot_list : {
-		KEEP(*(SORT(.u_boot_list*)));
+	__u_boot_list : {
+		KEEP(*(SORT(__u_boot_list*)));
 	}
 
 	. = ALIGN(4);
diff --git a/arch/nds32/cpu/n1213/u-boot.lds b/arch/nds32/cpu/n1213/u-boot.lds
index 4abaf0af1a..1040171415 100644
--- a/arch/nds32/cpu/n1213/u-boot.lds
+++ b/arch/nds32/cpu/n1213/u-boot.lds
@@ -35,8 +35,8 @@ SECTIONS
 	}
 
 	. = ALIGN(4);
-	.u_boot_list : {
-		KEEP(*(SORT(.u_boot_list*)));
+	__u_boot_list : {
+		KEEP(*(SORT(__u_boot_list*)));
 	}
 
 	. = ALIGN(4);
diff --git a/arch/nios2/cpu/u-boot.lds b/arch/nios2/cpu/u-boot.lds
index cbf54b4610..5b9e27d940 100644
--- a/arch/nios2/cpu/u-boot.lds
+++ b/arch/nios2/cpu/u-boot.lds
@@ -32,8 +32,8 @@ SECTIONS
 	 */
 
 	. = ALIGN(4);
-	.u_boot_list : {
-		KEEP(*(SORT(.u_boot_list*)));
+	__u_boot_list : {
+		KEEP(*(SORT(__u_boot_list*)));
 	}
 
 	/* INIT DATA sections - "Small" data (see the gcc -G option)
diff --git a/arch/powerpc/cpu/mpc83xx/u-boot.lds b/arch/powerpc/cpu/mpc83xx/u-boot.lds
index d10f528da4..1a1e537b2a 100644
--- a/arch/powerpc/cpu/mpc83xx/u-boot.lds
+++ b/arch/powerpc/cpu/mpc83xx/u-boot.lds
@@ -42,8 +42,8 @@ SECTIONS
   . = .;
 
   . = ALIGN(4);
-  .u_boot_list : {
-	KEEP(*(SORT(.u_boot_list*)));
+  __u_boot_list : {
+	KEEP(*(SORT(__u_boot_list*)));
   }
 
 
diff --git a/arch/powerpc/cpu/mpc85xx/u-boot-nand.lds b/arch/powerpc/cpu/mpc85xx/u-boot-nand.lds
index 75b0285e4e..3a9746c860 100644
--- a/arch/powerpc/cpu/mpc85xx/u-boot-nand.lds
+++ b/arch/powerpc/cpu/mpc85xx/u-boot-nand.lds
@@ -59,8 +59,8 @@ SECTIONS
 
   . = .;
 
-  .u_boot_list : {
-	KEEP(*(SORT(.u_boot_list*)));
+  __u_boot_list : {
+	KEEP(*(SORT(__u_boot_list*)));
   }
 
   . = .;
diff --git a/arch/powerpc/cpu/mpc85xx/u-boot-nand_spl.lds b/arch/powerpc/cpu/mpc85xx/u-boot-nand_spl.lds
index a2193bf768..fc2519d0b1 100644
--- a/arch/powerpc/cpu/mpc85xx/u-boot-nand_spl.lds
+++ b/arch/powerpc/cpu/mpc85xx/u-boot-nand_spl.lds
@@ -35,8 +35,8 @@ SECTIONS
 	}
 	_edata  =  .;
 
-	.u_boot_list : {
-		KEEP(*(SORT(.u_boot_list*)));
+	__u_boot_list : {
+		KEEP(*(SORT(__u_boot_list*)));
 	}
 
 	. = ALIGN(8);
diff --git a/arch/powerpc/cpu/mpc85xx/u-boot-spl.lds b/arch/powerpc/cpu/mpc85xx/u-boot-spl.lds
index 27a5fe6306..2f59b4fc12 100644
--- a/arch/powerpc/cpu/mpc85xx/u-boot-spl.lds
+++ b/arch/powerpc/cpu/mpc85xx/u-boot-spl.lds
@@ -43,8 +43,8 @@ SECTIONS
 	_edata  =  .;
 
 	. = ALIGN(4);
-	.u_boot_list : {
-		KEEP(*(SORT(.u_boot_list*)));
+	__u_boot_list : {
+		KEEP(*(SORT(__u_boot_list*)));
 	}
 
 	. = .;
diff --git a/arch/powerpc/cpu/mpc85xx/u-boot.lds b/arch/powerpc/cpu/mpc85xx/u-boot.lds
index 22bbac51aa..b6855f5571 100644
--- a/arch/powerpc/cpu/mpc85xx/u-boot.lds
+++ b/arch/powerpc/cpu/mpc85xx/u-boot.lds
@@ -66,8 +66,8 @@ SECTIONS
   . = .;
 
   . = ALIGN(4);
-  .u_boot_list : {
-	KEEP(*(SORT(.u_boot_list*)));
+  __u_boot_list : {
+	KEEP(*(SORT(__u_boot_list*)));
   }
 
   . = .;
diff --git a/arch/riscv/cpu/u-boot-spl.lds b/arch/riscv/cpu/u-boot-spl.lds
index d0495ce248..993536302a 100644
--- a/arch/riscv/cpu/u-boot-spl.lds
+++ b/arch/riscv/cpu/u-boot-spl.lds
@@ -40,8 +40,8 @@ SECTIONS
 
 	. = ALIGN(4);
 
-	.u_boot_list : {
-		KEEP(*(SORT(.u_boot_list*)));
+	__u_boot_list : {
+		KEEP(*(SORT(__u_boot_list*)));
 	} > .spl_mem
 
 	. = ALIGN(4);
diff --git a/arch/riscv/cpu/u-boot.lds b/arch/riscv/cpu/u-boot.lds
index c00d17c736..1c937aebee 100644
--- a/arch/riscv/cpu/u-boot.lds
+++ b/arch/riscv/cpu/u-boot.lds
@@ -44,8 +44,8 @@ SECTIONS
 
 	. = ALIGN(4);
 
-	.u_boot_list : {
-		KEEP(*(SORT(.u_boot_list*)));
+	__u_boot_list : {
+		KEEP(*(SORT(__u_boot_list*)));
 	}
 
 	. = ALIGN(4);
diff --git a/arch/sandbox/config.mk b/arch/sandbox/config.mk
index 2b1b657831..c42de2ff27 100644
--- a/arch/sandbox/config.mk
+++ b/arch/sandbox/config.mk
@@ -44,13 +44,13 @@ EFI_TARGET := --target=efi-app-ia32
 else ifeq ($(HOST_ARCH),$(HOST_ARCH_AARCH64))
 EFI_LDS := ${SRCDIR}/../../../arch/arm/lib/elf_aarch64_efi.lds
 OBJCOPYFLAGS += -j .text -j .secure_text -j .secure_data -j .rodata -j .data \
-		-j .u_boot_list -j .rela.dyn -j .got -j .got.plt \
+		-j __u_boot_list -j .rela.dyn -j .got -j .got.plt \
 		-j .binman_sym_table -j .text_rest \
 		-j .efi_runtime -j .efi_runtime_rel
 else ifeq ($(HOST_ARCH),$(HOST_ARCH_ARM))
 EFI_LDS := ${SRCDIR}/../../../arch/arm/lib/elf_arm_efi.lds
 OBJCOPYFLAGS += -j .text -j .secure_text -j .secure_data -j .rodata -j .hash \
-		-j .data -j .got -j .got.plt -j .u_boot_list -j .rel.dyn \
+		-j .data -j .got -j .got.plt -j __u_boot_list -j .rel.dyn \
 		-j .binman_sym_table -j .text_rest \
 		-j .efi_runtime -j .efi_runtime_rel
 else ifeq ($(HOST_ARCH),$(HOST_ARCH_RISCV32))
diff --git a/arch/sandbox/cpu/u-boot-spl.lds b/arch/sandbox/cpu/u-boot-spl.lds
index 5c19d090cb..046ed0875b 100644
--- a/arch/sandbox/cpu/u-boot-spl.lds
+++ b/arch/sandbox/cpu/u-boot-spl.lds
@@ -9,8 +9,8 @@ SECTIONS
 {
 
 	. = ALIGN(4);
-	.u_boot_list : {
-		KEEP(*(SORT(.u_boot_list*)));
+	__u_boot_list : {
+		KEEP(*(SORT(__u_boot_list*)));
 	}
 
 	/* Private data for devices with OF_PLATDATA_RT */
diff --git a/arch/sandbox/cpu/u-boot.lds b/arch/sandbox/cpu/u-boot.lds
index c3fc67a15b..cc2db24420 100644
--- a/arch/sandbox/cpu/u-boot.lds
+++ b/arch/sandbox/cpu/u-boot.lds
@@ -9,8 +9,8 @@ SECTIONS
 {
 
 	. = ALIGN(4);
-	.u_boot_list : {
-		KEEP(*(SORT(.u_boot_list*)));
+	__u_boot_list : {
+		KEEP(*(SORT(__u_boot_list*)));
 	}
 
 	/* Sandbox has empty EFI runtime lists. */
diff --git a/arch/sh/cpu/u-boot.lds b/arch/sh/cpu/u-boot.lds
index 4cc97737f1..ff80ce78f3 100644
--- a/arch/sh/cpu/u-boot.lds
+++ b/arch/sh/cpu/u-boot.lds
@@ -70,8 +70,8 @@ SECTIONS
 	} >ram
 	PROVIDE (_egot = .);
 
-	.u_boot_list : {
-		KEEP(*(SORT(.u_boot_list*)));
+	__u_boot_list : {
+		KEEP(*(SORT(__u_boot_list*)));
 	} >ram
 
 	PROVIDE (__init_end = .);
diff --git a/arch/x86/cpu/u-boot-64.lds b/arch/x86/cpu/u-boot-64.lds
index 92a30c2a38..53c56043a9 100644
--- a/arch/x86/cpu/u-boot-64.lds
+++ b/arch/x86/cpu/u-boot-64.lds
@@ -12,7 +12,7 @@ ENTRY(_start)
 SECTIONS
 {
 #ifndef CONFIG_CMDLINE
-	/DISCARD/ : { *(.u_boot_list_2_cmd_*) }
+	/DISCARD/ : { *(__u_boot_list_2_cmd_*) }
 #endif
 
 #ifdef CONFIG_SYS_TEXT_BASE
@@ -41,8 +41,8 @@ SECTIONS
 	. = ALIGN(4);
 
 	. = ALIGN(4);
-	.u_boot_list : {
-		KEEP(*(SORT(.u_boot_list*)));
+	__u_boot_list : {
+		KEEP(*(SORT(__u_boot_list*)));
 	}
 
 	. = ALIGN(4);
diff --git a/arch/x86/cpu/u-boot-spl.lds b/arch/x86/cpu/u-boot-spl.lds
index 346f60bdac..a0a2a06a18 100644
--- a/arch/x86/cpu/u-boot-spl.lds
+++ b/arch/x86/cpu/u-boot-spl.lds
@@ -12,7 +12,7 @@ ENTRY(_start)
 SECTIONS
 {
 #ifndef CONFIG_CMDLINE
-	/DISCARD/ : { *(.u_boot_list_2_cmd_*) }
+	/DISCARD/ : { *(__u_boot_list_2_cmd_*) }
 #endif
 
 	. = IMAGE_TEXT_BASE;	/* Location of bootcode in flash */
@@ -25,8 +25,8 @@ SECTIONS
 	. = ALIGN(4);
 
 	. = ALIGN(4);
-	.u_boot_list : {
-		KEEP(*(SORT(.u_boot_list*)));
+	__u_boot_list : {
+		KEEP(*(SORT(__u_boot_list*)));
 	}
 
 	. = ALIGN(4);
diff --git a/arch/x86/cpu/u-boot.lds b/arch/x86/cpu/u-boot.lds
index 22fde01e74..7c87209834 100644
--- a/arch/x86/cpu/u-boot.lds
+++ b/arch/x86/cpu/u-boot.lds
@@ -12,7 +12,7 @@ ENTRY(_start)
 SECTIONS
 {
 #ifndef CONFIG_CMDLINE
-	/DISCARD/ : { *(.u_boot_list_2_cmd_*) }
+	/DISCARD/ : { *(__u_boot_list_2_cmd_*) }
 #endif
 
 	. = CONFIG_SYS_TEXT_BASE;	/* Location of bootcode in flash */
@@ -39,8 +39,8 @@ SECTIONS
 	. = ALIGN(4);
 
 	. = ALIGN(4);
-	.u_boot_list : {
-		KEEP(*(SORT(.u_boot_list*)));
+	__u_boot_list : {
+		KEEP(*(SORT(__u_boot_list*)));
 	}
 
 	. = ALIGN(4);
diff --git a/arch/x86/lib/elf_ia32_efi.lds b/arch/x86/lib/elf_ia32_efi.lds
index aad61e7f81..6d89c1fbd5 100644
--- a/arch/x86/lib/elf_ia32_efi.lds
+++ b/arch/x86/lib/elf_ia32_efi.lds
@@ -51,7 +51,7 @@ SECTIONS
 
 		/* U-Boot lists and device tree */
 		. = ALIGN(8);
-		*(SORT(.u_boot_list*));
+		*(SORT(__u_boot_list*));
 		. = ALIGN(8);
 		*(.dtb*);
 	}
@@ -69,7 +69,7 @@ SECTIONS
 		*(.data.rel.local)
 		*(.data.rel.ro)
 		*(.data.rel*)
-		*(.rel.u_boot_list*)
+		*(.rel__u_boot_list*)
 	}
 	. = ALIGN(4096);
 		.reloc :	/* This is the PECOFF .reloc section! */
diff --git a/arch/x86/lib/elf_x86_64_efi.lds b/arch/x86/lib/elf_x86_64_efi.lds
index 75727400aa..ada024c05c 100644
--- a/arch/x86/lib/elf_x86_64_efi.lds
+++ b/arch/x86/lib/elf_x86_64_efi.lds
@@ -50,7 +50,7 @@ SECTIONS
 
 		/* U-Boot lists and device tree */
 		. = ALIGN(8);
-		*(SORT(.u_boot_list*));
+		*(SORT(__u_boot_list*));
 		. = ALIGN(8);
 		*(.dtb*);
 	}
@@ -63,7 +63,7 @@ SECTIONS
 		*(.rela.data*)
 		*(.rela.got)
 		*(.rela.stab)
-                *(.rela.u_boot_list*)
+                *(.rela__u_boot_list*)
 	}
 
 	. = ALIGN(4096);
diff --git a/arch/xtensa/cpu/u-boot.lds b/arch/xtensa/cpu/u-boot.lds
index 493f3fdb99..37dc92b308 100644
--- a/arch/xtensa/cpu/u-boot.lds
+++ b/arch/xtensa/cpu/u-boot.lds
@@ -78,7 +78,7 @@ SECTIONS
   SECTION_text(XTENSA_SYS_TEXT_ADDR, FOLLOWING(.DoubleExceptionVector.text))
   SECTION_rodata(ALIGN(16), FOLLOWING(.text))
   SECTION_u_boot_list(ALIGN(16), FOLLOWING(.rodata))
-  SECTION_data(ALIGN(16), FOLLOWING(.u_boot_list))
+  SECTION_data(ALIGN(16), FOLLOWING(__u_boot_list))
 
   __reloc_end = .;
   __init_end = .;
diff --git a/arch/xtensa/include/asm/ldscript.h b/arch/xtensa/include/asm/ldscript.h
index 08f5d0135e..4f75483356 100644
--- a/arch/xtensa/include/asm/ldscript.h
+++ b/arch/xtensa/include/asm/ldscript.h
@@ -100,10 +100,10 @@
 	}
 
 #define SECTION_u_boot_list(_vma_, _lma_)				\
-	.u_boot_list _vma_ : _lma_					\
+	__u_boot_list _vma_ : _lma_					\
 	{								\
 		_u_boot_list_start = ABSOLUTE(.);			\
-		KEEP(*(SORT(.u_boot_list*)));				\
+		KEEP(*(SORT(__u_boot_list*)));				\
 		_u_boot_list_end = ABSOLUTE(.);				\
 	}
 
diff --git a/board/compulab/cm_t335/u-boot.lds b/board/compulab/cm_t335/u-boot.lds
index b00e466d58..4993880461 100644
--- a/board/compulab/cm_t335/u-boot.lds
+++ b/board/compulab/cm_t335/u-boot.lds
@@ -36,8 +36,8 @@ SECTIONS
 	. = .;
 
 	. = ALIGN(4);
-	.u_boot_list : {
-		KEEP(*(SORT(.u_boot_list*)));
+	__u_boot_list : {
+		KEEP(*(SORT(__u_boot_list*)));
 	}
 
 	. = ALIGN(4);
diff --git a/board/cssi/MCR3000/u-boot.lds b/board/cssi/MCR3000/u-boot.lds
index 70aef3241c..24b535e724 100644
--- a/board/cssi/MCR3000/u-boot.lds
+++ b/board/cssi/MCR3000/u-boot.lds
@@ -59,8 +59,8 @@ SECTIONS
 	. = .;
 
 	. = ALIGN(4);
-	.u_boot_list : {
-		KEEP(*(SORT(.u_boot_list*)));
+	__u_boot_list : {
+		KEEP(*(SORT(__u_boot_list*)));
 	}
 
 	. = .;
diff --git a/board/davinci/da8xxevm/u-boot-spl-da850evm.lds b/board/davinci/da8xxevm/u-boot-spl-da850evm.lds
index 8f04911306..de1c9c6fce 100644
--- a/board/davinci/da8xxevm/u-boot-spl-da850evm.lds
+++ b/board/davinci/da8xxevm/u-boot-spl-da850evm.lds
@@ -36,7 +36,7 @@ SECTIONS
 	.data : { *(SORT_BY_ALIGNMENT(.data*)) } >.sram
 
 	. = ALIGN(4);
-	.u_boot_list : { KEEP(*(SORT(.u_boot_list*))); } >.sram
+	__u_boot_list : { KEEP(*(SORT(__u_boot_list*))); } >.sram
 
 	. = ALIGN(4);
 	.rel.dyn : {
diff --git a/board/qualcomm/dragonboard820c/u-boot.lds b/board/qualcomm/dragonboard820c/u-boot.lds
index dcf8256cec..5251b59fbe 100644
--- a/board/qualcomm/dragonboard820c/u-boot.lds
+++ b/board/qualcomm/dragonboard820c/u-boot.lds
@@ -49,8 +49,8 @@ SECTIONS
 	. = .;
 
 	. = ALIGN(8);
-	.u_boot_list : {
-		KEEP(*(SORT(.u_boot_list*)));
+	__u_boot_list : {
+		KEEP(*(SORT(__u_boot_list*)));
 	}
 
 	. = ALIGN(8);
diff --git a/board/samsung/common/exynos-uboot-spl.lds b/board/samsung/common/exynos-uboot-spl.lds
index 5b32f7feb8..73cd97a1b1 100644
--- a/board/samsung/common/exynos-uboot-spl.lds
+++ b/board/samsung/common/exynos-uboot-spl.lds
@@ -32,8 +32,8 @@ SECTIONS
 	.data : { *(SORT_BY_ALIGNMENT(.data*)) } >.sram
 	. = ALIGN(4);
 
-	.u_boot_list : {
-		KEEP(*(SORT(.u_boot_list*)));
+	__u_boot_list : {
+		KEEP(*(SORT(__u_boot_list*)));
 	} >.sram
 	. = ALIGN(4);
 
diff --git a/board/synopsys/iot_devkit/u-boot.lds b/board/synopsys/iot_devkit/u-boot.lds
index d083168705..dca2e2daee 100644
--- a/board/synopsys/iot_devkit/u-boot.lds
+++ b/board/synopsys/iot_devkit/u-boot.lds
@@ -39,8 +39,8 @@ SECTIONS
 	} > ROM
 
 	. = ALIGN(4);
-	.u_boot_list : {
-		KEEP(*(SORT(.u_boot_list*)));
+	__u_boot_list : {
+		KEEP(*(SORT(__u_boot_list*)));
 
 		/* Mark RAM's LMA */
 		. = ALIGN(4);
diff --git a/board/ti/am335x/u-boot.lds b/board/ti/am335x/u-boot.lds
index 03c1d5f73b..087dee8bb2 100644
--- a/board/ti/am335x/u-boot.lds
+++ b/board/ti/am335x/u-boot.lds
@@ -72,8 +72,8 @@ SECTIONS
 	. = .;
 
 	. = ALIGN(4);
-	.u_boot_list : {
-		KEEP(*(SORT(.u_boot_list*)));
+	__u_boot_list : {
+		KEEP(*(SORT(__u_boot_list*)));
 	}
 
 	. = ALIGN(4);
diff --git a/board/vscom/baltos/u-boot.lds b/board/vscom/baltos/u-boot.lds
index 315ba5b99a..cb2ee67697 100644
--- a/board/vscom/baltos/u-boot.lds
+++ b/board/vscom/baltos/u-boot.lds
@@ -53,8 +53,8 @@ SECTIONS
 	. = .;
 
 	. = ALIGN(4);
-	.u_boot_list : {
-		KEEP(*(SORT(.u_boot_list*)));
+	__u_boot_list : {
+		KEEP(*(SORT(__u_boot_list*)));
 	}
 
 	. = ALIGN(4);
diff --git a/doc/api/linker_lists.rst b/doc/api/linker_lists.rst
index 7063fdc831..3cd447f187 100644
--- a/doc/api/linker_lists.rst
+++ b/doc/api/linker_lists.rst
@@ -13,7 +13,7 @@ then the corresponding input section name is
 
 ::
 
-  .u_boot_list_ + 2_ + @_list + _2_ + @_entry
+  __u_boot_list_ + 2_ + @_list + _2_ + @_entry
 
 and the C variable name is
 
@@ -23,7 +23,7 @@ and the C variable name is
 
 This ensures uniqueness for both input section and C variable name.
 
-Note that the names differ only in the first character, "." for the
+Note that the names differ only in the characters, "__" for the
 section and "_" for the variable, so that the linker cannot confuse
 section and symbol names. From now on, both names will be referred
 to as
@@ -63,11 +63,11 @@ iterated at least once.
 
 ::
 
-  .u_boot_list_2_array_1
-  .u_boot_list_2_array_2_first
-  .u_boot_list_2_array_2_second
-  .u_boot_list_2_array_2_third
-  .u_boot_list_2_array_3
+  __u_boot_list_2_array_1
+  __u_boot_list_2_array_2_first
+  __u_boot_list_2_array_2_second
+  __u_boot_list_2_array_2_third
+  __u_boot_list_2_array_3
 
 If lists must be divided into sublists (e.g. for iterating only on
 part of a list), one can simply give the list a name of the form
@@ -129,17 +129,17 @@ the compiler cannot update the alignment of the linker_list item.
 
 In the first case, an 8-byte 'fill' region is added::
 
-   .u_boot_list_2_driver_2_testbus_drv
+   __u_boot_list_2_driver_2_testbus_drv
                0x0000000000270018       0x80 test/built-in.o
                0x0000000000270018                _u_boot_list_2_driver_2_testbus_drv
-   .u_boot_list_2_driver_2_testfdt1_drv
+   __u_boot_list_2_driver_2_testfdt1_drv
                0x0000000000270098       0x80 test/built-in.o
                0x0000000000270098                _u_boot_list_2_driver_2_testfdt1_drv
    *fill*         0x0000000000270118        0x8
-   .u_boot_list_2_driver_2_testfdt_drv
+   __u_boot_list_2_driver_2_testfdt_drv
                0x0000000000270120       0x80 test/built-in.o
                0x0000000000270120                _u_boot_list_2_driver_2_testfdt_drv
-   .u_boot_list_2_driver_2_testprobe_drv
+   __u_boot_list_2_driver_2_testprobe_drv
                0x00000000002701a0       0x80 test/built-in.o
                0x00000000002701a0                _u_boot_list_2_driver_2_testprobe_drv
 
diff --git a/doc/develop/commands.rst b/doc/develop/commands.rst
index c72d1b0aaa..ede880d248 100644
--- a/doc/develop/commands.rst
+++ b/doc/develop/commands.rst
@@ -169,8 +169,8 @@ by writing in u-boot.lds ($(srctree)/board/boardname/u-boot.lds) these
 
 .. code-block:: c
 
-    .u_boot_list : {
-        KEEP(*(SORT(.u_boot_list*)));
+    __u_boot_list : {
+        KEEP(*(SORT(__u_boot_list*)));
     }
 
 Writing tests
diff --git a/doc/develop/driver-model/of-plat.rst b/doc/develop/driver-model/of-plat.rst
index 237af38ad4..b454f7be85 100644
--- a/doc/develop/driver-model/of-plat.rst
+++ b/doc/develop/driver-model/of-plat.rst
@@ -707,9 +707,9 @@ Link errors / undefined reference
 Sometimes dtoc does not find the problem for you, but something is wrong and
 you get a link error, e.g.::
 
-   :(.u_boot_list_2_udevice_2_spl_test5+0x0): undefined reference to
+   :(__u_boot_list_2_udevice_2_spl_test5+0x0): undefined reference to
       `_u_boot_list_2_driver_2_sandbox_spl_test'
-   /usr/bin/ld: dts/dt-uclass.o:(.u_boot_list_2_uclass_2_misc+0x8):
+   /usr/bin/ld: dts/dt-uclass.o:(__u_boot_list_2_uclass_2_misc+0x8):
         undefined reference to `_u_boot_list_2_uclass_driver_2_misc'
 
 The first one indicates that the device cannot find its driver. This means that
diff --git a/include/linker_lists.h b/include/linker_lists.h
index 0575164ce4..d3da9d44e8 100644
--- a/include/linker_lists.h
+++ b/include/linker_lists.h
@@ -70,7 +70,7 @@
 #define ll_entry_declare(_type, _name, _list)				\
 	_type _u_boot_list_2_##_list##_2_##_name __aligned(4)		\
 			__attribute__((unused))				\
-			__section(".u_boot_list_2_"#_list"_2_"#_name)
+			__section("__u_boot_list_2_"#_list"_2_"#_name)
 
 /**
  * ll_entry_declare_list() - Declare a list of link-generated array entries
@@ -93,7 +93,7 @@
 #define ll_entry_declare_list(_type, _name, _list)			\
 	_type _u_boot_list_2_##_list##_2_##_name[] __aligned(4)		\
 			__attribute__((unused))				\
-			__section(".u_boot_list_2_"#_list"_2_"#_name)
+			__section("__u_boot_list_2_"#_list"_2_"#_name)
 
 /*
  * We need a 0-byte-size type for iterator symbols, and the compiler
@@ -110,7 +110,7 @@
  * @_list:	Name of the list in which this entry is placed
  *
  * This function returns ``(_type *)`` pointer to the very first entry of a
- * linker-generated array placed into subsection of .u_boot_list section
+ * linker-generated array placed into subsection of __u_boot_list section
  * specified by _list argument.
  *
  * Since this macro defines an array start symbol, its leftmost index
@@ -126,7 +126,7 @@
 ({									\
 	static char start[0] __aligned(CONFIG_LINKER_LIST_ALIGN)	\
 		__attribute__((unused))					\
-		__section(".u_boot_list_2_"#_list"_1");			\
+		__section("__u_boot_list_2_"#_list"_1");			\
 	(_type *)&start;						\
 })
 
@@ -137,7 +137,7 @@
  *		(with underscores instead of dots)
  *
  * This function returns ``(_type *)`` pointer after the very last entry of
- * a linker-generated array placed into subsection of .u_boot_list
+ * a linker-generated array placed into subsection of __u_boot_list
  * section specified by _list argument.
  *
  * Since this macro defines an array end symbol, its leftmost index
@@ -152,7 +152,7 @@
 #define ll_entry_end(_type, _list)					\
 ({									\
 	static char end[0] __aligned(4) __attribute__((unused))		\
-		__section(".u_boot_list_2_"#_list"_3");			\
+		__section("__u_boot_list_2_"#_list"_3");			\
 	(_type *)&end;							\
 })
 /**
@@ -161,7 +161,7 @@
  * @_list:	Name of the list of which the number of elements is computed
  *
  * This function returns the number of elements of a linker-generated array
- * placed into subsection of .u_boot_list section specified by _list
+ * placed into subsection of __u_boot_list section specified by _list
  * argument. The result is of an unsigned int type.
  *
  * Example:
@@ -246,7 +246,7 @@
 #define ll_start(_type)							\
 ({									\
 	static char start[0] __aligned(4) __attribute__((unused))	\
-		__section(".u_boot_list_1");				\
+		__section("__u_boot_list_1");				\
 	(_type *)&start;						\
 })
 
@@ -269,7 +269,7 @@
 #define ll_end(_type)							\
 ({									\
 	static char end[0] __aligned(4) __attribute__((unused))		\
-		__section(".u_boot_list_3");				\
+		__section("__u_boot_list_3");				\
 	(_type *)&end;							\
 })
 
-- 
2.35.1.1094.g7c7d902a7c-goog


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

* [PATCH 04/11] sandbox: Add support for Address Sanitizer
  2022-04-07  9:41 [PATCH 00/11] Fuzzing and ASAN for sandbox Andrew Scull
                   ` (2 preceding siblings ...)
  2022-04-07  9:41 ` [PATCH 03/11] linker_lists: Rename sections to remove . prefix Andrew Scull
@ 2022-04-07  9:41 ` Andrew Scull
  2022-04-11 18:35   ` Simon Glass
  2022-04-07  9:41 ` [PATCH 05/11] fuzzing_engine: Add fuzzing engine uclass Andrew Scull
                   ` (6 subsequent siblings)
  10 siblings, 1 reply; 30+ messages in thread
From: Andrew Scull @ 2022-04-07  9:41 UTC (permalink / raw)
  To: u-boot; +Cc: sjg, seanga2, Andrew Scull

Add CONFIG_ASAN to build with the Address Sanitizer. This only works
with the sandbox so the config is likewise dependent. The resulting
executable will have ASAN instrumentation, including the leak detector
that can be disabled with the ASAN_OPTIONS environment variable:

   ASAN_OPTIONS=detect_leaks=0 ./u-boot

Since u-boot uses its own dlmalloc, dynamic allocations aren't
automatically instrumented, but stack variables and globals are.

Instrumentation could be added to dlmalloc to poison and unpoison memory
as it is allocated and deallocated, and to introduce redzones between
allocations. Alternatively, the sandbox may be able to play games with
the system allocator and somehow still keep the required memory
abstraction. No effort to address dynamic allocation is made by this
patch.

Signed-off-by: Andrew Scull <ascull@google.com>
---
 Kconfig                   | 7 +++++++
 arch/sandbox/config.mk    | 8 ++++++++
 configs/sandbox_defconfig | 1 +
 3 files changed, 16 insertions(+)

diff --git a/Kconfig b/Kconfig
index 9dd9ec7f6d..ae7e92611d 100644
--- a/Kconfig
+++ b/Kconfig
@@ -137,6 +137,13 @@ config CC_COVERAGE
 	  Enabling this option will pass "--coverage" to gcc to compile
 	  and link code instrumented for coverage analysis.
 
+config ASAN
+	bool "Enable AddressSanitizer"
+	depends on SANDBOX
+	help
+	  Enables AddressSanitizer to discover out-of-bounds accesses,
+	  use-after-free, double-free and memory leaks.
+
 config CC_HAS_ASM_INLINE
 	def_bool $(success,echo 'void foo(void) { asm inline (""); }' | $(CC) -x c - -c -o /dev/null)
 
diff --git a/arch/sandbox/config.mk b/arch/sandbox/config.mk
index c42de2ff27..d7ce66fb6c 100644
--- a/arch/sandbox/config.mk
+++ b/arch/sandbox/config.mk
@@ -15,7 +15,14 @@ PLATFORM_LIBS += $(shell $(SDL_CONFIG) --libs)
 PLATFORM_CPPFLAGS += $(shell $(SDL_CONFIG) --cflags)
 endif
 
+SANITIZERS :=
+ifdef CONFIG_ASAN
+SANITIZERS	+= -fsanitize=address
+endif
+KBUILD_CFLAGS	+= $(SANITIZERS)
+
 cmd_u-boot__ = $(CC) -o $@ -Wl,-T u-boot.lds $(u-boot-init) \
+	$(SANITIZERS) \
 	$(LTO_FINAL_LDFLAGS) \
 	-Wl,--whole-archive \
 		$(u-boot-main) \
@@ -24,6 +31,7 @@ cmd_u-boot__ = $(CC) -o $@ -Wl,-T u-boot.lds $(u-boot-init) \
 	$(PLATFORM_LIBS) -Wl,-Map -Wl,u-boot.map
 
 cmd_u-boot-spl = (cd $(obj) && $(CC) -o $(SPL_BIN) -Wl,-T u-boot-spl.lds \
+	$(SANITIZERS) \
 	$(LTO_FINAL_LDFLAGS) \
 	$(patsubst $(obj)/%,%,$(u-boot-spl-init)) \
 	-Wl,--whole-archive \
diff --git a/configs/sandbox_defconfig b/configs/sandbox_defconfig
index 7ebeb89264..4862af07cd 100644
--- a/configs/sandbox_defconfig
+++ b/configs/sandbox_defconfig
@@ -1,3 +1,4 @@
+CONFIG_ASAN=y
 CONFIG_SYS_TEXT_BASE=0
 CONFIG_SYS_MALLOC_LEN=0x2000000
 CONFIG_NR_DRAM_BANKS=1
-- 
2.35.1.1094.g7c7d902a7c-goog


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

* [PATCH 05/11] fuzzing_engine: Add fuzzing engine uclass
  2022-04-07  9:41 [PATCH 00/11] Fuzzing and ASAN for sandbox Andrew Scull
                   ` (3 preceding siblings ...)
  2022-04-07  9:41 ` [PATCH 04/11] sandbox: Add support for Address Sanitizer Andrew Scull
@ 2022-04-07  9:41 ` Andrew Scull
  2022-04-11 18:35   ` Simon Glass
  2022-04-07  9:41 ` [PATCH 06/11] test: fuzz: Add framework for fuzzing Andrew Scull
                   ` (5 subsequent siblings)
  10 siblings, 1 reply; 30+ messages in thread
From: Andrew Scull @ 2022-04-07  9:41 UTC (permalink / raw)
  To: u-boot; +Cc: sjg, seanga2, Andrew Scull

This new class of device will provide fuzzing inputs from a fuzzing
engine.

Signed-off-by: Andrew Scull <ascull@google.com>
---
 drivers/Kconfig                               |  2 +
 drivers/Makefile                              |  1 +
 drivers/fuzzing_engine/Kconfig                |  6 +++
 drivers/fuzzing_engine/Makefile               |  7 +++
 .../fuzzing_engine/fuzzing_engine-uclass.c    | 28 ++++++++++
 include/dm/uclass-id.h                        |  1 +
 include/fuzzing_engine.h                      | 51 +++++++++++++++++++
 7 files changed, 96 insertions(+)
 create mode 100644 drivers/fuzzing_engine/Kconfig
 create mode 100644 drivers/fuzzing_engine/Makefile
 create mode 100644 drivers/fuzzing_engine/fuzzing_engine-uclass.c
 create mode 100644 include/fuzzing_engine.h

diff --git a/drivers/Kconfig b/drivers/Kconfig
index b26ca8cf70..54ad7f82fa 100644
--- a/drivers/Kconfig
+++ b/drivers/Kconfig
@@ -40,6 +40,8 @@ source "drivers/fastboot/Kconfig"
 
 source "drivers/firmware/Kconfig"
 
+source "drivers/fuzzing_engine/Kconfig"
+
 source "drivers/fpga/Kconfig"
 
 source "drivers/gpio/Kconfig"
diff --git a/drivers/Makefile b/drivers/Makefile
index 4e7cf28440..10a4a317c9 100644
--- a/drivers/Makefile
+++ b/drivers/Makefile
@@ -113,6 +113,7 @@ obj-$(CONFIG_W1) += w1/
 obj-$(CONFIG_W1_EEPROM) += w1-eeprom/
 
 obj-$(CONFIG_MACH_PIC32) += ddr/microchip/
+obj-$(CONFIG_FUZZ) += fuzzing_engine/
 obj-$(CONFIG_DM_HWSPINLOCK) += hwspinlock/
 obj-$(CONFIG_DM_RNG) += rng/
 endif
diff --git a/drivers/fuzzing_engine/Kconfig b/drivers/fuzzing_engine/Kconfig
new file mode 100644
index 0000000000..f405fc75e8
--- /dev/null
+++ b/drivers/fuzzing_engine/Kconfig
@@ -0,0 +1,6 @@
+config DM_FUZZING_ENGINE
+	bool "Driver support for fuzzing engine devices"
+	depends on DM
+	help
+	  Enable driver model for fuzzing engine devices. This interface is
+	  used to get fuzzing inputs from a fuzzing engine.
diff --git a/drivers/fuzzing_engine/Makefile b/drivers/fuzzing_engine/Makefile
new file mode 100644
index 0000000000..acd894999c
--- /dev/null
+++ b/drivers/fuzzing_engine/Makefile
@@ -0,0 +1,7 @@
+# SPDX-License-Identifier: GPL-2.0+
+#
+# Copyright (c) 2022 Google, Inc.
+# Written by Andrew Scull <ascull@google.com>
+#
+
+obj-$(CONFIG_DM_FUZZING_ENGINE) += fuzzing_engine-uclass.o
diff --git a/drivers/fuzzing_engine/fuzzing_engine-uclass.c b/drivers/fuzzing_engine/fuzzing_engine-uclass.c
new file mode 100644
index 0000000000..b16f1c4cfb
--- /dev/null
+++ b/drivers/fuzzing_engine/fuzzing_engine-uclass.c
@@ -0,0 +1,28 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * Copyright (c) 2022 Google, Inc.
+ * Written by Andrew Scull <ascull@google.com>
+ */
+
+#define LOG_CATEGORY UCLASS_FUZZING_ENGINE
+
+#include <common.h>
+#include <dm.h>
+#include <fuzzing_engine.h>
+
+int dm_fuzzing_engine_get_input(struct udevice *dev,
+				const uint8_t **data,
+				size_t *size)
+{
+	const struct dm_fuzzing_engine_ops *ops = device_get_ops(dev);
+
+	if (!ops->get_input)
+		return -ENOSYS;
+
+	return ops->get_input(dev, data, size);
+}
+
+UCLASS_DRIVER(fuzzing_engine) = {
+	.name = "fuzzing_engine",
+	.id = UCLASS_FUZZING_ENGINE,
+};
diff --git a/include/dm/uclass-id.h b/include/dm/uclass-id.h
index 0e26e1d138..b9411f1d59 100644
--- a/include/dm/uclass-id.h
+++ b/include/dm/uclass-id.h
@@ -53,6 +53,7 @@ enum uclass_id {
 	UCLASS_ETH,		/* Ethernet device */
 	UCLASS_ETH_PHY,		/* Ethernet PHY device */
 	UCLASS_FIRMWARE,	/* Firmware */
+	UCLASS_FUZZING_ENGINE,	/* Fuzzing engine */
 	UCLASS_FS_FIRMWARE_LOADER,		/* Generic loader */
 	UCLASS_GPIO,		/* Bank of general-purpose I/O pins */
 	UCLASS_HASH,		/* Hash device */
diff --git a/include/fuzzing_engine.h b/include/fuzzing_engine.h
new file mode 100644
index 0000000000..357346e93d
--- /dev/null
+++ b/include/fuzzing_engine.h
@@ -0,0 +1,51 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * Copyright (c) 2022 Google, Inc.
+ * Written by Andrew Scull <ascull@google.com>
+ */
+
+#ifndef __FUZZING_ENGINE_H
+#define __FUZZING_ENGINE_H
+
+struct udevice;
+
+/**
+ * dm_fuzzing_engine_get_input() - get an input from the fuzzing engine device
+ *
+ * The function will return a pointer to the input data and the size of the
+ * data pointed to. The pointer will remain valid until the next invocation of
+ * this function.
+ *
+ * @dev:	fuzzing engine device
+ * @data:	output pointer to input data
+ * @size	output size of input data
+ * Return:	0 if OK, -ve on error
+ */
+int dm_fuzzing_engine_get_input(struct udevice *dev,
+				const uint8_t **data,
+				size_t *size);
+
+/**
+ * struct dm_fuzzing_engine_ops - operations for the fuzzing engine uclass
+ *
+ * This contains the functions implemented by a fuzzing engine device.
+ */
+struct dm_fuzzing_engine_ops {
+	/**
+	 * @get_input() - get an input
+	 *
+	 * The function will return a pointer to the input data and the size of
+	 * the data pointed to. The pointer will remain valid until the next
+	 * invocation of this function.
+	 *
+	 * @get_input.dev:	fuzzing engine device
+	 * @get_input.data:	output pointer to input data
+	 * @get_input.size	output size of input data
+	 * @get_input.Return:	0 if OK, -ve on error
+	 */
+	int (*get_input)(struct udevice *dev,
+			 const uint8_t **data,
+			 size_t *size);
+};
+
+#endif /* __FUZZING_ENGINE_H */
-- 
2.35.1.1094.g7c7d902a7c-goog


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

* [PATCH 06/11] test: fuzz: Add framework for fuzzing
  2022-04-07  9:41 [PATCH 00/11] Fuzzing and ASAN for sandbox Andrew Scull
                   ` (4 preceding siblings ...)
  2022-04-07  9:41 ` [PATCH 05/11] fuzzing_engine: Add fuzzing engine uclass Andrew Scull
@ 2022-04-07  9:41 ` Andrew Scull
  2022-04-11 18:35   ` Simon Glass
  2022-04-07  9:41 ` [PATCH 07/11] sandbox: Decouple program entry from sandbox init Andrew Scull
                   ` (4 subsequent siblings)
  10 siblings, 1 reply; 30+ messages in thread
From: Andrew Scull @ 2022-04-07  9:41 UTC (permalink / raw)
  To: u-boot; +Cc: sjg, seanga2, Andrew Scull

Add the basic infrastructure for declaring fuzz tests and a command to
invoke them.

Signed-off-by: Andrew Scull <ascull@google.com>
---
 Kconfig              |  8 +++++
 include/test/fuzz.h  | 51 +++++++++++++++++++++++++++
 test/Makefile        |  1 +
 test/fuzz/Makefile   |  7 ++++
 test/fuzz/cmd_fuzz.c | 82 ++++++++++++++++++++++++++++++++++++++++++++
 5 files changed, 149 insertions(+)
 create mode 100644 include/test/fuzz.h
 create mode 100644 test/fuzz/Makefile
 create mode 100644 test/fuzz/cmd_fuzz.c

diff --git a/Kconfig b/Kconfig
index ae7e92611d..ce0a69d6aa 100644
--- a/Kconfig
+++ b/Kconfig
@@ -144,6 +144,14 @@ config ASAN
 	  Enables AddressSanitizer to discover out-of-bounds accesses,
 	  use-after-free, double-free and memory leaks.
 
+config FUZZ
+	bool "Enable fuzzing"
+	depends on DM_FUZZING_ENGINE
+	select ASAN
+	help
+	  Enables the fuzzing infrastructure to generate fuzzing data and run
+          fuzz tests.
+
 config CC_HAS_ASM_INLINE
 	def_bool $(success,echo 'void foo(void) { asm inline (""); }' | $(CC) -x c - -c -o /dev/null)
 
diff --git a/include/test/fuzz.h b/include/test/fuzz.h
new file mode 100644
index 0000000000..d4c57540eb
--- /dev/null
+++ b/include/test/fuzz.h
@@ -0,0 +1,51 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * Copyright (c) 2022 Google, Inc.
+ * Written by Andrew Scull <ascull@google.com>
+ */
+
+#ifndef __TEST_FUZZ_H
+#define __TEST_FUZZ_H
+
+#include <linker_lists.h>
+#include <linux/types.h>
+
+/**
+ * struct fuzz_test - Information about a fuzz test
+ *
+ * @name: Name of fuzz test
+ * @func: Function to call to perform fuzz test on an input
+ * @flags: Flags indicate pre-conditions for fuzz test
+ */
+struct fuzz_test {
+	const char *name;
+	int (*func)(const uint8_t * data, size_t size);
+	int flags;
+};
+
+/**
+ * FUZZ_TEST() - register a fuzz test
+ *
+ * The fuzz test function must return 0 as other values are reserved for future
+ * use.
+ *
+ * @_name:	the name of the fuzz test function
+ * @_flags:	an integer field that can be evaluated by the fuzzer
+ * 		implementation
+ */
+#define FUZZ_TEST(_name, _flags)					\
+	ll_entry_declare(struct fuzz_test, _name, fuzz_tests) = {	\
+		.name = #_name,						\
+		.func = _name,						\
+		.flags = _flags,					\
+	}
+
+/** Get the start of the list of fuzz tests */
+#define FUZZ_TEST_START() \
+	ll_entry_start(struct fuzz_test, fuzz_tests)
+
+/** Get the number of elements in the list of fuzz tests */
+#define FUZZ_TEST_COUNT() \
+	ll_entry_count(struct fuzz_test, fuzz_tests)
+
+#endif /* __TEST_FUZZ_H */
diff --git a/test/Makefile b/test/Makefile
index b3b2902e2e..bb2b0b5c73 100644
--- a/test/Makefile
+++ b/test/Makefile
@@ -16,6 +16,7 @@ obj-$(CONFIG_$(SPL_)CMDLINE) += cmd_ut.o
 obj-$(CONFIG_$(SPL_)CMDLINE) += command_ut.o
 obj-$(CONFIG_$(SPL_)UT_COMPRESSION) += compression.o
 obj-y += dm/
+obj-$(CONFIG_FUZZ) += fuzz/
 obj-$(CONFIG_$(SPL_)CMDLINE) += print_ut.o
 obj-$(CONFIG_$(SPL_)CMDLINE) += str_ut.o
 obj-$(CONFIG_UT_TIME) += time_ut.o
diff --git a/test/fuzz/Makefile b/test/fuzz/Makefile
new file mode 100644
index 0000000000..03eeeeb497
--- /dev/null
+++ b/test/fuzz/Makefile
@@ -0,0 +1,7 @@
+# SPDX-License-Identifier: GPL-2.0+
+#
+# Copyright (c) 2022 Google, Inc.
+# Written by Andrew Scull <ascull@google.com>
+#
+
+obj-$(CONFIG_$(SPL_)CMDLINE) += cmd_fuzz.o
diff --git a/test/fuzz/cmd_fuzz.c b/test/fuzz/cmd_fuzz.c
new file mode 100644
index 0000000000..0cc01dc199
--- /dev/null
+++ b/test/fuzz/cmd_fuzz.c
@@ -0,0 +1,82 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * Copyright (c) 2022 Google, Inc.
+ * Written by Andrew Scull <ascull@google.com>
+ */
+
+#include <command.h>
+#include <common.h>
+#include <dm.h>
+#include <fuzzing_engine.h>
+#include <test/fuzz.h>
+
+static struct fuzz_test *find_fuzz_test(const char *name)
+{
+	struct fuzz_test *fuzzer = FUZZ_TEST_START();
+	size_t count = FUZZ_TEST_COUNT();
+	size_t i;
+
+	for (i = 0; i < count; ++i) {
+		if (strcmp(name, fuzzer->name) == 0)
+			return fuzzer;
+		++fuzzer;
+	}
+
+	return NULL;
+}
+
+static struct udevice *find_fuzzing_engine(void)
+{
+	struct udevice *dev;
+
+	if (uclass_first_device(UCLASS_FUZZING_ENGINE, &dev))
+		return NULL;
+
+	return dev;
+}
+
+static int do_fuzz(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
+{
+	struct fuzz_test *fuzzer;
+	struct udevice *dev;
+
+	if (argc != 2)
+		return CMD_RET_USAGE;
+
+	fuzzer = find_fuzz_test(argv[1]);
+	if (!fuzzer) {
+		printf("Could not find fuzzer: %s\n", argv[1]);
+		return 1;
+	}
+
+	dev = find_fuzzing_engine();
+	if (!dev) {
+		puts("No fuzzing engine available\n");
+		return 1;
+	}
+
+	while (1) {
+		const uint8_t *data;
+		size_t size;
+
+		if (dm_fuzzing_engine_get_input(dev, &data, &size)) {
+			puts("Fuzzing engine failed\n");
+			return 1;
+		}
+
+		fuzzer->func(data, size);
+	}
+
+	return 1;
+}
+
+#ifdef CONFIG_SYS_LONGHELP
+static char fuzz_help_text[] =
+	"[fuzz-test-name] - execute the named fuzz test\n"
+	;
+#endif /* CONFIG_SYS_LONGHELP */
+
+U_BOOT_CMD(
+	fuzz, CONFIG_SYS_MAXARGS, 1, do_fuzz,
+	"fuzz tests", fuzz_help_text
+);
-- 
2.35.1.1094.g7c7d902a7c-goog


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

* [PATCH 07/11] sandbox: Decouple program entry from sandbox init
  2022-04-07  9:41 [PATCH 00/11] Fuzzing and ASAN for sandbox Andrew Scull
                   ` (5 preceding siblings ...)
  2022-04-07  9:41 ` [PATCH 06/11] test: fuzz: Add framework for fuzzing Andrew Scull
@ 2022-04-07  9:41 ` Andrew Scull
  2022-04-11 18:35   ` Simon Glass
  2022-04-07  9:41 ` [PATCH 08/11] sandbox: Add libfuzzer integration Andrew Scull
                   ` (3 subsequent siblings)
  10 siblings, 1 reply; 30+ messages in thread
From: Andrew Scull @ 2022-04-07  9:41 UTC (permalink / raw)
  To: u-boot; +Cc: sjg, seanga2, Andrew Scull

Move the program's entry point to os.c, in preparation for a separate
fuzzing entry point to be added.

Signed-off-by: Andrew Scull <ascull@google.com>
---
 arch/sandbox/cpu/os.c           |  6 ++++++
 arch/sandbox/cpu/start.c        |  2 +-
 arch/sandbox/include/asm/main.h | 18 ++++++++++++++++++
 3 files changed, 25 insertions(+), 1 deletion(-)
 create mode 100644 arch/sandbox/include/asm/main.h

diff --git a/arch/sandbox/cpu/os.c b/arch/sandbox/cpu/os.c
index 72a72029f2..5ea4135741 100644
--- a/arch/sandbox/cpu/os.c
+++ b/arch/sandbox/cpu/os.c
@@ -27,6 +27,7 @@
 #include <linux/types.h>
 
 #include <asm/getopt.h>
+#include <asm/main.h>
 #include <asm/sections.h>
 #include <asm/state.h>
 #include <os.h>
@@ -1000,3 +1001,8 @@ void os_relaunch(char *argv[])
 	execv(argv[0], argv);
 	os_exit(1);
 }
+
+int main(int argc, char *argv[])
+{
+	return sandbox_main(argc, argv);
+}
diff --git a/arch/sandbox/cpu/start.c b/arch/sandbox/cpu/start.c
index 5cb47e1156..ba67f4fbd7 100644
--- a/arch/sandbox/cpu/start.c
+++ b/arch/sandbox/cpu/start.c
@@ -451,7 +451,7 @@ void sandbox_reset(void)
 	os_relaunch(os_argv);
 }
 
-int main(int argc, char *argv[])
+int sandbox_main(int argc, char *argv[])
 {
 	struct sandbox_state *state;
 	void * text_base;
diff --git a/arch/sandbox/include/asm/main.h b/arch/sandbox/include/asm/main.h
new file mode 100644
index 0000000000..7a2f0d3a8d
--- /dev/null
+++ b/arch/sandbox/include/asm/main.h
@@ -0,0 +1,18 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * Copyright (c) 2022 Google, Inc.
+ * Written by Andrew Scull <ascull@google.com>
+ */
+
+#ifndef __ASM_SANDBOX_MAIN_H
+#define __ASM_SANDBOX_MAIN_H
+
+/**
+ * sandbox_main() - main entrypoint for sandbox
+ *
+ * @argc:	the number of arguments passed to the program
+ * @argv:	array of argc+1 pointers, of which the last one is null
+ */
+int sandbox_main(int argc, char *argv[]);
+
+#endif /* __ASM_SANDBOX_MAIN_H */
-- 
2.35.1.1094.g7c7d902a7c-goog


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

* [PATCH 08/11] sandbox: Add libfuzzer integration
  2022-04-07  9:41 [PATCH 00/11] Fuzzing and ASAN for sandbox Andrew Scull
                   ` (6 preceding siblings ...)
  2022-04-07  9:41 ` [PATCH 07/11] sandbox: Decouple program entry from sandbox init Andrew Scull
@ 2022-04-07  9:41 ` Andrew Scull
  2022-04-11 18:35   ` Simon Glass
  2022-04-07  9:41 ` [PATCH 09/11] sandbox: Implement fuzzing engine driver Andrew Scull
                   ` (2 subsequent siblings)
  10 siblings, 1 reply; 30+ messages in thread
From: Andrew Scull @ 2022-04-07  9:41 UTC (permalink / raw)
  To: u-boot; +Cc: sjg, seanga2, Andrew Scull

Add an implementation of LLVMFuzzerTestOneInput() that starts the
sandbox on a secondary thread and exposes a function to synchronize the
generation of fuzzing inputs with their consumption by the sandbox.

Signed-off-by: Andrew Scull <ascull@google.com>
---
 arch/sandbox/config.mk                    |  3 +
 arch/sandbox/cpu/os.c                     | 70 +++++++++++++++++++++++
 arch/sandbox/include/asm/fuzzing_engine.h | 25 ++++++++
 3 files changed, 98 insertions(+)
 create mode 100644 arch/sandbox/include/asm/fuzzing_engine.h

diff --git a/arch/sandbox/config.mk b/arch/sandbox/config.mk
index d7ce66fb6c..5fbe1f50e3 100644
--- a/arch/sandbox/config.mk
+++ b/arch/sandbox/config.mk
@@ -19,6 +19,9 @@ SANITIZERS :=
 ifdef CONFIG_ASAN
 SANITIZERS	+= -fsanitize=address
 endif
+ifdef CONFIG_FUZZ
+SANITIZERS	+= -fsanitize=fuzzer
+endif
 KBUILD_CFLAGS	+= $(SANITIZERS)
 
 cmd_u-boot__ = $(CC) -o $@ -Wl,-T u-boot.lds $(u-boot-init) \
diff --git a/arch/sandbox/cpu/os.c b/arch/sandbox/cpu/os.c
index 5ea4135741..cd45d7b6b6 100644
--- a/arch/sandbox/cpu/os.c
+++ b/arch/sandbox/cpu/os.c
@@ -8,6 +8,7 @@
 #include <dirent.h>
 #include <errno.h>
 #include <fcntl.h>
+#include <pthread.h>
 #include <getopt.h>
 #include <setjmp.h>
 #include <signal.h>
@@ -26,6 +27,7 @@
 #include <linux/compiler_attributes.h>
 #include <linux/types.h>
 
+#include <asm/fuzzing_engine.h>
 #include <asm/getopt.h>
 #include <asm/main.h>
 #include <asm/sections.h>
@@ -1002,7 +1004,75 @@ void os_relaunch(char *argv[])
 	os_exit(1);
 }
 
+
+#ifdef CONFIG_FUZZ
+static void *fuzzer_thread(void * ptr)
+{
+	char cmd[64];
+	char *argv[5] = {"./u-boot", "-T", "-c", cmd, NULL};
+	const char *fuzz_test;
+
+	/* Find which test to run from an environment variable. */
+	fuzz_test = getenv("UBOOT_SB_FUZZ_TEST");
+	if (!fuzz_test)
+		os_abort();
+
+	snprintf(cmd, sizeof(cmd), "fuzz %s", fuzz_test);
+
+	sandbox_main(4, argv);
+	os_abort();
+	return NULL;
+}
+
+static bool fuzzer_initialized = false;
+static pthread_mutex_t fuzzer_mutex = PTHREAD_MUTEX_INITIALIZER;
+static pthread_cond_t fuzzer_cond = PTHREAD_COND_INITIALIZER;
+static const uint8_t *fuzzer_data;
+static size_t fuzzer_size;
+
+int sandbox_fuzzing_engine_get_input(const uint8_t **data, size_t *size)
+{
+	if (!fuzzer_initialized)
+		return -ENOSYS;
+
+	/* Tell the main thread we need new inputs then wait for them. */
+	pthread_mutex_lock(&fuzzer_mutex);
+	pthread_cond_signal(&fuzzer_cond);
+	pthread_cond_wait(&fuzzer_cond, &fuzzer_mutex);
+	*data = fuzzer_data;
+	*size = fuzzer_size;
+	pthread_mutex_unlock(&fuzzer_mutex);
+	return 0;
+}
+
+int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
+{
+	static pthread_t tid;
+
+	pthread_mutex_lock(&fuzzer_mutex);
+
+	/* Initialize the sandbox on another thread. */
+	if (!fuzzer_initialized) {
+		fuzzer_initialized = true;
+		if (pthread_create(&tid, NULL, fuzzer_thread, NULL))
+			os_abort();
+		pthread_cond_wait(&fuzzer_cond, &fuzzer_mutex);
+	}
+
+	/* Hand over the input. */
+	fuzzer_data = data;
+	fuzzer_size = size;
+	pthread_cond_signal(&fuzzer_cond);
+
+	/* Wait for the inputs to be finished with. */
+	pthread_cond_wait(&fuzzer_cond, &fuzzer_mutex);
+	pthread_mutex_unlock(&fuzzer_mutex);
+
+	return 0;
+}
+#else
 int main(int argc, char *argv[])
 {
 	return sandbox_main(argc, argv);
 }
+#endif
diff --git a/arch/sandbox/include/asm/fuzzing_engine.h b/arch/sandbox/include/asm/fuzzing_engine.h
new file mode 100644
index 0000000000..cf6396363b
--- /dev/null
+++ b/arch/sandbox/include/asm/fuzzing_engine.h
@@ -0,0 +1,25 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * Copyright (c) 2022 Google, Inc.
+ * Written by Andrew Scull <ascull@google.com>
+ */
+
+#ifndef __ASM_FUZZING_ENGINE_H
+#define __ASM_FUZZING_ENGINE_H
+
+/** Function to get fuzzing engine input data. */
+/**
+ * sandbox_fuzzing_engine_get_input() - get an input from the sandbox fuzzing
+ * 					engine
+ *
+ * The function will return a pointer to the input data and the size of the
+ * data pointed to. The pointer will remain valid until the next invocation of
+ * this function.
+ *
+ * @data:	output pointer to input data
+ * @size	output size of input data
+ * Return:	0 if OK, -ve on error
+ */
+int sandbox_fuzzing_engine_get_input(const uint8_t **data, size_t *size);
+
+#endif /* __ASM_FUZZING_ENGINE_H */
-- 
2.35.1.1094.g7c7d902a7c-goog


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

* [PATCH 09/11] sandbox: Implement fuzzing engine driver
  2022-04-07  9:41 [PATCH 00/11] Fuzzing and ASAN for sandbox Andrew Scull
                   ` (7 preceding siblings ...)
  2022-04-07  9:41 ` [PATCH 08/11] sandbox: Add libfuzzer integration Andrew Scull
@ 2022-04-07  9:41 ` Andrew Scull
  2022-04-11 18:35   ` Simon Glass
  2022-04-07  9:41 ` [PATCH 10/11] fuzz: virtio: Add fuzzer for vring Andrew Scull
  2022-04-07  9:41 ` [PATCH 11/11] RFC: Hack dlmalloc to poison memory Andrew Scull
  10 siblings, 1 reply; 30+ messages in thread
From: Andrew Scull @ 2022-04-07  9:41 UTC (permalink / raw)
  To: u-boot; +Cc: sjg, seanga2, Andrew Scull

Add a fuzzing engine driver for the sandbox to take inputs from
libfuzzer and expose them to the fuzz tests.

Signed-off-by: Andrew Scull <ascull@google.com>
---
 arch/Kconfig                                  |  2 ++
 arch/sandbox/dts/test.dts                     |  4 +++
 drivers/fuzzing_engine/Kconfig                | 11 ++++++
 drivers/fuzzing_engine/Makefile               |  1 +
 .../fuzzing_engine/sandbox_fuzzing_engine.c   | 35 +++++++++++++++++++
 5 files changed, 53 insertions(+)
 create mode 100644 drivers/fuzzing_engine/sandbox_fuzzing_engine.c

diff --git a/arch/Kconfig b/arch/Kconfig
index e6191446a3..6320a98db6 100644
--- a/arch/Kconfig
+++ b/arch/Kconfig
@@ -135,6 +135,7 @@ config SANDBOX
 	select BZIP2
 	select CMD_POWEROFF
 	select DM
+	select DM_FUZZING_ENGINE
 	select DM_GPIO
 	select DM_I2C
 	select DM_KEYBOARD
@@ -170,6 +171,7 @@ config SANDBOX
 	imply CRC32_VERIFY
 	imply FAT_WRITE
 	imply FIRMWARE
+	imply FUZZING_ENGINE_SANDBOX
 	imply HASH_VERIFY
 	imply LZMA
 	imply TEE
diff --git a/arch/sandbox/dts/test.dts b/arch/sandbox/dts/test.dts
index 48ca3e1e47..848329fda5 100644
--- a/arch/sandbox/dts/test.dts
+++ b/arch/sandbox/dts/test.dts
@@ -71,6 +71,10 @@
 		};
 	};
 
+	fuzzing-engine {
+		compatible = "sandbox,sandbox-fuzzing-engine";
+	};
+
 	reboot-mode0 {
 		compatible = "reboot-mode-gpio";
 		gpios = <&gpio_c 0 GPIO_ACTIVE_HIGH>, <&gpio_c 1 GPIO_ACTIVE_HIGH>;
diff --git a/drivers/fuzzing_engine/Kconfig b/drivers/fuzzing_engine/Kconfig
index f405fc75e8..6311385222 100644
--- a/drivers/fuzzing_engine/Kconfig
+++ b/drivers/fuzzing_engine/Kconfig
@@ -4,3 +4,14 @@ config DM_FUZZING_ENGINE
 	help
 	  Enable driver model for fuzzing engine devices. This interface is
 	  used to get fuzzing inputs from a fuzzing engine.
+
+if DM_FUZZING_ENGINE
+
+config FUZZING_ENGINE_SANDBOX
+	bool "Sanbox fuzzing engine"
+	depends on SANDBOX
+	default y
+	help
+	  Enable fuzzing engine for sandbox.
+
+endif
diff --git a/drivers/fuzzing_engine/Makefile b/drivers/fuzzing_engine/Makefile
index acd894999c..073743ba94 100644
--- a/drivers/fuzzing_engine/Makefile
+++ b/drivers/fuzzing_engine/Makefile
@@ -5,3 +5,4 @@
 #
 
 obj-$(CONFIG_DM_FUZZING_ENGINE) += fuzzing_engine-uclass.o
+obj-$(CONFIG_FUZZING_ENGINE_SANDBOX) += sandbox_fuzzing_engine.o
diff --git a/drivers/fuzzing_engine/sandbox_fuzzing_engine.c b/drivers/fuzzing_engine/sandbox_fuzzing_engine.c
new file mode 100644
index 0000000000..4d187deaa4
--- /dev/null
+++ b/drivers/fuzzing_engine/sandbox_fuzzing_engine.c
@@ -0,0 +1,35 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * Copyright (c) 2022 Google, Inc.
+ * Written by Andrew Scull <ascull@google.com>
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <fuzzing_engine.h>
+#include <asm/fuzzing_engine.h>
+
+static int get_input(struct udevice *dev,
+		     const uint8_t **data,
+		     size_t *size)
+{
+	return sandbox_fuzzing_engine_get_input(data, size);
+}
+
+static const struct dm_fuzzing_engine_ops sandbox_fuzzing_engine_ops = {
+	.get_input = get_input,
+};
+
+static const struct udevice_id sandbox_fuzzing_engine_match[] = {
+	{
+		.compatible = "sandbox,sandbox-fuzzing-engine",
+	},
+	{},
+};
+
+U_BOOT_DRIVER(sandbox_fuzzing_engine) = {
+	.name = "sandbox-fuzzing-engine",
+	.id = UCLASS_FUZZING_ENGINE,
+	.of_match = sandbox_fuzzing_engine_match,
+	.ops = &sandbox_fuzzing_engine_ops,
+};
-- 
2.35.1.1094.g7c7d902a7c-goog


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

* [PATCH 10/11] fuzz: virtio: Add fuzzer for vring
  2022-04-07  9:41 [PATCH 00/11] Fuzzing and ASAN for sandbox Andrew Scull
                   ` (8 preceding siblings ...)
  2022-04-07  9:41 ` [PATCH 09/11] sandbox: Implement fuzzing engine driver Andrew Scull
@ 2022-04-07  9:41 ` Andrew Scull
  2022-04-11 18:35   ` Simon Glass
  2022-04-07  9:41 ` [PATCH 11/11] RFC: Hack dlmalloc to poison memory Andrew Scull
  10 siblings, 1 reply; 30+ messages in thread
From: Andrew Scull @ 2022-04-07  9:41 UTC (permalink / raw)
  To: u-boot; +Cc: sjg, seanga2, Andrew Scull

Add a fuzzer to test the vring handling code against unexpected
mutations from the virtio device.

After building the sandbox with CONFIG_FUZZ=y, the fuzzer can be invoked
with by:

   UBOOT_SB_FUZZ_TEST=fuzz_vring ./u-boot

This fuzzer finds unvalidated inputs in the vring driver that allow a
buggy or malicious device to make the driver chase wild pointers.

Signed-off-by: Andrew Scull <ascull@google.com>
---
 test/fuzz/Makefile |  1 +
 test/fuzz/virtio.c | 72 ++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 73 insertions(+)
 create mode 100644 test/fuzz/virtio.c

diff --git a/test/fuzz/Makefile b/test/fuzz/Makefile
index 03eeeeb497..663b79ce80 100644
--- a/test/fuzz/Makefile
+++ b/test/fuzz/Makefile
@@ -5,3 +5,4 @@
 #
 
 obj-$(CONFIG_$(SPL_)CMDLINE) += cmd_fuzz.o
+obj-$(CONFIG_VIRTIO_SANDBOX) += virtio.o
diff --git a/test/fuzz/virtio.c b/test/fuzz/virtio.c
new file mode 100644
index 0000000000..e5363d5638
--- /dev/null
+++ b/test/fuzz/virtio.c
@@ -0,0 +1,72 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * Copyright (c) 2022 Google, Inc.
+ * Written by Andrew Scull <ascull@google.com>
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <virtio.h>
+#include <virtio_ring.h>
+#include <test/fuzz.h>
+
+static int fuzz_vring(const uint8_t *data, size_t size)
+{
+	struct udevice *bus, *dev;
+	struct virtio_dev_priv *uc_priv;
+	struct virtqueue *vq;
+	struct virtio_sg sg[2];
+	struct virtio_sg *sgs[2];
+	unsigned int len;
+	u8 buffer[2][32];
+
+	/* hackily hardcode vring sizes */
+	size_t num = 4;
+	size_t desc_size = (sizeof(struct vring_desc) * num);
+	size_t avail_size = (3 + num) * sizeof(u16);
+	size_t used_size = (3 * sizeof(u16)) + (sizeof(struct vring_used_elem) * num);
+
+	if (size < (desc_size + avail_size + used_size))
+		return 0;
+
+	/* check probe success */
+	if (uclass_first_device(UCLASS_VIRTIO, &bus) || !bus)
+		panic("Could not find virtio bus\n");
+
+	/* check the child virtio-rng device is bound */
+	if (device_find_first_child(bus, &dev) || !dev)
+		panic("Could not find virtio device\n");
+
+	/*
+	 * fake the virtio device probe by filling in uc_priv->vdev
+	 * which is used by virtio_find_vqs/virtio_del_vqs.
+	 */
+	uc_priv = dev_get_uclass_priv(bus);
+	uc_priv->vdev = dev;
+
+	/* prepare the scatter-gather buffer */
+	sg[0].addr = buffer[0];
+	sg[0].length = sizeof(buffer[0]);
+	sg[1].addr = buffer[1];
+	sg[1].length = sizeof(buffer[1]);
+	sgs[0] = &sg[0];
+	sgs[1] = &sg[1];
+
+	if (virtio_find_vqs(dev, 1, &vq))
+		panic("Could not find vqs\n");
+	if (virtqueue_add(vq, sgs, 0, 1))
+		panic("Could not add to virtqueue\n");
+	/* Simulate device writing to vring */
+	memcpy(vq->vring.desc, data, desc_size);
+	memcpy(vq->vring.avail, data + desc_size, avail_size);
+	memcpy(vq->vring.used, data + desc_size + avail_size, used_size);
+	/* Make sure there is a response */
+	if (vq->vring.used->idx == 0)
+		vq->vring.used->idx = 1;
+	virtqueue_get_buf(vq, &len);
+	if (virtio_del_vqs(dev))
+		panic("Could not delete vqs\n");
+
+	return 0;
+}
+FUZZ_TEST(fuzz_vring, 0);
-- 
2.35.1.1094.g7c7d902a7c-goog


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

* [PATCH 11/11] RFC: Hack dlmalloc to poison memory
  2022-04-07  9:41 [PATCH 00/11] Fuzzing and ASAN for sandbox Andrew Scull
                   ` (9 preceding siblings ...)
  2022-04-07  9:41 ` [PATCH 10/11] fuzz: virtio: Add fuzzer for vring Andrew Scull
@ 2022-04-07  9:41 ` Andrew Scull
  2022-04-11 18:35   ` Simon Glass
  10 siblings, 1 reply; 30+ messages in thread
From: Andrew Scull @ 2022-04-07  9:41 UTC (permalink / raw)
  To: u-boot; +Cc: sjg, seanga2, Andrew Scull

This is a hugely ugly hack to poison and unpoison memory allocated by
dlmalloc. It wraps every access dlmalloc makes to the metadata breifly
allow it access, taking care not to then poison the parts of the record
which overlap.

The result is very small redzones between the allocations, which has
limted value but has able to spot immediate buffer overruns.

The instrumentation is extremely intrusive and would be benefited by
more intrusions to increase redzone sizes etc.

Signed-off-by: Andrew Scull <ascull@google.com>
---
 common/dlmalloc.c     | 284 ++++++++++++++++++++++++++++++++++++------
 include/compiler.h    |   1 +
 include/linux/types.h |   1 +
 3 files changed, 245 insertions(+), 41 deletions(-)

diff --git a/common/dlmalloc.c b/common/dlmalloc.c
index 11729e8c85..614f004579 100644
--- a/common/dlmalloc.c
+++ b/common/dlmalloc.c
@@ -8,6 +8,8 @@
  * as file malloc-2.6.6.c.
  */
 
+#define DEBUG
+
 #include <common.h>
 #include <log.h>
 #include <asm/global_data.h>
@@ -16,6 +18,8 @@
 #define DEBUG
 #endif
 
+#include <sanitizer/asan_interface.h>
+
 #include <malloc.h>
 #include <asm/io.h>
 
@@ -31,6 +35,17 @@ void malloc_stats();
 
 DECLARE_GLOBAL_DATA_PTR;
 
+/*
+#undef ASAN_POISON_MEMORY_REGION
+#define ASAN_POISON_MEMORY_REGION(p, s) do { \
+    if ((uintptr_t)p == 0x0000150200c0) { \
+        printf("size %lx\n", s); \
+        *(int*)NULL = 9; \
+    } \
+    __asan_poison_memory_region(p, s); \
+} while (0)
+*/
+
 /*
   Emulation of sbrk for WIN32
   All code within the ifdef WIN32 is untested by me.
@@ -409,12 +424,26 @@ nextchunk-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 
 /* Ptr to next physical malloc_chunk. */
 
-#define next_chunk(p) ((mchunkptr)( ((char*)(p)) + ((p)->size & ~PREV_INUSE) ))
+#define _next_chunk(p) ((mchunkptr)( ((char*)(p)) + ((p)->size & ~PREV_INUSE) ))
+#define next_chunk(p) ({ \
+        mchunkptr _ptr = (p); \
+        ASAN_UNPOISON_MEMORY_REGION(((char*)_ptr) + SIZE_SZ, SIZE_SZ); \
+        mchunkptr _ret = _next_chunk(_ptr); \
+        ASAN_POISON_MEMORY_REGION(((char*)_ptr) + SIZE_SZ, SIZE_SZ); \
+        _ret; \
+        })
 
 /* Ptr to previous physical malloc_chunk */
 
-#define prev_chunk(p)\
+#define _prev_chunk(p)\
    ((mchunkptr)( ((char*)(p)) - ((p)->prev_size) ))
+#define prev_chunk(p) ({ \
+        mchunkptr _ptr = (p); \
+        ASAN_UNPOISON_MEMORY_REGION(_ptr, SIZE_SZ); \
+        mchunkptr _ret = _prev_chunk(_ptr); \
+        ASAN_POISON_MEMORY_REGION(_ptr, SIZE_SZ); \
+        _ret; \
+        })
 
 
 /* Treat space at ptr + offset as a chunk */
@@ -430,35 +459,102 @@ nextchunk-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 
 /* extract p's inuse bit */
 
-#define inuse(p)\
+#define _inuse(p)\
 ((((mchunkptr)(((char*)(p))+((p)->size & ~PREV_INUSE)))->size) & PREV_INUSE)
+#define inuse(p) ({ \
+        mchunkptr _p = (p); \
+        ASAN_UNPOISON_MEMORY_REGION(((char*)_p) + SIZE_SZ, SIZE_SZ); \
+        mchunkptr _ptr = ((mchunkptr)(((char*)_p)+(_p->size & ~PREV_INUSE))); \
+        ASAN_UNPOISON_MEMORY_REGION(((char*)_ptr) + SIZE_SZ, SIZE_SZ); \
+        INTERNAL_SIZE_T _ret = _inuse(_p); \
+        ASAN_POISON_MEMORY_REGION(((char*)_ptr) + SIZE_SZ, SIZE_SZ); \
+        ASAN_POISON_MEMORY_REGION(((char*)_p) + SIZE_SZ, SIZE_SZ); \
+        _ret; \
+        })
 
 /* extract inuse bit of previous chunk */
 
-#define prev_inuse(p)  ((p)->size & PREV_INUSE)
+#define _prev_inuse(p)  ((p)->size & PREV_INUSE)
+#define prev_inuse(p) ({ \
+        mchunkptr _ptr = (p); \
+        ASAN_UNPOISON_MEMORY_REGION(((char*)_ptr) + SIZE_SZ, SIZE_SZ); \
+        INTERNAL_SIZE_T _ret = _prev_inuse(_ptr); \
+        ASAN_POISON_MEMORY_REGION(((char*)_ptr) + SIZE_SZ, SIZE_SZ); \
+        _ret; \
+        })
 
 /* check for mmap()'ed chunk */
 
-#define chunk_is_mmapped(p) ((p)->size & IS_MMAPPED)
+#define _chunk_is_mmapped(p) ((p)->size & IS_MMAPPED)
+#define chunk_is_mmapped(p) ({ \
+        mchunkptr _ptr = (p); \
+        ASAN_UNPOISON_MEMORY_REGION(((char*)_ptr) + SIZE_SZ, SIZE_SZ); \
+        INTERNAL_SIZE_T _ret = _chunk_is_mmapped(_ptr); \
+        ASAN_POISON_MEMORY_REGION(((char*)_ptr) + SIZE_SZ, SIZE_SZ); \
+        _ret; \
+        })
 
 /* set/clear chunk as in use without otherwise disturbing */
 
-#define set_inuse(p)\
+#define _set_inuse(p)\
 ((mchunkptr)(((char*)(p)) + ((p)->size & ~PREV_INUSE)))->size |= PREV_INUSE
-
-#define clear_inuse(p)\
+#define set_inuse(p, s) ({ \
+        mchunkptr _p = (p); \
+        ASAN_UNPOISON_MEMORY_REGION(((char*)_p) + SIZE_SZ, SIZE_SZ); \
+        mchunkptr _ptr = ((mchunkptr)(((char*)_p)+(_p->size & ~PREV_INUSE))); \
+        ASAN_UNPOISON_MEMORY_REGION(((char*)_ptr) + SIZE_SZ, SIZE_SZ); \
+        _set_inuse(_p, (s)); \
+        ASAN_POISON_MEMORY_REGION(((char*)_ptr) + SIZE_SZ, SIZE_SZ); \
+        ASAN_POISON_MEMORY_REGION(((char*)_p) + SIZE_SZ, SIZE_SZ); \
+        })
+
+#define _clear_inuse(p)\
 ((mchunkptr)(((char*)(p)) + ((p)->size & ~PREV_INUSE)))->size &= ~(PREV_INUSE)
+#define clear_inuse(p, s) ({ \
+        __typeof__(p) _p = (p); \
+        ASAN_UNPOISON_MEMORY_REGION(((char*)_p) + SIZE_SZ, SIZE_SZ); \
+        mchunkptr _ptr = ((mchunkptr)(((char*)_p)+(_p->size & ~PREV_INUSE))); \
+        ASAN_UNPOISON_MEMORY_REGION(((char*)_ptr) + SIZE_SZ, SIZE_SZ); \
+        _clear_inuse(_p, (s)); \
+        ASAN_POISON_MEMORY_REGION(((char*)_ptr) + SIZE_SZ, SIZE_SZ); \
+        ASAN_POISON_MEMORY_REGION(((char*)_p) + SIZE_SZ, SIZE_SZ); \
+        })
 
 /* check/set/clear inuse bits in known places */
 
-#define inuse_bit_at_offset(p, s)\
+#define _inuse_bit_at_offset(p, s)\
  (((mchunkptr)(((char*)(p)) + (s)))->size & PREV_INUSE)
-
-#define set_inuse_bit_at_offset(p, s)\
+#define inuse_bit_at_offset(p, s) ({ \
+        __typeof__(p) _p = (p); \
+        __typeof__(s) _s = (s); \
+        __typeof__(p) _ptr = (mchunkptr)(((char*)_p) + _s); \
+        ASAN_UNPOISON_MEMORY_REGION(((char*)_ptr) + SIZE_SZ, SIZE_SZ); \
+        INTERNAL_SIZE_T _ret = _inuse_bit_at_offset(_p, _s); \
+        ASAN_POISON_MEMORY_REGION(((char*)_ptr) + SIZE_SZ, SIZE_SZ); \
+        _ret; \
+        })
+
+#define _set_inuse_bit_at_offset(p, s)\
  (((mchunkptr)(((char*)(p)) + (s)))->size |= PREV_INUSE)
-
-#define clear_inuse_bit_at_offset(p, s)\
+#define set_inuse_bit_at_offset(p, s) ({ \
+        __typeof__(p) _p = (p); \
+        __typeof__(s) _s = (s); \
+        __typeof__(p) _ptr = (mchunkptr)(((char*)_p) + _s); \
+        ASAN_UNPOISON_MEMORY_REGION(((char*)_ptr) + SIZE_SZ, SIZE_SZ); \
+        _set_inuse_bit_at_offset(_p, _s); \
+        ASAN_POISON_MEMORY_REGION(((char*)_ptr) + SIZE_SZ, SIZE_SZ); \
+        })
+
+#define _clear_inuse_bit_at_offset(p, s)\
  (((mchunkptr)(((char*)(p)) + (s)))->size &= ~(PREV_INUSE))
+#define clear_inuse_bit_at_offset(p, s) ({ \
+        __typeof__(p) _p = (p); \
+        __typeof__(s) _s = (s); \
+        __typeof__(p) _ptr = (mchunkptr)(((char*)_p) + _s); \
+        ASAN_UNPOISON_MEMORY_REGION(((char*)_ptr) + SIZE_SZ, SIZE_SZ); \
+        _clear_inuse_bit_at_offset(_p, _s); \
+        ASAN_POISON_MEMORY_REGION(((char*)_ptr) + SIZE_SZ, SIZE_SZ); \
+        })
 
 
 
@@ -469,19 +565,46 @@ nextchunk-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 
 /* Get size, ignoring use bits */
 
-#define chunksize(p)          ((p)->size & ~(SIZE_BITS))
+#define _chunksize(p)          ((p)->size & ~(SIZE_BITS))
+#define chunksize(p) ({ \
+        mchunkptr _ptr = (p); \
+        ASAN_UNPOISON_MEMORY_REGION(((char*)_ptr) + SIZE_SZ, SIZE_SZ); \
+        INTERNAL_SIZE_T _ret = _chunksize(_ptr); \
+        ASAN_POISON_MEMORY_REGION(((char*)_ptr) + SIZE_SZ, SIZE_SZ); \
+        _ret; \
+        })
 
 /* Set size at head, without disturbing its use bit */
 
-#define set_head_size(p, s)   ((p)->size = (((p)->size & PREV_INUSE) | (s)))
+#define _set_head_size(p, s)   ((p)->size = (((p)->size & PREV_INUSE) | (s)))
+#define set_head_size(p, s) ({ \
+        __typeof__(p) _ptr = (p); \
+        ASAN_UNPOISON_MEMORY_REGION(((char*)_ptr) + SIZE_SZ, SIZE_SZ); \
+        _set_head_size(_ptr, (s)); \
+        ASAN_POISON_MEMORY_REGION(((char*)_ptr) + SIZE_SZ, SIZE_SZ); \
+        })
 
 /* Set size/use ignoring previous bits in header */
 
-#define set_head(p, s)        ((p)->size = (s))
+#define _set_head(p, s)        ((p)->size = (s))
+#define set_head(p, s) ({ \
+        __typeof__(p) _ptr = (p); \
+        ASAN_UNPOISON_MEMORY_REGION(((char*)_ptr) + SIZE_SZ, SIZE_SZ); \
+        _set_head(_ptr, (s)); \
+        ASAN_POISON_MEMORY_REGION(((char*)_ptr) + SIZE_SZ, SIZE_SZ); \
+        })
 
 /* Set size at footer (only when chunk is not in use) */
 
-#define set_foot(p, s)   (((mchunkptr)((char*)(p) + (s)))->prev_size = (s))
+#define _set_foot(p, s)   (((mchunkptr)((char*)(p) + (s)))->prev_size = (s))
+#define set_foot(p, s) ({ \
+        __typeof__(p) _p = (p); \
+        __typeof__(s) _s = (s); \
+        __typeof__(p) _ptr = (mchunkptr)(((char*)_p) + _s); \
+        ASAN_UNPOISON_MEMORY_REGION(_ptr, SIZE_SZ); \
+        _set_foot(_p, (s)); \
+        ASAN_POISON_MEMORY_REGION(_ptr, SIZE_SZ); \
+        })
 
 
 
@@ -604,8 +727,11 @@ void *sbrk(ptrdiff_t increment)
 	 * if we are giving memory back make sure we clear it out since
 	 * we set MORECORE_CLEARS to 1
 	 */
-	if (increment < 0)
+	if (increment < 0) {
+                ASAN_UNPOISON_MEMORY_REGION((void *)new, -increment);
 		memset((void *)new, 0, -increment);
+                ASAN_POISON_MEMORY_REGION((void *)new, -increment);
+        }
 
 	if ((new < mem_malloc_start) || (new > mem_malloc_end))
 		return (void *)MORECORE_FAILURE;
@@ -630,13 +756,24 @@ void mem_malloc_init(ulong start, ulong size)
 #ifdef CONFIG_SYS_MALLOC_CLEAR_ON_INIT
 	memset((void *)mem_malloc_start, 0x0, size);
 #endif
+        ASAN_POISON_MEMORY_REGION((void *)start, size);
 	malloc_bin_reloc();
 }
 
 /* field-extraction macros */
 
-#define first(b) ((b)->fd)
-#define last(b)  ((b)->bk)
+#define first(b) ({ \
+        ASAN_UNPOISON_MEMORY_REGION(((char*)b) + 2*SIZE_SZ, 2*sizeof(uintptr_t)); \
+        void *_ret = (b)->fd; \
+        ASAN_UNPOISON_MEMORY_REGION(((char*)b) + 2*SIZE_SZ, 2*sizeof(uintptr_t)); \
+        _ret; \
+        })
+#define last(b)  ({ \
+        ASAN_UNPOISON_MEMORY_REGION(((char*)b) + 2*SIZE_SZ, 2*sizeof(uintptr_t)); \
+        void *_ret = (b)->bk; \
+        ASAN_UNPOISON_MEMORY_REGION(((char*)b) + 2*SIZE_SZ, 2*sizeof(uintptr_t)); \
+        _ret; \
+        })
 
 /*
   Indexing into bins
@@ -781,7 +918,7 @@ static void do_check_chunk(mchunkptr p)
 static void do_check_chunk(p) mchunkptr p;
 #endif
 {
-  INTERNAL_SIZE_T sz = p->size & ~PREV_INUSE;
+  INTERNAL_SIZE_T sz = chunksize(p);
 
   /* No checkable chunk is mmapped */
   assert(!chunk_is_mmapped(p));
@@ -802,7 +939,7 @@ static void do_check_free_chunk(mchunkptr p)
 static void do_check_free_chunk(p) mchunkptr p;
 #endif
 {
-  INTERNAL_SIZE_T sz = p->size & ~PREV_INUSE;
+  INTERNAL_SIZE_T sz = chunksize(p);
   mchunkptr next = chunk_at_offset(p, sz);
 
   do_check_chunk(p);
@@ -816,14 +953,22 @@ static void do_check_free_chunk(p) mchunkptr p;
     assert((sz & MALLOC_ALIGN_MASK) == 0);
     assert(aligned_OK(chunk2mem(p)));
     /* ... matching footer field */
+    ASAN_UNPOISON_MEMORY_REGION(next, SIZE_SZ);
     assert(next->prev_size == sz);
+    ASAN_POISON_MEMORY_REGION(next, SIZE_SZ);
     /* ... and is fully consolidated */
     assert(prev_inuse(p));
     assert (next == top || inuse(next));
 
     /* ... and has minimally sane links */
+    ASAN_UNPOISON_MEMORY_REGION(((char*)p) + 2*SIZE_SZ, 2*sizeof(uintptr_t));
+    ASAN_UNPOISON_MEMORY_REGION(((char*)p->fd) + 2*SIZE_SZ, 2*sizeof(uintptr_t));
+    ASAN_UNPOISON_MEMORY_REGION(((char*)p->bk) + 2*SIZE_SZ, 2*sizeof(uintptr_t));
     assert(p->fd->bk == p);
     assert(p->bk->fd == p);
+    ASAN_POISON_MEMORY_REGION(((char*)p->fd) + 2*SIZE_SZ, 2*sizeof(uintptr_t));
+    ASAN_POISON_MEMORY_REGION(((char*)p->bk) + 2*SIZE_SZ, 2*sizeof(uintptr_t));
+    ASAN_POISON_MEMORY_REGION(((char*)p) + 2*SIZE_SZ, 2*sizeof(uintptr_t));
   }
   else /* markers are always of size SIZE_SZ */
     assert(sz == SIZE_SZ);
@@ -867,7 +1012,7 @@ static void do_check_malloced_chunk(mchunkptr p, INTERNAL_SIZE_T s)
 static void do_check_malloced_chunk(p, s) mchunkptr p; INTERNAL_SIZE_T s;
 #endif
 {
-  INTERNAL_SIZE_T sz = p->size & ~PREV_INUSE;
+  INTERNAL_SIZE_T sz = chunksize(p);
   long room = sz - s;
 
   do_check_inuse_chunk(p);
@@ -919,31 +1064,48 @@ static void do_check_malloced_chunk(p, s) mchunkptr p; INTERNAL_SIZE_T s;
 
 #define frontlink(P, S, IDX, BK, FD)                                          \
 {                                                                             \
+  ASAN_UNPOISON_MEMORY_REGION(((char*)P) + 2*SIZE_SZ, 2*sizeof(uintptr_t));                                 \
   if (S < MAX_SMALLBIN_SIZE)                                                  \
   {                                                                           \
     IDX = smallbin_index(S);                                                  \
     mark_binblock(IDX);                                                       \
     BK = bin_at(IDX);                                                         \
+  ASAN_UNPOISON_MEMORY_REGION(((char*)BK) + 2*SIZE_SZ, 2*sizeof(uintptr_t));                                 \
     FD = BK->fd;                                                              \
     P->bk = BK;                                                               \
     P->fd = FD;                                                               \
+  ASAN_UNPOISON_MEMORY_REGION(((char*)FD) + 2*SIZE_SZ, 2*sizeof(uintptr_t));                                 \
     FD->bk = BK->fd = P;                                                      \
   }                                                                           \
   else                                                                        \
   {                                                                           \
     IDX = bin_index(S);                                                       \
     BK = bin_at(IDX);                                                         \
+  ASAN_UNPOISON_MEMORY_REGION(((char*)BK) + 2*SIZE_SZ, 2*sizeof(uintptr_t));                                 \
     FD = BK->fd;                                                              \
+  ASAN_UNPOISON_MEMORY_REGION(((char*)FD) + 2*SIZE_SZ, 2*sizeof(uintptr_t));                                 \
     if (FD == BK) mark_binblock(IDX);                                         \
     else                                                                      \
     {                                                                         \
-      while (FD != BK && S < chunksize(FD)) FD = FD->fd;                      \
+      while (FD != BK && S < chunksize(FD)) { \
+          mchunkptr old = FD; \
+          FD = FD->fd;                      \
+        ASAN_POISON_MEMORY_REGION(((char*)old) + 2*SIZE_SZ, 2*sizeof(uintptr_t));                                 \
+        ASAN_UNPOISON_MEMORY_REGION(((char*)FD) + 2*SIZE_SZ, 2*sizeof(uintptr_t));                                 \
+      } \
+      mchunkptr oldbk = BK; \
       BK = FD->bk;                                                            \
+  ASAN_POISON_MEMORY_REGION(((char*)oldbk) + 2*SIZE_SZ, 2*sizeof(uintptr_t));                                 \
+  ASAN_UNPOISON_MEMORY_REGION(((char*)BK) + 2*SIZE_SZ, 2*sizeof(uintptr_t));                                 \
+        ASAN_UNPOISON_MEMORY_REGION(((char*)FD) + 2*SIZE_SZ, 2*sizeof(uintptr_t));                                 \
     }                                                                         \
     P->bk = BK;                                                               \
     P->fd = FD;                                                               \
     FD->bk = BK->fd = P;                                                      \
   }                                                                           \
+  ASAN_POISON_MEMORY_REGION(((char*)P) + 2*SIZE_SZ, 2*sizeof(uintptr_t));                                 \
+  ASAN_POISON_MEMORY_REGION(((char*)BK) + 2*SIZE_SZ, 2*sizeof(uintptr_t));                                 \
+  ASAN_POISON_MEMORY_REGION(((char*)FD) + 2*SIZE_SZ, 2*sizeof(uintptr_t));                                 \
 }
 
 
@@ -951,18 +1113,26 @@ static void do_check_malloced_chunk(p, s) mchunkptr p; INTERNAL_SIZE_T s;
 
 #define unlink(P, BK, FD)                                                     \
 {                                                                             \
+  ASAN_UNPOISON_MEMORY_REGION(((char*)P) + 2*SIZE_SZ, 2*sizeof(uintptr_t));                                 \
   BK = P->bk;                                                                 \
   FD = P->fd;                                                                 \
+  ASAN_POISON_MEMORY_REGION(((char*)P) + 2*SIZE_SZ, 2*sizeof(uintptr_t));                                 \
+  ASAN_UNPOISON_MEMORY_REGION(((char*)BK) + 2*SIZE_SZ, 2*sizeof(uintptr_t));                                 \
+  ASAN_UNPOISON_MEMORY_REGION(((char*)FD) + 2*SIZE_SZ, 2*sizeof(uintptr_t));                                 \
   FD->bk = BK;                                                                \
   BK->fd = FD;                                                                \
+  ASAN_POISON_MEMORY_REGION(((char*)BK) + 2*SIZE_SZ, 2*sizeof(uintptr_t));                                 \
+  ASAN_POISON_MEMORY_REGION(((char*)FD) + 2*SIZE_SZ, 2*sizeof(uintptr_t));                                 \
 }                                                                             \
 
 /* Place p as the last remainder */
 
 #define link_last_remainder(P)                                                \
 {                                                                             \
+  ASAN_UNPOISON_MEMORY_REGION(((char*)P) + 2*SIZE_SZ, 2*sizeof(uintptr_t));                                 \
   last_remainder->fd = last_remainder->bk =  P;                               \
   P->fd = P->bk = last_remainder;                                             \
+  ASAN_POISON_MEMORY_REGION(((char*)P) + 2*SIZE_SZ, 2*sizeof(uintptr_t));                                 \
 }
 
 /* Clear the last_remainder bin */
@@ -1280,6 +1450,14 @@ static void malloc_extend_top(nb) INTERNAL_SIZE_T nb;
 
 */
 
+#define publish_mem(p) ({ \
+        __typeof__(p) _chunk = (p); \
+        Void_t *_ret = chunk2mem(_chunk); \
+        INTERNAL_SIZE_T _size = malloc_usable_size(_ret); \
+        ASAN_UNPOISON_MEMORY_REGION(_ret, _size); \
+        _ret; \
+        })
+
 #if __STD_C
 Void_t* mALLOc(size_t bytes)
 #else
@@ -1339,7 +1517,7 @@ Void_t* mALLOc(bytes) size_t bytes;
       unlink(victim, bck, fwd);
       set_inuse_bit_at_offset(victim, victim_size);
       check_malloced_chunk(victim, nb);
-      return chunk2mem(victim);
+      return publish_mem(victim);
     }
 
     idx += 2; /* Set for bin scan below. We've already scanned 2 bins. */
@@ -1350,7 +1528,11 @@ Void_t* mALLOc(bytes) size_t bytes;
     idx = bin_index(nb);
     bin = bin_at(idx);
 
-    for (victim = last(bin); victim != bin; victim = victim->bk)
+    for (victim = last(bin); victim != bin;
+            ASAN_UNPOISON_MEMORY_REGION((char*)victim + 2*SIZE_SZ, 2*sizeof(uintptr_t)),
+            victim = victim->bk,
+            ASAN_POISON_MEMORY_REGION((char*)victim + 2*SIZE_SZ, 2*sizeof(uintptr_t))
+            )
     {
       victim_size = chunksize(victim);
       remainder_size = victim_size - nb;
@@ -1366,7 +1548,7 @@ Void_t* mALLOc(bytes) size_t bytes;
 	unlink(victim, bck, fwd);
 	set_inuse_bit_at_offset(victim, victim_size);
 	check_malloced_chunk(victim, nb);
-	return chunk2mem(victim);
+	return publish_mem(victim);
       }
     }
 
@@ -1389,7 +1571,7 @@ Void_t* mALLOc(bytes) size_t bytes;
       set_head(remainder, remainder_size | PREV_INUSE);
       set_foot(remainder, remainder_size);
       check_malloced_chunk(victim, nb);
-      return chunk2mem(victim);
+      return publish_mem(victim);
     }
 
     clear_last_remainder;
@@ -1398,7 +1580,7 @@ Void_t* mALLOc(bytes) size_t bytes;
     {
       set_inuse_bit_at_offset(victim, victim_size);
       check_malloced_chunk(victim, nb);
-      return chunk2mem(victim);
+      return publish_mem(victim);
     }
 
     /* Else place in bin */
@@ -1439,7 +1621,11 @@ Void_t* mALLOc(bytes) size_t bytes;
       {
 	/* Find and use first big enough chunk ... */
 
-	for (victim = last(bin); victim != bin; victim = victim->bk)
+	for (victim = last(bin); victim != bin; 
+                ASAN_UNPOISON_MEMORY_REGION((char*)victim + 2*SIZE_SZ, 2*sizeof(uintptr_t)),
+                victim = victim->bk,
+                ASAN_POISON_MEMORY_REGION((char*)victim + 2*SIZE_SZ, 2*sizeof(uintptr_t))
+                )
 	{
 	  victim_size = chunksize(victim);
 	  remainder_size = victim_size - nb;
@@ -1453,7 +1639,7 @@ Void_t* mALLOc(bytes) size_t bytes;
 	    set_head(remainder, remainder_size | PREV_INUSE);
 	    set_foot(remainder, remainder_size);
 	    check_malloced_chunk(victim, nb);
-	    return chunk2mem(victim);
+	    return publish_mem(victim);
 	  }
 
 	  else if (remainder_size >= 0)  /* take */
@@ -1461,7 +1647,7 @@ Void_t* mALLOc(bytes) size_t bytes;
 	    set_inuse_bit_at_offset(victim, victim_size);
 	    unlink(victim, bck, fwd);
 	    check_malloced_chunk(victim, nb);
-	    return chunk2mem(victim);
+	    return publish_mem(victim);
 	  }
 
 	}
@@ -1509,7 +1695,7 @@ Void_t* mALLOc(bytes) size_t bytes;
     /* If big and would otherwise need to extend, try to use mmap instead */
     if ((unsigned long)nb >= (unsigned long)mmap_threshold &&
 	(victim = mmap_chunk(nb)))
-      return chunk2mem(victim);
+      return publish_mem(victim);
 #endif
 
     /* Try to extend */
@@ -1523,7 +1709,8 @@ Void_t* mALLOc(bytes) size_t bytes;
   top = chunk_at_offset(victim, nb);
   set_head(top, remainder_size | PREV_INUSE);
   check_malloced_chunk(victim, nb);
-  return chunk2mem(victim);
+
+  return publish_mem(victim);
 
 }
 
@@ -1578,8 +1765,12 @@ void fREe(mem) Void_t* mem;
   if (mem == NULL)                              /* free(0) has no effect */
     return;
 
+  ASAN_POISON_MEMORY_REGION(mem, malloc_usable_size(mem));
+
   p = mem2chunk(mem);
+  ASAN_UNPOISON_MEMORY_REGION(((char*)p) + SIZE_SZ, SIZE_SZ);
   hd = p->size;
+  ASAN_POISON_MEMORY_REGION(((char*)p) + SIZE_SZ, SIZE_SZ);
 
 #if HAVE_MMAP
   if (hd & IS_MMAPPED)                       /* release mmapped memory. */
@@ -1601,7 +1792,9 @@ void fREe(mem) Void_t* mem;
 
     if (!(hd & PREV_INUSE))                    /* consolidate backward */
     {
+      ASAN_UNPOISON_MEMORY_REGION(((char*)p), SIZE_SZ);
       prevsz = p->prev_size;
+      ASAN_POISON_MEMORY_REGION(((char*)p), SIZE_SZ);
       p = chunk_at_offset(p, -((long) prevsz));
       sz += prevsz;
       unlink(p, bck, fwd);
@@ -1620,20 +1813,25 @@ void fREe(mem) Void_t* mem;
 
   if (!(hd & PREV_INUSE))                    /* consolidate backward */
   {
+    ASAN_UNPOISON_MEMORY_REGION(p, SIZE_SZ);
     prevsz = p->prev_size;
+    ASAN_POISON_MEMORY_REGION(p, SIZE_SZ);
     p = chunk_at_offset(p, -((long) prevsz));
     sz += prevsz;
 
+    ASAN_UNPOISON_MEMORY_REGION((char*)p + 2*SIZE_SZ, 2*sizeof(uintptr_t));
     if (p->fd == last_remainder)             /* keep as last_remainder */
       islr = 1;
     else
       unlink(p, bck, fwd);
+    ASAN_POISON_MEMORY_REGION((char*)p + 2*SIZE_SZ, 2*sizeof(uintptr_t));
   }
 
   if (!(inuse_bit_at_offset(next, nextsz)))   /* consolidate forward */
   {
     sz += nextsz;
 
+    ASAN_UNPOISON_MEMORY_REGION((char*)next + 2*SIZE_SZ, 2*sizeof(uintptr_t));
     if (!islr && next->fd == last_remainder)  /* re-insert last_remainder */
     {
       islr = 1;
@@ -1641,6 +1839,7 @@ void fREe(mem) Void_t* mem;
     }
     else
       unlink(next, bck, fwd);
+    ASAN_POISON_MEMORY_REGION((char*)next + 2*SIZE_SZ, 2*sizeof(uintptr_t));
   }
 
 
@@ -1747,7 +1946,7 @@ Void_t* rEALLOc(oldmem, bytes) Void_t* oldmem; size_t bytes;
   {
 #if HAVE_MREMAP
     newp = mremap_chunk(oldp, nb);
-    if(newp) return chunk2mem(newp);
+    if(newp) return publish_mem(newp);
 #endif
     /* Note the extra SIZE_SZ overhead. */
     if(oldsize - SIZE_SZ >= nb) return oldmem; /* do nothing */
@@ -1782,7 +1981,7 @@ Void_t* rEALLOc(oldmem, bytes) Void_t* oldmem; size_t bytes;
 	  top = chunk_at_offset(oldp, nb);
 	  set_head(top, (newsize - nb) | PREV_INUSE);
 	  set_head_size(oldp, nb);
-	  return chunk2mem(oldp);
+	  return publish_mem(oldp);
 	}
       }
 
@@ -1895,7 +2094,7 @@ Void_t* rEALLOc(oldmem, bytes) Void_t* oldmem; size_t bytes;
   }
 
   check_inuse_chunk(newp);
-  return chunk2mem(newp);
+  return publish_mem(newp);
 }
 
 
@@ -2006,7 +2205,7 @@ Void_t* mEMALIGn(alignment, bytes) size_t alignment; size_t bytes;
   {
 #if HAVE_MMAP
     if(chunk_is_mmapped(p))
-      return chunk2mem(p); /* nothing more to do */
+      return publish_mem(p); /* nothing more to do */
 #endif
   }
   else /* misaligned */
@@ -2032,7 +2231,7 @@ Void_t* mEMALIGn(alignment, bytes) size_t alignment; size_t bytes;
     {
       newp->prev_size = p->prev_size + leadsize;
       set_head(newp, newsize|IS_MMAPPED);
-      return chunk2mem(newp);
+      return publish_mem(newp);
     }
 #endif
 
@@ -2060,7 +2259,7 @@ Void_t* mEMALIGn(alignment, bytes) size_t alignment; size_t bytes;
   }
 
   check_inuse_chunk(p);
-  return chunk2mem(p);
+  return publish_mem(p);
 
 }
 
@@ -2318,7 +2517,10 @@ static void malloc_update_mallinfo()
   for (i = 1; i < NAV; ++i)
   {
     b = bin_at(i);
-    for (p = last(b); p != b; p = p->bk)
+    for (p = last(b); p != b;
+            ASAN_UNPOISON_MEMORY_REGION((char*)p + 2*SIZE_SZ, 2*sizeof(uintptr_t)),
+            p = p->bk,
+            ASAN_POISON_MEMORY_REGION((char*)p + 2*SIZE_SZ, 2*sizeof(uintptr_t)))
     {
 #ifdef DEBUG
       check_free_chunk(p);
diff --git a/include/compiler.h b/include/compiler.h
index ef7b2cb1f7..7f7e82daf7 100644
--- a/include/compiler.h
+++ b/include/compiler.h
@@ -126,6 +126,7 @@ typedef __u32 u32;
 
 /* Type for `void *' pointers. */
 typedef unsigned long int uintptr_t;
+typedef long int intptr_t;
 
 #include <linux/string.h>
 #include <linux/types.h>
diff --git a/include/linux/types.h b/include/linux/types.h
index baa2c491ea..d86d2611c0 100644
--- a/include/linux/types.h
+++ b/include/linux/types.h
@@ -25,6 +25,7 @@ typedef __kernel_uid16_t        uid16_t;
 typedef __kernel_gid16_t        gid16_t;
 
 typedef unsigned long		uintptr_t;
+typedef long		        intptr_t;
 
 #ifdef CONFIG_UID16
 /* This is defined by include/asm-{arch}/posix_types.h */
-- 
2.35.1.1094.g7c7d902a7c-goog


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

* Re: [PATCH 01/11] sandbox: Set the EFI symbols in linker script
  2022-04-07  9:41 ` [PATCH 01/11] sandbox: Set the EFI symbols in linker script Andrew Scull
@ 2022-04-11 18:35   ` Simon Glass
  2022-04-11 22:15   ` Heinrich Schuchardt
  1 sibling, 0 replies; 30+ messages in thread
From: Simon Glass @ 2022-04-11 18:35 UTC (permalink / raw)
  To: Andrew Scull; +Cc: U-Boot Mailing List, Sean Anderson

Hi Andrew,

On Thu, 7 Apr 2022 at 03:41, Andrew Scull <ascull@google.com> wrote:
>
> The sandbox doesn't populate the EFI lists so explicitly set the list
> start and end symbols to indicate that the lists are empty. This
> simplifies the linker scripts, removed references to non-existant
> sections and removes '.' prefixed sections that conflicted with clang's
> ASAN.
>
> Signed-off-by: Andrew Scull <ascull@google.com>
> ---
>  arch/sandbox/cpu/u-boot.lds | 32 +++++---------------------------
>  arch/sandbox/lib/Makefile   |  2 +-
>  arch/sandbox/lib/sections.c | 13 -------------
>  3 files changed, 6 insertions(+), 41 deletions(-)
>  delete mode 100644 arch/sandbox/lib/sections.c

I guess this it OK but it does make sandbox different in the link
scripts. Would it be possible to change the naming to avoid the ASAN
thing (which I don't understand)?

Reviewed-by: Simon Glass <sjg@chromium.org>

Regards,
Simon

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

* Re: [PATCH 02/11] sandbox: Migrate getopt section to linker list
  2022-04-07  9:41 ` [PATCH 02/11] sandbox: Migrate getopt section to linker list Andrew Scull
@ 2022-04-11 18:35   ` Simon Glass
  0 siblings, 0 replies; 30+ messages in thread
From: Simon Glass @ 2022-04-11 18:35 UTC (permalink / raw)
  To: Andrew Scull; +Cc: U-Boot Mailing List, Sean Anderson

On Thu, 7 Apr 2022 at 03:41, Andrew Scull <ascull@google.com> wrote:
>
> Use the common infrastructure to create a linker list of the sandbox
> command line flags rather than using a custom method.
>
> The list is changed from containing pointers to containing structs and
> the uses are updated accordingly.
>
> Signed-off-by: Andrew Scull <ascull@google.com>
> ---
>  arch/sandbox/cpu/os.c               | 21 ++++++++++-----------
>  arch/sandbox/cpu/start.c            | 10 +++++-----
>  arch/sandbox/cpu/u-boot-spl.lds     |  6 ------
>  arch/sandbox/cpu/u-boot.lds         |  6 ------
>  arch/sandbox/include/asm/getopt.h   | 19 ++++++++++++-------
>  arch/sandbox/include/asm/sections.h | 25 -------------------------
>  6 files changed, 27 insertions(+), 60 deletions(-)

Reviewed-by: Simon Glass <sjg@chromium.org>

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

* Re: [PATCH 03/11] linker_lists: Rename sections to remove . prefix
  2022-04-07  9:41 ` [PATCH 03/11] linker_lists: Rename sections to remove . prefix Andrew Scull
@ 2022-04-11 18:35   ` Simon Glass
  0 siblings, 0 replies; 30+ messages in thread
From: Simon Glass @ 2022-04-11 18:35 UTC (permalink / raw)
  To: Andrew Scull; +Cc: U-Boot Mailing List, Sean Anderson

On Thu, 7 Apr 2022 at 03:41, Andrew Scull <ascull@google.com> wrote:
>
> Rename the sections used to implement linker lists so they begin with
> '__u_boot_list' rather than '.u_boot_list'. The double underscore at the
> start is still distinct from the single underscore used by the symbol
> names.
>
> Having a '.' in the section names conflicts with clang's ASAN
> instrumentation which tries to add redzones between the linker list
> elements, causing expected accesses to fail. However, clang doesn't try
> to add redzones to user sections, which are names with all alphanumeric
> and underscore characters.
>
> Signed-off-by: Andrew Scull <ascull@google.com>

Reviewed-by: Simon Glass <sjg@chromium.org>

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

* Re: [PATCH 04/11] sandbox: Add support for Address Sanitizer
  2022-04-07  9:41 ` [PATCH 04/11] sandbox: Add support for Address Sanitizer Andrew Scull
@ 2022-04-11 18:35   ` Simon Glass
  2022-04-12  9:26     ` Andrew Scull
  0 siblings, 1 reply; 30+ messages in thread
From: Simon Glass @ 2022-04-11 18:35 UTC (permalink / raw)
  To: Andrew Scull; +Cc: U-Boot Mailing List, Sean Anderson

Hi Andrew,

On Thu, 7 Apr 2022 at 03:41, Andrew Scull <ascull@google.com> wrote:
>
> Add CONFIG_ASAN to build with the Address Sanitizer. This only works
> with the sandbox so the config is likewise dependent. The resulting
> executable will have ASAN instrumentation, including the leak detector
> that can be disabled with the ASAN_OPTIONS environment variable:
>
>    ASAN_OPTIONS=detect_leaks=0 ./u-boot
>
> Since u-boot uses its own dlmalloc, dynamic allocations aren't
> automatically instrumented, but stack variables and globals are.
>
> Instrumentation could be added to dlmalloc to poison and unpoison memory
> as it is allocated and deallocated, and to introduce redzones between
> allocations. Alternatively, the sandbox may be able to play games with
> the system allocator and somehow still keep the required memory
> abstraction. No effort to address dynamic allocation is made by this
> patch.

I have toyed with what to do here. I originally was thinking of using
normal malloc() instead of dlmalloc() when running sandbox. But then
of course it makes sandbox very diffferent from other archs, so it is
not desirable. So I did not go down that path. Having said that,
os_malloc() is used for some sandbox-specific things.

I would love to have an extra string parameter to malloc() which
indicates what is doing the allocation (malloc_tag(size_t size, char
*id)), so it is easier to see failures and get an annotated 'core
dump'. But again, changing the alloc API is not so nice.

One weird thing to be aware of is that truetype fonts cause constant
allocs and frees. It happens in the background but you'll notice it if
you start tracing things.

>
> Signed-off-by: Andrew Scull <ascull@google.com>
> ---
>  Kconfig                   | 7 +++++++
>  arch/sandbox/config.mk    | 8 ++++++++
>  configs/sandbox_defconfig | 1 +
>  3 files changed, 16 insertions(+)

Reviewed-by: Simon Glass <sjg@chromium.org>

Regards,
Simon

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

* Re: [PATCH 05/11] fuzzing_engine: Add fuzzing engine uclass
  2022-04-07  9:41 ` [PATCH 05/11] fuzzing_engine: Add fuzzing engine uclass Andrew Scull
@ 2022-04-11 18:35   ` Simon Glass
  0 siblings, 0 replies; 30+ messages in thread
From: Simon Glass @ 2022-04-11 18:35 UTC (permalink / raw)
  To: Andrew Scull; +Cc: U-Boot Mailing List, Sean Anderson

Hi Andrew,

On Thu, 7 Apr 2022 at 03:41, Andrew Scull <ascull@google.com> wrote:
>
> This new class of device will provide fuzzing inputs from a fuzzing
> engine.
>
> Signed-off-by: Andrew Scull <ascull@google.com>
> ---
>  drivers/Kconfig                               |  2 +
>  drivers/Makefile                              |  1 +
>  drivers/fuzzing_engine/Kconfig                |  6 +++
>  drivers/fuzzing_engine/Makefile               |  7 +++
>  .../fuzzing_engine/fuzzing_engine-uclass.c    | 28 ++++++++++

How about just fuzz/ for the directory ?

>  include/dm/uclass-id.h                        |  1 +
>  include/fuzzing_engine.h                      | 51 +++++++++++++++++++
>  7 files changed, 96 insertions(+)
>  create mode 100644 drivers/fuzzing_engine/Kconfig
>  create mode 100644 drivers/fuzzing_engine/Makefile
>  create mode 100644 drivers/fuzzing_engine/fuzzing_engine-uclass.c
>  create mode 100644 include/fuzzing_engine.h

Reviewed-by: Simon Glass <sjg@chromium.org>

>
> diff --git a/drivers/Kconfig b/drivers/Kconfig
> index b26ca8cf70..54ad7f82fa 100644
> --- a/drivers/Kconfig
> +++ b/drivers/Kconfig
> @@ -40,6 +40,8 @@ source "drivers/fastboot/Kconfig"
>
>  source "drivers/firmware/Kconfig"
>
> +source "drivers/fuzzing_engine/Kconfig"
> +
>  source "drivers/fpga/Kconfig"
>
>  source "drivers/gpio/Kconfig"
> diff --git a/drivers/Makefile b/drivers/Makefile
> index 4e7cf28440..10a4a317c9 100644
> --- a/drivers/Makefile
> +++ b/drivers/Makefile
> @@ -113,6 +113,7 @@ obj-$(CONFIG_W1) += w1/
>  obj-$(CONFIG_W1_EEPROM) += w1-eeprom/
>
>  obj-$(CONFIG_MACH_PIC32) += ddr/microchip/
> +obj-$(CONFIG_FUZZ) += fuzzing_engine/
>  obj-$(CONFIG_DM_HWSPINLOCK) += hwspinlock/
>  obj-$(CONFIG_DM_RNG) += rng/
>  endif
> diff --git a/drivers/fuzzing_engine/Kconfig b/drivers/fuzzing_engine/Kconfig
> new file mode 100644
> index 0000000000..f405fc75e8
> --- /dev/null
> +++ b/drivers/fuzzing_engine/Kconfig
> @@ -0,0 +1,6 @@
> +config DM_FUZZING_ENGINE
> +       bool "Driver support for fuzzing engine devices"
> +       depends on DM
> +       help
> +         Enable driver model for fuzzing engine devices. This interface is
> +         used to get fuzzing inputs from a fuzzing engine.

Can you expand a bit what these things are?

Regards,
Simon

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

* Re: [PATCH 06/11] test: fuzz: Add framework for fuzzing
  2022-04-07  9:41 ` [PATCH 06/11] test: fuzz: Add framework for fuzzing Andrew Scull
@ 2022-04-11 18:35   ` Simon Glass
  0 siblings, 0 replies; 30+ messages in thread
From: Simon Glass @ 2022-04-11 18:35 UTC (permalink / raw)
  To: Andrew Scull; +Cc: U-Boot Mailing List, Sean Anderson

On Thu, 7 Apr 2022 at 03:41, Andrew Scull <ascull@google.com> wrote:
>
> Add the basic infrastructure for declaring fuzz tests and a command to
> invoke them.
>
> Signed-off-by: Andrew Scull <ascull@google.com>
> ---
>  Kconfig              |  8 +++++
>  include/test/fuzz.h  | 51 +++++++++++++++++++++++++++
>  test/Makefile        |  1 +
>  test/fuzz/Makefile   |  7 ++++
>  test/fuzz/cmd_fuzz.c | 82 ++++++++++++++++++++++++++++++++++++++++++++
>  5 files changed, 149 insertions(+)
>  create mode 100644 include/test/fuzz.h
>  create mode 100644 test/fuzz/Makefile
>  create mode 100644 test/fuzz/cmd_fuzz.c
>

Reviewed-by: Simon Glass <sjg@chromium.org>

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

* Re: [PATCH 07/11] sandbox: Decouple program entry from sandbox init
  2022-04-07  9:41 ` [PATCH 07/11] sandbox: Decouple program entry from sandbox init Andrew Scull
@ 2022-04-11 18:35   ` Simon Glass
  0 siblings, 0 replies; 30+ messages in thread
From: Simon Glass @ 2022-04-11 18:35 UTC (permalink / raw)
  To: Andrew Scull; +Cc: U-Boot Mailing List, Sean Anderson

On Thu, 7 Apr 2022 at 03:41, Andrew Scull <ascull@google.com> wrote:
>
> Move the program's entry point to os.c, in preparation for a separate
> fuzzing entry point to be added.
>
> Signed-off-by: Andrew Scull <ascull@google.com>
> ---
>  arch/sandbox/cpu/os.c           |  6 ++++++
>  arch/sandbox/cpu/start.c        |  2 +-
>  arch/sandbox/include/asm/main.h | 18 ++++++++++++++++++
>  3 files changed, 25 insertions(+), 1 deletion(-)
>  create mode 100644 arch/sandbox/include/asm/main.h
>

Reviewed-by: Simon Glass <sjg@chromium.org>

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

* Re: [PATCH 08/11] sandbox: Add libfuzzer integration
  2022-04-07  9:41 ` [PATCH 08/11] sandbox: Add libfuzzer integration Andrew Scull
@ 2022-04-11 18:35   ` Simon Glass
  0 siblings, 0 replies; 30+ messages in thread
From: Simon Glass @ 2022-04-11 18:35 UTC (permalink / raw)
  To: Andrew Scull; +Cc: U-Boot Mailing List, Sean Anderson

On Thu, 7 Apr 2022 at 03:41, Andrew Scull <ascull@google.com> wrote:
>
> Add an implementation of LLVMFuzzerTestOneInput() that starts the
> sandbox on a secondary thread and exposes a function to synchronize the
> generation of fuzzing inputs with their consumption by the sandbox.
>
> Signed-off-by: Andrew Scull <ascull@google.com>
> ---
>  arch/sandbox/config.mk                    |  3 +
>  arch/sandbox/cpu/os.c                     | 70 +++++++++++++++++++++++
>  arch/sandbox/include/asm/fuzzing_engine.h | 25 ++++++++
>  3 files changed, 98 insertions(+)
>  create mode 100644 arch/sandbox/include/asm/fuzzing_engine.h

Reviewed-by: Simon Glass <sjg@chromium.org>

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

* Re: [PATCH 09/11] sandbox: Implement fuzzing engine driver
  2022-04-07  9:41 ` [PATCH 09/11] sandbox: Implement fuzzing engine driver Andrew Scull
@ 2022-04-11 18:35   ` Simon Glass
  2022-04-14 13:44     ` Andrew Scull
  0 siblings, 1 reply; 30+ messages in thread
From: Simon Glass @ 2022-04-11 18:35 UTC (permalink / raw)
  To: Andrew Scull; +Cc: U-Boot Mailing List, Sean Anderson

Hi Andrew,

On Thu, 7 Apr 2022 at 03:41, Andrew Scull <ascull@google.com> wrote:
>
> Add a fuzzing engine driver for the sandbox to take inputs from
> libfuzzer and expose them to the fuzz tests.
>
> Signed-off-by: Andrew Scull <ascull@google.com>
> ---
>  arch/Kconfig                                  |  2 ++
>  arch/sandbox/dts/test.dts                     |  4 +++
>  drivers/fuzzing_engine/Kconfig                | 11 ++++++
>  drivers/fuzzing_engine/Makefile               |  1 +
>  .../fuzzing_engine/sandbox_fuzzing_engine.c   | 35 +++++++++++++++++++
>  5 files changed, 53 insertions(+)
>  create mode 100644 drivers/fuzzing_engine/sandbox_fuzzing_engine.c
>

Reviewed-by: Simon Glass <sjg@chromium.org>

Thoughts below

> diff --git a/arch/Kconfig b/arch/Kconfig
> index e6191446a3..6320a98db6 100644
> --- a/arch/Kconfig
> +++ b/arch/Kconfig
> @@ -135,6 +135,7 @@ config SANDBOX
>         select BZIP2
>         select CMD_POWEROFF
>         select DM
> +       select DM_FUZZING_ENGINE
>         select DM_GPIO
>         select DM_I2C
>         select DM_KEYBOARD
> @@ -170,6 +171,7 @@ config SANDBOX
>         imply CRC32_VERIFY
>         imply FAT_WRITE
>         imply FIRMWARE
> +       imply FUZZING_ENGINE_SANDBOX
>         imply HASH_VERIFY
>         imply LZMA
>         imply TEE
> diff --git a/arch/sandbox/dts/test.dts b/arch/sandbox/dts/test.dts
> index 48ca3e1e47..848329fda5 100644
> --- a/arch/sandbox/dts/test.dts
> +++ b/arch/sandbox/dts/test.dts
> @@ -71,6 +71,10 @@
>                 };
>         };
>
> +       fuzzing-engine {
> +               compatible = "sandbox,sandbox-fuzzing-engine";
> +       };
> +
>         reboot-mode0 {
>                 compatible = "reboot-mode-gpio";
>                 gpios = <&gpio_c 0 GPIO_ACTIVE_HIGH>, <&gpio_c 1 GPIO_ACTIVE_HIGH>;
> diff --git a/drivers/fuzzing_engine/Kconfig b/drivers/fuzzing_engine/Kconfig
> index f405fc75e8..6311385222 100644
> --- a/drivers/fuzzing_engine/Kconfig
> +++ b/drivers/fuzzing_engine/Kconfig
> @@ -4,3 +4,14 @@ config DM_FUZZING_ENGINE
>         help
>           Enable driver model for fuzzing engine devices. This interface is
>           used to get fuzzing inputs from a fuzzing engine.
> +
> +if DM_FUZZING_ENGINE
> +
> +config FUZZING_ENGINE_SANDBOX
> +       bool "Sanbox fuzzing engine"
> +       depends on SANDBOX
> +       default y
> +       help
> +         Enable fuzzing engine for sandbox.
> +
> +endif
> diff --git a/drivers/fuzzing_engine/Makefile b/drivers/fuzzing_engine/Makefile
> index acd894999c..073743ba94 100644
> --- a/drivers/fuzzing_engine/Makefile
> +++ b/drivers/fuzzing_engine/Makefile
> @@ -5,3 +5,4 @@
>  #
>
>  obj-$(CONFIG_DM_FUZZING_ENGINE) += fuzzing_engine-uclass.o
> +obj-$(CONFIG_FUZZING_ENGINE_SANDBOX) += sandbox_fuzzing_engine.o
> diff --git a/drivers/fuzzing_engine/sandbox_fuzzing_engine.c b/drivers/fuzzing_engine/sandbox_fuzzing_engine.c
> new file mode 100644
> index 0000000000..4d187deaa4
> --- /dev/null
> +++ b/drivers/fuzzing_engine/sandbox_fuzzing_engine.c
> @@ -0,0 +1,35 @@
> +/* SPDX-License-Identifier: GPL-2.0+ */
> +/*
> + * Copyright (c) 2022 Google, Inc.
> + * Written by Andrew Scull <ascull@google.com>
> + */
> +
> +#include <common.h>
> +#include <dm.h>
> +#include <fuzzing_engine.h>
> +#include <asm/fuzzing_engine.h>
> +
> +static int get_input(struct udevice *dev,
> +                    const uint8_t **data,
> +                    size_t *size)
> +{
> +       return sandbox_fuzzing_engine_get_input(data, size);
> +}
> +
> +static const struct dm_fuzzing_engine_ops sandbox_fuzzing_engine_ops = {
> +       .get_input = get_input,
> +};
> +
> +static const struct udevice_id sandbox_fuzzing_engine_match[] = {

In the interests of brevity, perhaps sb_fuzz_engine as the prefix, or
sbfuzz_engine?

> +       {
> +               .compatible = "sandbox,sandbox-fuzzing-engine",

Do you need the second 'sandbox-' ?

> +       },
> +       {},
> +};
> +
> +U_BOOT_DRIVER(sandbox_fuzzing_engine) = {
> +       .name = "sandbox-fuzzing-engine",
> +       .id = UCLASS_FUZZING_ENGINE,
> +       .of_match = sandbox_fuzzing_engine_match,
> +       .ops = &sandbox_fuzzing_engine_ops,
> +};
> --
> 2.35.1.1094.g7c7d902a7c-goog
>

Regards,
Simon

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

* Re: [PATCH 10/11] fuzz: virtio: Add fuzzer for vring
  2022-04-07  9:41 ` [PATCH 10/11] fuzz: virtio: Add fuzzer for vring Andrew Scull
@ 2022-04-11 18:35   ` Simon Glass
  2022-04-12 14:04     ` Andrew Scull
  0 siblings, 1 reply; 30+ messages in thread
From: Simon Glass @ 2022-04-11 18:35 UTC (permalink / raw)
  To: Andrew Scull; +Cc: U-Boot Mailing List, Sean Anderson

Hi Andrew,

On Thu, 7 Apr 2022 at 03:41, Andrew Scull <ascull@google.com> wrote:
>
> Add a fuzzer to test the vring handling code against unexpected
> mutations from the virtio device.
>
> After building the sandbox with CONFIG_FUZZ=y, the fuzzer can be invoked
> with by:
>
>    UBOOT_SB_FUZZ_TEST=fuzz_vring ./u-boot
>
> This fuzzer finds unvalidated inputs in the vring driver that allow a
> buggy or malicious device to make the driver chase wild pointers.
>
> Signed-off-by: Andrew Scull <ascull@google.com>
> ---
>  test/fuzz/Makefile |  1 +
>  test/fuzz/virtio.c | 72 ++++++++++++++++++++++++++++++++++++++++++++++
>  2 files changed, 73 insertions(+)
>  create mode 100644 test/fuzz/virtio.c
>
> diff --git a/test/fuzz/Makefile b/test/fuzz/Makefile
> index 03eeeeb497..663b79ce80 100644
> --- a/test/fuzz/Makefile
> +++ b/test/fuzz/Makefile
> @@ -5,3 +5,4 @@
>  #
>
>  obj-$(CONFIG_$(SPL_)CMDLINE) += cmd_fuzz.o
> +obj-$(CONFIG_VIRTIO_SANDBOX) += virtio.o
> diff --git a/test/fuzz/virtio.c b/test/fuzz/virtio.c
> new file mode 100644
> index 0000000000..e5363d5638
> --- /dev/null
> +++ b/test/fuzz/virtio.c
> @@ -0,0 +1,72 @@
> +/* SPDX-License-Identifier: GPL-2.0+ */
> +/*
> + * Copyright (c) 2022 Google, Inc.
> + * Written by Andrew Scull <ascull@google.com>
> + */
> +
> +#include <common.h>
> +#include <dm.h>
> +#include <virtio.h>
> +#include <virtio_ring.h>
> +#include <test/fuzz.h>
> +
> +static int fuzz_vring(const uint8_t *data, size_t size)
> +{
> +       struct udevice *bus, *dev;
> +       struct virtio_dev_priv *uc_priv;
> +       struct virtqueue *vq;
> +       struct virtio_sg sg[2];
> +       struct virtio_sg *sgs[2];
> +       unsigned int len;
> +       u8 buffer[2][32];
> +
> +       /* hackily hardcode vring sizes */
> +       size_t num = 4;
> +       size_t desc_size = (sizeof(struct vring_desc) * num);
> +       size_t avail_size = (3 + num) * sizeof(u16);
> +       size_t used_size = (3 * sizeof(u16)) + (sizeof(struct vring_used_elem) * num);
> +
> +       if (size < (desc_size + avail_size + used_size))
> +               return 0;
> +
> +       /* check probe success */
> +       if (uclass_first_device(UCLASS_VIRTIO, &bus) || !bus)
> +               panic("Could not find virtio bus\n");

Do we have to panic? Could this use some sort of assert function, or
similar? It seems like we should try to show the error then return an
error code from this function, rather than just panic in the middle.
We could have something like the ut_assert... stuff.

> +
> +       /* check the child virtio-rng device is bound */
> +       if (device_find_first_child(bus, &dev) || !dev)
> +               panic("Could not find virtio device\n");
> +
> +       /*
> +        * fake the virtio device probe by filling in uc_priv->vdev
> +        * which is used by virtio_find_vqs/virtio_del_vqs.
> +        */
> +       uc_priv = dev_get_uclass_priv(bus);
> +       uc_priv->vdev = dev;
> +
> +       /* prepare the scatter-gather buffer */
> +       sg[0].addr = buffer[0];
> +       sg[0].length = sizeof(buffer[0]);
> +       sg[1].addr = buffer[1];
> +       sg[1].length = sizeof(buffer[1]);
> +       sgs[0] = &sg[0];
> +       sgs[1] = &sg[1];
> +
> +       if (virtio_find_vqs(dev, 1, &vq))
> +               panic("Could not find vqs\n");
> +       if (virtqueue_add(vq, sgs, 0, 1))
> +               panic("Could not add to virtqueue\n");
> +       /* Simulate device writing to vring */
> +       memcpy(vq->vring.desc, data, desc_size);
> +       memcpy(vq->vring.avail, data + desc_size, avail_size);
> +       memcpy(vq->vring.used, data + desc_size + avail_size, used_size);
> +       /* Make sure there is a response */
> +       if (vq->vring.used->idx == 0)
> +               vq->vring.used->idx = 1;
> +       virtqueue_get_buf(vq, &len);
> +       if (virtio_del_vqs(dev))
> +               panic("Could not delete vqs\n");
> +
> +       return 0;
> +}
> +FUZZ_TEST(fuzz_vring, 0);
> --
> 2.35.1.1094.g7c7d902a7c-goog
>

Regards,
Simon

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

* Re: [PATCH 11/11] RFC: Hack dlmalloc to poison memory
  2022-04-07  9:41 ` [PATCH 11/11] RFC: Hack dlmalloc to poison memory Andrew Scull
@ 2022-04-11 18:35   ` Simon Glass
  2022-04-12 10:19     ` Andrew Scull
  0 siblings, 1 reply; 30+ messages in thread
From: Simon Glass @ 2022-04-11 18:35 UTC (permalink / raw)
  To: Andrew Scull; +Cc: U-Boot Mailing List, Sean Anderson

Hi Andrew,

On Thu, 7 Apr 2022 at 03:41, Andrew Scull <ascull@google.com> wrote:
>
> This is a hugely ugly hack to poison and unpoison memory allocated by
> dlmalloc. It wraps every access dlmalloc makes to the metadata breifly
> allow it access, taking care not to then poison the parts of the record
> which overlap.
>
> The result is very small redzones between the allocations, which has
> limted value but has able to spot immediate buffer overruns.
>
> The instrumentation is extremely intrusive and would be benefited by
> more intrusions to increase redzone sizes etc.
>
> Signed-off-by: Andrew Scull <ascull@google.com>
> ---
>  common/dlmalloc.c     | 284 ++++++++++++++++++++++++++++++++++++------
>  include/compiler.h    |   1 +
>  include/linux/types.h |   1 +
>  3 files changed, 245 insertions(+), 41 deletions(-)

This actually seems very useful to me. I wonder if it could be split
into a few patches, for easier review?

Also what is the mechanism to enable/disable this?

I've made a few comments anyway.

The changes to include/ need a look. I'm not sure whether we can avoid
them, but if not, they could go in their own patch.

>
> diff --git a/common/dlmalloc.c b/common/dlmalloc.c
> index 11729e8c85..614f004579 100644
> --- a/common/dlmalloc.c
> +++ b/common/dlmalloc.c
> @@ -8,6 +8,8 @@
>   * as file malloc-2.6.6.c.
>   */
>
> +#define DEBUG
> +
>  #include <common.h>
>  #include <log.h>
>  #include <asm/global_data.h>
> @@ -16,6 +18,8 @@
>  #define DEBUG
>  #endif
>
> +#include <sanitizer/asan_interface.h>
> +
>  #include <malloc.h>
>  #include <asm/io.h>
>
> @@ -31,6 +35,17 @@ void malloc_stats();
>
>  DECLARE_GLOBAL_DATA_PTR;
>
> +/*
> +#undef ASAN_POISON_MEMORY_REGION
> +#define ASAN_POISON_MEMORY_REGION(p, s) do { \
> +    if ((uintptr_t)p == 0x0000150200c0) { \
> +        printf("size %lx\n", s); \
> +        *(int*)NULL = 9; \
> +    } \
> +    __asan_poison_memory_region(p, s); \
> +} while (0)
> +*/
> +
>  /*
>    Emulation of sbrk for WIN32
>    All code within the ifdef WIN32 is untested by me.
> @@ -409,12 +424,26 @@ nextchunk-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
>
>  /* Ptr to next physical malloc_chunk. */
>
> -#define next_chunk(p) ((mchunkptr)( ((char*)(p)) + ((p)->size & ~PREV_INUSE) ))
> +#define _next_chunk(p) ((mchunkptr)( ((char*)(p)) + ((p)->size & ~PREV_INUSE) ))
> +#define next_chunk(p) ({ \
> +        mchunkptr _ptr = (p); \
> +        ASAN_UNPOISON_MEMORY_REGION(((char*)_ptr) + SIZE_SZ, SIZE_SZ); \

Where is that defined?

> +        mchunkptr _ret = _next_chunk(_ptr); \
> +        ASAN_POISON_MEMORY_REGION(((char*)_ptr) + SIZE_SZ, SIZE_SZ); \
> +        _ret; \
> +        })
>
>  /* Ptr to previous physical malloc_chunk */
>
> -#define prev_chunk(p)\
> +#define _prev_chunk(p)\
>     ((mchunkptr)( ((char*)(p)) - ((p)->prev_size) ))
> +#define prev_chunk(p) ({ \
> +        mchunkptr _ptr = (p); \
> +        ASAN_UNPOISON_MEMORY_REGION(_ptr, SIZE_SZ); \

How about ASON_CURE() for brevity

> +        mchunkptr _ret = _prev_chunk(_ptr); \
> +        ASAN_POISON_MEMORY_REGION(_ptr, SIZE_SZ); \

ASON_POISON() ?

> +        _ret; \
> +        })
>
>
>  /* Treat space at ptr + offset as a chunk */
> @@ -430,35 +459,102 @@ nextchunk-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
>
>  /* extract p's inuse bit */
>
> -#define inuse(p)\
> +#define _inuse(p)\
>  ((((mchunkptr)(((char*)(p))+((p)->size & ~PREV_INUSE)))->size) & PREV_INUSE)
> +#define inuse(p) ({ \
> +        mchunkptr _p = (p); \
> +        ASAN_UNPOISON_MEMORY_REGION(((char*)_p) + SIZE_SZ, SIZE_SZ); \
> +        mchunkptr _ptr = ((mchunkptr)(((char*)_p)+(_p->size & ~PREV_INUSE))); \
> +        ASAN_UNPOISON_MEMORY_REGION(((char*)_ptr) + SIZE_SZ, SIZE_SZ); \
> +        INTERNAL_SIZE_T _ret = _inuse(_p); \
> +        ASAN_POISON_MEMORY_REGION(((char*)_ptr) + SIZE_SZ, SIZE_SZ); \
> +        ASAN_POISON_MEMORY_REGION(((char*)_p) + SIZE_SZ, SIZE_SZ); \
> +        _ret; \
> +        })
>
>  /* extract inuse bit of previous chunk */
>
> -#define prev_inuse(p)  ((p)->size & PREV_INUSE)
> +#define _prev_inuse(p)  ((p)->size & PREV_INUSE)
> +#define prev_inuse(p) ({ \
> +        mchunkptr _ptr = (p); \
> +        ASAN_UNPOISON_MEMORY_REGION(((char*)_ptr) + SIZE_SZ, SIZE_SZ); \
> +        INTERNAL_SIZE_T _ret = _prev_inuse(_ptr); \
> +        ASAN_POISON_MEMORY_REGION(((char*)_ptr) + SIZE_SZ, SIZE_SZ); \
> +        _ret; \
> +        })
>
>  /* check for mmap()'ed chunk */
>
> -#define chunk_is_mmapped(p) ((p)->size & IS_MMAPPED)
> +#define _chunk_is_mmapped(p) ((p)->size & IS_MMAPPED)
> +#define chunk_is_mmapped(p) ({ \
> +        mchunkptr _ptr = (p); \
> +        ASAN_UNPOISON_MEMORY_REGION(((char*)_ptr) + SIZE_SZ, SIZE_SZ); \
> +        INTERNAL_SIZE_T _ret = _chunk_is_mmapped(_ptr); \
> +        ASAN_POISON_MEMORY_REGION(((char*)_ptr) + SIZE_SZ, SIZE_SZ); \
> +        _ret; \
> +        })
>
>  /* set/clear chunk as in use without otherwise disturbing */
>
> -#define set_inuse(p)\
> +#define _set_inuse(p)\
>  ((mchunkptr)(((char*)(p)) + ((p)->size & ~PREV_INUSE)))->size |= PREV_INUSE
> -
> -#define clear_inuse(p)\
> +#define set_inuse(p, s) ({ \
> +        mchunkptr _p = (p); \
> +        ASAN_UNPOISON_MEMORY_REGION(((char*)_p) + SIZE_SZ, SIZE_SZ); \
> +        mchunkptr _ptr = ((mchunkptr)(((char*)_p)+(_p->size & ~PREV_INUSE))); \
> +        ASAN_UNPOISON_MEMORY_REGION(((char*)_ptr) + SIZE_SZ, SIZE_SZ); \
> +        _set_inuse(_p, (s)); \
> +        ASAN_POISON_MEMORY_REGION(((char*)_ptr) + SIZE_SZ, SIZE_SZ); \
> +        ASAN_POISON_MEMORY_REGION(((char*)_p) + SIZE_SZ, SIZE_SZ); \
> +        })
> +
> +#define _clear_inuse(p)\
>  ((mchunkptr)(((char*)(p)) + ((p)->size & ~PREV_INUSE)))->size &= ~(PREV_INUSE)
> +#define clear_inuse(p, s) ({ \
> +        __typeof__(p) _p = (p); \
> +        ASAN_UNPOISON_MEMORY_REGION(((char*)_p) + SIZE_SZ, SIZE_SZ); \
> +        mchunkptr _ptr = ((mchunkptr)(((char*)_p)+(_p->size & ~PREV_INUSE))); \
> +        ASAN_UNPOISON_MEMORY_REGION(((char*)_ptr) + SIZE_SZ, SIZE_SZ); \
> +        _clear_inuse(_p, (s)); \
> +        ASAN_POISON_MEMORY_REGION(((char*)_ptr) + SIZE_SZ, SIZE_SZ); \
> +        ASAN_POISON_MEMORY_REGION(((char*)_p) + SIZE_SZ, SIZE_SZ); \
> +        })
>
>  /* check/set/clear inuse bits in known places */
>
> -#define inuse_bit_at_offset(p, s)\
> +#define _inuse_bit_at_offset(p, s)\
>   (((mchunkptr)(((char*)(p)) + (s)))->size & PREV_INUSE)
> -
> -#define set_inuse_bit_at_offset(p, s)\
> +#define inuse_bit_at_offset(p, s) ({ \
> +        __typeof__(p) _p = (p); \
> +        __typeof__(s) _s = (s); \
> +        __typeof__(p) _ptr = (mchunkptr)(((char*)_p) + _s); \
> +        ASAN_UNPOISON_MEMORY_REGION(((char*)_ptr) + SIZE_SZ, SIZE_SZ); \
> +        INTERNAL_SIZE_T _ret = _inuse_bit_at_offset(_p, _s); \
> +        ASAN_POISON_MEMORY_REGION(((char*)_ptr) + SIZE_SZ, SIZE_SZ); \
> +        _ret; \
> +        })
> +
> +#define _set_inuse_bit_at_offset(p, s)\
>   (((mchunkptr)(((char*)(p)) + (s)))->size |= PREV_INUSE)
> -
> -#define clear_inuse_bit_at_offset(p, s)\
> +#define set_inuse_bit_at_offset(p, s) ({ \
> +        __typeof__(p) _p = (p); \
> +        __typeof__(s) _s = (s); \
> +        __typeof__(p) _ptr = (mchunkptr)(((char*)_p) + _s); \
> +        ASAN_UNPOISON_MEMORY_REGION(((char*)_ptr) + SIZE_SZ, SIZE_SZ); \
> +        _set_inuse_bit_at_offset(_p, _s); \
> +        ASAN_POISON_MEMORY_REGION(((char*)_ptr) + SIZE_SZ, SIZE_SZ); \
> +        })
> +
> +#define _clear_inuse_bit_at_offset(p, s)\
>   (((mchunkptr)(((char*)(p)) + (s)))->size &= ~(PREV_INUSE))
> +#define clear_inuse_bit_at_offset(p, s) ({ \
> +        __typeof__(p) _p = (p); \
> +        __typeof__(s) _s = (s); \
> +        __typeof__(p) _ptr = (mchunkptr)(((char*)_p) + _s); \
> +        ASAN_UNPOISON_MEMORY_REGION(((char*)_ptr) + SIZE_SZ, SIZE_SZ); \
> +        _clear_inuse_bit_at_offset(_p, _s); \
> +        ASAN_POISON_MEMORY_REGION(((char*)_ptr) + SIZE_SZ, SIZE_SZ); \
> +        })
>
>
>
> @@ -469,19 +565,46 @@ nextchunk-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
>
>  /* Get size, ignoring use bits */
>
> -#define chunksize(p)          ((p)->size & ~(SIZE_BITS))
> +#define _chunksize(p)          ((p)->size & ~(SIZE_BITS))
> +#define chunksize(p) ({ \
> +        mchunkptr _ptr = (p); \
> +        ASAN_UNPOISON_MEMORY_REGION(((char*)_ptr) + SIZE_SZ, SIZE_SZ); \
> +        INTERNAL_SIZE_T _ret = _chunksize(_ptr); \
> +        ASAN_POISON_MEMORY_REGION(((char*)_ptr) + SIZE_SZ, SIZE_SZ); \
> +        _ret; \
> +        })
>
>  /* Set size at head, without disturbing its use bit */
>
> -#define set_head_size(p, s)   ((p)->size = (((p)->size & PREV_INUSE) | (s)))
> +#define _set_head_size(p, s)   ((p)->size = (((p)->size & PREV_INUSE) | (s)))
> +#define set_head_size(p, s) ({ \
> +        __typeof__(p) _ptr = (p); \
> +        ASAN_UNPOISON_MEMORY_REGION(((char*)_ptr) + SIZE_SZ, SIZE_SZ); \
> +        _set_head_size(_ptr, (s)); \
> +        ASAN_POISON_MEMORY_REGION(((char*)_ptr) + SIZE_SZ, SIZE_SZ); \
> +        })
>
>  /* Set size/use ignoring previous bits in header */
>
> -#define set_head(p, s)        ((p)->size = (s))
> +#define _set_head(p, s)        ((p)->size = (s))
> +#define set_head(p, s) ({ \
> +        __typeof__(p) _ptr = (p); \
> +        ASAN_UNPOISON_MEMORY_REGION(((char*)_ptr) + SIZE_SZ, SIZE_SZ); \
> +        _set_head(_ptr, (s)); \
> +        ASAN_POISON_MEMORY_REGION(((char*)_ptr) + SIZE_SZ, SIZE_SZ); \
> +        })
>
>  /* Set size at footer (only when chunk is not in use) */
>
> -#define set_foot(p, s)   (((mchunkptr)((char*)(p) + (s)))->prev_size = (s))
> +#define _set_foot(p, s)   (((mchunkptr)((char*)(p) + (s)))->prev_size = (s))
> +#define set_foot(p, s) ({ \
> +        __typeof__(p) _p = (p); \
> +        __typeof__(s) _s = (s); \
> +        __typeof__(p) _ptr = (mchunkptr)(((char*)_p) + _s); \
> +        ASAN_UNPOISON_MEMORY_REGION(_ptr, SIZE_SZ); \
> +        _set_foot(_p, (s)); \
> +        ASAN_POISON_MEMORY_REGION(_ptr, SIZE_SZ); \
> +        })
>
>
>
> @@ -604,8 +727,11 @@ void *sbrk(ptrdiff_t increment)
>          * if we are giving memory back make sure we clear it out since
>          * we set MORECORE_CLEARS to 1
>          */
> -       if (increment < 0)
> +       if (increment < 0) {
> +                ASAN_UNPOISON_MEMORY_REGION((void *)new, -increment);
>                 memset((void *)new, 0, -increment);
> +                ASAN_POISON_MEMORY_REGION((void *)new, -increment);
> +        }
>
>         if ((new < mem_malloc_start) || (new > mem_malloc_end))
>                 return (void *)MORECORE_FAILURE;
> @@ -630,13 +756,24 @@ void mem_malloc_init(ulong start, ulong size)
>  #ifdef CONFIG_SYS_MALLOC_CLEAR_ON_INIT
>         memset((void *)mem_malloc_start, 0x0, size);
>  #endif
> +        ASAN_POISON_MEMORY_REGION((void *)start, size);
>         malloc_bin_reloc();
>  }
>
>  /* field-extraction macros */
>
> -#define first(b) ((b)->fd)
> -#define last(b)  ((b)->bk)
> +#define first(b) ({ \
> +        ASAN_UNPOISON_MEMORY_REGION(((char*)b) + 2*SIZE_SZ, 2*sizeof(uintptr_t)); \
> +        void *_ret = (b)->fd; \
> +        ASAN_UNPOISON_MEMORY_REGION(((char*)b) + 2*SIZE_SZ, 2*sizeof(uintptr_t)); \
> +        _ret; \
> +        })
> +#define last(b)  ({ \
> +        ASAN_UNPOISON_MEMORY_REGION(((char*)b) + 2*SIZE_SZ, 2*sizeof(uintptr_t)); \
> +        void *_ret = (b)->bk; \
> +        ASAN_UNPOISON_MEMORY_REGION(((char*)b) + 2*SIZE_SZ, 2*sizeof(uintptr_t)); \
> +        _ret; \
> +        })
>
>  /*
>    Indexing into bins
> @@ -781,7 +918,7 @@ static void do_check_chunk(mchunkptr p)
>  static void do_check_chunk(p) mchunkptr p;
>  #endif
>  {
> -  INTERNAL_SIZE_T sz = p->size & ~PREV_INUSE;
> +  INTERNAL_SIZE_T sz = chunksize(p);
>
>    /* No checkable chunk is mmapped */
>    assert(!chunk_is_mmapped(p));
> @@ -802,7 +939,7 @@ static void do_check_free_chunk(mchunkptr p)
>  static void do_check_free_chunk(p) mchunkptr p;
>  #endif
>  {
> -  INTERNAL_SIZE_T sz = p->size & ~PREV_INUSE;
> +  INTERNAL_SIZE_T sz = chunksize(p);
>    mchunkptr next = chunk_at_offset(p, sz);
>
>    do_check_chunk(p);
> @@ -816,14 +953,22 @@ static void do_check_free_chunk(p) mchunkptr p;
>      assert((sz & MALLOC_ALIGN_MASK) == 0);
>      assert(aligned_OK(chunk2mem(p)));
>      /* ... matching footer field */
> +    ASAN_UNPOISON_MEMORY_REGION(next, SIZE_SZ);
>      assert(next->prev_size == sz);
> +    ASAN_POISON_MEMORY_REGION(next, SIZE_SZ);
>      /* ... and is fully consolidated */
>      assert(prev_inuse(p));
>      assert (next == top || inuse(next));
>
>      /* ... and has minimally sane links */
> +    ASAN_UNPOISON_MEMORY_REGION(((char*)p) + 2*SIZE_SZ, 2*sizeof(uintptr_t));
> +    ASAN_UNPOISON_MEMORY_REGION(((char*)p->fd) + 2*SIZE_SZ, 2*sizeof(uintptr_t));
> +    ASAN_UNPOISON_MEMORY_REGION(((char*)p->bk) + 2*SIZE_SZ, 2*sizeof(uintptr_t));
>      assert(p->fd->bk == p);
>      assert(p->bk->fd == p);
> +    ASAN_POISON_MEMORY_REGION(((char*)p->fd) + 2*SIZE_SZ, 2*sizeof(uintptr_t));
> +    ASAN_POISON_MEMORY_REGION(((char*)p->bk) + 2*SIZE_SZ, 2*sizeof(uintptr_t));
> +    ASAN_POISON_MEMORY_REGION(((char*)p) + 2*SIZE_SZ, 2*sizeof(uintptr_t));
>    }
>    else /* markers are always of size SIZE_SZ */
>      assert(sz == SIZE_SZ);
> @@ -867,7 +1012,7 @@ static void do_check_malloced_chunk(mchunkptr p, INTERNAL_SIZE_T s)
>  static void do_check_malloced_chunk(p, s) mchunkptr p; INTERNAL_SIZE_T s;
>  #endif
>  {
> -  INTERNAL_SIZE_T sz = p->size & ~PREV_INUSE;
> +  INTERNAL_SIZE_T sz = chunksize(p);
>    long room = sz - s;
>
>    do_check_inuse_chunk(p);
> @@ -919,31 +1064,48 @@ static void do_check_malloced_chunk(p, s) mchunkptr p; INTERNAL_SIZE_T s;
>
>  #define frontlink(P, S, IDX, BK, FD)                                          \
>  {                                                                             \
> +  ASAN_UNPOISON_MEMORY_REGION(((char*)P) + 2*SIZE_SZ, 2*sizeof(uintptr_t));                                 \
>    if (S < MAX_SMALLBIN_SIZE)                                                  \
>    {                                                                           \
>      IDX = smallbin_index(S);                                                  \
>      mark_binblock(IDX);                                                       \
>      BK = bin_at(IDX);                                                         \
> +  ASAN_UNPOISON_MEMORY_REGION(((char*)BK) + 2*SIZE_SZ, 2*sizeof(uintptr_t));                                 \
>      FD = BK->fd;                                                              \
>      P->bk = BK;                                                               \
>      P->fd = FD;                                                               \
> +  ASAN_UNPOISON_MEMORY_REGION(((char*)FD) + 2*SIZE_SZ, 2*sizeof(uintptr_t));                                 \
>      FD->bk = BK->fd = P;                                                      \
>    }                                                                           \
>    else                                                                        \
>    {                                                                           \
>      IDX = bin_index(S);                                                       \
>      BK = bin_at(IDX);                                                         \
> +  ASAN_UNPOISON_MEMORY_REGION(((char*)BK) + 2*SIZE_SZ, 2*sizeof(uintptr_t));                                 \
>      FD = BK->fd;                                                              \
> +  ASAN_UNPOISON_MEMORY_REGION(((char*)FD) + 2*SIZE_SZ, 2*sizeof(uintptr_t));                                 \
>      if (FD == BK) mark_binblock(IDX);                                         \
>      else                                                                      \
>      {                                                                         \
> -      while (FD != BK && S < chunksize(FD)) FD = FD->fd;                      \
> +      while (FD != BK && S < chunksize(FD)) { \
> +          mchunkptr old = FD; \
> +          FD = FD->fd;                      \
> +        ASAN_POISON_MEMORY_REGION(((char*)old) + 2*SIZE_SZ, 2*sizeof(uintptr_t));                                 \
> +        ASAN_UNPOISON_MEMORY_REGION(((char*)FD) + 2*SIZE_SZ, 2*sizeof(uintptr_t));                                 \
> +      } \
> +      mchunkptr oldbk = BK; \
>        BK = FD->bk;                                                            \
> +  ASAN_POISON_MEMORY_REGION(((char*)oldbk) + 2*SIZE_SZ, 2*sizeof(uintptr_t));                                 \
> +  ASAN_UNPOISON_MEMORY_REGION(((char*)BK) + 2*SIZE_SZ, 2*sizeof(uintptr_t));                                 \
> +        ASAN_UNPOISON_MEMORY_REGION(((char*)FD) + 2*SIZE_SZ, 2*sizeof(uintptr_t));                                 \
>      }                                                                         \
>      P->bk = BK;                                                               \
>      P->fd = FD;                                                               \
>      FD->bk = BK->fd = P;                                                      \
>    }                                                                           \
> +  ASAN_POISON_MEMORY_REGION(((char*)P) + 2*SIZE_SZ, 2*sizeof(uintptr_t));                                 \
> +  ASAN_POISON_MEMORY_REGION(((char*)BK) + 2*SIZE_SZ, 2*sizeof(uintptr_t));                                 \
> +  ASAN_POISON_MEMORY_REGION(((char*)FD) + 2*SIZE_SZ, 2*sizeof(uintptr_t));                                 \
>  }
>
>
> @@ -951,18 +1113,26 @@ static void do_check_malloced_chunk(p, s) mchunkptr p; INTERNAL_SIZE_T s;
>
>  #define unlink(P, BK, FD)                                                     \
>  {                                                                             \
> +  ASAN_UNPOISON_MEMORY_REGION(((char*)P) + 2*SIZE_SZ, 2*sizeof(uintptr_t));                                 \
>    BK = P->bk;                                                                 \
>    FD = P->fd;                                                                 \
> +  ASAN_POISON_MEMORY_REGION(((char*)P) + 2*SIZE_SZ, 2*sizeof(uintptr_t));                                 \
> +  ASAN_UNPOISON_MEMORY_REGION(((char*)BK) + 2*SIZE_SZ, 2*sizeof(uintptr_t));                                 \
> +  ASAN_UNPOISON_MEMORY_REGION(((char*)FD) + 2*SIZE_SZ, 2*sizeof(uintptr_t));                                 \
>    FD->bk = BK;                                                                \
>    BK->fd = FD;                                                                \
> +  ASAN_POISON_MEMORY_REGION(((char*)BK) + 2*SIZE_SZ, 2*sizeof(uintptr_t));                                 \
> +  ASAN_POISON_MEMORY_REGION(((char*)FD) + 2*SIZE_SZ, 2*sizeof(uintptr_t));                                 \
>  }                                                                             \
>
>  /* Place p as the last remainder */
>
>  #define link_last_remainder(P)                                                \
>  {                                                                             \
> +  ASAN_UNPOISON_MEMORY_REGION(((char*)P) + 2*SIZE_SZ, 2*sizeof(uintptr_t));                                 \
>    last_remainder->fd = last_remainder->bk =  P;                               \
>    P->fd = P->bk = last_remainder;                                             \
> +  ASAN_POISON_MEMORY_REGION(((char*)P) + 2*SIZE_SZ, 2*sizeof(uintptr_t));                                 \
>  }
>
>  /* Clear the last_remainder bin */
> @@ -1280,6 +1450,14 @@ static void malloc_extend_top(nb) INTERNAL_SIZE_T nb;
>
>  */
>
> +#define publish_mem(p) ({ \

Could use a comment

> +        __typeof__(p) _chunk = (p); \
> +        Void_t *_ret = chunk2mem(_chunk); \
> +        INTERNAL_SIZE_T _size = malloc_usable_size(_ret); \
> +        ASAN_UNPOISON_MEMORY_REGION(_ret, _size); \
> +        _ret; \
> +        })
> +
>  #if __STD_C
>  Void_t* mALLOc(size_t bytes)
>  #else
> @@ -1339,7 +1517,7 @@ Void_t* mALLOc(bytes) size_t bytes;
>        unlink(victim, bck, fwd);
>        set_inuse_bit_at_offset(victim, victim_size);
>        check_malloced_chunk(victim, nb);
> -      return chunk2mem(victim);
> +      return publish_mem(victim);
>      }
>
>      idx += 2; /* Set for bin scan below. We've already scanned 2 bins. */
> @@ -1350,7 +1528,11 @@ Void_t* mALLOc(bytes) size_t bytes;
>      idx = bin_index(nb);
>      bin = bin_at(idx);
>
> -    for (victim = last(bin); victim != bin; victim = victim->bk)
> +    for (victim = last(bin); victim != bin;
> +            ASAN_UNPOISON_MEMORY_REGION((char*)victim + 2*SIZE_SZ, 2*sizeof(uintptr_t)),
> +            victim = victim->bk,
> +            ASAN_POISON_MEMORY_REGION((char*)victim + 2*SIZE_SZ, 2*sizeof(uintptr_t))
> +            )
>      {
>        victim_size = chunksize(victim);
>        remainder_size = victim_size - nb;
> @@ -1366,7 +1548,7 @@ Void_t* mALLOc(bytes) size_t bytes;
>         unlink(victim, bck, fwd);
>         set_inuse_bit_at_offset(victim, victim_size);
>         check_malloced_chunk(victim, nb);
> -       return chunk2mem(victim);
> +       return publish_mem(victim);
>        }
>      }
>
> @@ -1389,7 +1571,7 @@ Void_t* mALLOc(bytes) size_t bytes;
>        set_head(remainder, remainder_size | PREV_INUSE);
>        set_foot(remainder, remainder_size);
>        check_malloced_chunk(victim, nb);
> -      return chunk2mem(victim);
> +      return publish_mem(victim);
>      }
>
>      clear_last_remainder;
> @@ -1398,7 +1580,7 @@ Void_t* mALLOc(bytes) size_t bytes;
>      {
>        set_inuse_bit_at_offset(victim, victim_size);
>        check_malloced_chunk(victim, nb);
> -      return chunk2mem(victim);
> +      return publish_mem(victim);
>      }
>
>      /* Else place in bin */
> @@ -1439,7 +1621,11 @@ Void_t* mALLOc(bytes) size_t bytes;
>        {
>         /* Find and use first big enough chunk ... */
>
> -       for (victim = last(bin); victim != bin; victim = victim->bk)
> +       for (victim = last(bin); victim != bin;
> +                ASAN_UNPOISON_MEMORY_REGION((char*)victim + 2*SIZE_SZ, 2*sizeof(uintptr_t)),
> +                victim = victim->bk,
> +                ASAN_POISON_MEMORY_REGION((char*)victim + 2*SIZE_SZ, 2*sizeof(uintptr_t))
> +                )
>         {
>           victim_size = chunksize(victim);
>           remainder_size = victim_size - nb;
> @@ -1453,7 +1639,7 @@ Void_t* mALLOc(bytes) size_t bytes;
>             set_head(remainder, remainder_size | PREV_INUSE);
>             set_foot(remainder, remainder_size);
>             check_malloced_chunk(victim, nb);
> -           return chunk2mem(victim);
> +           return publish_mem(victim);
>           }
>
>           else if (remainder_size >= 0)  /* take */
> @@ -1461,7 +1647,7 @@ Void_t* mALLOc(bytes) size_t bytes;
>             set_inuse_bit_at_offset(victim, victim_size);
>             unlink(victim, bck, fwd);
>             check_malloced_chunk(victim, nb);
> -           return chunk2mem(victim);
> +           return publish_mem(victim);
>           }
>
>         }
> @@ -1509,7 +1695,7 @@ Void_t* mALLOc(bytes) size_t bytes;
>      /* If big and would otherwise need to extend, try to use mmap instead */
>      if ((unsigned long)nb >= (unsigned long)mmap_threshold &&
>         (victim = mmap_chunk(nb)))
> -      return chunk2mem(victim);
> +      return publish_mem(victim);
>  #endif
>
>      /* Try to extend */
> @@ -1523,7 +1709,8 @@ Void_t* mALLOc(bytes) size_t bytes;
>    top = chunk_at_offset(victim, nb);
>    set_head(top, remainder_size | PREV_INUSE);
>    check_malloced_chunk(victim, nb);
> -  return chunk2mem(victim);
> +
> +  return publish_mem(victim);
>
>  }
>
> @@ -1578,8 +1765,12 @@ void fREe(mem) Void_t* mem;
>    if (mem == NULL)                              /* free(0) has no effect */
>      return;
>
> +  ASAN_POISON_MEMORY_REGION(mem, malloc_usable_size(mem));
> +
>    p = mem2chunk(mem);
> +  ASAN_UNPOISON_MEMORY_REGION(((char*)p) + SIZE_SZ, SIZE_SZ);
>    hd = p->size;
> +  ASAN_POISON_MEMORY_REGION(((char*)p) + SIZE_SZ, SIZE_SZ);
>
>  #if HAVE_MMAP
>    if (hd & IS_MMAPPED)                       /* release mmapped memory. */
> @@ -1601,7 +1792,9 @@ void fREe(mem) Void_t* mem;
>
>      if (!(hd & PREV_INUSE))                    /* consolidate backward */
>      {
> +      ASAN_UNPOISON_MEMORY_REGION(((char*)p), SIZE_SZ);
>        prevsz = p->prev_size;
> +      ASAN_POISON_MEMORY_REGION(((char*)p), SIZE_SZ);
>        p = chunk_at_offset(p, -((long) prevsz));
>        sz += prevsz;
>        unlink(p, bck, fwd);
> @@ -1620,20 +1813,25 @@ void fREe(mem) Void_t* mem;
>
>    if (!(hd & PREV_INUSE))                    /* consolidate backward */
>    {
> +    ASAN_UNPOISON_MEMORY_REGION(p, SIZE_SZ);
>      prevsz = p->prev_size;
> +    ASAN_POISON_MEMORY_REGION(p, SIZE_SZ);
>      p = chunk_at_offset(p, -((long) prevsz));
>      sz += prevsz;
>
> +    ASAN_UNPOISON_MEMORY_REGION((char*)p + 2*SIZE_SZ, 2*sizeof(uintptr_t));
>      if (p->fd == last_remainder)             /* keep as last_remainder */
>        islr = 1;
>      else
>        unlink(p, bck, fwd);
> +    ASAN_POISON_MEMORY_REGION((char*)p + 2*SIZE_SZ, 2*sizeof(uintptr_t));
>    }
>
>    if (!(inuse_bit_at_offset(next, nextsz)))   /* consolidate forward */
>    {
>      sz += nextsz;
>
> +    ASAN_UNPOISON_MEMORY_REGION((char*)next + 2*SIZE_SZ, 2*sizeof(uintptr_t));
>      if (!islr && next->fd == last_remainder)  /* re-insert last_remainder */
>      {
>        islr = 1;
> @@ -1641,6 +1839,7 @@ void fREe(mem) Void_t* mem;
>      }
>      else
>        unlink(next, bck, fwd);
> +    ASAN_POISON_MEMORY_REGION((char*)next + 2*SIZE_SZ, 2*sizeof(uintptr_t));
>    }
>
>
> @@ -1747,7 +1946,7 @@ Void_t* rEALLOc(oldmem, bytes) Void_t* oldmem; size_t bytes;
>    {
>  #if HAVE_MREMAP
>      newp = mremap_chunk(oldp, nb);
> -    if(newp) return chunk2mem(newp);
> +    if(newp) return publish_mem(newp);
>  #endif
>      /* Note the extra SIZE_SZ overhead. */
>      if(oldsize - SIZE_SZ >= nb) return oldmem; /* do nothing */
> @@ -1782,7 +1981,7 @@ Void_t* rEALLOc(oldmem, bytes) Void_t* oldmem; size_t bytes;
>           top = chunk_at_offset(oldp, nb);
>           set_head(top, (newsize - nb) | PREV_INUSE);
>           set_head_size(oldp, nb);
> -         return chunk2mem(oldp);
> +         return publish_mem(oldp);
>         }
>        }
>
> @@ -1895,7 +2094,7 @@ Void_t* rEALLOc(oldmem, bytes) Void_t* oldmem; size_t bytes;
>    }
>
>    check_inuse_chunk(newp);
> -  return chunk2mem(newp);
> +  return publish_mem(newp);
>  }
>
>
> @@ -2006,7 +2205,7 @@ Void_t* mEMALIGn(alignment, bytes) size_t alignment; size_t bytes;
>    {
>  #if HAVE_MMAP
>      if(chunk_is_mmapped(p))
> -      return chunk2mem(p); /* nothing more to do */
> +      return publish_mem(p); /* nothing more to do */
>  #endif
>    }
>    else /* misaligned */
> @@ -2032,7 +2231,7 @@ Void_t* mEMALIGn(alignment, bytes) size_t alignment; size_t bytes;
>      {
>        newp->prev_size = p->prev_size + leadsize;
>        set_head(newp, newsize|IS_MMAPPED);
> -      return chunk2mem(newp);
> +      return publish_mem(newp);
>      }
>  #endif
>
> @@ -2060,7 +2259,7 @@ Void_t* mEMALIGn(alignment, bytes) size_t alignment; size_t bytes;
>    }
>
>    check_inuse_chunk(p);
> -  return chunk2mem(p);
> +  return publish_mem(p);
>
>  }
>
> @@ -2318,7 +2517,10 @@ static void malloc_update_mallinfo()
>    for (i = 1; i < NAV; ++i)
>    {
>      b = bin_at(i);
> -    for (p = last(b); p != b; p = p->bk)
> +    for (p = last(b); p != b;
> +            ASAN_UNPOISON_MEMORY_REGION((char*)p + 2*SIZE_SZ, 2*sizeof(uintptr_t)),
> +            p = p->bk,
> +            ASAN_POISON_MEMORY_REGION((char*)p + 2*SIZE_SZ, 2*sizeof(uintptr_t)))
>      {
>  #ifdef DEBUG
>        check_free_chunk(p);
> diff --git a/include/compiler.h b/include/compiler.h
> index ef7b2cb1f7..7f7e82daf7 100644
> --- a/include/compiler.h
> +++ b/include/compiler.h
> @@ -126,6 +126,7 @@ typedef __u32 u32;
>
>  /* Type for `void *' pointers. */
>  typedef unsigned long int uintptr_t;
> +typedef long int intptr_t;
>
>  #include <linux/string.h>
>  #include <linux/types.h>
> diff --git a/include/linux/types.h b/include/linux/types.h
> index baa2c491ea..d86d2611c0 100644
> --- a/include/linux/types.h
> +++ b/include/linux/types.h
> @@ -25,6 +25,7 @@ typedef __kernel_uid16_t        uid16_t;
>  typedef __kernel_gid16_t        gid16_t;
>
>  typedef unsigned long          uintptr_t;
> +typedef long                   intptr_t;
>
>  #ifdef CONFIG_UID16
>  /* This is defined by include/asm-{arch}/posix_types.h */
> --
> 2.35.1.1094.g7c7d902a7c-goog
>

Regards,
Simon

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

* Re: [PATCH 01/11] sandbox: Set the EFI symbols in linker script
  2022-04-07  9:41 ` [PATCH 01/11] sandbox: Set the EFI symbols in linker script Andrew Scull
  2022-04-11 18:35   ` Simon Glass
@ 2022-04-11 22:15   ` Heinrich Schuchardt
  2022-04-11 22:37     ` Andrew Scull
  1 sibling, 1 reply; 30+ messages in thread
From: Heinrich Schuchardt @ 2022-04-11 22:15 UTC (permalink / raw)
  To: Andrew Scull; +Cc: sjg, seanga2, u-boot

On 4/7/22 11:41, Andrew Scull wrote:
> The sandbox doesn't populate the EFI lists so explicitly set the list
> start and end symbols to indicate that the lists are empty. This
> simplifies the linker scripts, removed references to non-existant
> sections and removes '.' prefixed sections that conflicted with clang's
> ASAN.


In u-boot.map I see:

10636  .text.efi_runtime
10637                 0x00000000000df50a      0x72d
/tmp/cctuEBRS.ltrans19.ltrans.o
10638                 0x00000000000df50a                efi_get_time
10639                 0x00000000000df519                efi_set_time
10640                 0x00000000000df528
efi_unimplemented.lto_priv.0
10641                 0x00000000000df54a
efi_update_capsule_unsupported
10642                 0x00000000000df559
efi_query_capsule_caps_unsupported

So there are definively functions that should go between
__efi_runtime_start and __efi_runtime_stop.

If ._efi_runtime_start == .__efi_runtime_stop, there is a bug in the
linker script. Deleting the symbols is the wrong way to deal with this
deficiency. Instead ensure correct placement of the functions marked as
__efi_runtime and the data marked as __efi_runtime_data.

Best regards

Heinrich

>
> Signed-off-by: Andrew Scull <ascull@google.com>
> ---
>   arch/sandbox/cpu/u-boot.lds | 32 +++++---------------------------
>   arch/sandbox/lib/Makefile   |  2 +-
>   arch/sandbox/lib/sections.c | 13 -------------
>   3 files changed, 6 insertions(+), 41 deletions(-)
>   delete mode 100644 arch/sandbox/lib/sections.c
>
> diff --git a/arch/sandbox/cpu/u-boot.lds b/arch/sandbox/cpu/u-boot.lds
> index 6d710618f5..dd675cc3d2 100644
> --- a/arch/sandbox/cpu/u-boot.lds
> +++ b/arch/sandbox/cpu/u-boot.lds
> @@ -19,33 +19,11 @@ SECTIONS
>   		*(.u_boot_sandbox_getopt_end)
>   	}
>
> -	.__efi_runtime_start : {
> -		*(.__efi_runtime_start)
> -	}
> -
> -	.efi_runtime : {
> -		*(efi_runtime_text)
> -		*(efi_runtime_data)
> -	}
> -
> -	.__efi_runtime_stop : {
> -		*(.__efi_runtime_stop)
> -	}
> -
> -	.efi_runtime_rel_start :
> -	{
> -		*(.__efi_runtime_rel_start)
> -	}
> -
> -	.efi_runtime_rel : {
> -		*(.relefi_runtime_text)
> -		*(.relefi_runtime_data)
> -	}
> -
> -	.efi_runtime_rel_stop :
> -	{
> -		*(.__efi_runtime_rel_stop)
> -	}
> +	/* Sandbox has empty EFI runtime lists. */
> +	__efi_runtime_start = .;
> +	__efi_runtime_stop = __efi_runtime_start;
> +	__efi_runtime_rel_start = .;
> +	__efi_runtime_rel_stop = __efi_runtime_rel_start;
>
>   	.dynsym :
>   	{
> diff --git a/arch/sandbox/lib/Makefile b/arch/sandbox/lib/Makefile
> index a2bc5a7ee6..05f06180f8 100644
> --- a/arch/sandbox/lib/Makefile
> +++ b/arch/sandbox/lib/Makefile
> @@ -5,7 +5,7 @@
>   # (C) Copyright 2002-2006
>   # Wolfgang Denk, DENX Software Engineering, wd@denx.de.
>
> -obj-y	+= fdt_fixup.o interrupts.o sections.o
> +obj-y	+= fdt_fixup.o interrupts.o
>   obj-$(CONFIG_PCI)	+= pci_io.o
>   obj-$(CONFIG_CMD_BOOTM) += bootm.o
>   obj-$(CONFIG_CMD_BOOTZ) += bootm.o
> diff --git a/arch/sandbox/lib/sections.c b/arch/sandbox/lib/sections.c
> deleted file mode 100644
> index 2559eeea38..0000000000
> --- a/arch/sandbox/lib/sections.c
> +++ /dev/null
> @@ -1,13 +0,0 @@
> -// SPDX-License-Identifier: GPL-2.0+
> -/*
> - * Copyright 2013 Albert ARIBAUD <albert.u.boot@aribaud.net>
> - *
> - */
> -#include <linux/compiler.h>
> -
> -char __efi_runtime_start[0] __section(".__efi_runtime_start");
> -char __efi_runtime_stop[0] __section(".__efi_runtime_stop");
> -char __efi_runtime_rel_start[0]
> -		__section(".__efi_runtime_rel_start");
> -char __efi_runtime_rel_stop[0]
> -		__section(".__efi_runtime_rel_stop");


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

* Re: [PATCH 01/11] sandbox: Set the EFI symbols in linker script
  2022-04-11 22:15   ` Heinrich Schuchardt
@ 2022-04-11 22:37     ` Andrew Scull
  0 siblings, 0 replies; 30+ messages in thread
From: Andrew Scull @ 2022-04-11 22:37 UTC (permalink / raw)
  To: Heinrich Schuchardt; +Cc: Simon Glass, Sean Anderson, U-Boot Mailing List

On Mon, 11 Apr 2022 at 23:15, Heinrich Schuchardt <xypron.glpk@gmx.de> wrote:
>
> On 4/7/22 11:41, Andrew Scull wrote:
> > The sandbox doesn't populate the EFI lists so explicitly set the list
> > start and end symbols to indicate that the lists are empty. This
> > simplifies the linker scripts, removed references to non-existant
> > sections and removes '.' prefixed sections that conflicted with clang's
> > ASAN.
>
>
> In u-boot.map I see:
>
> 10636  .text.efi_runtime
> 10637                 0x00000000000df50a      0x72d
> /tmp/cctuEBRS.ltrans19.ltrans.o
> 10638                 0x00000000000df50a                efi_get_time
> 10639                 0x00000000000df519                efi_set_time
> 10640                 0x00000000000df528
> efi_unimplemented.lto_priv.0
> 10641                 0x00000000000df54a
> efi_update_capsule_unsupported
> 10642                 0x00000000000df559
> efi_query_capsule_caps_unsupported
>
> So there are definively functions that should go between
> __efi_runtime_start and __efi_runtime_stop.
>
> If ._efi_runtime_start == .__efi_runtime_stop, there is a bug in the
> linker script. Deleting the symbols is the wrong way to deal with this
> deficiency. Instead ensure correct placement of the functions marked as
> __efi_runtime and the data marked as __efi_runtime_data.

I notice you point at the .text.efi_runtime section rather than the
.efi_runtime_text section that's listed in the sandbox linker script.
Looking at the other architectures, sandbox doesn't match them,
through whatever course of history, but it sounds like it's meant to.
I can try updating this patch to use the blocks below and see how
sandbox handles it.

.efi_runtime : {
        *(.text.efi_runtime*)
        *(.rodata.efi_runtime*)
        *(.data.efi_runtime*)
}

.efi_runtime_rel : {
        *(.rel*.efi_runtime)
        *(.rel*.efi_runtime.*)
}

> Best regards
>
> Heinrich
>
> >
> > Signed-off-by: Andrew Scull <ascull@google.com>
> > ---
> >   arch/sandbox/cpu/u-boot.lds | 32 +++++---------------------------
> >   arch/sandbox/lib/Makefile   |  2 +-
> >   arch/sandbox/lib/sections.c | 13 -------------
> >   3 files changed, 6 insertions(+), 41 deletions(-)
> >   delete mode 100644 arch/sandbox/lib/sections.c
> >
> > diff --git a/arch/sandbox/cpu/u-boot.lds b/arch/sandbox/cpu/u-boot.lds
> > index 6d710618f5..dd675cc3d2 100644
> > --- a/arch/sandbox/cpu/u-boot.lds
> > +++ b/arch/sandbox/cpu/u-boot.lds
> > @@ -19,33 +19,11 @@ SECTIONS
> >               *(.u_boot_sandbox_getopt_end)
> >       }
> >
> > -     .__efi_runtime_start : {
> > -             *(.__efi_runtime_start)
> > -     }
> > -
> > -     .efi_runtime : {
> > -             *(efi_runtime_text)
> > -             *(efi_runtime_data)
> > -     }
> > -
> > -     .__efi_runtime_stop : {
> > -             *(.__efi_runtime_stop)
> > -     }
> > -
> > -     .efi_runtime_rel_start :
> > -     {
> > -             *(.__efi_runtime_rel_start)
> > -     }
> > -
> > -     .efi_runtime_rel : {
> > -             *(.relefi_runtime_text)
> > -             *(.relefi_runtime_data)
> > -     }
> > -
> > -     .efi_runtime_rel_stop :
> > -     {
> > -             *(.__efi_runtime_rel_stop)
> > -     }
> > +     /* Sandbox has empty EFI runtime lists. */
> > +     __efi_runtime_start = .;
> > +     __efi_runtime_stop = __efi_runtime_start;
> > +     __efi_runtime_rel_start = .;
> > +     __efi_runtime_rel_stop = __efi_runtime_rel_start;
> >
> >       .dynsym :
> >       {
> > diff --git a/arch/sandbox/lib/Makefile b/arch/sandbox/lib/Makefile
> > index a2bc5a7ee6..05f06180f8 100644
> > --- a/arch/sandbox/lib/Makefile
> > +++ b/arch/sandbox/lib/Makefile
> > @@ -5,7 +5,7 @@
> >   # (C) Copyright 2002-2006
> >   # Wolfgang Denk, DENX Software Engineering, wd@denx.de.
> >
> > -obj-y        += fdt_fixup.o interrupts.o sections.o
> > +obj-y        += fdt_fixup.o interrupts.o
> >   obj-$(CONFIG_PCI)   += pci_io.o
> >   obj-$(CONFIG_CMD_BOOTM) += bootm.o
> >   obj-$(CONFIG_CMD_BOOTZ) += bootm.o
> > diff --git a/arch/sandbox/lib/sections.c b/arch/sandbox/lib/sections.c
> > deleted file mode 100644
> > index 2559eeea38..0000000000
> > --- a/arch/sandbox/lib/sections.c
> > +++ /dev/null
> > @@ -1,13 +0,0 @@
> > -// SPDX-License-Identifier: GPL-2.0+
> > -/*
> > - * Copyright 2013 Albert ARIBAUD <albert.u.boot@aribaud.net>
> > - *
> > - */
> > -#include <linux/compiler.h>
> > -
> > -char __efi_runtime_start[0] __section(".__efi_runtime_start");
> > -char __efi_runtime_stop[0] __section(".__efi_runtime_stop");
> > -char __efi_runtime_rel_start[0]
> > -             __section(".__efi_runtime_rel_start");
> > -char __efi_runtime_rel_stop[0]
> > -             __section(".__efi_runtime_rel_stop");
>

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

* Re: [PATCH 04/11] sandbox: Add support for Address Sanitizer
  2022-04-11 18:35   ` Simon Glass
@ 2022-04-12  9:26     ` Andrew Scull
  0 siblings, 0 replies; 30+ messages in thread
From: Andrew Scull @ 2022-04-12  9:26 UTC (permalink / raw)
  To: Simon Glass; +Cc: U-Boot Mailing List, Sean Anderson

On Mon, 11 Apr 2022 at 19:35, Simon Glass <sjg@chromium.org> wrote:
>
> Hi Andrew,
>
> On Thu, 7 Apr 2022 at 03:41, Andrew Scull <ascull@google.com> wrote:
> >
> > Add CONFIG_ASAN to build with the Address Sanitizer. This only works
> > with the sandbox so the config is likewise dependent. The resulting
> > executable will have ASAN instrumentation, including the leak detector
> > that can be disabled with the ASAN_OPTIONS environment variable:
> >
> >    ASAN_OPTIONS=detect_leaks=0 ./u-boot
> >
> > Since u-boot uses its own dlmalloc, dynamic allocations aren't
> > automatically instrumented, but stack variables and globals are.
> >
> > Instrumentation could be added to dlmalloc to poison and unpoison memory
> > as it is allocated and deallocated, and to introduce redzones between
> > allocations. Alternatively, the sandbox may be able to play games with
> > the system allocator and somehow still keep the required memory
> > abstraction. No effort to address dynamic allocation is made by this
> > patch.
>
> I have toyed with what to do here. I originally was thinking of using
> normal malloc() instead of dlmalloc() when running sandbox. But then
> of course it makes sandbox very diffferent from other archs, so it is
> not desirable. So I did not go down that path. Having said that,
> os_malloc() is used for some sandbox-specific things.
>
> I would love to have an extra string parameter to malloc() which
> indicates what is doing the allocation (malloc_tag(size_t size, char
> *id)), so it is easier to see failures and get an annotated 'core
> dump'. But again, changing the alloc API is not so nice.
>
> One weird thing to be aware of is that truetype fonts cause constant
> allocs and frees. It happens in the background but you'll notice it if
> you start tracing things.

Using the system allocator would give the nicest ASAN experience
because a special allocator gets injected that tracks where
allocations were made etc. so when a problem occurs it can point to
the likely allocations automatically.

How did you go about keeping the memory model when using the system allocator?

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

* Re: [PATCH 11/11] RFC: Hack dlmalloc to poison memory
  2022-04-11 18:35   ` Simon Glass
@ 2022-04-12 10:19     ` Andrew Scull
  0 siblings, 0 replies; 30+ messages in thread
From: Andrew Scull @ 2022-04-12 10:19 UTC (permalink / raw)
  To: Simon Glass; +Cc: U-Boot Mailing List, Sean Anderson

On Mon, 11 Apr 2022 at 19:36, Simon Glass <sjg@chromium.org> wrote:
>
> Hi Andrew,
>
> On Thu, 7 Apr 2022 at 03:41, Andrew Scull <ascull@google.com> wrote:
> >
> > This is a hugely ugly hack to poison and unpoison memory allocated by
> > dlmalloc. It wraps every access dlmalloc makes to the metadata breifly
> > allow it access, taking care not to then poison the parts of the record
> > which overlap.
> >
> > The result is very small redzones between the allocations, which has
> > limted value but has able to spot immediate buffer overruns.
> >
> > The instrumentation is extremely intrusive and would be benefited by
> > more intrusions to increase redzone sizes etc.
> >
> > Signed-off-by: Andrew Scull <ascull@google.com>
> > ---
> >  common/dlmalloc.c     | 284 ++++++++++++++++++++++++++++++++++++------
> >  include/compiler.h    |   1 +
> >  include/linux/types.h |   1 +
> >  3 files changed, 245 insertions(+), 41 deletions(-)
>
> This actually seems very useful to me. I wonder if it could be split
> into a few patches, for easier review?
>
> Also what is the mechanism to enable/disable this?
>
> I've made a few comments anyway.
>
> The changes to include/ need a look. I'm not sure whether we can avoid
> them, but if not, they could go in their own patch.

This is an integration with ASAN [1] so it's enabled/disabled along
with CONFIG_ASAN (although not fully in this extremely messy hack).

If this level of intrucivity is acceptable, there's a reasonable
amount of cleanup that could be done, some that you've pointed out,
but the macros are still going to be littered all around unless a
deeper understanding of the dlmalloc implementation makes further
simplification possible. Even after cleaning up, the limitations from
the commit message would still apply, limitations that wouldn't exist
with the system allocator.

[1] -- https://github.com/google/sanitizers/wiki/AddressSanitizerManualPoisoning

> >
> > diff --git a/common/dlmalloc.c b/common/dlmalloc.c
> > index 11729e8c85..614f004579 100644
> > --- a/common/dlmalloc.c
> > +++ b/common/dlmalloc.c
> > @@ -8,6 +8,8 @@
> >   * as file malloc-2.6.6.c.
> >   */
> >
> > +#define DEBUG
> > +
> >  #include <common.h>
> >  #include <log.h>
> >  #include <asm/global_data.h>
> > @@ -16,6 +18,8 @@
> >  #define DEBUG
> >  #endif
> >
> > +#include <sanitizer/asan_interface.h>
> > +
> >  #include <malloc.h>
> >  #include <asm/io.h>
> >
> > @@ -31,6 +35,17 @@ void malloc_stats();
> >
> >  DECLARE_GLOBAL_DATA_PTR;
> >
> > +/*
> > +#undef ASAN_POISON_MEMORY_REGION
> > +#define ASAN_POISON_MEMORY_REGION(p, s) do { \
> > +    if ((uintptr_t)p == 0x0000150200c0) { \
> > +        printf("size %lx\n", s); \
> > +        *(int*)NULL = 9; \
> > +    } \
> > +    __asan_poison_memory_region(p, s); \
> > +} while (0)
> > +*/
> > +
> >  /*
> >    Emulation of sbrk for WIN32
> >    All code within the ifdef WIN32 is untested by me.
> > @@ -409,12 +424,26 @@ nextchunk-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
> >
> >  /* Ptr to next physical malloc_chunk. */
> >
> > -#define next_chunk(p) ((mchunkptr)( ((char*)(p)) + ((p)->size & ~PREV_INUSE) ))
> > +#define _next_chunk(p) ((mchunkptr)( ((char*)(p)) + ((p)->size & ~PREV_INUSE) ))
> > +#define next_chunk(p) ({ \
> > +        mchunkptr _ptr = (p); \
> > +        ASAN_UNPOISON_MEMORY_REGION(((char*)_ptr) + SIZE_SZ, SIZE_SZ); \
>
> Where is that defined?
>
> > +        mchunkptr _ret = _next_chunk(_ptr); \
> > +        ASAN_POISON_MEMORY_REGION(((char*)_ptr) + SIZE_SZ, SIZE_SZ); \
> > +        _ret; \
> > +        })
> >
> >  /* Ptr to previous physical malloc_chunk */
> >
> > -#define prev_chunk(p)\
> > +#define _prev_chunk(p)\
> >     ((mchunkptr)( ((char*)(p)) - ((p)->prev_size) ))
> > +#define prev_chunk(p) ({ \
> > +        mchunkptr _ptr = (p); \
> > +        ASAN_UNPOISON_MEMORY_REGION(_ptr, SIZE_SZ); \
>
> How about ASON_CURE() for brevity
>
> > +        mchunkptr _ret = _prev_chunk(_ptr); \
> > +        ASAN_POISON_MEMORY_REGION(_ptr, SIZE_SZ); \
>
> ASON_POISON() ?
>
> > +        _ret; \
> > +        })
> >
> >
> >  /* Treat space at ptr + offset as a chunk */
> > @@ -430,35 +459,102 @@ nextchunk-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
> >
> >  /* extract p's inuse bit */
> >
> > -#define inuse(p)\
> > +#define _inuse(p)\
> >  ((((mchunkptr)(((char*)(p))+((p)->size & ~PREV_INUSE)))->size) & PREV_INUSE)
> > +#define inuse(p) ({ \
> > +        mchunkptr _p = (p); \
> > +        ASAN_UNPOISON_MEMORY_REGION(((char*)_p) + SIZE_SZ, SIZE_SZ); \
> > +        mchunkptr _ptr = ((mchunkptr)(((char*)_p)+(_p->size & ~PREV_INUSE))); \
> > +        ASAN_UNPOISON_MEMORY_REGION(((char*)_ptr) + SIZE_SZ, SIZE_SZ); \
> > +        INTERNAL_SIZE_T _ret = _inuse(_p); \
> > +        ASAN_POISON_MEMORY_REGION(((char*)_ptr) + SIZE_SZ, SIZE_SZ); \
> > +        ASAN_POISON_MEMORY_REGION(((char*)_p) + SIZE_SZ, SIZE_SZ); \
> > +        _ret; \
> > +        })
> >
> >  /* extract inuse bit of previous chunk */
> >
> > -#define prev_inuse(p)  ((p)->size & PREV_INUSE)
> > +#define _prev_inuse(p)  ((p)->size & PREV_INUSE)
> > +#define prev_inuse(p) ({ \
> > +        mchunkptr _ptr = (p); \
> > +        ASAN_UNPOISON_MEMORY_REGION(((char*)_ptr) + SIZE_SZ, SIZE_SZ); \
> > +        INTERNAL_SIZE_T _ret = _prev_inuse(_ptr); \
> > +        ASAN_POISON_MEMORY_REGION(((char*)_ptr) + SIZE_SZ, SIZE_SZ); \
> > +        _ret; \
> > +        })
> >
> >  /* check for mmap()'ed chunk */
> >
> > -#define chunk_is_mmapped(p) ((p)->size & IS_MMAPPED)
> > +#define _chunk_is_mmapped(p) ((p)->size & IS_MMAPPED)
> > +#define chunk_is_mmapped(p) ({ \
> > +        mchunkptr _ptr = (p); \
> > +        ASAN_UNPOISON_MEMORY_REGION(((char*)_ptr) + SIZE_SZ, SIZE_SZ); \
> > +        INTERNAL_SIZE_T _ret = _chunk_is_mmapped(_ptr); \
> > +        ASAN_POISON_MEMORY_REGION(((char*)_ptr) + SIZE_SZ, SIZE_SZ); \
> > +        _ret; \
> > +        })
> >
> >  /* set/clear chunk as in use without otherwise disturbing */
> >
> > -#define set_inuse(p)\
> > +#define _set_inuse(p)\
> >  ((mchunkptr)(((char*)(p)) + ((p)->size & ~PREV_INUSE)))->size |= PREV_INUSE
> > -
> > -#define clear_inuse(p)\
> > +#define set_inuse(p, s) ({ \
> > +        mchunkptr _p = (p); \
> > +        ASAN_UNPOISON_MEMORY_REGION(((char*)_p) + SIZE_SZ, SIZE_SZ); \
> > +        mchunkptr _ptr = ((mchunkptr)(((char*)_p)+(_p->size & ~PREV_INUSE))); \
> > +        ASAN_UNPOISON_MEMORY_REGION(((char*)_ptr) + SIZE_SZ, SIZE_SZ); \
> > +        _set_inuse(_p, (s)); \
> > +        ASAN_POISON_MEMORY_REGION(((char*)_ptr) + SIZE_SZ, SIZE_SZ); \
> > +        ASAN_POISON_MEMORY_REGION(((char*)_p) + SIZE_SZ, SIZE_SZ); \
> > +        })
> > +
> > +#define _clear_inuse(p)\
> >  ((mchunkptr)(((char*)(p)) + ((p)->size & ~PREV_INUSE)))->size &= ~(PREV_INUSE)
> > +#define clear_inuse(p, s) ({ \
> > +        __typeof__(p) _p = (p); \
> > +        ASAN_UNPOISON_MEMORY_REGION(((char*)_p) + SIZE_SZ, SIZE_SZ); \
> > +        mchunkptr _ptr = ((mchunkptr)(((char*)_p)+(_p->size & ~PREV_INUSE))); \
> > +        ASAN_UNPOISON_MEMORY_REGION(((char*)_ptr) + SIZE_SZ, SIZE_SZ); \
> > +        _clear_inuse(_p, (s)); \
> > +        ASAN_POISON_MEMORY_REGION(((char*)_ptr) + SIZE_SZ, SIZE_SZ); \
> > +        ASAN_POISON_MEMORY_REGION(((char*)_p) + SIZE_SZ, SIZE_SZ); \
> > +        })
> >
> >  /* check/set/clear inuse bits in known places */
> >
> > -#define inuse_bit_at_offset(p, s)\
> > +#define _inuse_bit_at_offset(p, s)\
> >   (((mchunkptr)(((char*)(p)) + (s)))->size & PREV_INUSE)
> > -
> > -#define set_inuse_bit_at_offset(p, s)\
> > +#define inuse_bit_at_offset(p, s) ({ \
> > +        __typeof__(p) _p = (p); \
> > +        __typeof__(s) _s = (s); \
> > +        __typeof__(p) _ptr = (mchunkptr)(((char*)_p) + _s); \
> > +        ASAN_UNPOISON_MEMORY_REGION(((char*)_ptr) + SIZE_SZ, SIZE_SZ); \
> > +        INTERNAL_SIZE_T _ret = _inuse_bit_at_offset(_p, _s); \
> > +        ASAN_POISON_MEMORY_REGION(((char*)_ptr) + SIZE_SZ, SIZE_SZ); \
> > +        _ret; \
> > +        })
> > +
> > +#define _set_inuse_bit_at_offset(p, s)\
> >   (((mchunkptr)(((char*)(p)) + (s)))->size |= PREV_INUSE)
> > -
> > -#define clear_inuse_bit_at_offset(p, s)\
> > +#define set_inuse_bit_at_offset(p, s) ({ \
> > +        __typeof__(p) _p = (p); \
> > +        __typeof__(s) _s = (s); \
> > +        __typeof__(p) _ptr = (mchunkptr)(((char*)_p) + _s); \
> > +        ASAN_UNPOISON_MEMORY_REGION(((char*)_ptr) + SIZE_SZ, SIZE_SZ); \
> > +        _set_inuse_bit_at_offset(_p, _s); \
> > +        ASAN_POISON_MEMORY_REGION(((char*)_ptr) + SIZE_SZ, SIZE_SZ); \
> > +        })
> > +
> > +#define _clear_inuse_bit_at_offset(p, s)\
> >   (((mchunkptr)(((char*)(p)) + (s)))->size &= ~(PREV_INUSE))
> > +#define clear_inuse_bit_at_offset(p, s) ({ \
> > +        __typeof__(p) _p = (p); \
> > +        __typeof__(s) _s = (s); \
> > +        __typeof__(p) _ptr = (mchunkptr)(((char*)_p) + _s); \
> > +        ASAN_UNPOISON_MEMORY_REGION(((char*)_ptr) + SIZE_SZ, SIZE_SZ); \
> > +        _clear_inuse_bit_at_offset(_p, _s); \
> > +        ASAN_POISON_MEMORY_REGION(((char*)_ptr) + SIZE_SZ, SIZE_SZ); \
> > +        })
> >
> >
> >
> > @@ -469,19 +565,46 @@ nextchunk-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
> >
> >  /* Get size, ignoring use bits */
> >
> > -#define chunksize(p)          ((p)->size & ~(SIZE_BITS))
> > +#define _chunksize(p)          ((p)->size & ~(SIZE_BITS))
> > +#define chunksize(p) ({ \
> > +        mchunkptr _ptr = (p); \
> > +        ASAN_UNPOISON_MEMORY_REGION(((char*)_ptr) + SIZE_SZ, SIZE_SZ); \
> > +        INTERNAL_SIZE_T _ret = _chunksize(_ptr); \
> > +        ASAN_POISON_MEMORY_REGION(((char*)_ptr) + SIZE_SZ, SIZE_SZ); \
> > +        _ret; \
> > +        })
> >
> >  /* Set size at head, without disturbing its use bit */
> >
> > -#define set_head_size(p, s)   ((p)->size = (((p)->size & PREV_INUSE) | (s)))
> > +#define _set_head_size(p, s)   ((p)->size = (((p)->size & PREV_INUSE) | (s)))
> > +#define set_head_size(p, s) ({ \
> > +        __typeof__(p) _ptr = (p); \
> > +        ASAN_UNPOISON_MEMORY_REGION(((char*)_ptr) + SIZE_SZ, SIZE_SZ); \
> > +        _set_head_size(_ptr, (s)); \
> > +        ASAN_POISON_MEMORY_REGION(((char*)_ptr) + SIZE_SZ, SIZE_SZ); \
> > +        })
> >
> >  /* Set size/use ignoring previous bits in header */
> >
> > -#define set_head(p, s)        ((p)->size = (s))
> > +#define _set_head(p, s)        ((p)->size = (s))
> > +#define set_head(p, s) ({ \
> > +        __typeof__(p) _ptr = (p); \
> > +        ASAN_UNPOISON_MEMORY_REGION(((char*)_ptr) + SIZE_SZ, SIZE_SZ); \
> > +        _set_head(_ptr, (s)); \
> > +        ASAN_POISON_MEMORY_REGION(((char*)_ptr) + SIZE_SZ, SIZE_SZ); \
> > +        })
> >
> >  /* Set size at footer (only when chunk is not in use) */
> >
> > -#define set_foot(p, s)   (((mchunkptr)((char*)(p) + (s)))->prev_size = (s))
> > +#define _set_foot(p, s)   (((mchunkptr)((char*)(p) + (s)))->prev_size = (s))
> > +#define set_foot(p, s) ({ \
> > +        __typeof__(p) _p = (p); \
> > +        __typeof__(s) _s = (s); \
> > +        __typeof__(p) _ptr = (mchunkptr)(((char*)_p) + _s); \
> > +        ASAN_UNPOISON_MEMORY_REGION(_ptr, SIZE_SZ); \
> > +        _set_foot(_p, (s)); \
> > +        ASAN_POISON_MEMORY_REGION(_ptr, SIZE_SZ); \
> > +        })
> >
> >
> >
> > @@ -604,8 +727,11 @@ void *sbrk(ptrdiff_t increment)
> >          * if we are giving memory back make sure we clear it out since
> >          * we set MORECORE_CLEARS to 1
> >          */
> > -       if (increment < 0)
> > +       if (increment < 0) {
> > +                ASAN_UNPOISON_MEMORY_REGION((void *)new, -increment);
> >                 memset((void *)new, 0, -increment);
> > +                ASAN_POISON_MEMORY_REGION((void *)new, -increment);
> > +        }
> >
> >         if ((new < mem_malloc_start) || (new > mem_malloc_end))
> >                 return (void *)MORECORE_FAILURE;
> > @@ -630,13 +756,24 @@ void mem_malloc_init(ulong start, ulong size)
> >  #ifdef CONFIG_SYS_MALLOC_CLEAR_ON_INIT
> >         memset((void *)mem_malloc_start, 0x0, size);
> >  #endif
> > +        ASAN_POISON_MEMORY_REGION((void *)start, size);
> >         malloc_bin_reloc();
> >  }
> >
> >  /* field-extraction macros */
> >
> > -#define first(b) ((b)->fd)
> > -#define last(b)  ((b)->bk)
> > +#define first(b) ({ \
> > +        ASAN_UNPOISON_MEMORY_REGION(((char*)b) + 2*SIZE_SZ, 2*sizeof(uintptr_t)); \
> > +        void *_ret = (b)->fd; \
> > +        ASAN_UNPOISON_MEMORY_REGION(((char*)b) + 2*SIZE_SZ, 2*sizeof(uintptr_t)); \
> > +        _ret; \
> > +        })
> > +#define last(b)  ({ \
> > +        ASAN_UNPOISON_MEMORY_REGION(((char*)b) + 2*SIZE_SZ, 2*sizeof(uintptr_t)); \
> > +        void *_ret = (b)->bk; \
> > +        ASAN_UNPOISON_MEMORY_REGION(((char*)b) + 2*SIZE_SZ, 2*sizeof(uintptr_t)); \
> > +        _ret; \
> > +        })
> >
> >  /*
> >    Indexing into bins
> > @@ -781,7 +918,7 @@ static void do_check_chunk(mchunkptr p)
> >  static void do_check_chunk(p) mchunkptr p;
> >  #endif
> >  {
> > -  INTERNAL_SIZE_T sz = p->size & ~PREV_INUSE;
> > +  INTERNAL_SIZE_T sz = chunksize(p);
> >
> >    /* No checkable chunk is mmapped */
> >    assert(!chunk_is_mmapped(p));
> > @@ -802,7 +939,7 @@ static void do_check_free_chunk(mchunkptr p)
> >  static void do_check_free_chunk(p) mchunkptr p;
> >  #endif
> >  {
> > -  INTERNAL_SIZE_T sz = p->size & ~PREV_INUSE;
> > +  INTERNAL_SIZE_T sz = chunksize(p);
> >    mchunkptr next = chunk_at_offset(p, sz);
> >
> >    do_check_chunk(p);
> > @@ -816,14 +953,22 @@ static void do_check_free_chunk(p) mchunkptr p;
> >      assert((sz & MALLOC_ALIGN_MASK) == 0);
> >      assert(aligned_OK(chunk2mem(p)));
> >      /* ... matching footer field */
> > +    ASAN_UNPOISON_MEMORY_REGION(next, SIZE_SZ);
> >      assert(next->prev_size == sz);
> > +    ASAN_POISON_MEMORY_REGION(next, SIZE_SZ);
> >      /* ... and is fully consolidated */
> >      assert(prev_inuse(p));
> >      assert (next == top || inuse(next));
> >
> >      /* ... and has minimally sane links */
> > +    ASAN_UNPOISON_MEMORY_REGION(((char*)p) + 2*SIZE_SZ, 2*sizeof(uintptr_t));
> > +    ASAN_UNPOISON_MEMORY_REGION(((char*)p->fd) + 2*SIZE_SZ, 2*sizeof(uintptr_t));
> > +    ASAN_UNPOISON_MEMORY_REGION(((char*)p->bk) + 2*SIZE_SZ, 2*sizeof(uintptr_t));
> >      assert(p->fd->bk == p);
> >      assert(p->bk->fd == p);
> > +    ASAN_POISON_MEMORY_REGION(((char*)p->fd) + 2*SIZE_SZ, 2*sizeof(uintptr_t));
> > +    ASAN_POISON_MEMORY_REGION(((char*)p->bk) + 2*SIZE_SZ, 2*sizeof(uintptr_t));
> > +    ASAN_POISON_MEMORY_REGION(((char*)p) + 2*SIZE_SZ, 2*sizeof(uintptr_t));
> >    }
> >    else /* markers are always of size SIZE_SZ */
> >      assert(sz == SIZE_SZ);
> > @@ -867,7 +1012,7 @@ static void do_check_malloced_chunk(mchunkptr p, INTERNAL_SIZE_T s)
> >  static void do_check_malloced_chunk(p, s) mchunkptr p; INTERNAL_SIZE_T s;
> >  #endif
> >  {
> > -  INTERNAL_SIZE_T sz = p->size & ~PREV_INUSE;
> > +  INTERNAL_SIZE_T sz = chunksize(p);
> >    long room = sz - s;
> >
> >    do_check_inuse_chunk(p);
> > @@ -919,31 +1064,48 @@ static void do_check_malloced_chunk(p, s) mchunkptr p; INTERNAL_SIZE_T s;
> >
> >  #define frontlink(P, S, IDX, BK, FD)                                          \
> >  {                                                                             \
> > +  ASAN_UNPOISON_MEMORY_REGION(((char*)P) + 2*SIZE_SZ, 2*sizeof(uintptr_t));                                 \
> >    if (S < MAX_SMALLBIN_SIZE)                                                  \
> >    {                                                                           \
> >      IDX = smallbin_index(S);                                                  \
> >      mark_binblock(IDX);                                                       \
> >      BK = bin_at(IDX);                                                         \
> > +  ASAN_UNPOISON_MEMORY_REGION(((char*)BK) + 2*SIZE_SZ, 2*sizeof(uintptr_t));                                 \
> >      FD = BK->fd;                                                              \
> >      P->bk = BK;                                                               \
> >      P->fd = FD;                                                               \
> > +  ASAN_UNPOISON_MEMORY_REGION(((char*)FD) + 2*SIZE_SZ, 2*sizeof(uintptr_t));                                 \
> >      FD->bk = BK->fd = P;                                                      \
> >    }                                                                           \
> >    else                                                                        \
> >    {                                                                           \
> >      IDX = bin_index(S);                                                       \
> >      BK = bin_at(IDX);                                                         \
> > +  ASAN_UNPOISON_MEMORY_REGION(((char*)BK) + 2*SIZE_SZ, 2*sizeof(uintptr_t));                                 \
> >      FD = BK->fd;                                                              \
> > +  ASAN_UNPOISON_MEMORY_REGION(((char*)FD) + 2*SIZE_SZ, 2*sizeof(uintptr_t));                                 \
> >      if (FD == BK) mark_binblock(IDX);                                         \
> >      else                                                                      \
> >      {                                                                         \
> > -      while (FD != BK && S < chunksize(FD)) FD = FD->fd;                      \
> > +      while (FD != BK && S < chunksize(FD)) { \
> > +          mchunkptr old = FD; \
> > +          FD = FD->fd;                      \
> > +        ASAN_POISON_MEMORY_REGION(((char*)old) + 2*SIZE_SZ, 2*sizeof(uintptr_t));                                 \
> > +        ASAN_UNPOISON_MEMORY_REGION(((char*)FD) + 2*SIZE_SZ, 2*sizeof(uintptr_t));                                 \
> > +      } \
> > +      mchunkptr oldbk = BK; \
> >        BK = FD->bk;                                                            \
> > +  ASAN_POISON_MEMORY_REGION(((char*)oldbk) + 2*SIZE_SZ, 2*sizeof(uintptr_t));                                 \
> > +  ASAN_UNPOISON_MEMORY_REGION(((char*)BK) + 2*SIZE_SZ, 2*sizeof(uintptr_t));                                 \
> > +        ASAN_UNPOISON_MEMORY_REGION(((char*)FD) + 2*SIZE_SZ, 2*sizeof(uintptr_t));                                 \
> >      }                                                                         \
> >      P->bk = BK;                                                               \
> >      P->fd = FD;                                                               \
> >      FD->bk = BK->fd = P;                                                      \
> >    }                                                                           \
> > +  ASAN_POISON_MEMORY_REGION(((char*)P) + 2*SIZE_SZ, 2*sizeof(uintptr_t));                                 \
> > +  ASAN_POISON_MEMORY_REGION(((char*)BK) + 2*SIZE_SZ, 2*sizeof(uintptr_t));                                 \
> > +  ASAN_POISON_MEMORY_REGION(((char*)FD) + 2*SIZE_SZ, 2*sizeof(uintptr_t));                                 \
> >  }
> >
> >
> > @@ -951,18 +1113,26 @@ static void do_check_malloced_chunk(p, s) mchunkptr p; INTERNAL_SIZE_T s;
> >
> >  #define unlink(P, BK, FD)                                                     \
> >  {                                                                             \
> > +  ASAN_UNPOISON_MEMORY_REGION(((char*)P) + 2*SIZE_SZ, 2*sizeof(uintptr_t));                                 \
> >    BK = P->bk;                                                                 \
> >    FD = P->fd;                                                                 \
> > +  ASAN_POISON_MEMORY_REGION(((char*)P) + 2*SIZE_SZ, 2*sizeof(uintptr_t));                                 \
> > +  ASAN_UNPOISON_MEMORY_REGION(((char*)BK) + 2*SIZE_SZ, 2*sizeof(uintptr_t));                                 \
> > +  ASAN_UNPOISON_MEMORY_REGION(((char*)FD) + 2*SIZE_SZ, 2*sizeof(uintptr_t));                                 \
> >    FD->bk = BK;                                                                \
> >    BK->fd = FD;                                                                \
> > +  ASAN_POISON_MEMORY_REGION(((char*)BK) + 2*SIZE_SZ, 2*sizeof(uintptr_t));                                 \
> > +  ASAN_POISON_MEMORY_REGION(((char*)FD) + 2*SIZE_SZ, 2*sizeof(uintptr_t));                                 \
> >  }                                                                             \
> >
> >  /* Place p as the last remainder */
> >
> >  #define link_last_remainder(P)                                                \
> >  {                                                                             \
> > +  ASAN_UNPOISON_MEMORY_REGION(((char*)P) + 2*SIZE_SZ, 2*sizeof(uintptr_t));                                 \
> >    last_remainder->fd = last_remainder->bk =  P;                               \
> >    P->fd = P->bk = last_remainder;                                             \
> > +  ASAN_POISON_MEMORY_REGION(((char*)P) + 2*SIZE_SZ, 2*sizeof(uintptr_t));                                 \
> >  }
> >
> >  /* Clear the last_remainder bin */
> > @@ -1280,6 +1450,14 @@ static void malloc_extend_top(nb) INTERNAL_SIZE_T nb;
> >
> >  */
> >
> > +#define publish_mem(p) ({ \
>
> Could use a comment
>
> > +        __typeof__(p) _chunk = (p); \
> > +        Void_t *_ret = chunk2mem(_chunk); \
> > +        INTERNAL_SIZE_T _size = malloc_usable_size(_ret); \
> > +        ASAN_UNPOISON_MEMORY_REGION(_ret, _size); \
> > +        _ret; \
> > +        })
> > +
> >  #if __STD_C
> >  Void_t* mALLOc(size_t bytes)
> >  #else
> > @@ -1339,7 +1517,7 @@ Void_t* mALLOc(bytes) size_t bytes;
> >        unlink(victim, bck, fwd);
> >        set_inuse_bit_at_offset(victim, victim_size);
> >        check_malloced_chunk(victim, nb);
> > -      return chunk2mem(victim);
> > +      return publish_mem(victim);
> >      }
> >
> >      idx += 2; /* Set for bin scan below. We've already scanned 2 bins. */
> > @@ -1350,7 +1528,11 @@ Void_t* mALLOc(bytes) size_t bytes;
> >      idx = bin_index(nb);
> >      bin = bin_at(idx);
> >
> > -    for (victim = last(bin); victim != bin; victim = victim->bk)
> > +    for (victim = last(bin); victim != bin;
> > +            ASAN_UNPOISON_MEMORY_REGION((char*)victim + 2*SIZE_SZ, 2*sizeof(uintptr_t)),
> > +            victim = victim->bk,
> > +            ASAN_POISON_MEMORY_REGION((char*)victim + 2*SIZE_SZ, 2*sizeof(uintptr_t))
> > +            )
> >      {
> >        victim_size = chunksize(victim);
> >        remainder_size = victim_size - nb;
> > @@ -1366,7 +1548,7 @@ Void_t* mALLOc(bytes) size_t bytes;
> >         unlink(victim, bck, fwd);
> >         set_inuse_bit_at_offset(victim, victim_size);
> >         check_malloced_chunk(victim, nb);
> > -       return chunk2mem(victim);
> > +       return publish_mem(victim);
> >        }
> >      }
> >
> > @@ -1389,7 +1571,7 @@ Void_t* mALLOc(bytes) size_t bytes;
> >        set_head(remainder, remainder_size | PREV_INUSE);
> >        set_foot(remainder, remainder_size);
> >        check_malloced_chunk(victim, nb);
> > -      return chunk2mem(victim);
> > +      return publish_mem(victim);
> >      }
> >
> >      clear_last_remainder;
> > @@ -1398,7 +1580,7 @@ Void_t* mALLOc(bytes) size_t bytes;
> >      {
> >        set_inuse_bit_at_offset(victim, victim_size);
> >        check_malloced_chunk(victim, nb);
> > -      return chunk2mem(victim);
> > +      return publish_mem(victim);
> >      }
> >
> >      /* Else place in bin */
> > @@ -1439,7 +1621,11 @@ Void_t* mALLOc(bytes) size_t bytes;
> >        {
> >         /* Find and use first big enough chunk ... */
> >
> > -       for (victim = last(bin); victim != bin; victim = victim->bk)
> > +       for (victim = last(bin); victim != bin;
> > +                ASAN_UNPOISON_MEMORY_REGION((char*)victim + 2*SIZE_SZ, 2*sizeof(uintptr_t)),
> > +                victim = victim->bk,
> > +                ASAN_POISON_MEMORY_REGION((char*)victim + 2*SIZE_SZ, 2*sizeof(uintptr_t))
> > +                )
> >         {
> >           victim_size = chunksize(victim);
> >           remainder_size = victim_size - nb;
> > @@ -1453,7 +1639,7 @@ Void_t* mALLOc(bytes) size_t bytes;
> >             set_head(remainder, remainder_size | PREV_INUSE);
> >             set_foot(remainder, remainder_size);
> >             check_malloced_chunk(victim, nb);
> > -           return chunk2mem(victim);
> > +           return publish_mem(victim);
> >           }
> >
> >           else if (remainder_size >= 0)  /* take */
> > @@ -1461,7 +1647,7 @@ Void_t* mALLOc(bytes) size_t bytes;
> >             set_inuse_bit_at_offset(victim, victim_size);
> >             unlink(victim, bck, fwd);
> >             check_malloced_chunk(victim, nb);
> > -           return chunk2mem(victim);
> > +           return publish_mem(victim);
> >           }
> >
> >         }
> > @@ -1509,7 +1695,7 @@ Void_t* mALLOc(bytes) size_t bytes;
> >      /* If big and would otherwise need to extend, try to use mmap instead */
> >      if ((unsigned long)nb >= (unsigned long)mmap_threshold &&
> >         (victim = mmap_chunk(nb)))
> > -      return chunk2mem(victim);
> > +      return publish_mem(victim);
> >  #endif
> >
> >      /* Try to extend */
> > @@ -1523,7 +1709,8 @@ Void_t* mALLOc(bytes) size_t bytes;
> >    top = chunk_at_offset(victim, nb);
> >    set_head(top, remainder_size | PREV_INUSE);
> >    check_malloced_chunk(victim, nb);
> > -  return chunk2mem(victim);
> > +
> > +  return publish_mem(victim);
> >
> >  }
> >
> > @@ -1578,8 +1765,12 @@ void fREe(mem) Void_t* mem;
> >    if (mem == NULL)                              /* free(0) has no effect */
> >      return;
> >
> > +  ASAN_POISON_MEMORY_REGION(mem, malloc_usable_size(mem));
> > +
> >    p = mem2chunk(mem);
> > +  ASAN_UNPOISON_MEMORY_REGION(((char*)p) + SIZE_SZ, SIZE_SZ);
> >    hd = p->size;
> > +  ASAN_POISON_MEMORY_REGION(((char*)p) + SIZE_SZ, SIZE_SZ);
> >
> >  #if HAVE_MMAP
> >    if (hd & IS_MMAPPED)                       /* release mmapped memory. */
> > @@ -1601,7 +1792,9 @@ void fREe(mem) Void_t* mem;
> >
> >      if (!(hd & PREV_INUSE))                    /* consolidate backward */
> >      {
> > +      ASAN_UNPOISON_MEMORY_REGION(((char*)p), SIZE_SZ);
> >        prevsz = p->prev_size;
> > +      ASAN_POISON_MEMORY_REGION(((char*)p), SIZE_SZ);
> >        p = chunk_at_offset(p, -((long) prevsz));
> >        sz += prevsz;
> >        unlink(p, bck, fwd);
> > @@ -1620,20 +1813,25 @@ void fREe(mem) Void_t* mem;
> >
> >    if (!(hd & PREV_INUSE))                    /* consolidate backward */
> >    {
> > +    ASAN_UNPOISON_MEMORY_REGION(p, SIZE_SZ);
> >      prevsz = p->prev_size;
> > +    ASAN_POISON_MEMORY_REGION(p, SIZE_SZ);
> >      p = chunk_at_offset(p, -((long) prevsz));
> >      sz += prevsz;
> >
> > +    ASAN_UNPOISON_MEMORY_REGION((char*)p + 2*SIZE_SZ, 2*sizeof(uintptr_t));
> >      if (p->fd == last_remainder)             /* keep as last_remainder */
> >        islr = 1;
> >      else
> >        unlink(p, bck, fwd);
> > +    ASAN_POISON_MEMORY_REGION((char*)p + 2*SIZE_SZ, 2*sizeof(uintptr_t));
> >    }
> >
> >    if (!(inuse_bit_at_offset(next, nextsz)))   /* consolidate forward */
> >    {
> >      sz += nextsz;
> >
> > +    ASAN_UNPOISON_MEMORY_REGION((char*)next + 2*SIZE_SZ, 2*sizeof(uintptr_t));
> >      if (!islr && next->fd == last_remainder)  /* re-insert last_remainder */
> >      {
> >        islr = 1;
> > @@ -1641,6 +1839,7 @@ void fREe(mem) Void_t* mem;
> >      }
> >      else
> >        unlink(next, bck, fwd);
> > +    ASAN_POISON_MEMORY_REGION((char*)next + 2*SIZE_SZ, 2*sizeof(uintptr_t));
> >    }
> >
> >
> > @@ -1747,7 +1946,7 @@ Void_t* rEALLOc(oldmem, bytes) Void_t* oldmem; size_t bytes;
> >    {
> >  #if HAVE_MREMAP
> >      newp = mremap_chunk(oldp, nb);
> > -    if(newp) return chunk2mem(newp);
> > +    if(newp) return publish_mem(newp);
> >  #endif
> >      /* Note the extra SIZE_SZ overhead. */
> >      if(oldsize - SIZE_SZ >= nb) return oldmem; /* do nothing */
> > @@ -1782,7 +1981,7 @@ Void_t* rEALLOc(oldmem, bytes) Void_t* oldmem; size_t bytes;
> >           top = chunk_at_offset(oldp, nb);
> >           set_head(top, (newsize - nb) | PREV_INUSE);
> >           set_head_size(oldp, nb);
> > -         return chunk2mem(oldp);
> > +         return publish_mem(oldp);
> >         }
> >        }
> >
> > @@ -1895,7 +2094,7 @@ Void_t* rEALLOc(oldmem, bytes) Void_t* oldmem; size_t bytes;
> >    }
> >
> >    check_inuse_chunk(newp);
> > -  return chunk2mem(newp);
> > +  return publish_mem(newp);
> >  }
> >
> >
> > @@ -2006,7 +2205,7 @@ Void_t* mEMALIGn(alignment, bytes) size_t alignment; size_t bytes;
> >    {
> >  #if HAVE_MMAP
> >      if(chunk_is_mmapped(p))
> > -      return chunk2mem(p); /* nothing more to do */
> > +      return publish_mem(p); /* nothing more to do */
> >  #endif
> >    }
> >    else /* misaligned */
> > @@ -2032,7 +2231,7 @@ Void_t* mEMALIGn(alignment, bytes) size_t alignment; size_t bytes;
> >      {
> >        newp->prev_size = p->prev_size + leadsize;
> >        set_head(newp, newsize|IS_MMAPPED);
> > -      return chunk2mem(newp);
> > +      return publish_mem(newp);
> >      }
> >  #endif
> >
> > @@ -2060,7 +2259,7 @@ Void_t* mEMALIGn(alignment, bytes) size_t alignment; size_t bytes;
> >    }
> >
> >    check_inuse_chunk(p);
> > -  return chunk2mem(p);
> > +  return publish_mem(p);
> >
> >  }
> >
> > @@ -2318,7 +2517,10 @@ static void malloc_update_mallinfo()
> >    for (i = 1; i < NAV; ++i)
> >    {
> >      b = bin_at(i);
> > -    for (p = last(b); p != b; p = p->bk)
> > +    for (p = last(b); p != b;
> > +            ASAN_UNPOISON_MEMORY_REGION((char*)p + 2*SIZE_SZ, 2*sizeof(uintptr_t)),
> > +            p = p->bk,
> > +            ASAN_POISON_MEMORY_REGION((char*)p + 2*SIZE_SZ, 2*sizeof(uintptr_t)))
> >      {
> >  #ifdef DEBUG
> >        check_free_chunk(p);
> > diff --git a/include/compiler.h b/include/compiler.h
> > index ef7b2cb1f7..7f7e82daf7 100644
> > --- a/include/compiler.h
> > +++ b/include/compiler.h
> > @@ -126,6 +126,7 @@ typedef __u32 u32;
> >
> >  /* Type for `void *' pointers. */
> >  typedef unsigned long int uintptr_t;
> > +typedef long int intptr_t;
> >
> >  #include <linux/string.h>
> >  #include <linux/types.h>
> > diff --git a/include/linux/types.h b/include/linux/types.h
> > index baa2c491ea..d86d2611c0 100644
> > --- a/include/linux/types.h
> > +++ b/include/linux/types.h
> > @@ -25,6 +25,7 @@ typedef __kernel_uid16_t        uid16_t;
> >  typedef __kernel_gid16_t        gid16_t;
> >
> >  typedef unsigned long          uintptr_t;
> > +typedef long                   intptr_t;
> >
> >  #ifdef CONFIG_UID16
> >  /* This is defined by include/asm-{arch}/posix_types.h */
> > --
> > 2.35.1.1094.g7c7d902a7c-goog
> >
>
> Regards,
> Simon

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

* Re: [PATCH 10/11] fuzz: virtio: Add fuzzer for vring
  2022-04-11 18:35   ` Simon Glass
@ 2022-04-12 14:04     ` Andrew Scull
  0 siblings, 0 replies; 30+ messages in thread
From: Andrew Scull @ 2022-04-12 14:04 UTC (permalink / raw)
  To: Simon Glass; +Cc: U-Boot Mailing List, Sean Anderson

On Mon, 11 Apr 2022 at 19:36, Simon Glass <sjg@chromium.org> wrote:
>
> Hi Andrew,
>
> On Thu, 7 Apr 2022 at 03:41, Andrew Scull <ascull@google.com> wrote:
> >
> > Add a fuzzer to test the vring handling code against unexpected
> > mutations from the virtio device.
> >
> > After building the sandbox with CONFIG_FUZZ=y, the fuzzer can be invoked
> > with by:
> >
> >    UBOOT_SB_FUZZ_TEST=fuzz_vring ./u-boot
> >
> > This fuzzer finds unvalidated inputs in the vring driver that allow a
> > buggy or malicious device to make the driver chase wild pointers.
> >
> > Signed-off-by: Andrew Scull <ascull@google.com>
> > ---
> >  test/fuzz/Makefile |  1 +
> >  test/fuzz/virtio.c | 72 ++++++++++++++++++++++++++++++++++++++++++++++
> >  2 files changed, 73 insertions(+)
> >  create mode 100644 test/fuzz/virtio.c
> >
> > diff --git a/test/fuzz/Makefile b/test/fuzz/Makefile
> > index 03eeeeb497..663b79ce80 100644
> > --- a/test/fuzz/Makefile
> > +++ b/test/fuzz/Makefile
> > @@ -5,3 +5,4 @@
> >  #
> >
> >  obj-$(CONFIG_$(SPL_)CMDLINE) += cmd_fuzz.o
> > +obj-$(CONFIG_VIRTIO_SANDBOX) += virtio.o
> > diff --git a/test/fuzz/virtio.c b/test/fuzz/virtio.c
> > new file mode 100644
> > index 0000000000..e5363d5638
> > --- /dev/null
> > +++ b/test/fuzz/virtio.c
> > @@ -0,0 +1,72 @@
> > +/* SPDX-License-Identifier: GPL-2.0+ */
> > +/*
> > + * Copyright (c) 2022 Google, Inc.
> > + * Written by Andrew Scull <ascull@google.com>
> > + */
> > +
> > +#include <common.h>
> > +#include <dm.h>
> > +#include <virtio.h>
> > +#include <virtio_ring.h>
> > +#include <test/fuzz.h>
> > +
> > +static int fuzz_vring(const uint8_t *data, size_t size)
> > +{
> > +       struct udevice *bus, *dev;
> > +       struct virtio_dev_priv *uc_priv;
> > +       struct virtqueue *vq;
> > +       struct virtio_sg sg[2];
> > +       struct virtio_sg *sgs[2];
> > +       unsigned int len;
> > +       u8 buffer[2][32];
> > +
> > +       /* hackily hardcode vring sizes */
> > +       size_t num = 4;
> > +       size_t desc_size = (sizeof(struct vring_desc) * num);
> > +       size_t avail_size = (3 + num) * sizeof(u16);
> > +       size_t used_size = (3 * sizeof(u16)) + (sizeof(struct vring_used_elem) * num);
> > +
> > +       if (size < (desc_size + avail_size + used_size))
> > +               return 0;
> > +
> > +       /* check probe success */
> > +       if (uclass_first_device(UCLASS_VIRTIO, &bus) || !bus)
> > +               panic("Could not find virtio bus\n");
>
> Do we have to panic? Could this use some sort of assert function, or
> similar? It seems like we should try to show the error then return an
> error code from this function, rather than just panic in the middle.
> We could have something like the ut_assert... stuff.

Would a basic assert() be better rather than handling with panic()? We
should never see this fail, and if it does we want something quite
dramatic to happen so that the fuzzer notices and tells us something
went wrong.

> > +
> > +       /* check the child virtio-rng device is bound */
> > +       if (device_find_first_child(bus, &dev) || !dev)
> > +               panic("Could not find virtio device\n");
> > +
> > +       /*
> > +        * fake the virtio device probe by filling in uc_priv->vdev
> > +        * which is used by virtio_find_vqs/virtio_del_vqs.
> > +        */
> > +       uc_priv = dev_get_uclass_priv(bus);
> > +       uc_priv->vdev = dev;
> > +
> > +       /* prepare the scatter-gather buffer */
> > +       sg[0].addr = buffer[0];
> > +       sg[0].length = sizeof(buffer[0]);
> > +       sg[1].addr = buffer[1];
> > +       sg[1].length = sizeof(buffer[1]);
> > +       sgs[0] = &sg[0];
> > +       sgs[1] = &sg[1];
> > +
> > +       if (virtio_find_vqs(dev, 1, &vq))
> > +               panic("Could not find vqs\n");
> > +       if (virtqueue_add(vq, sgs, 0, 1))
> > +               panic("Could not add to virtqueue\n");
> > +       /* Simulate device writing to vring */
> > +       memcpy(vq->vring.desc, data, desc_size);
> > +       memcpy(vq->vring.avail, data + desc_size, avail_size);
> > +       memcpy(vq->vring.used, data + desc_size + avail_size, used_size);
> > +       /* Make sure there is a response */
> > +       if (vq->vring.used->idx == 0)
> > +               vq->vring.used->idx = 1;
> > +       virtqueue_get_buf(vq, &len);
> > +       if (virtio_del_vqs(dev))
> > +               panic("Could not delete vqs\n");
> > +
> > +       return 0;
> > +}
> > +FUZZ_TEST(fuzz_vring, 0);
> > --
> > 2.35.1.1094.g7c7d902a7c-goog
> >
>
> Regards,
> Simon

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

* Re: [PATCH 09/11] sandbox: Implement fuzzing engine driver
  2022-04-11 18:35   ` Simon Glass
@ 2022-04-14 13:44     ` Andrew Scull
  0 siblings, 0 replies; 30+ messages in thread
From: Andrew Scull @ 2022-04-14 13:44 UTC (permalink / raw)
  To: Simon Glass; +Cc: U-Boot Mailing List, Sean Anderson

On Mon, 11 Apr 2022 at 19:36, Simon Glass <sjg@chromium.org> wrote:
>
> Hi Andrew,
>
> On Thu, 7 Apr 2022 at 03:41, Andrew Scull <ascull@google.com> wrote:
> >
> > Add a fuzzing engine driver for the sandbox to take inputs from
> > libfuzzer and expose them to the fuzz tests.
> >
> > Signed-off-by: Andrew Scull <ascull@google.com>
> > ---
> >  arch/Kconfig                                  |  2 ++
> >  arch/sandbox/dts/test.dts                     |  4 +++
> >  drivers/fuzzing_engine/Kconfig                | 11 ++++++
> >  drivers/fuzzing_engine/Makefile               |  1 +
> >  .../fuzzing_engine/sandbox_fuzzing_engine.c   | 35 +++++++++++++++++++
> >  5 files changed, 53 insertions(+)
> >  create mode 100644 drivers/fuzzing_engine/sandbox_fuzzing_engine.c
> >
>
> Reviewed-by: Simon Glass <sjg@chromium.org>
>
> Thoughts below
>
> > diff --git a/arch/Kconfig b/arch/Kconfig
> > index e6191446a3..6320a98db6 100644
> > --- a/arch/Kconfig
> > +++ b/arch/Kconfig
> > @@ -135,6 +135,7 @@ config SANDBOX
> >         select BZIP2
> >         select CMD_POWEROFF
> >         select DM
> > +       select DM_FUZZING_ENGINE
> >         select DM_GPIO
> >         select DM_I2C
> >         select DM_KEYBOARD
> > @@ -170,6 +171,7 @@ config SANDBOX
> >         imply CRC32_VERIFY
> >         imply FAT_WRITE
> >         imply FIRMWARE
> > +       imply FUZZING_ENGINE_SANDBOX
> >         imply HASH_VERIFY
> >         imply LZMA
> >         imply TEE
> > diff --git a/arch/sandbox/dts/test.dts b/arch/sandbox/dts/test.dts
> > index 48ca3e1e47..848329fda5 100644
> > --- a/arch/sandbox/dts/test.dts
> > +++ b/arch/sandbox/dts/test.dts
> > @@ -71,6 +71,10 @@
> >                 };
> >         };
> >
> > +       fuzzing-engine {
> > +               compatible = "sandbox,sandbox-fuzzing-engine";
> > +       };
> > +
> >         reboot-mode0 {
> >                 compatible = "reboot-mode-gpio";
> >                 gpios = <&gpio_c 0 GPIO_ACTIVE_HIGH>, <&gpio_c 1 GPIO_ACTIVE_HIGH>;
> > diff --git a/drivers/fuzzing_engine/Kconfig b/drivers/fuzzing_engine/Kconfig
> > index f405fc75e8..6311385222 100644
> > --- a/drivers/fuzzing_engine/Kconfig
> > +++ b/drivers/fuzzing_engine/Kconfig
> > @@ -4,3 +4,14 @@ config DM_FUZZING_ENGINE
> >         help
> >           Enable driver model for fuzzing engine devices. This interface is
> >           used to get fuzzing inputs from a fuzzing engine.
> > +
> > +if DM_FUZZING_ENGINE
> > +
> > +config FUZZING_ENGINE_SANDBOX
> > +       bool "Sanbox fuzzing engine"
> > +       depends on SANDBOX
> > +       default y
> > +       help
> > +         Enable fuzzing engine for sandbox.
> > +
> > +endif
> > diff --git a/drivers/fuzzing_engine/Makefile b/drivers/fuzzing_engine/Makefile
> > index acd894999c..073743ba94 100644
> > --- a/drivers/fuzzing_engine/Makefile
> > +++ b/drivers/fuzzing_engine/Makefile
> > @@ -5,3 +5,4 @@
> >  #
> >
> >  obj-$(CONFIG_DM_FUZZING_ENGINE) += fuzzing_engine-uclass.o
> > +obj-$(CONFIG_FUZZING_ENGINE_SANDBOX) += sandbox_fuzzing_engine.o
> > diff --git a/drivers/fuzzing_engine/sandbox_fuzzing_engine.c b/drivers/fuzzing_engine/sandbox_fuzzing_engine.c
> > new file mode 100644
> > index 0000000000..4d187deaa4
> > --- /dev/null
> > +++ b/drivers/fuzzing_engine/sandbox_fuzzing_engine.c
> > @@ -0,0 +1,35 @@
> > +/* SPDX-License-Identifier: GPL-2.0+ */
> > +/*
> > + * Copyright (c) 2022 Google, Inc.
> > + * Written by Andrew Scull <ascull@google.com>
> > + */
> > +
> > +#include <common.h>
> > +#include <dm.h>
> > +#include <fuzzing_engine.h>
> > +#include <asm/fuzzing_engine.h>
> > +
> > +static int get_input(struct udevice *dev,
> > +                    const uint8_t **data,
> > +                    size_t *size)
> > +{
> > +       return sandbox_fuzzing_engine_get_input(data, size);
> > +}
> > +
> > +static const struct dm_fuzzing_engine_ops sandbox_fuzzing_engine_ops = {
> > +       .get_input = get_input,
> > +};
> > +
> > +static const struct udevice_id sandbox_fuzzing_engine_match[] = {
>
> In the interests of brevity, perhaps sb_fuzz_engine as the prefix, or
> sbfuzz_engine?

I've left them longform for now as they symbols don't get widely used.

> > +       {
> > +               .compatible = "sandbox,sandbox-fuzzing-engine",
>
> Do you need the second 'sandbox-' ?

I was copying "sandbox,sandbox-rng" but turns out that was the
odd-one-out. Dropping the 'sandbox-'

> > +       },
> > +       {},
> > +};
> > +
> > +U_BOOT_DRIVER(sandbox_fuzzing_engine) = {
> > +       .name = "sandbox-fuzzing-engine",
> > +       .id = UCLASS_FUZZING_ENGINE,
> > +       .of_match = sandbox_fuzzing_engine_match,
> > +       .ops = &sandbox_fuzzing_engine_ops,
> > +};
> > --
> > 2.35.1.1094.g7c7d902a7c-goog
> >
>
> Regards,
> Simon

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

* [PATCH 00/11] Fuzzing and ASAN for sandbox
@ 2022-04-14 13:59 Andrew Scull
  0 siblings, 0 replies; 30+ messages in thread
From: Andrew Scull @ 2022-04-14 13:59 UTC (permalink / raw)
  To: u-boot; +Cc: sjg, xypron.glpk, Andrew Scull

This series sets up a basic fuzzing infrastructure that works with
sandbox. The example fuzz test towards the end of the series will find
something pretty quickly. That something is fixed by the series
"virtio: Harden and test vring" that needs to be applied for the final
patch in this series.

There is some refactoring to stop using '.' prefixed sections that elf
defines as being for system use and clang's ASAN instrumentation happily
adds redzones between, but that's not what we want for things like
linker lists where the linker script has carefully placed the sections
contiguously.

It may require patches from the "Fix misc ASAN reports" series to be
applied as I've already dealt with the first set of ASAN reports from
running the tests.

From v1:
 - corrected handling of EFI symbols by sandbox linker script
 - per comments, some renaming and explaining
 - dropped RFC for dlmalloc ASAN instrumentation (work required to improve it)
 - added patch to reduce logging noise in fuzzer

Andrew Scull (12):
  sandbox: Fix EFI runtime symbol placement
  sandbox: Rename EFI runtime sections
  sandbox: Migrate getopt section to linker list
  linker_lists: Rename sections to remove . prefix
  sandbox: Add support for Address Sanitizer
  fuzzing_engine: Add fuzzing engine uclass
  test: fuzz: Add framework for fuzzing
  sandbox: Decouple program entry from sandbox init
  sandbox: Add libfuzzer integration
  sandbox: Implement fuzzing engine driver
  fuzz: virtio: Add fuzzer for vring
  virtio_ring: Reduce logging noise

 Kconfig                                       | 16 +++
 arch/Kconfig                                  |  2 +
 arch/arc/cpu/u-boot.lds                       |  4 +-
 arch/arm/config.mk                            |  4 +-
 arch/arm/cpu/arm926ejs/sunxi/u-boot-spl.lds   |  4 +-
 arch/arm/cpu/armv7/sunxi/u-boot-spl.lds       |  4 +-
 arch/arm/cpu/armv8/u-boot-spl.lds             |  4 +-
 arch/arm/cpu/armv8/u-boot.lds                 |  4 +-
 arch/arm/cpu/u-boot-spl.lds                   |  4 +-
 arch/arm/cpu/u-boot.lds                       |  6 +-
 arch/arm/mach-at91/arm926ejs/u-boot-spl.lds   |  2 +-
 arch/arm/mach-at91/armv7/u-boot-spl.lds       |  2 +-
 arch/arm/mach-omap2/u-boot-spl.lds            |  4 +-
 arch/arm/mach-orion5x/u-boot-spl.lds          |  4 +-
 arch/arm/mach-rockchip/u-boot-tpl-v8.lds      |  4 +-
 arch/arm/mach-zynq/u-boot-spl.lds             |  4 +-
 arch/arm/mach-zynq/u-boot.lds                 |  4 +-
 arch/m68k/cpu/u-boot.lds                      |  4 +-
 arch/microblaze/cpu/u-boot-spl.lds            |  4 +-
 arch/microblaze/cpu/u-boot.lds                |  4 +-
 arch/mips/config.mk                           |  2 +-
 arch/mips/cpu/u-boot-spl.lds                  |  4 +-
 arch/mips/cpu/u-boot.lds                      |  4 +-
 arch/nds32/cpu/n1213/u-boot.lds               |  4 +-
 arch/nios2/cpu/u-boot.lds                     |  4 +-
 arch/powerpc/cpu/mpc83xx/u-boot.lds           |  4 +-
 arch/powerpc/cpu/mpc85xx/u-boot-nand.lds      |  4 +-
 arch/powerpc/cpu/mpc85xx/u-boot-nand_spl.lds  |  4 +-
 arch/powerpc/cpu/mpc85xx/u-boot-spl.lds       |  4 +-
 arch/powerpc/cpu/mpc85xx/u-boot.lds           |  4 +-
 arch/riscv/cpu/u-boot-spl.lds                 |  4 +-
 arch/riscv/cpu/u-boot.lds                     |  4 +-
 arch/sandbox/config.mk                        | 15 ++-
 arch/sandbox/cpu/os.c                         | 97 ++++++++++++++++---
 arch/sandbox/cpu/start.c                      | 12 +--
 arch/sandbox/cpu/u-boot-spl.lds               | 10 +-
 arch/sandbox/cpu/u-boot.lds                   | 41 ++++----
 arch/sandbox/dts/test.dts                     |  4 +
 arch/sandbox/include/asm/fuzzing_engine.h     | 25 +++++
 arch/sandbox/include/asm/getopt.h             | 19 ++--
 arch/sandbox/include/asm/main.h               | 18 ++++
 arch/sandbox/include/asm/sections.h           | 25 -----
 arch/sandbox/lib/sections.c                   |  8 +-
 arch/sh/cpu/u-boot.lds                        |  4 +-
 arch/x86/cpu/u-boot-64.lds                    |  6 +-
 arch/x86/cpu/u-boot-spl.lds                   |  6 +-
 arch/x86/cpu/u-boot.lds                       |  6 +-
 arch/x86/lib/elf_ia32_efi.lds                 |  4 +-
 arch/x86/lib/elf_x86_64_efi.lds               |  4 +-
 arch/xtensa/cpu/u-boot.lds                    |  2 +-
 arch/xtensa/include/asm/ldscript.h            |  4 +-
 board/compulab/cm_t335/u-boot.lds             |  4 +-
 board/cssi/MCR3000/u-boot.lds                 |  4 +-
 .../davinci/da8xxevm/u-boot-spl-da850evm.lds  |  2 +-
 board/qualcomm/dragonboard820c/u-boot.lds     |  4 +-
 board/samsung/common/exynos-uboot-spl.lds     |  4 +-
 board/synopsys/iot_devkit/u-boot.lds          |  4 +-
 board/ti/am335x/u-boot.lds                    |  4 +-
 board/vscom/baltos/u-boot.lds                 |  4 +-
 configs/sandbox_defconfig                     |  1 +
 doc/api/linker_lists.rst                      | 22 ++---
 doc/develop/commands.rst                      |  4 +-
 doc/develop/driver-model/of-plat.rst          |  4 +-
 drivers/Kconfig                               |  2 +
 drivers/Makefile                              |  1 +
 drivers/fuzz/Kconfig                          | 17 ++++
 drivers/fuzz/Makefile                         |  8 ++
 drivers/fuzz/fuzzing_engine-uclass.c          | 28 ++++++
 drivers/fuzz/sandbox_fuzzing_engine.c         | 35 +++++++
 drivers/virtio/virtio_ring.c                  |  4 +-
 include/dm/uclass-id.h                        |  1 +
 include/fuzzing_engine.h                      | 51 ++++++++++
 include/linker_lists.h                        | 18 ++--
 include/test/fuzz.h                           | 51 ++++++++++
 test/Makefile                                 |  1 +
 test/fuzz/Makefile                            |  8 ++
 test/fuzz/cmd_fuzz.c                          | 82 ++++++++++++++++
 test/fuzz/virtio.c                            | 72 ++++++++++++++
 78 files changed, 680 insertions(+), 204 deletions(-)
 create mode 100644 arch/sandbox/include/asm/fuzzing_engine.h
 create mode 100644 arch/sandbox/include/asm/main.h
 create mode 100644 drivers/fuzz/Kconfig
 create mode 100644 drivers/fuzz/Makefile
 create mode 100644 drivers/fuzz/fuzzing_engine-uclass.c
 create mode 100644 drivers/fuzz/sandbox_fuzzing_engine.c
 create mode 100644 include/fuzzing_engine.h
 create mode 100644 include/test/fuzz.h
 create mode 100644 test/fuzz/Makefile
 create mode 100644 test/fuzz/cmd_fuzz.c
 create mode 100644 test/fuzz/virtio.c

-- 
2.35.1.1178.g4f1659d476-goog


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

end of thread, other threads:[~2022-04-14 13:59 UTC | newest]

Thread overview: 30+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-04-07  9:41 [PATCH 00/11] Fuzzing and ASAN for sandbox Andrew Scull
2022-04-07  9:41 ` [PATCH 01/11] sandbox: Set the EFI symbols in linker script Andrew Scull
2022-04-11 18:35   ` Simon Glass
2022-04-11 22:15   ` Heinrich Schuchardt
2022-04-11 22:37     ` Andrew Scull
2022-04-07  9:41 ` [PATCH 02/11] sandbox: Migrate getopt section to linker list Andrew Scull
2022-04-11 18:35   ` Simon Glass
2022-04-07  9:41 ` [PATCH 03/11] linker_lists: Rename sections to remove . prefix Andrew Scull
2022-04-11 18:35   ` Simon Glass
2022-04-07  9:41 ` [PATCH 04/11] sandbox: Add support for Address Sanitizer Andrew Scull
2022-04-11 18:35   ` Simon Glass
2022-04-12  9:26     ` Andrew Scull
2022-04-07  9:41 ` [PATCH 05/11] fuzzing_engine: Add fuzzing engine uclass Andrew Scull
2022-04-11 18:35   ` Simon Glass
2022-04-07  9:41 ` [PATCH 06/11] test: fuzz: Add framework for fuzzing Andrew Scull
2022-04-11 18:35   ` Simon Glass
2022-04-07  9:41 ` [PATCH 07/11] sandbox: Decouple program entry from sandbox init Andrew Scull
2022-04-11 18:35   ` Simon Glass
2022-04-07  9:41 ` [PATCH 08/11] sandbox: Add libfuzzer integration Andrew Scull
2022-04-11 18:35   ` Simon Glass
2022-04-07  9:41 ` [PATCH 09/11] sandbox: Implement fuzzing engine driver Andrew Scull
2022-04-11 18:35   ` Simon Glass
2022-04-14 13:44     ` Andrew Scull
2022-04-07  9:41 ` [PATCH 10/11] fuzz: virtio: Add fuzzer for vring Andrew Scull
2022-04-11 18:35   ` Simon Glass
2022-04-12 14:04     ` Andrew Scull
2022-04-07  9:41 ` [PATCH 11/11] RFC: Hack dlmalloc to poison memory Andrew Scull
2022-04-11 18:35   ` Simon Glass
2022-04-12 10:19     ` Andrew Scull
2022-04-14 13:59 [PATCH 00/11] Fuzzing and ASAN for sandbox Andrew Scull

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.