mailweb.openeuler.org
Manage this list

Keyboard Shortcuts

Thread View

  • j: Next unread message
  • k: Previous unread message
  • j a: Jump to all threads
  • j l: Jump to MailingList overview

Kernel

Threads by month
  • ----- 2026 -----
  • September
  • August
  • July
  • June
  • May
  • April
  • March
  • February
  • January
  • ----- 2025 -----
  • December
  • November
  • October
  • September
  • August
  • July
  • June
  • May
  • April
  • March
  • February
  • January
  • ----- 2024 -----
  • December
  • November
  • October
  • September
  • August
  • July
  • June
  • May
  • April
  • March
  • February
  • January
  • ----- 2023 -----
  • December
  • November
  • October
  • September
  • August
  • July
  • June
  • May
  • April
  • March
  • February
  • January
  • ----- 2022 -----
  • December
  • November
  • October
  • September
  • August
  • July
  • June
  • May
  • April
  • March
  • February
  • January
  • ----- 2021 -----
  • December
  • November
  • October
  • September
  • August
  • July
  • June
  • May
  • April
  • March
  • February
  • January
  • ----- 2020 -----
  • December
  • November
  • October
  • September
  • August
  • July
  • June
  • May
  • April
  • March
  • February
  • January
  • ----- 2019 -----
  • December
kernel@openeuler.org

  • 43 participants
  • 24907 discussions
[PATCH openEuler-1.0-LTS V1] IB/isert: reject login PDUs declaring more data than was received
by Yao Yiqi 21 Sep '26

21 Sep '26
From: Yehyeong Lee <yhlee(a)isslab.korea.ac.kr> stable inclusion from stable-v5.10.270 commit b1f3313e7b3e396e4985fea5c709477387e0a065 category: bugfix bugzilla: https://atomgit.com/src-openeuler/kernel/issues/19431 CVE: CVE-2026-90413 Reference: https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/commit/?id… ------------------------------ [ Upstream commit 2488b5b4827e5415768afc8daf097e8eb83c98df ] isert_login_recv_done() records how many bytes the HCA actually placed in the login buffer, but nothing compares that against the length the login PDU's BHS declares. isert_rx_login_req() copies min(login_req_len, MAX_KEY_VALUE_PAIRS) bytes into login->req_buf, and the login code then reads the declared length back out of that buffer - for the first PDU in iscsi_target_locate_portal(), payload_length = ntoh24(login_req->dlength); tmpbuf = kmemdup_nul(login->req_buf, payload_length, GFP_KERNEL); and for the ones after it in iscsi_decode_text_input(), reached from iscsi_target_do_login(). login->req_buf is a fixed MAX_KEY_VALUE_PAIRS (8192) byte allocation, so an initiator that declares more than it sends reads off the end of it, before authentication and with the length under its control: BUG: KASAN: slab-out-of-bounds in kmemdup_nul+0x43/0x80 Read of size 8193 at addr ffff8881056a8000 by task iscsi_np/167 __asan_memcpy+0x23/0x60 kmemdup_nul+0x43/0x80 iscsi_target_locate_portal+0x48d/0x1180 iscsi_target_login_thread+0x19a9/0x3350 Allocated by task 167: __kmalloc_cache_noprof+0x158/0x370 iscsi_target_login_thread+0x971/0x3350 which belongs to the cache kmalloc-8k of size 8192 allocated 8192-byte region Falsifying the second login PDU instead reaches the other reader, on the same buffer: BUG: KASAN: slab-out-of-bounds in kmemdup_nul+0x43/0x80 Read of size 8193 at addr ffff888104d10000 by task kworker/1:1/50 Workqueue: isert_login_wq iscsi_target_do_login_rx __asan_memcpy+0x23/0x60 kmemdup_nul+0x43/0x80 iscsi_decode_text_input+0xc6/0x11c0 iscsi_target_do_login+0x261/0x1470 iscsi_target_do_login_rx+0x51d/0x7d0 iscsit over TCP is not exposed: iscsit_get_login_rx() validates the declared length with iscsi_target_check_login_request() and then reads exactly that many bytes off the socket, so the declared length governs how much arrives rather than how much is copied out of an already-filled buffer. isert does not call iscsi_target_check_login_request() at all. Reject a login PDU whose declared DataSegmentLength exceeds what was received, in both paths that reach isert_rx_login_req(): isert_get_login_rx() for the first login PDU and isert_login_recv_done() for the ones after it. dlength <= login_req_len is allowed because the received count can include up to three bytes of iSCSI padding. Once the check is in place the copy out can no longer exceed the copy in: the posted login SGE is ISER_RX_PAYLOAD_SIZE, so login_req_len cannot exceed MAX_KEY_VALUE_PAIRS and the min() in isert_rx_login_req() is login_req_len. Like the existing short-PDU check added by 29e7b925ae6d, the reject in isert_login_recv_done() returns without completing login_req_comp, so a malformed subsequent PDU leaves the login to be torn down by the login timer rather than failing immediately. The first-PDU path returns an error and fails straight away. Reproduced on 7.2.0-rc4 with soft-RoCE (rdma_rxe) under KASAN, using an initiator that sends the real key=value payload while declaring 8193 in the BHS, on the first login PDU and on the second in separate runs. The reported read size tracks the declared value exactly; 16384 and 61440 behave the same. Unpatched 3 of 3 runs report on each of the two paths, patched 0 of 3 on both, run alternately in a single session, and a normal login still completes on the patched build. Fixes: b8d26b3be8b3 ("iser-target: Add iSCSI Extensions for RDMA (iSER) target driver") Suggested-by: Leon Romanovsky <leonro(a)nvidia.com> Signed-off-by: Yehyeong Lee <yhlee(a)isslab.korea.ac.kr> Link: https://patch.msgid.link/20260726163931.971063-3-yhlee@isslab.korea.ac.kr Signed-off-by: Leon Romanovsky <leon(a)kernel.org> Signed-off-by: Sasha Levin <sashal(a)kernel.org> Conflicts: drivers/infiniband/ulp/isert/ib_isert.c [ 4.19 does not have isert_get_iscsi_hdr helper funciton ] Signed-off-by: Yao Yiqi <yaoyiqi3(a)huawei.com> --- drivers/infiniband/ulp/isert/ib_isert.c | 25 ++++++++++++++++++++++++- 1 file changed, 24 insertions(+), 1 deletion(-) diff --git a/drivers/infiniband/ulp/isert/ib_isert.c b/drivers/infiniband/ulp/isert/ib_isert.c index 97119e8e0751..fbe073ebfbcc 100644 --- a/drivers/infiniband/ulp/isert/ib_isert.c +++ b/drivers/infiniband/ulp/isert/ib_isert.c @@ -1056,6 +1056,21 @@ isert_put_login_tx(struct iscsi_conn *conn, struct iscsi_login *login, return 0; } +static int +isert_check_login_req(struct isert_conn *isert_conn) +{ + struct iscsi_hdr *hdr = &isert_conn->login_req_buf->iscsi_header; + u32 dlength = ntoh24(hdr->dlength); + + if (unlikely(dlength > (u32)isert_conn->login_req_len)) { + isert_dbg("login PDU declares %u data bytes but only %d were received\n", + dlength, isert_conn->login_req_len); + return -EINVAL; + } + + return 0; +} + static void isert_rx_login_req(struct isert_conn *isert_conn) { @@ -1484,8 +1499,12 @@ isert_login_recv_done(struct ib_cq *cq, struct ib_wc *wc) if (isert_conn->conn) { struct iscsi_login *login = isert_conn->conn->conn_login; - if (login && !login->first_request) + if (login && !login->first_request) { + if (isert_check_login_req(isert_conn)) + return; + isert_rx_login_req(isert_conn); + } } mutex_lock(&isert_conn->mutex); @@ -2445,6 +2464,10 @@ isert_get_login_rx(struct iscsi_conn *conn, struct iscsi_login *login) if (!login->first_request) return 0; + ret = isert_check_login_req(isert_conn); + if (ret) + return ret; + isert_rx_login_req(isert_conn); isert_info("before login_comp conn: %p\n", conn); -- 2.34.1
2 1
0 0
[PATCH openEuler-1.0-LTS] selinux: check connect-related permissions on TCP Fast Open
by Yi Yang 21 Sep '26

