From 511a1303c9cf9663c7d4312e3a0693319f41095b Mon Sep 17 00:00:00 2001 From: Qu Wenruo Date: Mon, 13 Feb 2023 08:37:59 +0800 Subject: [PATCH 1/5] fs: btrfs: limit the mapped length to the original length [BUG] There is a bug report that btrfs driver caused hang during file read: This breaks btrfs on the HiFive Unmatched. => pci enum PCIE-0: Link up (Gen1-x8, Bus0) => nvme scan => load nvme 0:2 0x8c000000 /boot/dtb/sifive/hifive-unmatched-a00.dtb [hangs] [CAUSE] The reporter provided some debug output: read_extent_data: cur=615817216, orig_len=16384, cur_len=16384 read_extent_data: btrfs_map_block: cur_len=479944704; ret=0 read_extent_data: ret=0 read_extent_data: cur=615833600, orig_len=4096, cur_len=4096 read_extent_data: btrfs_map_block: cur_len=479928320; ret=0 Note the second and the last line, the @cur_len is 450+MiB, which is almost a chunk size. And inside __btrfs_map_block(), we limits the returned value to stripe length, but that's depending on the chunk type: if (map->type & (BTRFS_BLOCK_GROUP_RAID0 | BTRFS_BLOCK_GROUP_RAID1 | BTRFS_BLOCK_GROUP_RAID1C3 | BTRFS_BLOCK_GROUP_RAID1C4 | BTRFS_BLOCK_GROUP_RAID5 | BTRFS_BLOCK_GROUP_RAID6 | BTRFS_BLOCK_GROUP_RAID10 | BTRFS_BLOCK_GROUP_DUP)) { /* we limit the length of each bio to what fits in a stripe */ *length = min_t(u64, ce->size - offset, map->stripe_len - stripe_offset); } else { *length = ce->size - offset; } This means, if the chunk is SINGLE profile, then we don't limit the returned length at all, and even for other profiles, we can still return a length much larger than the requested one. [FIX] Properly clamp the returned length, preventing it from returning a much larger range than expected. Reported-by: Andreas Schwab Signed-off-by: Qu Wenruo --- fs/btrfs/volumes.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/fs/btrfs/volumes.c b/fs/btrfs/volumes.c index 4aaaeab663f..7d4095d9ca8 100644 --- a/fs/btrfs/volumes.c +++ b/fs/btrfs/volumes.c @@ -956,6 +956,7 @@ int __btrfs_map_block(struct btrfs_fs_info *fs_info, int rw, struct btrfs_mapping_tree *map_tree = &fs_info->mapping_tree; struct cache_extent *ce; struct map_lookup *map; + u64 orig_len = *length; u64 offset; u64 stripe_offset; u64 *raid_map = NULL; @@ -1047,6 +1048,7 @@ again: } else { *length = ce->size - offset; } + *length = min_t(u64, *length, orig_len); if (!multi_ret) goto out; From 57450d8661b3ec2e6b6f1d938e59f426cafb06d2 Mon Sep 17 00:00:00 2001 From: Tom Rini Date: Tue, 14 Feb 2023 15:09:31 -0500 Subject: [PATCH 2/5] Makefile: Link with -z noexectack When moving to gcc-12.2 we started trying to quiet some of the new linker warnings, that are not relevant to us. However, a misunderstanding of the mechanics at play meant that I intentionally omitted passing -z noexecstack to the linker, when we do need to. Add this flag and in turn remove warnings from the linker. Fixes: 1e1c51f8ace8 ("Makefile: link with --no-warn-rwx-segments") Signed-off-by: Tom Rini Reviewed-by: Simon Glass --- Makefile | 1 + 1 file changed, 1 insertion(+) diff --git a/Makefile b/Makefile index 54f894dab84..bc1ee94fb74 100644 --- a/Makefile +++ b/Makefile @@ -806,6 +806,7 @@ KBUILD_CPPFLAGS += $(KCPPFLAGS) KBUILD_AFLAGS += $(KAFLAGS) KBUILD_CFLAGS += $(KCFLAGS) +KBUILD_LDFLAGS += -z noexecstack KBUILD_LDFLAGS += $(call ld-option,--no-warn-rwx-segments) KBUILD_HOSTCFLAGS += $(if $(CONFIG_TOOLS_DEBUG),-g) From d85bc196cbf9b70be203047a3450643f1999fe4c Mon Sep 17 00:00:00 2001 From: Tom Rini Date: Tue, 14 Feb 2023 15:09:32 -0500 Subject: [PATCH 3/5] x86: Pass -z execstack for EFI payload flags To match how we link EFI executables elsewhere, and to silence a linker warning, pass -z execstack here as well. Cc: Bin Meng Cc: Heinrich Schuchardt Signed-off-by: Tom Rini --- arch/x86/config.mk | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/arch/x86/config.mk b/arch/x86/config.mk index a4a694ddf31..26ec1af2f0b 100644 --- a/arch/x86/config.mk +++ b/arch/x86/config.mk @@ -37,7 +37,8 @@ KBUILD_LDFLAGS += -m $(if $(IS_32BIT),elf_i386,elf_x86_64) # This is used in the top-level Makefile which does not include # KBUILD_LDFLAGS -LDFLAGS_EFI_PAYLOAD := -Bsymbolic -Bsymbolic-functions -shared --no-undefined -s +LDFLAGS_EFI_PAYLOAD := -Bsymbolic -Bsymbolic-functions -shared --no-undefined \ + -s -zexecstack OBJCOPYFLAGS_EFI := -j .text -j .sdata -j .data -j .dynamic -j .dynsym \ -j .rel -j .rela -j .reloc --strip-all From c1d266a781600f8c4c18449016edffb5597153cb Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Fri, 17 Feb 2023 15:45:16 -0700 Subject: [PATCH 4/5] trace: Relax test requirements We expect the profile and bootstage to agree on timing, but when running on slow machines there can be a larger descrepency. Increase the tolerance to fix this. Fixes: 9cea4797aeb ("trace: Add a test") Signed-off-by: Simon Glass --- test/py/tests/test_trace.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/test/py/tests/test_trace.py b/test/py/tests/test_trace.py index 14584d11a23..ac3e95925e9 100644 --- a/test/py/tests/test_trace.py +++ b/test/py/tests/test_trace.py @@ -299,6 +299,7 @@ def test_trace(u_boot_console): fg_time = check_flamegraph(cons, fname, proftool, map_fname, trace_fg) - # Check that bootstage and flamegraph agree to within 10% + # Check that bootstage and flamegraph agree to within 30% + # This allows for CI being slow to run diff = abs(fg_time - dm_f_time) - assert diff / dm_f_time < 0.1 + assert diff / dm_f_time < 0.3 From 5b4acb0ff79df642ef6b1e35fd4b193a4dc3c62b Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Thu, 9 Feb 2023 13:30:10 +0100 Subject: [PATCH 5/5] env: mmc: Apply GPT only on eMMC user HW partition Apply the GPT U-Boot environment GUID type look up only on eMMC user HW partition, do not apply the look up on eMMC boot HW partitions as mmc_offset_try_partition() assumes either SD partitions or eMMC user HW partition. This fixes environment operation on systems where CONFIG_SYS_MMC_ENV_PART is non-zero and CONFIG_SYS_REDUNDAND_ENVIRONMENT is set. Fixes: 80105d8fd52 ("env: mmc: select GPT env partition by type guid") Signed-off-by: Marek Vasut Reviewed-by: Tom Rini --- env/mmc.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/env/mmc.c b/env/mmc.c index 5b01f657a7a..7a5836ad66c 100644 --- a/env/mmc.c +++ b/env/mmc.c @@ -94,7 +94,7 @@ static inline int mmc_offset_try_partition(const char *str, int copy, s64 *val) return 0; } -static inline s64 mmc_offset(int copy) +static inline s64 mmc_offset(struct mmc *mmc, int copy) { const struct { const char *offset_redund; @@ -108,8 +108,12 @@ static inline s64 mmc_offset(int copy) s64 val = 0, defvalue; const char *propname; const char *str; + int hwpart = 0; int err; + if (IS_ENABLED(CONFIG_SYS_MMC_ENV_PART)) + hwpart = mmc_get_env_part(mmc); + /* look for the partition in mmc CONFIG_SYS_MMC_ENV_DEV */ str = ofnode_conf_read_str(dt_prop.partition); if (str) { @@ -121,7 +125,7 @@ static inline s64 mmc_offset(int copy) } /* try the GPT partition with "U-Boot ENV" TYPE GUID */ - if (IS_ENABLED(CONFIG_PARTITION_TYPE_GUID)) { + if (IS_ENABLED(CONFIG_PARTITION_TYPE_GUID) && hwpart == 0) { err = mmc_offset_try_partition(NULL, copy, &val); if (!err) return val; @@ -138,7 +142,7 @@ static inline s64 mmc_offset(int copy) return ofnode_conf_read_int(propname, defvalue); } #else -static inline s64 mmc_offset(int copy) +static inline s64 mmc_offset(struct mmc *mmc, int copy) { s64 offset = ENV_MMC_OFFSET; @@ -151,7 +155,7 @@ static inline s64 mmc_offset(int copy) __weak int mmc_get_env_addr(struct mmc *mmc, int copy, u32 *env_addr) { - s64 offset = mmc_offset(copy); + s64 offset = mmc_offset(mmc, copy); if (offset == ENV_MMC_INVALID_OFFSET) { printf("Invalid ENV offset in MMC, copy=%d\n", copy);