FAILED: patch "[PATCH] nvmet-tcp: Fix a possible UAF in queue intialization setup" failed to apply to 5.4-stable tree
Subsystems (2)
[email protected]
maintainerThe patch below does not apply to the 5.4-stable tree.
If someone wants it applied there, or to any other stable or longterm tree, then please email the backport, including the original git commit id to <[email protected]>.
To reproduce the conflict and resubmit, you may use the following commands:
git fetch https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/ linux-5.4.y
git checkout FETCH_HEAD
git cherry-pick -x d920abd1e7c4884f9ecd0749d1921b7ab19ddfbd
# <resolve conflicts, build, test, etc.>
git commit -s
git send-email --to '<[email protected]>' --in-reply-to '2023102012-pleat-snippet-29cf@gregkh' --subject-prefix 'PATCH 5.4.y' HEAD^..
Possible dependencies:
thanks,
greg k-h
------------------ original commit in Linus's tree ------------------
From d920abd1e7c4884f9ecd0749d1921b7ab19ddfbd Mon Sep 17 00:00:00 2001
From: Sagi Grimberg <[email protected]>
Date: Mon, 2 Oct 2023 13:54:28 +0300
Subject: [PATCH] nvmet-tcp: Fix a possible UAF in queue intialization setup
From Alon:
"Due to a logical bug in the NVMe-oF/TCP subsystem in the Linux kernel, a malicious user can cause a UAF and a double free, which may lead to RCE (may also lead to an LPE in case the attacker already has local privileges)."
Hence, when a queue initialization fails after the ahash requests are allocated, it is guaranteed that the queue removal async work will be called, hence leave the deallocation to the queue removal.
Also, be extra careful not to continue processing the socket, so set queue rcv_state to NVMET_TCP_RECV_ERR upon a socket error.
drivers/nvme/target/tcp.c +2 -5
@@ -372,6 +372,7 @@ static void nvmet_tcp_fatal_error(struct nvmet_tcp_queue *queue)static void nvmet_tcp_socket_error (struct nvmet_tcp_queue *queue,int status) { + queue->rcv_state =NVMET_TCP_RECV_ERR ;if (status == -EPIPE || status == -ECONNRESET )kernel_sock_shutdown (queue->sock,SHUT_RDWR );else
@@ -910,15 +911,11 @@ static int nvmet_tcp_handle_icreq(struct nvmet_tcp_queue *queue) iov.iov_len =sizeof (*icresp); ret =kernel_sendmsg (queue->sock, &msg, &iov,1 , iov.iov_len);if (ret <0 ) - goto free_crypto; +return ret;/* queue removal will cleanup */ queue->state =NVMET_TCP_Q_LIVE ;nvmet_prepare_receive_pdu (queue);return 0 ; -free_crypto: -if (queue->hdr_digest || queue->data_digest) -nvmet_tcp_free_crypto (queue); -return ret; } static void nvmet_tcp_handle_req_failure(struct nvmet_tcp_queue *queue,
cover nvmet-tcp: backport fix for CVE-2023-5178
The following commit is needed to fix CVE-2023-5178:
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=d920abd1e7c4884f9ecd0749d1921b7ab19ddfbd
Support patch:
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=0236d3437909ff888e5c79228e2d5a851651c4c6
Sagi Grimberg (2):
nvmet-tcp: move send/recv error handling in the send/recv methods
instead of call-sites
nvmet-tcp: Fix a possible UAF in queue intialization setup
drivers/nvme/target/tcp.c | 50 ++++++++++++++++++++------------------- 1 file changed, 26 insertions(+), 24 deletions(-)
base-commit: 86ea40e6ad22d9d7daa54b9e8167ad1e4a8a48ee
Signature · 1 line
2.42.0
PATCH 1/2 nvmet-tcp: move send/recv error handling in the send/recv methods instead of call-sites
From: Sagi Grimberg <[email protected]>
commit 0236d3437909ff888e5c79228e2d5a851651c4c6 upstream.
Have routines handle errors and just bail out of the poll loop. This simplifies the code and will help as we may enhance the poll loop logic and these are somewhat in the way.
--- drivers/nvme/target/tcp.c | 43 ++++++++++++++++++++++----------------- 1 file changed, 24 insertions(+), 19 deletions(-)
drivers/nvme/target/tcp.c +24 -19
@@ -321,6 +321,14 @@ static void nvmet_tcp_fatal_error(struct nvmet_tcp_queue *queue)kernel_sock_shutdown (queue->sock,SHUT_RDWR ); } +static void nvmet_tcp_socket_error (struct nvmet_tcp_queue *queue,int status) +{ +if (status == -EPIPE || status == -ECONNRESET ) +kernel_sock_shutdown (queue->sock,SHUT_RDWR ); +else +nvmet_tcp_fatal_error (queue); +} +static int nvmet_tcp_map_data (struct nvmet_tcp_cmd *cmd) {struct nvme_sgl_desc *sgl = &cmd->req.cmd->common.dptr.sgl;
@@ -714,11 +722,15 @@ static int nvmet_tcp_try_send(struct nvmet_tcp_queue *queue,for (i =0 ; i < budget; i++) { ret =nvmet_tcp_try_send_one (queue, i == budget -1 ); -if (ret <=0 ) +if (unlikely (ret <0 )) { +nvmet_tcp_socket_error (queue, ret); + goto done; + }else if (ret ==0 ) {break ; + } (*sends)++; } - +done:return ret; }
@@ -1167,11 +1179,15 @@ static int nvmet_tcp_try_recv(struct nvmet_tcp_queue *queue,for (i =0 ; i < budget; i++) { ret =nvmet_tcp_try_recv_one (queue); -if (ret <=0 ) +if (unlikely (ret <0 )) { +nvmet_tcp_socket_error (queue, ret); + goto done; + }else if (ret ==0 ) {break ; + } (*recvs)++; } - +done:return ret; }
@@ -1196,27 +1212,16 @@ static void nvmet_tcp_io_work(struct work_struct *w) pending = false; ret =nvmet_tcp_try_recv (queue,NVMET_TCP_RECV_BUDGET , &ops); -if (ret >0 ) { +if (ret >0 ) pending = true; - }else if (ret <0 ) { -if (ret == -EPIPE || ret == -ECONNRESET ) -kernel_sock_shutdown (queue->sock,SHUT_RDWR ); -else -nvmet_tcp_fatal_error (queue); +else if (ret <0 )return ; - } ret =nvmet_tcp_try_send (queue,NVMET_TCP_SEND_BUDGET , &ops); -if (ret >0 ) { -/* transmitted message/data */ +if (ret >0 ) pending = true; - }else if (ret <0 ) { -if (ret == -EPIPE || ret == -ECONNRESET ) -kernel_sock_shutdown (queue->sock,SHUT_RDWR ); -else -nvmet_tcp_fatal_error (queue); +else if (ret <0 )return ; - } }while (pending && ops <NVMET_TCP_IO_WORK_BUDGET );
Signature · 1 line
2.42.0
PATCH 2/2 nvmet-tcp: Fix a possible UAF in queue intialization setup
In reply to Dragos-Marian PanaitFrom: Sagi Grimberg <[email protected]>
commit d920abd1e7c4884f9ecd0749d1921b7ab19ddfbd upstream.
From Alon:
"Due to a logical bug in the NVMe-oF/TCP subsystem in the Linux kernel, a malicious user can cause a UAF and a double free, which may lead to RCE (may also lead to an LPE in case the attacker already has local privileges)."
Hence, when a queue initialization fails after the ahash requests are allocated, it is guaranteed that the queue removal async work will be called, hence leave the deallocation to the queue removal.
Also, be extra careful not to continue processing the socket, so set queue rcv_state to NVMET_TCP_RECV_ERR upon a socket error.
--- drivers/nvme/target/tcp.c | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-)
drivers/nvme/target/tcp.c +2 -5
@@ -323,6 +323,7 @@ static void nvmet_tcp_fatal_error(struct nvmet_tcp_queue *queue)static void nvmet_tcp_socket_error (struct nvmet_tcp_queue *queue,int status) { + queue->rcv_state =NVMET_TCP_RECV_ERR ;if (status == -EPIPE || status == -ECONNRESET )kernel_sock_shutdown (queue->sock,SHUT_RDWR );else
@@ -828,15 +829,11 @@ static int nvmet_tcp_handle_icreq(struct nvmet_tcp_queue *queue) iov.iov_len =sizeof (*icresp); ret =kernel_sendmsg (queue->sock, &msg, &iov,1 , iov.iov_len);if (ret <0 ) - goto free_crypto; +return ret;/* queue removal will cleanup */ queue->state =NVMET_TCP_Q_LIVE ;nvmet_prepare_receive_pdu (queue);return 0 ; -free_crypto: -if (queue->hdr_digest || queue->data_digest) -nvmet_tcp_free_crypto (queue); -return ret; } static void nvmet_tcp_handle_req_failure(struct nvmet_tcp_queue *queue,
Signature · 1 line
2.42.0
Greg KH
maintainerRe: [PATCH 5.4 0/2] nvmet-tcp: backport fix for CVE-2023-5178
In reply to Dragos-Marian PanaitQuoted 5 lines · Dragos-Marian Panait
The following commit is needed to fix CVE-2023-5178:
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=d920abd1e7c4884f9ecd0749d1921b7ab19ddfbdSupport patch:
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=0236d3437909ff888e5c79228e2d5a851651c4c6
Now queued up, thanks.
greg k-h