From 339f652992919be11e3f1b791515140de646a3ef Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pali=20Roh=C3=A1r?= Date: Tue, 17 May 2022 22:45:28 +0200 Subject: [PATCH 1/9] ubifs: Fix lockup/crash when reading files MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Commit b1a14f8a1c2e ("UBIFS: Change ubifsload to not read beyond the requested size") added optimization to do not read more bytes than it is really needed. But this commit introduced incorrect handling of the hole at the end of file. This logic cause U-Boot to crash or lockup when trying to read from the ubifs filesystem. When read_block() call returns -ENOENT error (not an error, but the hole) then dn-> structure is not filled and contain garbage. So using of dn->size for memcpy() argument cause that U-Boot tries to copy unspecified amount of bytes from possible unmapped memory. Which randomly cause lockup of P2020 CPU. Fix this issue by copying UBIFS_BLOCK_SIZE bytes from read buffer when dn->size is not available. UBIFS_BLOCK_SIZE is the size of the buffer itself and read_block() fills buffer by zeros when it returns -ENOENT. This patch fixes ubifsload on P2020. Fixes: b1a14f8a1c2e ("UBIFS: Change ubifsload to not read beyond the requested size") Signed-off-by: Pali Rohár Reviewed-by: Stefan Roese --- fs/ubifs/ubifs.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/fs/ubifs/ubifs.c b/fs/ubifs/ubifs.c index d6be5c947d7..d3026e31016 100644 --- a/fs/ubifs/ubifs.c +++ b/fs/ubifs/ubifs.c @@ -788,6 +788,8 @@ static int do_readpage(struct ubifs_info *c, struct inode *inode, if (last_block_size) dlen = last_block_size; + else if (ret) + dlen = UBIFS_BLOCK_SIZE; else dlen = le32_to_cpu(dn->size); From 7704b7fd673a603805f5ddd8807f69d4bc3b9188 Mon Sep 17 00:00:00 2001 From: Michael Walle Date: Tue, 31 May 2022 18:36:16 +0200 Subject: [PATCH 2/9] net: enetc: unregister mdiobus If the device fails to probe - for example, when there is no ethaddr set - then the private data is automatically freed but the mdiobus remains registered. Fixes: 1e354cb39314 ("drivers: net: fsl_enetc: register internal MDIO bus") Signed-off-by: Michael Walle --- drivers/net/fsl_enetc.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/net/fsl_enetc.c b/drivers/net/fsl_enetc.c index 9b97a03ccb3..cd4c2c29a65 100644 --- a/drivers/net/fsl_enetc.c +++ b/drivers/net/fsl_enetc.c @@ -361,6 +361,9 @@ static int enetc_remove(struct udevice *dev) { struct enetc_priv *priv = dev_get_priv(dev); + if (miiphy_get_dev_by_name(priv->imdio.name)) + mdio_unregister(&priv->imdio); + free(priv->enetc_txbd); free(priv->enetc_rxbd); From 2b641211c51d5357eacadf571d2ee70da16749e1 Mon Sep 17 00:00:00 2001 From: Andre Przywara Date: Mon, 9 May 2022 17:08:49 +0100 Subject: [PATCH 3/9] armv8: Fix TCR 64-bit writes The AArch64 TCR_ELx register is a 64-bit register, and many newer architecture features use bits in the upper half. So far U-Boot was igorant of those bits, trying to leave them alone. However, in an effort to set bit 31 to 1, it failed doing so, because the compiler sign-extended "1 << 31", so that all bits[63:31] got set. Older ARMv8.0 cores don't define anything dangerous up there, but newer architecture revisions do, and setting all those bits will end badly: ================= $ qemu-system-aarch64 -cpu max .... U-Boot 2022.07-rc1 (May 09 2022 - 15:21:00 +0100) DRAM: 1.5 GiB ================= (hangs here) Defining TCR_ELx_RSVD to "1U << 31" avoids the sign-extension, so all upper bits stay at a safe 0 value. This means no more surprises when U-Boot runs on a more capable CPU core. Reported-by: Balaji Anandapadmanaban Signed-off-by: Andre Przywara Reviewed-by: Peng Fan Tested-by: Peter Collingbourne Reviewed-by: Peter Collingbourne --- arch/arm/include/asm/armv8/mmu.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/arch/arm/include/asm/armv8/mmu.h b/arch/arm/include/asm/armv8/mmu.h index fc97c551146..c36b2cf5a58 100644 --- a/arch/arm/include/asm/armv8/mmu.h +++ b/arch/arm/include/asm/armv8/mmu.h @@ -99,9 +99,9 @@ #define TCR_TG0_16K (2 << 14) #define TCR_EPD1_DISABLE (1 << 23) -#define TCR_EL1_RSVD (1 << 31) -#define TCR_EL2_RSVD (1 << 31 | 1 << 23) -#define TCR_EL3_RSVD (1 << 31 | 1 << 23) +#define TCR_EL1_RSVD (1U << 31) +#define TCR_EL2_RSVD (1U << 31 | 1 << 23) +#define TCR_EL3_RSVD (1U << 31 | 1 << 23) #ifndef __ASSEMBLY__ static inline void set_ttbr_tcr_mair(int el, u64 table, u64 tcr, u64 attr) From b85d130ea0cac152c21ec38ac9417b31d41b5552 Mon Sep 17 00:00:00 2001 From: Fabio Estevam Date: Thu, 26 May 2022 11:14:37 -0300 Subject: [PATCH 4/9] net: Check for the minimum IP fragmented datagram size Nicolas Bidron and Nicolas Guigo reported the two bugs below: " ----------BUG 1---------- In compiled versions of U-Boot that define CONFIG_IP_DEFRAG, a value of `ip->ip_len` (IP packet header's Total Length) higher than `IP_HDR_SIZE` and strictly lower than `IP_HDR_SIZE+8` will lead to a value for `len` comprised between `0` and `7`. This will ultimately result in a truncated division by `8` resulting value of `0` forcing the hole metadata and fragment to point to the same location. The subsequent memcopy will overwrite the hole metadata with the fragment data. Through a second fragment, this can be exploited to write to an arbitrary offset controlled by that overwritten hole metadata value. This bug is only exploitable locally as it requires crafting two packets the first of which would most likely be dropped through routing due to its unexpectedly low Total Length. However, this bug can potentially be exploited to root linux based embedded devices locally. ```C static struct ip_udp_hdr *__net_defragment(struct ip_udp_hdr *ip, int *lenp) { static uchar pkt_buff[IP_PKTSIZE] __aligned(PKTALIGN); static u16 first_hole, total_len; struct hole *payload, *thisfrag, *h, *newh; struct ip_udp_hdr *localip = (struct ip_udp_hdr *)pkt_buff; uchar *indata = (uchar *)ip; int offset8, start, len, done = 0; u16 ip_off = ntohs(ip->ip_off); /* payload starts after IP header, this fragment is in there */ payload = (struct hole *)(pkt_buff + IP_HDR_SIZE); offset8 = (ip_off & IP_OFFS); thisfrag = payload + offset8; start = offset8 * 8; len = ntohs(ip->ip_len) - IP_HDR_SIZE; ``` The last line of the previous excerpt from `u-boot/net/net.c` shows how the attacker can control the value of `len` to be strictly lower than `8` by issuing a packet with `ip_len` between `21` and `27` (`IP_HDR_SIZE` has a value of `20`). Also note that `offset8` here is `0` which leads to `thisfrag = payload`. ```C } else if (h >= thisfrag) { /* overlaps with initial part of the hole: move this hole */ newh = thisfrag + (len / 8); *newh = *h; h = newh; if (h->next_hole) payload[h->next_hole].prev_hole = (h - payload); if (h->prev_hole) payload[h->prev_hole].next_hole = (h - payload); else first_hole = (h - payload); } else { ``` Lower down the same function, execution reaches the above code path. Here, `len / 8` evaluates to `0` leading to `newh = thisfrag`. Also note that `first_hole` here is `0` since `h` and `payload` point to the same location. ```C /* finally copy this fragment and possibly return whole packet */ memcpy((uchar *)thisfrag, indata + IP_HDR_SIZE, len); ``` Finally, in the above excerpt the `memcpy` overwrites the hole metadata since `thisfrag` and `h` both point to the same location. The hole metadata is effectively overwritten with arbitrary data from the fragmented IP packet data. If `len` was crafted to be `6`, `last_byte`, `next_hole`, and `prev_hole` of the `first_hole` can be controlled by the attacker. Finally the arbitrary offset write occurs through a second fragment that only needs to be crafted to write data in the hole pointed to by the previously controlled hole metadata (`next_hole`) from the first packet. ### Recommendation Handle cases where `len` is strictly lower than 8 by preventing the overwrite of the hole metadata during the memcpy of the fragment. This could be achieved by either: * Moving the location where the hole metadata is stored when `len` is lower than `8`. * Or outright rejecting fragmented IP datagram with a Total Length (`ip_len`) lower than 28 bytes which is the minimum valid fragmented IP datagram size (as defined as the minimum fragment of 8 octets in the IP Specification Document: [RFC791](https://datatracker.ietf.org/doc/html/rfc791) page 25). ----------BUG 2---------- In compiled versions of U-Boot that define CONFIG_IP_DEFRAG, a value of `ip->ip_len` (IP packet header's Total Length) lower than `IP_HDR_SIZE` will lead to a negative value for `len` which will ultimately result in a buffer overflow during the subsequent `memcpy` that uses `len` as it's `count` parameter. This bug is only exploitable on local ethernet as it requires crafting an invalid packet to include an unexpected `ip_len` value in the IP UDP header that's lower than the minimum accepted Total Length of a packet (21 as defined in the IP Specification Document: [RFC791](https://datatracker.ietf.org/doc/html/rfc791)). Such packet would in all likelihood be dropped while being routed to its final destination through most routing equipment and as such requires the attacker to be in a local position in order to be exploited. ```C static struct ip_udp_hdr *__net_defragment(struct ip_udp_hdr *ip, int *lenp) { static uchar pkt_buff[IP_PKTSIZE] __aligned(PKTALIGN); static u16 first_hole, total_len; struct hole *payload, *thisfrag, *h, *newh; struct ip_udp_hdr *localip = (struct ip_udp_hdr *)pkt_buff; uchar *indata = (uchar *)ip; int offset8, start, len, done = 0; u16 ip_off = ntohs(ip->ip_off); /* payload starts after IP header, this fragment is in there */ payload = (struct hole *)(pkt_buff + IP_HDR_SIZE); offset8 = (ip_off & IP_OFFS); thisfrag = payload + offset8; start = offset8 * 8; len = ntohs(ip->ip_len) - IP_HDR_SIZE; ``` The last line of the previous excerpt from `u-boot/net/net.c` shows where the underflow to a negative `len` value occurs if `ip_len` is set to a value strictly lower than 20 (`IP_HDR_SIZE` being 20). Also note that in the above excerpt the `pkt_buff` buffer has a size of `CONFIG_NET_MAXDEFRAG` which defaults to 16 KB but can range from 1KB to 64 KB depending on configurations. ```C /* finally copy this fragment and possibly return whole packet */ memcpy((uchar *)thisfrag, indata + IP_HDR_SIZE, len); ``` In the above excerpt the `memcpy` overflows the destination by attempting to make a copy of nearly 4 gigabytes in a buffer that's designed to hold `CONFIG_NET_MAXDEFRAG` bytes at most which leads to a DoS. ### Recommendation Stop processing of the packet if `ip_len` is lower than 21 (as defined by the minimum length of a data carrying datagram in the IP Specification Document: [RFC791](https://datatracker.ietf.org/doc/html/rfc791) page 34)." Add a check for ip_len lesser than 28 and stop processing the packet in this case. Such a check covers the two reported bugs. Reported-by: Nicolas Bidron Signed-off-by: Fabio Estevam --- include/net.h | 2 ++ net/net.c | 3 +++ 2 files changed, 5 insertions(+) diff --git a/include/net.h b/include/net.h index 675bf4171b1..e3889a0bc85 100644 --- a/include/net.h +++ b/include/net.h @@ -391,6 +391,8 @@ struct ip_hdr { #define IP_HDR_SIZE (sizeof(struct ip_hdr)) +#define IP_MIN_FRAG_DATAGRAM_SIZE (IP_HDR_SIZE + 8) + /* * Internet Protocol (IP) + UDP header. */ diff --git a/net/net.c b/net/net.c index 034a5d6e67c..81905f63159 100644 --- a/net/net.c +++ b/net/net.c @@ -907,6 +907,9 @@ static struct ip_udp_hdr *__net_defragment(struct ip_udp_hdr *ip, int *lenp) int offset8, start, len, done = 0; u16 ip_off = ntohs(ip->ip_off); + if (ip->ip_len < IP_MIN_FRAG_DATAGRAM_SIZE) + return NULL; + /* payload starts after IP header, this fragment is in there */ payload = (struct hole *)(pkt_buff + IP_HDR_SIZE); offset8 = (ip_off & IP_OFFS); From 622ecee93a604c017aca23906c5cc903b4002b78 Mon Sep 17 00:00:00 2001 From: Francesco Dolcini Date: Thu, 19 May 2022 16:22:26 +0200 Subject: [PATCH 5/9] fdt: Add U-Boot version to chosen node Add a new device tree property "u-boot,version" in the chosen node to pass the U-Boot version to the operating system. This can be useful to implement a firmware upgrade procedure from the operating system. Signed-off-by: Francesco Dolcini Reviewed-by: Tom Rini --- common/fdt_support.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/common/fdt_support.c b/common/fdt_support.c index 7e9e6542041..8c18af2ce15 100644 --- a/common/fdt_support.c +++ b/common/fdt_support.c @@ -19,6 +19,7 @@ #include #include #include +#include /** * fdt_getprop_u32_default_node - Return a node's property or a default @@ -305,6 +306,15 @@ int fdt_chosen(void *fdt) } } + /* add u-boot version */ + err = fdt_setprop(fdt, nodeoffset, "u-boot,version", PLAIN_VERSION, + strlen(PLAIN_VERSION) + 1); + if (err < 0) { + printf("WARNING: could not set u-boot,version %s.\n", + fdt_strerror(err)); + return err; + } + return fdt_fixup_stdout(fdt, nodeoffset); } From 4230d68aa8292d3fceacb55a4b823e5e001da33f Mon Sep 17 00:00:00 2001 From: Peng Fan Date: Mon, 23 May 2022 19:38:27 +0800 Subject: [PATCH 6/9] imx: imx8mq: default select CLK_IMX8MQ Since the power domain driver default select CONFIG_CLK, so we will meet lots failures without CLK_IMX8MQ, so default select it. Fixes: commit 4eb82c2e56a7c ("imx: power-domain: Get rid of SMCCC dependency") Signed-off-by: Peng Fan --- arch/arm/mach-imx/imx8m/Kconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm/mach-imx/imx8m/Kconfig b/arch/arm/mach-imx/imx8m/Kconfig index 61397bf88d1..ef8518c06bd 100644 --- a/arch/arm/mach-imx/imx8m/Kconfig +++ b/arch/arm/mach-imx/imx8m/Kconfig @@ -8,6 +8,7 @@ config IMX8M config IMX8MQ bool select IMX8M + select CLK_IMX8MQ config IMX8MM bool From ad9f3771f61228a16a1ada09e4daaceb022a6e1b Mon Sep 17 00:00:00 2001 From: Peng Fan Date: Mon, 23 May 2022 19:38:28 +0800 Subject: [PATCH 7/9] imx: imx8mq: select CONFIG_CMD_CLK select CONFIG_CMD_CLK to enable dump clk in uboot shell Signed-off-by: Peng Fan --- configs/imx8mq_evk_defconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/configs/imx8mq_evk_defconfig b/configs/imx8mq_evk_defconfig index 780f93103c7..9f54a280d9b 100644 --- a/configs/imx8mq_evk_defconfig +++ b/configs/imx8mq_evk_defconfig @@ -40,6 +40,7 @@ CONFIG_SYS_PROMPT="u-boot=> " # CONFIG_CMD_EXPORTENV is not set # CONFIG_CMD_IMPORTENV is not set # CONFIG_CMD_CRC32 is not set +CONFIG_CMD_CLK=y CONFIG_CMD_FUSE=y CONFIG_CMD_GPIO=y CONFIG_CMD_I2C=y From 9320db0926ae4c2a24015298e3b374a07023267e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pali=20Roh=C3=A1r?= Date: Wed, 6 Apr 2022 23:31:53 +0200 Subject: [PATCH 8/9] squashfs: Fix compilation on big endian systems MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Pali Rohár Reviewed-by: Miquel Raynal --- fs/squashfs/sqfs.c | 3 +-- fs/squashfs/sqfs_dir.c | 3 +-- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/fs/squashfs/sqfs.c b/fs/squashfs/sqfs.c index b4484fa17f5..547d2fd4b30 100644 --- a/fs/squashfs/sqfs.c +++ b/fs/squashfs/sqfs.c @@ -12,8 +12,7 @@ #include #include #include -#include -#include +#include #include #include #include diff --git a/fs/squashfs/sqfs_dir.c b/fs/squashfs/sqfs_dir.c index a265b98fe68..ed83c90682f 100644 --- a/fs/squashfs/sqfs_dir.c +++ b/fs/squashfs/sqfs_dir.c @@ -7,8 +7,7 @@ #include #include -#include -#include +#include #include #include #include From c30f6d62f07d788263e1f1ac4909f929feefba3f Mon Sep 17 00:00:00 2001 From: Dave Gerlach Date: Fri, 3 Jun 2022 14:30:20 -0500 Subject: [PATCH 9/9] board: ti: am64x: Update MAINTAINERS Move maintainership of TI AM64x boards to Vignesh. Signed-off-by: Dave Gerlach --- board/ti/am64x/MAINTAINERS | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/board/ti/am64x/MAINTAINERS b/board/ti/am64x/MAINTAINERS index eaca2b865f5..78a21d66af7 100644 --- a/board/ti/am64x/MAINTAINERS +++ b/board/ti/am64x/MAINTAINERS @@ -1,5 +1,5 @@ AM64x BOARD -M: Dave Gerlach +M: Vignesh Raghavendra M: Tom Rini S: Maintained F: board/ti/am64x/