diff -Nru u-boot-nezha-2022.10-1089-g528ae9bc6c/debian/changelog u-boot-nezha-2022.10-1089-g528ae9bc6c/debian/changelog --- u-boot-nezha-2022.10-1089-g528ae9bc6c/debian/changelog 2022-11-29 10:20:07.000000000 +0100 +++ u-boot-nezha-2022.10-1089-g528ae9bc6c/debian/changelog 2023-03-24 12:50:58.000000000 +0100 @@ -1,3 +1,14 @@ +u-boot-nezha (2022.10-1089-g528ae9bc6c-0ubuntu2) lunar; urgency=medium + + * Add security fixes (LP: #2012644) + d/p/0001-usb-gadget-dfu-Fix-the-unchecked-length-field.patch + d/p/0001-net-actually-better-deal-with-CVE-2022-30790-30552.patch + d/p/0001-usb-gadget-dfu-Fix-check-of-transfer-direction.patch + * Enable sbi command + d/p/0001-enable-sbi-command.patch + + -- Heinrich Schuchardt Fri, 24 Mar 2023 12:50:58 +0100 + u-boot-nezha (2022.10-1089-g528ae9bc6c-0ubuntu1) lunar; urgency=medium * Bump version to 2022.10 (LP: #1998197) diff -Nru u-boot-nezha-2022.10-1089-g528ae9bc6c/debian/patches/0001-enable-sbi-command.patch u-boot-nezha-2022.10-1089-g528ae9bc6c/debian/patches/0001-enable-sbi-command.patch --- u-boot-nezha-2022.10-1089-g528ae9bc6c/debian/patches/0001-enable-sbi-command.patch 1970-01-01 01:00:00.000000000 +0100 +++ u-boot-nezha-2022.10-1089-g528ae9bc6c/debian/patches/0001-enable-sbi-command.patch 2023-03-24 12:50:58.000000000 +0100 @@ -0,0 +1,23 @@ +Subject: enable CMD_SBI by default + +Provide the sbi command on RISC-V by default. + +Author: Heinrich Schuchardt +Forwarded: no +Last-Update: 2023-03-24 + +Patch-Name: 0001-enable-sbi-command.patch +--- + cmd/Kconfig | 1 + + 1 file changed, 1 insertion(+) + +--- a/cmd/Kconfig ++++ b/cmd/Kconfig +@@ -201,6 +201,7 @@ + config CMD_SBI + bool "sbi" + depends on RISCV_SMODE && SBI_V02 ++ default y + help + Display information about the SBI implementation. + diff -Nru u-boot-nezha-2022.10-1089-g528ae9bc6c/debian/patches/0001-net-actually-better-deal-with-CVE-2022-30790-30552.patch u-boot-nezha-2022.10-1089-g528ae9bc6c/debian/patches/0001-net-actually-better-deal-with-CVE-2022-30790-30552.patch --- u-boot-nezha-2022.10-1089-g528ae9bc6c/debian/patches/0001-net-actually-better-deal-with-CVE-2022-30790-30552.patch 1970-01-01 01:00:00.000000000 +0100 +++ u-boot-nezha-2022.10-1089-g528ae9bc6c/debian/patches/0001-net-actually-better-deal-with-CVE-2022-30790-30552.patch 2023-03-23 15:50:43.000000000 +0100 @@ -0,0 +1,145 @@ +From 1817c3824a08bbad7fd2fbae1a6e73be896e8e5e Mon Sep 17 00:00:00 2001 +From: Rasmus Villemoes +Date: Fri, 14 Oct 2022 19:43:39 +0200 +Subject: [PATCH] net: (actually/better) deal with CVE-2022-{30790,30552} + +I hit a strange problem with v2022.10: Sometimes my tftp transfer +would seemingly just hang. It only happened for some files. Moreover, +changing tftpblocksize from 65464 to 65460 or 65000 made it work again +for all the files I tried. So I started suspecting it had something to +do with the file sizes and in particular the way the tftp blocks get +fragmented and reassembled. + +v2022.01 showed no problems with any of the files or any value of +tftpblocksize. + +Looking at what had changed in net.c or tftp.c since January showed +only one remotely interesting thing, b85d130ea0ca. + +So I fired up wireshark on my host to see if somehow one of the +packets would be too small. But no, with both v2022.01 and v2022.10, +the exact same sequence of packets were sent, all but the last of size +1500, and the last being 1280 bytes. + +But then it struck me that 1280 is 5*256, so one of the two bytes +on-the-wire is 0 and the other is 5, and when then looking at the code +again the lack of endianness conversion becomes obvious. [ntohs is +both applied to ip->ip_off just above, as well as to ip->ip_len just a +little further down when the "len" is actually computed]. + +IOWs the current code would falsely reject any packet which happens to +be a multiple of 256 bytes in size, breaking tftp transfers somewhat +randomly, and if it did get one of those "malicious" packets with +ip_len set to, say, 27, it would be seen by this check as being 6912 +and hence not rejected. + +==== + +Now, just adding the missing ntohs() would make my initial problem go +away, in that I can now download the file where the last fragment ends +up being 1280 bytes. But there's another bug in the code and/or +analysis: The right-hand side is too strict, in that it is ok for the +last fragment not to have a multiple of 8 bytes as payload - it really +must be ok, because nothing in the IP spec says that IP datagrams must +have a multiple of 8 bytes as payload. And comments in the code also +mention this. + +To fix that, replace the comparison with <= IP_HDR_SIZE and add +another check that len is actually a multiple of 8 when the "more +fragments" bit is set - which it necessarily is for the case where +offset8 ends up being 0, since we're only called when + + (ip_off & (IP_OFFS | IP_FLAGS_MFRAG)). + +==== + +So, does this fix CVE-2022-30790 for real? It certainly correctly +rejects the POC code which relies on sending a packet of size 27 with +the MFRAG flag set. Can the attack be carried out with a size 27 +packet that doesn't set MFRAG (hence must set a non-zero fragment +offset)? I dunno. If we get a packet without MFRAG, we update +h->last_byte in the hole we've found to be start+len, hence we'd enter +one of + + if ((h >= thisfrag) && (h->last_byte <= start + len)) { + +or + + } else if (h->last_byte <= start + len) { + +and thus won't reach any of the + + /* overlaps with initial part of the hole: move this hole */ + newh = thisfrag + (len / 8); + + /* fragment sits in the middle: split the hole */ + newh = thisfrag + (len / 8); + +IOW these division are now guaranteed to be exact, and thus I think +the scenario in CVE-2022-30790 cannot happen anymore. + +==== + +However, there's a big elephant in the room, which has always been +spelled out in the comments, and which makes me believe that one can +still cause mayhem even with packets whose payloads are all 8-byte +aligned: + + This code doesn't deal with a fragment that overlaps with two + different holes (thus being a superset of a previously-received + fragment). + +Suppose each character below represents 8 bytes, with D being already +received data, H being a hole descriptor (struct hole), h being +non-populated chunks, and P representing where the payload of a just +received packet should go: + + DDDHhhhhDDDDHhhhDDDD + PPPPPPPPP + +I'm pretty sure in this case we'd end up with h being the first hole, +enter the simple + + } else if (h->last_byte <= start + len) { + /* overlaps with final part of the hole: shorten this hole */ + h->last_byte = start; + +case, and thus in the memcpy happily overwrite the second H with our +chosen payload. This is probably worth fixing... + +Signed-off-by: Rasmus Villemoes +--- + net/net.c | 10 +++++++++- + 1 file changed, 9 insertions(+), 1 deletion(-) + +diff --git a/net/net.c b/net/net.c +index 434c3b411e..987c25931e 100644 +--- a/net/net.c ++++ b/net/net.c +@@ -924,7 +924,11 @@ 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) ++ /* ++ * Calling code already rejected <, but we don't have to deal ++ * with an IP fragment with no payload. ++ */ ++ if (ntohs(ip->ip_len) <= IP_HDR_SIZE) + return NULL; + + /* payload starts after IP header, this fragment is in there */ +@@ -934,6 +938,10 @@ static struct ip_udp_hdr *__net_defragment(struct ip_udp_hdr *ip, int *lenp) + start = offset8 * 8; + len = ntohs(ip->ip_len) - IP_HDR_SIZE; + ++ /* All but last fragment must have a multiple-of-8 payload. */ ++ if ((len & 7) && (ip_off & IP_FLAGS_MFRAG)) ++ return NULL; ++ + if (start + len > IP_MAXUDP) /* fragment extends too far */ + return NULL; + +-- +2.39.2 + diff -Nru u-boot-nezha-2022.10-1089-g528ae9bc6c/debian/patches/0001-usb-gadget-dfu-Fix-check-of-transfer-direction.patch u-boot-nezha-2022.10-1089-g528ae9bc6c/debian/patches/0001-usb-gadget-dfu-Fix-check-of-transfer-direction.patch --- u-boot-nezha-2022.10-1089-g528ae9bc6c/debian/patches/0001-usb-gadget-dfu-Fix-check-of-transfer-direction.patch 1970-01-01 01:00:00.000000000 +0100 +++ u-boot-nezha-2022.10-1089-g528ae9bc6c/debian/patches/0001-usb-gadget-dfu-Fix-check-of-transfer-direction.patch 2023-03-23 15:50:56.000000000 +0100 @@ -0,0 +1,62 @@ +From 14dc0ab138988a8e45ffa086444ec8db48b3f103 Mon Sep 17 00:00:00 2001 +From: Hugo SIMELIERE +Date: Wed, 30 Nov 2022 09:29:16 +0100 +Subject: [PATCH] usb: gadget: dfu: Fix check of transfer direction + +Commit fbce985e28eaca3af82afecc11961aadaf971a7e to fix CVE-2022-2347 +blocks DFU usb requests. +The verification of the transfer direction was done by an equality +but it is a bit mask. + +Signed-off-by: Hugo SIMELIERE +Reviewed-by: Fabio Estevam +Reviewed-by: Sultan Qasim Khan +Reviewed-by: Marek Vasut +Tested-by: Marek Vasut +--- + drivers/usb/gadget/f_dfu.c | 8 ++++---- + 1 file changed, 4 insertions(+), 4 deletions(-) + +diff --git a/drivers/usb/gadget/f_dfu.c b/drivers/usb/gadget/f_dfu.c +index 33ef62f8ba..44877df4ec 100644 +--- a/drivers/usb/gadget/f_dfu.c ++++ b/drivers/usb/gadget/f_dfu.c +@@ -325,7 +325,7 @@ static int state_dfu_idle(struct f_dfu *f_dfu, + + switch (ctrl->bRequest) { + case USB_REQ_DFU_DNLOAD: +- if (ctrl->bRequestType == USB_DIR_OUT) { ++ if (!(ctrl->bRequestType & USB_DIR_IN)) { + if (len == 0) { + f_dfu->dfu_state = DFU_STATE_dfuERROR; + value = RET_STALL; +@@ -337,7 +337,7 @@ static int state_dfu_idle(struct f_dfu *f_dfu, + } + break; + case USB_REQ_DFU_UPLOAD: +- if (ctrl->bRequestType == USB_DIR_IN) { ++ if (ctrl->bRequestType & USB_DIR_IN) { + f_dfu->dfu_state = DFU_STATE_dfuUPLOAD_IDLE; + f_dfu->blk_seq_num = 0; + value = handle_upload(req, len); +@@ -436,7 +436,7 @@ static int state_dfu_dnload_idle(struct f_dfu *f_dfu, + + switch (ctrl->bRequest) { + case USB_REQ_DFU_DNLOAD: +- if (ctrl->bRequestType == USB_DIR_OUT) { ++ if (!(ctrl->bRequestType & USB_DIR_IN)) { + f_dfu->dfu_state = DFU_STATE_dfuDNLOAD_SYNC; + f_dfu->blk_seq_num = w_value; + value = handle_dnload(gadget, len); +@@ -527,7 +527,7 @@ static int state_dfu_upload_idle(struct f_dfu *f_dfu, + + switch (ctrl->bRequest) { + case USB_REQ_DFU_UPLOAD: +- if (ctrl->bRequestType == USB_DIR_IN) { ++ if (ctrl->bRequestType & USB_DIR_IN) { + /* state transition if less data then requested */ + f_dfu->blk_seq_num = w_value; + value = handle_upload(req, len); +-- +2.39.2 + diff -Nru u-boot-nezha-2022.10-1089-g528ae9bc6c/debian/patches/0001-usb-gadget-dfu-Fix-the-unchecked-length-field.patch u-boot-nezha-2022.10-1089-g528ae9bc6c/debian/patches/0001-usb-gadget-dfu-Fix-the-unchecked-length-field.patch --- u-boot-nezha-2022.10-1089-g528ae9bc6c/debian/patches/0001-usb-gadget-dfu-Fix-the-unchecked-length-field.patch 1970-01-01 01:00:00.000000000 +0100 +++ u-boot-nezha-2022.10-1089-g528ae9bc6c/debian/patches/0001-usb-gadget-dfu-Fix-the-unchecked-length-field.patch 2023-03-23 15:50:15.000000000 +0100 @@ -0,0 +1,127 @@ +From fbce985e28eaca3af82afecc11961aadaf971a7e Mon Sep 17 00:00:00 2001 +From: Venkatesh Yadav Abbarapu +Date: Thu, 3 Nov 2022 09:37:48 +0530 +Subject: [PATCH] usb: gadget: dfu: Fix the unchecked length field + +DFU implementation does not bound the length field in USB +DFU download setup packets, and it does not verify that +the transfer direction. Fixing the length and transfer +direction. + +CVE-2022-2347 + +Signed-off-by: Venkatesh Yadav Abbarapu +Reviewed-by: Marek Vasut +--- + drivers/usb/gadget/f_dfu.c | 58 ++++++++++++++++++++++++-------------- + 1 file changed, 37 insertions(+), 21 deletions(-) + +diff --git a/drivers/usb/gadget/f_dfu.c b/drivers/usb/gadget/f_dfu.c +index e9340ff5cb..33ef62f8ba 100644 +--- a/drivers/usb/gadget/f_dfu.c ++++ b/drivers/usb/gadget/f_dfu.c +@@ -321,23 +321,29 @@ static int state_dfu_idle(struct f_dfu *f_dfu, + u16 len = le16_to_cpu(ctrl->wLength); + int value = 0; + ++ len = len > DFU_USB_BUFSIZ ? DFU_USB_BUFSIZ : len; ++ + switch (ctrl->bRequest) { + case USB_REQ_DFU_DNLOAD: +- if (len == 0) { +- f_dfu->dfu_state = DFU_STATE_dfuERROR; +- value = RET_STALL; +- break; ++ if (ctrl->bRequestType == USB_DIR_OUT) { ++ if (len == 0) { ++ f_dfu->dfu_state = DFU_STATE_dfuERROR; ++ value = RET_STALL; ++ break; ++ } ++ f_dfu->dfu_state = DFU_STATE_dfuDNLOAD_SYNC; ++ f_dfu->blk_seq_num = w_value; ++ value = handle_dnload(gadget, len); + } +- f_dfu->dfu_state = DFU_STATE_dfuDNLOAD_SYNC; +- f_dfu->blk_seq_num = w_value; +- value = handle_dnload(gadget, len); + break; + case USB_REQ_DFU_UPLOAD: +- f_dfu->dfu_state = DFU_STATE_dfuUPLOAD_IDLE; +- f_dfu->blk_seq_num = 0; +- value = handle_upload(req, len); +- if (value >= 0 && value < len) +- f_dfu->dfu_state = DFU_STATE_dfuIDLE; ++ if (ctrl->bRequestType == USB_DIR_IN) { ++ f_dfu->dfu_state = DFU_STATE_dfuUPLOAD_IDLE; ++ f_dfu->blk_seq_num = 0; ++ value = handle_upload(req, len); ++ if (value >= 0 && value < len) ++ f_dfu->dfu_state = DFU_STATE_dfuIDLE; ++ } + break; + case USB_REQ_DFU_ABORT: + /* no zlp? */ +@@ -426,11 +432,15 @@ static int state_dfu_dnload_idle(struct f_dfu *f_dfu, + u16 len = le16_to_cpu(ctrl->wLength); + int value = 0; + ++ len = len > DFU_USB_BUFSIZ ? DFU_USB_BUFSIZ : len; ++ + switch (ctrl->bRequest) { + case USB_REQ_DFU_DNLOAD: +- f_dfu->dfu_state = DFU_STATE_dfuDNLOAD_SYNC; +- f_dfu->blk_seq_num = w_value; +- value = handle_dnload(gadget, len); ++ if (ctrl->bRequestType == USB_DIR_OUT) { ++ f_dfu->dfu_state = DFU_STATE_dfuDNLOAD_SYNC; ++ f_dfu->blk_seq_num = w_value; ++ value = handle_dnload(gadget, len); ++ } + break; + case USB_REQ_DFU_ABORT: + f_dfu->dfu_state = DFU_STATE_dfuIDLE; +@@ -513,13 +523,17 @@ static int state_dfu_upload_idle(struct f_dfu *f_dfu, + u16 len = le16_to_cpu(ctrl->wLength); + int value = 0; + ++ len = len > DFU_USB_BUFSIZ ? DFU_USB_BUFSIZ : len; ++ + switch (ctrl->bRequest) { + case USB_REQ_DFU_UPLOAD: +- /* state transition if less data then requested */ +- f_dfu->blk_seq_num = w_value; +- value = handle_upload(req, len); +- if (value >= 0 && value < len) +- f_dfu->dfu_state = DFU_STATE_dfuIDLE; ++ if (ctrl->bRequestType == USB_DIR_IN) { ++ /* state transition if less data then requested */ ++ f_dfu->blk_seq_num = w_value; ++ value = handle_upload(req, len); ++ if (value >= 0 && value < len) ++ f_dfu->dfu_state = DFU_STATE_dfuIDLE; ++ } + break; + case USB_REQ_DFU_ABORT: + f_dfu->dfu_state = DFU_STATE_dfuIDLE; +@@ -595,6 +609,8 @@ dfu_handle(struct usb_function *f, const struct usb_ctrlrequest *ctrl) + int value = 0; + u8 req_type = ctrl->bRequestType & USB_TYPE_MASK; + ++ len = len > DFU_USB_BUFSIZ ? DFU_USB_BUFSIZ : len; ++ + debug("w_value: 0x%x len: 0x%x\n", w_value, len); + debug("req_type: 0x%x ctrl->bRequest: 0x%x f_dfu->dfu_state: 0x%x\n", + req_type, ctrl->bRequest, f_dfu->dfu_state); +@@ -614,7 +630,7 @@ dfu_handle(struct usb_function *f, const struct usb_ctrlrequest *ctrl) + value = dfu_state[f_dfu->dfu_state] (f_dfu, ctrl, gadget, req); + + if (value >= 0) { +- req->length = value; ++ req->length = value > DFU_USB_BUFSIZ ? DFU_USB_BUFSIZ : value; + req->zero = value < len; + value = usb_ep_queue(gadget->ep0, req, 0); + if (value < 0) { +-- +2.39.2 + diff -Nru u-boot-nezha-2022.10-1089-g528ae9bc6c/debian/patches/series u-boot-nezha-2022.10-1089-g528ae9bc6c/debian/patches/series --- u-boot-nezha-2022.10-1089-g528ae9bc6c/debian/patches/series 2022-11-29 10:20:07.000000000 +0100 +++ u-boot-nezha-2022.10-1089-g528ae9bc6c/debian/patches/series 2023-03-24 12:16:34.000000000 +0100 @@ -1,2 +1,6 @@ 0001-configs-SUN20I_D1-don-t-enable-watchdog-by-default.patch 0001-add-efi-commands.patch +0001-enable-sbi-command.patch +0001-usb-gadget-dfu-Fix-the-unchecked-length-field.patch +0001-net-actually-better-deal-with-CVE-2022-30790-30552.patch +0001-usb-gadget-dfu-Fix-check-of-transfer-direction.patch