FAILED: patch "[PATCH] scsi: target: iscsi: Bound iscsi_encode_text_output() appends" failed to apply to 5.15-stable tree
Subsystems (2)
[email protected]
maintainerThe patch below does not apply to the 5.15-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.15.y
git checkout FETCH_HEAD
git cherry-pick -x bf33e01f88388c43e285492a63e539df6ffed64c
# <resolve conflicts, build, test, etc.>
git commit -s
git send-email --to '<[email protected]>' --in-reply-to '2026060410-slam-conch-e2f1@gregkh' --subject-prefix 'PATCH 5.15.y' HEAD^..
Possible dependencies:
thanks,
greg k-h
------------------ original commit in Linus's tree ------------------
From bf33e01f88388c43e285492a63e539df6ffed64c Mon Sep 17 00:00:00 2001
From: Michael Bommarito <[email protected]>
Date: Mon, 11 May 2026 14:49:14 -0400
Subject: [PATCH] scsi: target: iscsi: Bound iscsi_encode_text_output() appends
to rsp_buf
iscsi_encode_text_output() concatenates "key=value\0" records into login->rsp_buf, an 8192-byte kzalloc(MAX_KEY_VALUE_PAIRS) buffer allocated in iscsit_alloc_login_setup_buffer(). The three sprintf() call sites in this function (lines 1398, 1411, 1424 in v7.1-rc2) never check the remaining buffer capacity:
*length += sprintf(output_buf, "%s=%s", er->key, er->value); *length += 1; output_buf = textbuf + *length;
The 8192-byte ceiling at iscsi_target_check_login_request() bounds the *input* Login PDU payload, but a single PDU can carry up to 2048 minimal four-byte "a=b\0" pairs, each unknown key expanding to a 16-byte "a=NotUnderstood\0" output record via iscsi_add_notunderstood_response(). 2048 * 16 = 32 KiB of output into an 8 KiB buffer, producing a ~24 KiB heap overrun in the kmalloc-8k slab.
The fix introduces a static iscsi_encode_text_record() helper that uses snprintf() with a per-call bounds check against the remaining buffer, and threads a u32 textbuf_size parameter through iscsi_encode_text_output(). Both call sites in iscsi_target_handle_csg_zero() (PHASE_SECURITY) and iscsi_target_handle_csg_one() (PHASE_OPERATIONAL) pass MAX_KEY_VALUE_PAIRS. On overflow the encoder logs the condition, calls iscsi_release_extra_responses() to drop queued records, and returns -1; both caller sites now emit ISCSI_STATUS_CLS_INITIATOR_ERR / ISCSI_LOGIN_STATUS_INIT_ERR via iscsit_tx_login_rsp() before returning, so the initiator sees an explicit failed-login response rather than a silent connection drop. (Prior to this patch only the PHASE_OPERATIONAL caller did that; the PHASE_SECURITY caller is converted to the same shape.)
drivers/target/iscsi/iscsi_target_nego.c +6 -1
@@ -899,10 +899,14 @@ static int iscsi_target_handle_csg_zero(SENDER_TARGET , login->rsp_buf, &login->rsp_length, +MAX_KEY_VALUE_PAIRS , conn->param_list, conn->tpg->tpg_attrib.login_keys_workaround); -if (ret <0 ) +if (ret <0 ) { +iscsit_tx_login_rsp (conn,ISCSI_STATUS_CLS_INITIATOR_ERR , +ISCSI_LOGIN_STATUS_INIT_ERR );return -1 ; + }if (!iscsi_check_negotiated_keys (conn->param_list)) {bool auth_required =iscsi_conn_auth_required (conn);
@@ -986,6 +990,7 @@ static int iscsi_target_handle_csg_one(struct iscsit_conn *conn, struct iscsi_loSENDER_TARGET , login->rsp_buf, &login->rsp_length, +MAX_KEY_VALUE_PAIRS , conn->param_list, conn->tpg->tpg_attrib.login_keys_workaround);if (ret <0 ) {
drivers/target/iscsi/iscsi_target_parameters.c +48 -14
101 lines not on this page · raw message
drivers/target/iscsi/iscsi_target_parameters.h +1 -1
@@ -43,7 +43,7 @@ extern struct iscsi_param *iscsi_find_param_from_key(char *, struct iscsi_param_extern int iscsi_extract_key_value (char *,char **,char **);extern int iscsi_update_param_value (struct iscsi_param *,char *);extern int iscsi_decode_text_input (u8 ,u8 ,char *,u32 ,struct iscsit_conn *); -extern int iscsi_encode_text_output (u8 ,u8 ,char *,u32 *, +extern int iscsi_encode_text_output (u8 ,u8 ,char *,u32 *,u32 ,struct iscsi_param_list *,bool );extern int iscsi_check_negotiated_keys (struct iscsi_param_list *); extern void iscsi_set_connection_parameters(struct iscsi_conn_ops *,
Sasha Levin
maintainerPATCH 1/1 scsi: target: iscsi: Bound iscsi_encode_text_output() appends to rsp_buf
From: Michael Bommarito <[email protected]>
[ Upstream commit bf33e01f88388c43e285492a63e539df6ffed64c ]
iscsi_encode_text_output() concatenates "key=value\0" records into login->rsp_buf, an 8192-byte kzalloc(MAX_KEY_VALUE_PAIRS) buffer allocated in iscsit_alloc_login_setup_buffer(). The three sprintf() call sites in this function (lines 1398, 1411, 1424 in v7.1-rc2) never check the remaining buffer capacity:
*length += sprintf(output_buf, "%s=%s", er->key, er->value); *length += 1; output_buf = textbuf + *length;
The 8192-byte ceiling at iscsi_target_check_login_request() bounds the *input* Login PDU payload, but a single PDU can carry up to 2048 minimal four-byte "a=b\0" pairs, each unknown key expanding to a 16-byte "a=NotUnderstood\0" output record via iscsi_add_notunderstood_response(). 2048 * 16 = 32 KiB of output into an 8 KiB buffer, producing a ~24 KiB heap overrun in the kmalloc-8k slab.
The fix introduces a static iscsi_encode_text_record() helper that uses snprintf() with a per-call bounds check against the remaining buffer, and threads a u32 textbuf_size parameter through iscsi_encode_text_output(). Both call sites in iscsi_target_handle_csg_zero() (PHASE_SECURITY) and iscsi_target_handle_csg_one() (PHASE_OPERATIONAL) pass MAX_KEY_VALUE_PAIRS. On overflow the encoder logs the condition, calls iscsi_release_extra_responses() to drop queued records, and returns -1; both caller sites now emit ISCSI_STATUS_CLS_INITIATOR_ERR / ISCSI_LOGIN_STATUS_INIT_ERR via iscsit_tx_login_rsp() before returning, so the initiator sees an explicit failed-login response rather than a silent connection drop. (Prior to this patch only the PHASE_OPERATIONAL caller did that; the PHASE_SECURITY caller is converted to the same shape.)
--- drivers/target/iscsi/iscsi_target_nego.c | 7 ++- .../target/iscsi/iscsi_target_parameters.c | 62 ++++++++++++++----- .../target/iscsi/iscsi_target_parameters.h | 2 +- 3 files changed, 55 insertions(+), 16 deletions(-)
drivers/target/iscsi/iscsi_target_nego.c +6 -1
@@ -870,10 +870,14 @@ static int iscsi_target_handle_csg_zero(SENDER_TARGET , login->rsp_buf, &login->rsp_length, +MAX_KEY_VALUE_PAIRS , conn->param_list, conn->tpg->tpg_attrib.login_keys_workaround); -if (ret <0 ) +if (ret <0 ) { +iscsit_tx_login_rsp (conn,ISCSI_STATUS_CLS_INITIATOR_ERR , +ISCSI_LOGIN_STATUS_INIT_ERR );return -1 ; + }if (!iscsi_check_negotiated_keys (conn->param_list)) { if (conn->tpg->tpg_attrib.authentication &&
@@ -941,6 +945,7 @@ static int iscsi_target_handle_csg_one(struct iscsi_conn *conn, struct iscsi_logSENDER_TARGET , login->rsp_buf, &login->rsp_length, +MAX_KEY_VALUE_PAIRS , conn->param_list, conn->tpg->tpg_attrib.login_keys_workaround);if (ret <0 ) {
drivers/target/iscsi/iscsi_target_parameters.c +48 -14
101 lines not on this page · raw message
drivers/target/iscsi/iscsi_target_parameters.h +1 -1
@@ -46,7 +46,7 @@ extern struct iscsi_param *iscsi_find_param_from_key(char *, struct iscsi_param_extern int iscsi_extract_key_value (char *,char **,char **);extern int iscsi_update_param_value (struct iscsi_param *,char *);extern int iscsi_decode_text_input (u8 ,u8 ,char *,u32 ,struct iscsi_conn *); -extern int iscsi_encode_text_output (u8 ,u8 ,char *,u32 *, +extern int iscsi_encode_text_output (u8 ,u8 ,char *,u32 *,u32 ,struct iscsi_param_list *,bool );extern int iscsi_check_negotiated_keys (struct iscsi_param_list *); extern void iscsi_set_connection_parameters(struct iscsi_conn_ops *,
Signature · 1 line
2.53.0