21 Sep '26
From: Stephen Smalley <stephen.smalley.work(a)gmail.com> mainline inclusion from mainline-v7.2-rc3 commit 44c74d27d1b9aaa99fa8a83640c1223575262b80 category: bugfix bugzilla: https://atomgit.com/src-openeuler/kernel/issues/17775 CVE: CVE-2026-72243 Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?… -------------------------------- Similar to Landlock, SELinux was not updated when TCP Fast Open support was introduced to ensure connect-related permissions are checked when using TCP Fast Open. Update its socket_sendmsg() hook to call selinux_socket_connect() when MSG_FASTOPEN is passed. Cc: stable(a)vger.kernel.org Link: https://lore.kernel.org/linux-security-module/20260616201615.275032-1-hexla… Link: https://lore.kernel.org/linux-security-module/20260617180526.15627-2-matthi… Reported-by: Bryam Vargas <hexlabsecurity(a)proton.me> Reported-by: Matthieu Buffet <matthieu(a)buffet.re> Reported-by: Mikhail Ivanov <ivanov.mikhail1(a)huawei-partners.com> Signed-off-by: Stephen Smalley <stephen.smalley.work(a)gmail.com> Tested-by: Bryam Vargas <hexlabsecurity(a)proton.me> Signed-off-by: Paul Moore <paul(a)paul-moore.com> Conflicts: security/selinux/hooks.c [The sk_is_tcp function was not introduced.] Signed-off-by: Yi Yang <yiyang13(a)huawei.com> --- security/selinux/hooks.c | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c index 3550ded07457..f85147d8704d 100644 --- a/security/selinux/hooks.c +++ b/security/selinux/hooks.c @@ -4910,7 +4910,25 @@ static int selinux_socket_accept(struct socket *sock, struct socket *newsock) static int selinux_socket_sendmsg(struct socket *sock, struct msghdr *msg, int size) { - return sock_has_perm(sock->sk, SOCKET__WRITE); + int rc; + struct sockaddr *const addr = msg->msg_name; + const int addrlen = msg->msg_namelen; + + rc = sock_has_perm(sock->sk, SOCKET__WRITE); + if (rc) + return rc; + + if (addr && (msg->msg_flags & MSG_FASTOPEN) && + (sock->sk->sk_family == AF_INET || + sock->sk->sk_family == AF_INET6) && + sock->sk->sk_type == SOCK_STREAM && + sock->sk->sk_protocol == IPPROTO_TCP) { + rc = selinux_socket_connect(sock, addr, addrlen); + if (rc) + return rc; + } + + return 0; } static int selinux_socket_recvmsg(struct socket *sock, struct msghdr *msg, -- 2.25.1
2 1
0 0
[PATCH openEuler-1.0-LTS V1] IB/isert: reject login PDUs declaring more data than was received
by Yao Yiqi 21 Sep '26

21 Sep '26
From: Yehyeong Lee <yhlee(a)isslab.korea.ac.kr> stable inclusion from stable-v5.10.270 commit b1f3313e7b3e396e4985fea5c709477387e0a065 category: bugfix bugzilla: https://atomgit.com/src-openeuler/kernel/issues/19431 CVE: CVE-2026-90413 Reference: https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/commit/?id… ------------------------------ [ Upstream commit 2488b5b4827e5415768afc8daf097e8eb83c98df ] isert_login_recv_done() records how many bytes the HCA actually placed in the login buffer, but nothing compares that against the length the login PDU's BHS declares. isert_rx_login_req() copies min(login_req_len, MAX_KEY_VALUE_PAIRS) bytes into login->req_buf, and the login code then reads the declared length back out of that buffer - for the first PDU in iscsi_target_locate_portal(), payload_length = ntoh24(login_req->dlength); tmpbuf = kmemdup_nul(login->req_buf, payload_length, GFP_KERNEL); and for the ones after it in iscsi_decode_text_input(), reached from iscsi_target_do_login(). login->req_buf is a fixed MAX_KEY_VALUE_PAIRS (8192) byte allocation, so an initiator that declares more than it sends reads off the end of it, before authentication and with the length under its control: BUG: KASAN: slab-out-of-bounds in kmemdup_nul+0x43/0x80 Read of size 8193 at addr ffff8881056a8000 by task iscsi_np/167 __asan_memcpy+0x23/0x60 kmemdup_nul+0x43/0x80 iscsi_target_locate_portal+0x48d/0x1180 iscsi_target_login_thread+0x19a9/0x3350 Allocated by task 167: __kmalloc_cache_noprof+0x158/0x370 iscsi_target_login_thread+0x971/0x3350 which belongs to the cache kmalloc-8k of size 8192 allocated 8192-byte region Falsifying the second login PDU instead reaches the other reader, on the same buffer: BUG: KASAN: slab-out-of-bounds in kmemdup_nul+0x43/0x80 Read of size 8193 at addr ffff888104d10000 by task kworker/1:1/50 Workqueue: isert_login_wq iscsi_target_do_login_rx __asan_memcpy+0x23/0x60 kmemdup_nul+0x43/0x80 iscsi_decode_text_input+0xc6/0x11c0 iscsi_target_do_login+0x261/0x1470 iscsi_target_do_login_rx+0x51d/0x7d0 iscsit over TCP is not exposed: iscsit_get_login_rx() validates the declared length with iscsi_target_check_login_request() and then reads exactly that many bytes off the socket, so the declared length governs how much arrives rather than how much is copied out of an already-filled buffer. isert does not call iscsi_target_check_login_request() at all. Reject a login PDU whose declared DataSegmentLength exceeds what was received, in both paths that reach isert_rx_login_req(): isert_get_login_rx() for the first login PDU and isert_login_recv_done() for the ones after it. dlength <= login_req_len is allowed because the received count can include up to three bytes of iSCSI padding. Once the check is in place the copy out can no longer exceed the copy in: the posted login SGE is ISER_RX_PAYLOAD_SIZE, so login_req_len cannot exceed MAX_KEY_VALUE_PAIRS and the min() in isert_rx_login_req() is login_req_len. Like the existing short-PDU check added by 29e7b925ae6d, the reject in isert_login_recv_done() returns without completing login_req_comp, so a malformed subsequent PDU leaves the login to be torn down by the login timer rather than failing immediately. The first-PDU path returns an error and fails straight away. Reproduced on 7.2.0-rc4 with soft-RoCE (rdma_rxe) under KASAN, using an initiator that sends the real key=value payload while declaring 8193 in the BHS, on the first login PDU and on the second in separate runs. The reported read size tracks the declared value exactly; 16384 and 61440 behave the same. Unpatched 3 of 3 runs report on each of the two paths, patched 0 of 3 on both, run alternately in a single session, and a normal login still completes on the patched build. Fixes: b8d26b3be8b3 ("iser-target: Add iSCSI Extensions for RDMA (iSER) target driver") Suggested-by: Leon Romanovsky <leonro(a)nvidia.com> Signed-off-by: Yehyeong Lee <yhlee(a)isslab.korea.ac.kr> Link: https://patch.msgid.link/20260726163931.971063-3-yhlee@isslab.korea.ac.kr Signed-off-by: Leon Romanovsky <leon(a)kernel.org> Signed-off-by: Sasha Levin <sashal(a)kernel.org> Signed-off-by: Yao Yiqi <yaoyiqi3(a)huawei.com> --- drivers/infiniband/ulp/isert/ib_isert.c | 25 ++++++++++++++++++++++++- 1 file changed, 24 insertions(+), 1 deletion(-) diff --git a/drivers/infiniband/ulp/isert/ib_isert.c b/drivers/infiniband/ulp/isert/ib_isert.c index 97119e8e0751..4d0da69103cf 100644 --- a/drivers/infiniband/ulp/isert/ib_isert.c +++ b/drivers/infiniband/ulp/isert/ib_isert.c @@ -1056,6 +1056,21 @@ isert_put_login_tx(struct iscsi_conn *conn, struct iscsi_login *login, return 0; } +static int +isert_check_login_req(struct isert_conn *isert_conn) +{ + struct iscsi_hdr *hdr = isert_get_iscsi_hdr(isert_conn->login_desc); + u32 dlength = ntoh24(hdr->dlength); + + if (unlikely(dlength > (u32)isert_conn->login_req_len)) { + isert_dbg("login PDU declares %u data bytes but only %d were received\n", + dlength, isert_conn->login_req_len); + return -EINVAL; + } + + return 0; +} + static void isert_rx_login_req(struct isert_conn *isert_conn) { @@ -1484,8 +1499,12 @@ isert_login_recv_done(struct ib_cq *cq, struct ib_wc *wc) if (isert_conn->conn) { struct iscsi_login *login = isert_conn->conn->conn_login; - if (login && !login->first_request) + if (login && !login->first_request) { + if (isert_check_login_req(isert_conn)) + return; + isert_rx_login_req(isert_conn); + } } mutex_lock(&isert_conn->mutex); @@ -2445,6 +2464,10 @@ isert_get_login_rx(struct iscsi_conn *conn, struct iscsi_login *login) if (!login->first_request) return 0; + ret = isert_check_login_req(isert_conn); + if (ret) + return ret; + isert_rx_login_req(isert_conn); isert_info("before login_comp conn: %p\n", conn); -- 2.34.1
2 1
0 0
[PATCH openEuler-1.0-LTS V1] IB/isert: reject PDUs declaring more data than was received
by Yao Yiqi 21 Sep '26

21 Sep '26
From: Yehyeong Lee <yhlee(a)isslab.korea.ac.kr> stable inclusion from stable-v5.10.270 commit b4706722ed3ea72882b3c986a19b4a1ba66384c4 category: bugfix bugzilla: https://atomgit.com/src-openeuler/kernel/issues/19430 CVE: CVE-2026-90414 Reference: https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/commit/?id… ------------------------------ [ Upstream commit 957f92ea4022fb6af4618271615a2a21a7b5bef9 ] isert_recv_done() hands each received PDU to the opcode handlers without ever looking at wc->byte_len, the number of bytes the HCA actually placed in the receive descriptor. The handlers then copy that many bytes - the data-segment length the initiator declared in the BHS (ntoh24(hdr->dlength), via the derived unsol_data_len / imm_data_len) - out of the fixed-size descriptor: isert_handle_iscsi_dataout(): sg_copy_from_buffer(sg_start, sg_nents, isert_get_data(rx_desc), unsol_data_len); isert_handle_scsi_cmd(): sg_copy_from_buffer(cmd->se_cmd.t_data_sg, sg_nents, isert_get_data(rx_desc), imm_data_len); Because the declared length is never checked against wc->byte_len, an initiator can declare a data segment larger than the bytes it actually sent (and larger than the descriptor) and cause an out-of-bounds read of the receive buffer. Nothing upstream of isert closes this door: - __iscsit_check_dataout_hdr() bounds the inbound payload against conn_ops->MaxXmitDataSegmentLength (MXDSL) - a transmit parameter, used here for the inbound check. - iscsi_set_connection_parameters() sets ops->MaxXmitDataSegmentLength = ops->TargetRecvDataSegmentLength; and TARGETRECVDATASEGMENTLENGTH is absent from the min()-clamp list in iscsi_check_acceptor_state(), so the value the initiator declares is adopted verbatim (type range 512..16777215). The initiator effectively raises its own ceiling. - isert never clamps the negotiated value to its own fixed receive descriptor (ISER_RX_SIZE, 9216 bytes), so the target core's bound and the descriptor size are unrelated. The imm_data_len == data_len path is more than an over-read: it aliases the receive descriptor via sg_set_buf() and passes it to the backend as the data source for the SCSI WRITE, so an over-declared length causes heap contents past the descriptor to be written through the backend to the backing store. The backend is the victim of the oversized scatterlist isert hands it, not the cause; no read-back of the written bytes was demonstrated. Trigger: after login completes (full feature phase), an initiator that has declared a large TargetRecvDataSegmentLength and a FirstBurstLength that permits unsolicited/immediate data sends a PDU whose declared data-segment length exceeds what was received. With KASAN: BUG: KASAN: slab-out-of-bounds in sg_copy_buffer+0x150/0x1c0 Read of size 4096 at addr ffff888109720800 by task kworker/1:0H/25 Workqueue: ib-comp-wq ib_cq_poll_work Call Trace: sg_copy_buffer+0x150/0x1c0 isert_recv_done+0xba6/0x2390 __ib_process_cq+0xe1/0x390 ib_cq_poll_work+0x46/0x150 isert_recv_done+0xba6 resolves to isert_handle_iscsi_dataout() (ib_isert.c:1160), inlined through isert_rx_opcode(). Validate wc->byte_len against the framing in isert_recv_done() before the PDU reaches any handler, and reinstate the connection if it is short. Because the test compares without subtracting the header length, it also rejects PDUs shorter than the iSER and iSCSI headers, which would otherwise be parsed out of stale descriptor contents. The login handler rejects PDUs shorter than ISER_HEADERS_LEN (commit 29e7b925ae6d ("IB/isert: Reject login PDUs shorter than ISER_HEADERS_LEN")) but does not bound the declared length either; that is fixed in the next patch. The data handlers had no length check at all. isert reads the data segment from a fixed offset: isert_get_data() returns the iSER header plus ISER_HEADERS_LEN and makes no adjustment for an AHS. The bytes the handlers touch are therefore exactly [ISER_HEADERS_LEN, ISER_HEADERS_LEN + dlength), and comparing that sum against wc->byte_len bounds precisely the region that is read. An AHS term would only make the test stricter without bounding anything further, and cannot cause a false reject: a PDU carrying an AHS is longer, not shorter. This is a memory-safety fix that verifies the bytes that were actually received; it does not touch RFC 7145 length negotiation and is not the MaxXmitDataSegmentLength negotiation redesign raised in the 2017 "[Query] iSER-Target: QP errors observed on increasing MaxXmitDataSegmentLength" discussion. That redesign is explicitly out of scope here. The patched kernel rejects the malformed DataOut PDU and both immediate-data variants with "PDU declares ... bytes were received" and continues to pass normal traffic with no regression. Reproduced with soft-RoCE (rdma_rxe) and a raw rdma_cm/ibv initiator; no kernel-side test hooks were needed. Fixes: b8d26b3be8b3 ("iser-target: Add iSCSI Extensions for RDMA (iSER) target driver") Signed-off-by: Yehyeong Lee <yhlee(a)isslab.korea.ac.kr> Link: https://patch.msgid.link/20260726163931.971063-2-yhlee@isslab.korea.ac.kr Signed-off-by: Leon Romanovsky <leon(a)kernel.org> Signed-off-by: Sasha Levin <sashal(a)kernel.org> Conflicts: drivers/infiniband/ulp/isert/ib_isert.c [ Context conflicts ] Signed-off-by: Yao Yiqi <yaoyiqi3(a)huawei.com> --- drivers/infiniband/ulp/isert/ib_isert.c | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/drivers/infiniband/ulp/isert/ib_isert.c b/drivers/infiniband/ulp/isert/ib_isert.c index 97119e8e0751..d950cfd1be53 100644 --- a/drivers/infiniband/ulp/isert/ib_isert.c +++ b/drivers/infiniband/ulp/isert/ib_isert.c @@ -1423,6 +1423,21 @@ isert_recv_done(struct ib_cq *cq, struct ib_wc *wc) ib_dma_sync_single_for_cpu(ib_dev, rx_desc->dma_addr, ISER_RX_PAYLOAD_SIZE, DMA_FROM_DEVICE); + /* + * The data segment length declared in the BHS is attacker controlled + * and is used further down to read that many bytes out of the fixed + * size receive descriptor, so it has to be checked against the number + * of bytes that were actually received. Comparing without subtracting + * also rejects PDUs shorter than the iSER and iSCSI headers, which + * would otherwise be parsed out of stale descriptor contents. + */ + if (unlikely(wc->byte_len < ISER_HEADERS_LEN + ntoh24(hdr->dlength))) { + isert_err("PDU declares %u data bytes but only %u bytes were received\n", + ntoh24(hdr->dlength), wc->byte_len); + iscsit_cause_connection_reinstatement(isert_conn->conn, 0); + return; + } + isert_dbg("DMA: 0x%llx, iSCSI opcode: 0x%02x, ITT: 0x%08x, flags: 0x%02x dlen: %d\n", rx_desc->dma_addr, hdr->opcode, hdr->itt, hdr->flags, (int)(wc->byte_len - ISER_HEADERS_LEN)); -- 2.34.1
2 1
0 0
[PATCH openEuler-1.0-LTS] openvswitch: fix GSO userspace truncation underflow
by Yi Yang 21 Sep '26

21 Sep '26
From: Kyle Zeng <kylebot(a)openai.com> stable inclusion from stable-v5.10.265 commit 50a6a85f3d6b1d22d8436848606cdef5d2c490b4 category: bugfix bugzilla: https://atomgit.com/src-openeuler/kernel/issues/16932 CVE: CVE-2026-68123 Reference: https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/commit/?id… -------------------------------- [ Upstream commit 4032f8ed10fcb84d41c508dfb04be96589f78dfe ] OVS_ACTION_ATTR_TRUNC currently stores a delta from the original skb length in OVS_CB(skb)->cutlen. When a later userspace action segments a GSO skb, queue_gso_packets() reuses that delta for each smaller segment. A segment can then reach queue_userspace_packet() with cutlen greater than skb->len, underflowing the length passed to skb_zerocopy(). Store the maximum preserved length instead and bound each consumer against the current skb length. Use U32_MAX as the no-truncation sentinel so the value remains valid if skb geometry changes before a consumer handles it. Fixes: f2a4d086ed4c ("openvswitch: Add packet truncation support.") Cc: stable(a)vger.kernel.org Assisted-by: Codex:gpt-5.5 Signed-off-by: Kyle Zeng <kylebot(a)openai.com> Reviewed-by: Ilya Maximets <i.maximets(a)ovn.org> Reviewed-by: Aaron Conole <aconole(a)redhat.com> Link: https://patch.msgid.link/20260707221635.27489-1-kylebot@openai.com Signed-off-by: Paolo Abeni <pabeni(a)redhat.com> [5.10.y supports neither OVS_ACTION_ATTR_PSAMPLE nor OVS drop reasons] Signed-off-by: Ilya Maximets <i.maximets(a)ovn.org> Signed-off-by: Sasha Levin <sashal(a)kernel.org> Conflicts: net/openvswitch/datapath.c [Context conflicts.] Signed-off-by: Yi Yang <yiyang13(a)huawei.com> --- net/openvswitch/actions.c | 15 +++++---------- net/openvswitch/datapath.c | 25 ++++++++++++++----------- net/openvswitch/datapath.h | 2 +- net/openvswitch/vport.c | 2 +- 4 files changed, 21 insertions(+), 23 deletions(-) diff --git a/net/openvswitch/actions.c b/net/openvswitch/actions.c index 7ac5f75e06a9..f3b3fd459600 100644 --- a/net/openvswitch/actions.c +++ b/net/openvswitch/actions.c @@ -949,12 +949,8 @@ static void do_output(struct datapath *dp, struct sk_buff *skb, int out_port, u16 mru = OVS_CB(skb)->mru; u32 cutlen = OVS_CB(skb)->cutlen; - if (unlikely(cutlen > 0)) { - if (skb->len - cutlen > ovs_mac_header_len(key)) - pskb_trim(skb, skb->len - cutlen); - else - pskb_trim(skb, ovs_mac_header_len(key)); - } + if (unlikely(cutlen < skb->len)) + pskb_trim(skb, max(cutlen, ovs_mac_header_len(key))); if (likely(!mru || (skb->len <= mru + vport->dev->hard_header_len))) { @@ -1237,22 +1233,21 @@ static int do_execute_actions(struct datapath *dp, struct sk_buff *skb, clone = skb_clone(skb, GFP_ATOMIC); if (clone) do_output(dp, clone, port, key); - OVS_CB(skb)->cutlen = 0; + OVS_CB(skb)->cutlen = U32_MAX; break; } case OVS_ACTION_ATTR_TRUNC: { struct ovs_action_trunc *trunc = nla_data(a); - if (skb->len > trunc->max_len) - OVS_CB(skb)->cutlen = skb->len - trunc->max_len; + OVS_CB(skb)->cutlen = trunc->max_len; break; } case OVS_ACTION_ATTR_USERSPACE: output_userspace(dp, skb, key, a, attr, len, OVS_CB(skb)->cutlen); - OVS_CB(skb)->cutlen = 0; + OVS_CB(skb)->cutlen = U32_MAX; break; case OVS_ACTION_ATTR_HASH: diff --git a/net/openvswitch/datapath.c b/net/openvswitch/datapath.c index bd00e63603ca..1aeeb18c8812 100644 --- a/net/openvswitch/datapath.c +++ b/net/openvswitch/datapath.c @@ -248,7 +248,7 @@ void ovs_dp_process_packet(struct sk_buff *skb, struct sw_flow_key *key) upcall.cmd = OVS_PACKET_CMD_MISS; upcall.portid = ovs_vport_find_upcall_portid(p, skb); upcall.mru = OVS_CB(skb)->mru; - error = ovs_dp_upcall(dp, skb, key, &upcall, 0); + error = ovs_dp_upcall(dp, skb, key, &upcall, U32_MAX); if (unlikely(error)) kfree_skb(skb); else @@ -399,7 +399,8 @@ static int queue_userspace_packet(struct datapath *dp, struct sk_buff *skb, struct sk_buff *nskb = NULL; struct sk_buff *user_skb = NULL; /* to be queued to userspace */ struct nlattr *nla; - size_t len; + size_t msg_size; + size_t skb_len; unsigned int hlen; int err, dp_ifindex; @@ -419,7 +420,8 @@ static int queue_userspace_packet(struct datapath *dp, struct sk_buff *skb, skb = nskb; } - if (nla_attr_size(skb->len) > USHRT_MAX) { + skb_len = min(skb->len, cutlen); + if (nla_attr_size(skb_len) > USHRT_MAX) { err = -EFBIG; goto out; } @@ -434,13 +436,13 @@ static int queue_userspace_packet(struct datapath *dp, struct sk_buff *skb, * padding logic. Only perform zerocopy if padding is not required. */ if (dp->user_features & OVS_DP_F_UNALIGNED) - hlen = skb_zerocopy_headlen(skb); + hlen = min(skb_zerocopy_headlen(skb), cutlen); else - hlen = skb->len; + hlen = skb_len; - len = upcall_msg_size(upcall_info, hlen - cutlen, - OVS_CB(skb)->acts_origlen); - user_skb = genlmsg_new(len, GFP_ATOMIC); + msg_size = upcall_msg_size(upcall_info, hlen, + OVS_CB(skb)->acts_origlen); + user_skb = genlmsg_new(msg_size, GFP_ATOMIC); if (!user_skb) { err = -ENOMEM; goto out; @@ -503,7 +505,7 @@ static int queue_userspace_packet(struct datapath *dp, struct sk_buff *skb, } /* Add OVS_PACKET_ATTR_LEN when packet is truncated */ - if (cutlen > 0) { + if (skb_len < skb->len) { if (nla_put_u32(user_skb, OVS_PACKET_ATTR_LEN, skb->len)) { err = -ENOBUFS; @@ -518,9 +520,9 @@ static int queue_userspace_packet(struct datapath *dp, struct sk_buff *skb, err = -ENOBUFS; goto out; } - nla->nla_len = nla_attr_size(skb->len - cutlen); + nla->nla_len = nla_attr_size(skb_len); - err = skb_zerocopy(user_skb, skb, skb->len - cutlen, hlen); + err = skb_zerocopy(user_skb, skb, skb_len, hlen); if (err) goto out; @@ -575,6 +577,7 @@ static int ovs_packet_cmd_execute(struct sk_buff *skb, struct genl_info *info) packet->ignore_df = 1; } OVS_CB(packet)->mru = mru; + OVS_CB(packet)->cutlen = U32_MAX; /* Build an sw_flow for sending this packet. */ flow = ovs_flow_alloc(); diff --git a/net/openvswitch/datapath.h b/net/openvswitch/datapath.h index c9eb267c6f7e..9192c9970cc3 100644 --- a/net/openvswitch/datapath.h +++ b/net/openvswitch/datapath.h @@ -105,7 +105,7 @@ struct datapath { * @mru: The maximum received fragement size; 0 if the packet is not * fragmented. * @acts_origlen: The netlink size of the flow actions applied to this skb. - * @cutlen: The number of bytes from the packet end to be removed. + * @cutlen: The number of bytes in the packet to preserve on output. */ struct ovs_skb_cb { struct vport *input_vport; diff --git a/net/openvswitch/vport.c b/net/openvswitch/vport.c index 5541f4c9a0a1..586428d2015d 100644 --- a/net/openvswitch/vport.c +++ b/net/openvswitch/vport.c @@ -447,7 +447,7 @@ int ovs_vport_receive(struct vport *vport, struct sk_buff *skb, OVS_CB(skb)->input_vport = vport; OVS_CB(skb)->mru = 0; - OVS_CB(skb)->cutlen = 0; + OVS_CB(skb)->cutlen = U32_MAX; if (unlikely(dev_net(skb->dev) != ovs_dp_get_net(vport->dp))) { u32 mark; -- 2.25.1
2 1
0 0
[PATCH openEuler-1.0-LTS] pppoe: reload header pointer after dev_hard_header()
by Yi Yang 21 Sep '26

21 Sep '26
From: Asim Viladi Oglu Manizada <manizada(a)pm.me> mainline inclusion from mainline-v7.2-rc5 commit e9c238f6fe42fb1b4dba3a578277de32cb487937 category: bugfix bugzilla: https://atomgit.com/src-openeuler/kernel/issues/16930 CVE: CVE-2026-68121 Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?… -------------------------------- pppoe_sendmsg() saves a pointer to the PPPoE header before calling dev_hard_header(). Device header callbacks are allowed to reallocate the skb head, invalidating pointers into it. This can happen when a send is blocked in copy_from_user() while the first non-Ethernet port is added to an empty team device. The team's delegated GRE header callback then expands the skb head. PPPoE subsequently writes six bytes through the stale pointer into the freed head. Reload the PPPoE header through the skb's network-header offset after device header creation. pskb_expand_head() updates that offset when it relocates the head. Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2") Cc: stable(a)vger.kernel.org Signed-off-by: Asim Viladi Oglu Manizada <manizada(a)pm.me> Reviewed-by: Vadim Fedorenko <vadim.fedorenko(a)linux.dev> Reviewed-by: Eric Dumazet <edumazet(a)google.com> Link: https://patch.msgid.link/20260722093814.3017176-1-manizada@pm.me Signed-off-by: Jakub Kicinski <kuba(a)kernel.org> Signed-off-by: Yi Yang <yiyang13(a)huawei.com> --- drivers/net/ppp/pppoe.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/net/ppp/pppoe.c b/drivers/net/ppp/pppoe.c index c04f3dc17d76..86fc5f7551ff 100644 --- a/drivers/net/ppp/pppoe.c +++ b/drivers/net/ppp/pppoe.c @@ -897,6 +897,7 @@ static int pppoe_sendmsg(struct socket *sock, struct msghdr *m, dev_hard_header(skb, dev, ETH_P_PPP_SES, po->pppoe_pa.remote, NULL, total_len); + ph = pppoe_hdr(skb); memcpy(ph, &hdr, sizeof(struct pppoe_hdr)); ph->length = htons(total_len); -- 2.25.1
2 1
0 0
[PATCH openEuler-1.0-LTS] openvswitch: fix GSO userspace truncation underflow
by Yi Yang 21 Sep '26

21 Sep '26
From: Kyle Zeng <kylebot(a)openai.com> stable inclusion from stable-v5.10.265 commit 50a6a85f3d6b1d22d8436848606cdef5d2c490b4 category: bugfix bugzilla: https://atomgit.com/src-openeuler/kernel/issues/16932 CVE: CVE-2026-68123 Reference: https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/commit/?id… -------------------------------- [ Upstream commit 4032f8ed10fcb84d41c508dfb04be96589f78dfe ] OVS_ACTION_ATTR_TRUNC currently stores a delta from the original skb length in OVS_CB(skb)->cutlen. When a later userspace action segments a GSO skb, queue_gso_packets() reuses that delta for each smaller segment. A segment can then reach queue_userspace_packet() with cutlen greater than skb->len, underflowing the length passed to skb_zerocopy(). Store the maximum preserved length instead and bound each consumer against the current skb length. Use U32_MAX as the no-truncation sentinel so the value remains valid if skb geometry changes before a consumer handles it. Fixes: f2a4d086ed4c ("openvswitch: Add packet truncation support.") Cc: stable(a)vger.kernel.org Assisted-by: Codex:gpt-5.5 Signed-off-by: Kyle Zeng <kylebot(a)openai.com> Reviewed-by: Ilya Maximets <i.maximets(a)ovn.org> Reviewed-by: Aaron Conole <aconole(a)redhat.com> Link: https://patch.msgid.link/20260707221635.27489-1-kylebot@openai.com Signed-off-by: Paolo Abeni <pabeni(a)redhat.com> [5.10.y supports neither OVS_ACTION_ATTR_PSAMPLE nor OVS drop reasons] Signed-off-by: Ilya Maximets <i.maximets(a)ovn.org> Signed-off-by: Sasha Levin <sashal(a)kernel.org> Conflicts: net/openvswitch/datapath.c [Context conflicts.] Signed-off-by: Yi Yang <yiyang13(a)huawei.com> --- net/openvswitch/actions.c | 15 +++++---------- net/openvswitch/datapath.c | 25 ++++++++++++++----------- net/openvswitch/datapath.h | 2 +- net/openvswitch/vport.c | 2 +- 4 files changed, 21 insertions(+), 23 deletions(-) diff --git a/net/openvswitch/actions.c b/net/openvswitch/actions.c index 7ac5f75e06a9..f3b3fd459600 100644 --- a/net/openvswitch/actions.c +++ b/net/openvswitch/actions.c @@ -949,12 +949,8 @@ static void do_output(struct datapath *dp, struct sk_buff *skb, int out_port, u16 mru = OVS_CB(skb)->mru; u32 cutlen = OVS_CB(skb)->cutlen; - if (unlikely(cutlen > 0)) { - if (skb->len - cutlen > ovs_mac_header_len(key)) - pskb_trim(skb, skb->len - cutlen); - else - pskb_trim(skb, ovs_mac_header_len(key)); - } + if (unlikely(cutlen < skb->len)) + pskb_trim(skb, max(cutlen, ovs_mac_header_len(key))); if (likely(!mru || (skb->len <= mru + vport->dev->hard_header_len))) { @@ -1237,22 +1233,21 @@ static int do_execute_actions(struct datapath *dp, struct sk_buff *skb, clone = skb_clone(skb, GFP_ATOMIC); if (clone) do_output(dp, clone, port, key); - OVS_CB(skb)->cutlen = 0; + OVS_CB(skb)->cutlen = U32_MAX; break; } case OVS_ACTION_ATTR_TRUNC: { struct ovs_action_trunc *trunc = nla_data(a); - if (skb->len > trunc->max_len) - OVS_CB(skb)->cutlen = skb->len - trunc->max_len; + OVS_CB(skb)->cutlen = trunc->max_len; break; } case OVS_ACTION_ATTR_USERSPACE: output_userspace(dp, skb, key, a, attr, len, OVS_CB(skb)->cutlen); - OVS_CB(skb)->cutlen = 0; + OVS_CB(skb)->cutlen = U32_MAX; break; case OVS_ACTION_ATTR_HASH: diff --git a/net/openvswitch/datapath.c b/net/openvswitch/datapath.c index bd00e63603ca..1aeeb18c8812 100644 --- a/net/openvswitch/datapath.c +++ b/net/openvswitch/datapath.c @@ -248,7 +248,7 @@ void ovs_dp_process_packet(struct sk_buff *skb, struct sw_flow_key *key) upcall.cmd = OVS_PACKET_CMD_MISS; upcall.portid = ovs_vport_find_upcall_portid(p, skb); upcall.mru = OVS_CB(skb)->mru; - error = ovs_dp_upcall(dp, skb, key, &upcall, 0); + error = ovs_dp_upcall(dp, skb, key, &upcall, U32_MAX); if (unlikely(error)) kfree_skb(skb); else @@ -399,7 +399,8 @@ static int queue_userspace_packet(struct datapath *dp, struct sk_buff *skb, struct sk_buff *nskb = NULL; struct sk_buff *user_skb = NULL; /* to be queued to userspace */ struct nlattr *nla; - size_t len; + size_t msg_size; + size_t skb_len; unsigned int hlen; int err, dp_ifindex; @@ -419,7 +420,8 @@ static int queue_userspace_packet(struct datapath *dp, struct sk_buff *skb, skb = nskb; } - if (nla_attr_size(skb->len) > USHRT_MAX) { + skb_len = min(skb->len, cutlen); + if (nla_attr_size(skb_len) > USHRT_MAX) { err = -EFBIG; goto out; } @@ -434,13 +436,13 @@ static int queue_userspace_packet(struct datapath *dp, struct sk_buff *skb, * padding logic. Only perform zerocopy if padding is not required. */ if (dp->user_features & OVS_DP_F_UNALIGNED) - hlen = skb_zerocopy_headlen(skb); + hlen = min(skb_zerocopy_headlen(skb), cutlen); else - hlen = skb->len; + hlen = skb_len; - len = upcall_msg_size(upcall_info, hlen - cutlen, - OVS_CB(skb)->acts_origlen); - user_skb = genlmsg_new(len, GFP_ATOMIC); + msg_size = upcall_msg_size(upcall_info, hlen, + OVS_CB(skb)->acts_origlen); + user_skb = genlmsg_new(msg_size, GFP_ATOMIC); if (!user_skb) { err = -ENOMEM; goto out; @@ -503,7 +505,7 @@ static int queue_userspace_packet(struct datapath *dp, struct sk_buff *skb, } /* Add OVS_PACKET_ATTR_LEN when packet is truncated */ - if (cutlen > 0) { + if (skb_len < skb->len) { if (nla_put_u32(user_skb, OVS_PACKET_ATTR_LEN, skb->len)) { err = -ENOBUFS; @@ -518,9 +520,9 @@ static int queue_userspace_packet(struct datapath *dp, struct sk_buff *skb, err = -ENOBUFS; goto out; } - nla->nla_len = nla_attr_size(skb->len - cutlen); + nla->nla_len = nla_attr_size(skb_len); - err = skb_zerocopy(user_skb, skb, skb->len - cutlen, hlen); + err = skb_zerocopy(user_skb, skb, skb_len, hlen); if (err) goto out; @@ -575,6 +577,7 @@ static int ovs_packet_cmd_execute(struct sk_buff *skb, struct genl_info *info) packet->ignore_df = 1; } OVS_CB(packet)->mru = mru; + OVS_CB(packet)->cutlen = U32_MAX; /* Build an sw_flow for sending this packet. */ flow = ovs_flow_alloc(); diff --git a/net/openvswitch/datapath.h b/net/openvswitch/datapath.h index c9eb267c6f7e..9192c9970cc3 100644 --- a/net/openvswitch/datapath.h +++ b/net/openvswitch/datapath.h @@ -105,7 +105,7 @@ struct datapath { * @mru: The maximum received fragement size; 0 if the packet is not * fragmented. * @acts_origlen: The netlink size of the flow actions applied to this skb. - * @cutlen: The number of bytes from the packet end to be removed. + * @cutlen: The number of bytes in the packet to preserve on output. */ struct ovs_skb_cb { struct vport *input_vport; diff --git a/net/openvswitch/vport.c b/net/openvswitch/vport.c index 5541f4c9a0a1..586428d2015d 100644 --- a/net/openvswitch/vport.c +++ b/net/openvswitch/vport.c @@ -447,7 +447,7 @@ int ovs_vport_receive(struct vport *vport, struct sk_buff *skb, OVS_CB(skb)->input_vport = vport; OVS_CB(skb)->mru = 0; - OVS_CB(skb)->cutlen = 0; + OVS_CB(skb)->cutlen = U32_MAX; if (unlikely(dev_net(skb->dev) != ovs_dp_get_net(vport->dp))) { u32 mark; -- 2.25.1
2 1
0 0
[PATCH openEuler-1.0-LTS] selinux: check connect-related permissions on TCP Fast Open
by Yi Yang 20 Sep '26

20 Sep '26
From: Stephen Smalley <stephen.smalley.work(a)gmail.com> mainline inclusion from mainline-v7.2-rc3 commit 44c74d27d1b9aaa99fa8a83640c1223575262b80 category: bugfix bugzilla: https://atomgit.com/src-openeuler/kernel/issues/17775 CVE: CVE-2026-72243 Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?… -------------------------------- Similar to Landlock, SELinux was not updated when TCP Fast Open support was introduced to ensure connect-related permissions are checked when using TCP Fast Open. Update its socket_sendmsg() hook to call selinux_socket_connect() when MSG_FASTOPEN is passed. Cc: stable(a)vger.kernel.org Link: https://lore.kernel.org/linux-security-module/20260616201615.275032-1-hexla… Link: https://lore.kernel.org/linux-security-module/20260617180526.15627-2-matthi… Reported-by: Bryam Vargas <hexlabsecurity(a)proton.me> Reported-by: Matthieu Buffet <matthieu(a)buffet.re> Reported-by: Mikhail Ivanov <ivanov.mikhail1(a)huawei-partners.com> Signed-off-by: Stephen Smalley <stephen.smalley.work(a)gmail.com> Tested-by: Bryam Vargas <hexlabsecurity(a)proton.me> Signed-off-by: Paul Moore <paul(a)paul-moore.com> Signed-off-by: Yi Yang <yiyang13(a)huawei.com> --- security/selinux/hooks.c | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c index 3550ded07457..c0b5af6a82a7 100644 --- a/security/selinux/hooks.c +++ b/security/selinux/hooks.c @@ -4910,7 +4910,24 @@ static int selinux_socket_accept(struct socket *sock, struct socket *newsock) static int selinux_socket_sendmsg(struct socket *sock, struct msghdr *msg, int size) { - return sock_has_perm(sock->sk, SOCKET__WRITE); + int rc; + struct sockaddr *const addr = msg->msg_name; + const int addrlen = msg->msg_namelen; + + rc = sock_has_perm(sock->sk, SOCKET__WRITE); + if (rc) + return rc; + + if (addr && (msg->msg_flags & MSG_FASTOPEN) && + (sk_is_tcp(sock->sk) || + (sk_is_inet(sock->sk) && sock->sk->sk_type == SOCK_STREAM && + sock->sk->sk_protocol == IPPROTO_MPTCP))) { + rc = selinux_socket_connect(sock, addr, addrlen); + if (rc) + return rc; + } + + return 0; } static int selinux_socket_recvmsg(struct socket *sock, struct msghdr *msg, -- 2.25.1
2 1
0 0
[PATCH OLK-6.6 0/4] arm64: smt: Introduce VIP-SMT QoS mode for SMT
by Yipeng Zou 20 Sep '26

20 Sep '26
This patchset introduces VIP-SMT, an Hisilicon-specific SMT QoS enhancement for Arm64. It allows marking specific hardware threads as "VIP" (high-priority) and others as non-VIP within the same physical core, enabling differentiated resource allocation (instruction fetch, execution pipeline, and out-of-order resources) for latency-sensitive workloads while background tasks run on non-VIP threads. Use cases include running real-time/network packet processing on VIP threads, performance isolation for mixed-criticality tasks, and QoS enforcement for cloud/virtualization scenarios. The series is organized as follows: Patch 1 refactors arch_cpu_idle_{enter,exit}() so the SMT measurement and the VIP-SMT hooks can be shared cleanly across all configs; the ACTLR_XCALL_XINT register save/restore is moved under its own config guard. Patch 2 is the core feature. It adds CONFIG_ARM64_VIP_SMT and a new vip_smt.c driver exposing per-CPU sysfs entries under /sys/devices/system/cpu/cpuN/regs/vip-smt/ to configure three ACTLR system registers (IFU_ACTLR1_EL1, OOO_DEC_ROB_SHA_CTLR_EL1, and OOO_DEC_DSP_CTLR_EL1). Feature detection is based on MIDR (HIP13), restricted to EL2 at the moment, and requires SMT to be enabled on the physical core. Per-CPU register values are shadowed and restored on idle exit so they survive core power-down. Patch 3 adds a "novipsmt" kernel command line parameter (with an optional "force" value) that disables the feature at boot time and prevents the vip_smt sysfs directory from being created. Yipeng Zou (4): arm64: idle: make arch_cpu_idle_{enter,exit} more refactorable arm64: smt: Introduce VIP-SMT a QoS Mode for SMT arm64: smt: Add novipsmt kernel command line parameter arm64: configs: Enable ARM64_VIP_SMT in openeuler_defconfig .../admin-guide/kernel-parameters.txt | 4 + arch/arm64/Kconfig | 16 + arch/arm64/configs/openeuler_defconfig | 1 + arch/arm64/include/asm/vip_smt.h | 109 ++++ arch/arm64/kernel/Makefile | 1 + arch/arm64/kernel/cpufeature.c | 9 + arch/arm64/kernel/cpuinfo.c | 7 + arch/arm64/kernel/idle.c | 51 +- arch/arm64/kernel/vip_smt.c | 483 ++++++++++++++++++ arch/arm64/tools/cpucaps | 2 +- 10 files changed, 653 insertions(+), 30 deletions(-) create mode 100644 arch/arm64/include/asm/vip_smt.h create mode 100644 arch/arm64/kernel/vip_smt.c -- 2.34.1
2 5
0 0
[PATCH OLK-6.6] ceph: cap delegated inode count in ceph_parse_deleg_inos()
by Pan Taixi 20 Sep '26

20 Sep '26
From: Michael Bommarito <michael.bommarito(a)gmail.com> mainline inclusion from mainline-v7.3-rc1 commit 4bd3158bd62466d57ed72a3f7bc5f205fedd6919 category: bugfix bugzilla: https://atomgit.com/openeuler/kernel/issues/18927 CVE: CVE-2026-89648 Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?… --------------------------- ceph_parse_deleg_inos() decodes interval sets of delegated inode numbers from an MDS create-with-delegation reply. For each set it reads a 64-bit start and a 64-bit len with ceph_decode_64_safe(), which only validates that the eight bytes are present in the message, not the value, and then loops over len while inserting entries into s_delegated_inos. len is fully attacker controlled. A malicious or compromised MDS can send one huge interval, many intervals in one reply, duplicate intervals, or repeated replies that accumulate delegated inodes on the same session. The original code bounded none of these and could spin the insert loop or grow the xarray without limit. Bound both dimensions with a single enforcement point. Track the number of delegated inodes held by each MDS session in an atomic counter and grow it only in ceph_insert_deleg_ino(), which uses atomic_add_unless() to refuse to push the count past CEPH_MAX_DELEG_INOS. Because that helper is the only place the counter grows, the per-session population can never exceed the cap, so no separate per-session pre-check is needed. The counter is decremented when async create consumes a delegated inode or when an insert fails, incremented when a delegated inode is restored, initialized with the session xarray, and reset when reconnect destroys the xarray. A per-session cap alone still lets one reply spin the insert loop on duplicate ranges without growing the counter, so also cap the aggregate interval length accepted from a single reply. Together these bound both the loop trip count per reply and the xarray population across replies. The cap is a fixed, client-chosen constant rather than a value derived from the MDS. mds_client_prealloc_inos is a userspace MDS configuration option; it is never sent to the kernel client on the wire, and a server-supplied bound could not be trusted for a defensive limit in any case. The constant is set well above that option's documented default of 1000 (a generous multiple), so legitimate refill behavior is unaffected while the CPU and xarray memory a malformed delegation stream can consume stays bounded. Impact: a malicious or compromised Ceph MDS can no longer make a client spin through an unbounded delegated-inode interval or grow one session's delegated-inode xarray without limit. Cc: stable(a)vger.kernel.org Fixes: d48464878708 ("ceph: decode interval_sets for delegated inos") Suggested-by: Viacheslav Dubeyko <Slava.Dubeyko(a)ibm.com> Assisted-by: Claude:claude-opus-4-8 Signed-off-by: Michael Bommarito <michael.bommarito(a)gmail.com> Reviewed-by: Viacheslav Dubeyko <Slava.Dubeyko(a)ibm.com> Signed-off-by: Ilya Dryomov <idryomov(a)gmail.com> Conflicts: fs/ceph/mds_client.c [backport to OLK-6.6: context adjusted for this tree: pr_warn_ratelimited_client()/doutc() from 38d46409c4639 are not used here, so the new warnings use plain pr_warn_ratelimited() and the struct ceph_client *cl local is not added. CEPH_MAX_DELEG_INOS is inserted right after CEPH_INO_SYSTEM_BASE. s_num_deleg_inos is reset next to the existing xa_destroy() in send_mds_reconnect(), which still runs before mutex_lock(&session->s_mutex) in this tree (39fe30315893 not applied); this matches the linux-6.18.y stable backport c040e139f1a62.] Signed-off-by: Pan Taixi <pantaixi1(a)huawei.com> --- fs/ceph/mds_client.c | 56 +++++++++++++++++++++++++++++++++++++++----- fs/ceph/mds_client.h | 1 + fs/ceph/super.h | 9 +++++++ 3 files changed, 60 insertions(+), 6 deletions(-) diff --git a/fs/ceph/mds_client.c b/fs/ceph/mds_client.c index 00b9f9f3f4d7..a3fa2fd0b974 100644 --- a/fs/ceph/mds_client.c +++ b/fs/ceph/mds_client.c @@ -566,13 +566,37 @@ static int parse_reply_info_filelock(void **p, void *end, #if BITS_PER_LONG == 64 #define DELEGATED_INO_AVAILABLE xa_mk_value(1) +static int ceph_insert_deleg_ino(struct ceph_mds_session *s, u64 ino) +{ + int err; + + /* + * Cap how many delegated inodes a single session may hold. This is + * the only place that grows the count, so atomic_add_unless() bounds + * it at exactly CEPH_MAX_DELEG_INOS; s_num_deleg_inos can never exceed + * that. + */ + if (!atomic_add_unless(&s->s_num_deleg_inos, 1, CEPH_MAX_DELEG_INOS)) { + pr_warn_ratelimited("MDS session already holds %d delegated inodes\n", + CEPH_MAX_DELEG_INOS); + return -EOVERFLOW; + } + + err = xa_insert(&s->s_delegated_inos, ino, DELEGATED_INO_AVAILABLE, + GFP_KERNEL); + if (err) + atomic_dec(&s->s_num_deleg_inos); + return err; +} + static int ceph_parse_deleg_inos(void **p, void *end, struct ceph_mds_session *s) { + u64 msg_deleg_inos = 0; u32 sets; ceph_decode_32_safe(p, end, sets, bad); dout("got %u sets of delegated inodes\n", sets); while (sets--) { @@ -585,20 +609,37 @@ static int ceph_parse_deleg_inos(void **p, void *end, if (start < CEPH_INO_SYSTEM_BASE) { pr_warn_ratelimited("ceph: ignoring reserved inode range delegation (start=0x%llx len=0x%llx)\n", start, len); continue; } + + /* + * Bound the number of inodes one reply may delegate. + * ceph_insert_deleg_ino() separately caps the per-session + * population, so this only has to stop one reply from spinning + * the insert loop under an attacker-controlled len. + */ + if (len > (u64)CEPH_MAX_DELEG_INOS || + msg_deleg_inos > (u64)CEPH_MAX_DELEG_INOS - len) { + pr_warn_ratelimited("MDS reply delegates too many inodes (have %llu, +%llu, max %d)\n", + msg_deleg_inos, len, CEPH_MAX_DELEG_INOS); + return -EIO; + } + msg_deleg_inos += len; + while (len--) { - int err = xa_insert(&s->s_delegated_inos, start++, - DELEGATED_INO_AVAILABLE, - GFP_KERNEL); + int err = ceph_insert_deleg_ino(s, start++); + if (!err) { dout("added delegated inode 0x%llx\n", start - 1); } else if (err == -EBUSY) { pr_warn("MDS delegated inode 0x%llx more than once.\n", start - 1); + } else if (err == -EOVERFLOW) { + /* ceph_insert_deleg_ino() already warned. */ + return -EIO; } else { return err; } } } @@ -612,20 +653,21 @@ u64 ceph_get_deleg_ino(struct ceph_mds_session *s) unsigned long ino; void *val; xa_for_each(&s->s_delegated_inos, ino, val) { val = xa_erase(&s->s_delegated_inos, ino); - if (val == DELEGATED_INO_AVAILABLE) + if (val == DELEGATED_INO_AVAILABLE) { + atomic_dec(&s->s_num_deleg_inos); return ino; + } } return 0; } int ceph_restore_deleg_ino(struct ceph_mds_session *s, u64 ino) { - return xa_insert(&s->s_delegated_inos, ino, DELEGATED_INO_AVAILABLE, - GFP_KERNEL); + return ceph_insert_deleg_ino(s, ino); } #else /* BITS_PER_LONG == 64 */ /* * FIXME: xarrays can't handle 64-bit indexes on a 32-bit arch. For now, just * ignore delegated_inos on 32 bit arch. Maybe eventually add xarrays for top @@ -1002,10 +1044,11 @@ static struct ceph_mds_session *register_session(struct ceph_mds_client *mdsc, INIT_LIST_HEAD(&s->s_caps); refcount_set(&s->s_ref, 1); INIT_LIST_HEAD(&s->s_waiting); INIT_LIST_HEAD(&s->s_unsafe); xa_init(&s->s_delegated_inos); + atomic_set(&s->s_num_deleg_inos, 0); INIT_LIST_HEAD(&s->s_cap_releases); INIT_WORK(&s->s_cap_release_work, ceph_cap_release_work); INIT_LIST_HEAD(&s->s_cap_dirty); INIT_LIST_HEAD(&s->s_cap_flushing); @@ -4619,10 +4662,11 @@ static void send_mds_reconnect(struct ceph_mds_client *mdsc, reply = ceph_msg_new2(CEPH_MSG_CLIENT_RECONNECT, 0, 1, GFP_NOFS, false); if (!reply) goto fail_nomsg; xa_destroy(&session->s_delegated_inos); + atomic_set(&session->s_num_deleg_inos, 0); mutex_lock(&session->s_mutex); session->s_state = CEPH_MDS_SESSION_RECONNECTING; session->s_seq = 0; diff --git a/fs/ceph/mds_client.h b/fs/ceph/mds_client.h index 22398ccb21a4..9916acd901ab 100644 --- a/fs/ceph/mds_client.h +++ b/fs/ceph/mds_client.h @@ -228,10 +228,11 @@ struct ceph_mds_session { u64 s_renew_seq; struct list_head s_waiting; /* waiting requests */ struct list_head s_unsafe; /* unsafe requests */ struct xarray s_delegated_inos; + atomic_t s_num_deleg_inos; }; /* * modes of choosing which MDS to send a request to */ diff --git a/fs/ceph/super.h b/fs/ceph/super.h index 5903e3fb6d75..09bf04f4452e 100644 --- a/fs/ceph/super.h +++ b/fs/ceph/super.h @@ -588,10 +588,19 @@ static inline int ceph_ino_compare(struct inode *inode, void *data) #define CEPH_NUM_STRAY 10 #define CEPH_MDS_INO_MDSDIR_OFFSET (1 * CEPH_MAX_MDS) #define CEPH_MDS_INO_LOG_OFFSET (2 * CEPH_MAX_MDS) #define CEPH_INO_SYSTEM_BASE ((6*CEPH_MAX_MDS) + (CEPH_MAX_MDS * CEPH_NUM_STRAY)) +/* + * Upper bound on the number of delegated inodes a single MDS session may + * hold. The MDS normally hands out a small preallocation window (the + * userspace mds_client_prealloc_inos option defaults to 1000) and refills + * it as the client consumes entries. This leaves generous headroom while + * bounding the CPU and memory a malformed delegation interval can consume. + */ +#define CEPH_MAX_DELEG_INOS 8192 + static inline bool ceph_vino_is_reserved(const struct ceph_vino vino) { if (vino.ino >= CEPH_INO_SYSTEM_BASE || vino.ino < CEPH_MDS_INO_MDSDIR_OFFSET) return false; -- 2.34.1
2 1
0 0
  • ← Newer
  • 1
  • ...
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • ...
  • 2491
  • Older →

HyperKitty Powered by HyperKitty