Blob Blame History Raw
From 5fe8bfedd40a614374fdcb430694de00aedae2c5 Mon Sep 17 00:00:00 2001
From: Joe Lawrence <joe.lawrence@redhat.com>
Date: Thu, 18 Jan 2024 09:42:47 -0500
Subject: [KPATCH CVE-2022-42896] kpatch fixes for CVE-2022-42896
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Kernels:
3.10.0-1160.95.1.el7
3.10.0-1160.99.1.el7
3.10.0-1160.102.1.el7
3.10.0-1160.105.1.el7


Kpatch-MR: https://gitlab.com/redhat/prdsc/rhel/src/kpatch/rhel-7/-/merge_requests/66
Changes since last build:
[x86_64]:
igb_main.o: changed function: igb_configure
l2cap_core.o: changed function: l2cap_chan_hold
l2cap_core.o: changed function: l2cap_conn_get
l2cap_core.o: changed function: l2cap_global_chan_by_psm
l2cap_core.o: changed function: l2cap_recv_frame
l2cap_core.o: new function: klp_l2cap_le_sig_cmd
sch_atm.o: changed function: atm_tc_peek
sch_atm.o: changed function: sch_atm_dequeue
sch_drr.o: changed function: drr_dequeue
sch_dsmark.o: changed function: dsmark_peek
sch_hfsc.o: changed function: hfsc_enqueue
sch_hfsc.o: changed function: qdisc_peek_len
sch_multiq.o: changed function: multiq_peek
sch_prio.o: changed function: prio_peek
sch_qfq.o: changed function: qfq_dequeue
sch_qfq.o: changed function: qfq_enqueue
sch_red.o: changed function: red_peek
sch_sfb.o: changed function: sfb_peek
sch_tbf.o: changed function: tbf_dequeue

[ppc64le]:
l2cap_core.o: changed function: __l2cap_chan_add
l2cap_core.o: changed function: __l2cap_physical_cfm
l2cap_core.o: changed function: __set_monitor_timer
l2cap_core.o: changed function: __set_retrans_timer.part.24
l2cap_core.o: changed function: l2cap_ack_timeout
l2cap_core.o: changed function: l2cap_build_conf_req
l2cap_core.o: changed function: l2cap_chan_busy
l2cap_core.o: changed function: l2cap_chan_close
l2cap_core.o: changed function: l2cap_chan_connect
l2cap_core.o: changed function: l2cap_chan_del
l2cap_core.o: changed function: l2cap_chan_hold
l2cap_core.o: changed function: l2cap_chan_put
l2cap_core.o: changed function: l2cap_chan_send
l2cap_core.o: changed function: l2cap_chan_timeout
l2cap_core.o: changed function: l2cap_conn_add.part.28
l2cap_core.o: changed function: l2cap_conn_del
l2cap_core.o: changed function: l2cap_conn_start
l2cap_core.o: changed function: l2cap_connect
l2cap_core.o: changed function: l2cap_connect_cfm
l2cap_core.o: changed function: l2cap_connect_create_rsp
l2cap_core.o: changed function: l2cap_data_channel
l2cap_core.o: changed function: l2cap_disconn_cfm
l2cap_core.o: changed function: l2cap_do_create
l2cap_core.o: changed function: l2cap_do_start
l2cap_core.o: changed function: l2cap_ertm_resend
l2cap_core.o: changed function: l2cap_ertm_send
l2cap_core.o: changed function: l2cap_global_fixed_chan
l2cap_core.o: changed function: l2cap_handle_rej
l2cap_core.o: changed function: l2cap_handle_srej
l2cap_core.o: changed function: l2cap_logical_cfm
l2cap_core.o: changed function: l2cap_monitor_timeout
l2cap_core.o: changed function: l2cap_move_done
l2cap_core.o: changed function: l2cap_move_setup
l2cap_core.o: changed function: l2cap_parse_conf_rsp.constprop.36
l2cap_core.o: changed function: l2cap_pass_to_tx
l2cap_core.o: changed function: l2cap_process_reqseq
l2cap_core.o: changed function: l2cap_recv_frame
l2cap_core.o: changed function: l2cap_retrans_timeout
l2cap_core.o: changed function: l2cap_retransmit_all
l2cap_core.o: changed function: l2cap_rx
l2cap_core.o: changed function: l2cap_rx_state_recv
l2cap_core.o: changed function: l2cap_security_cfm
l2cap_core.o: changed function: l2cap_send_ack
l2cap_core.o: changed function: l2cap_send_efs_conf_rsp
l2cap_core.o: changed function: l2cap_send_i_or_rr_or_rnr
l2cap_core.o: changed function: l2cap_send_move_chan_cfm
l2cap_core.o: changed function: l2cap_send_move_chan_cfm_icid
l2cap_core.o: changed function: l2cap_send_move_chan_req
l2cap_core.o: changed function: l2cap_send_rr_or_rnr
l2cap_core.o: changed function: l2cap_send_sframe
l2cap_core.o: changed function: l2cap_send_srej
l2cap_core.o: changed function: l2cap_send_srej_tail
l2cap_core.o: changed function: l2cap_start_connection
l2cap_core.o: new function: l2cap_connect_req
sch_atm.o: changed function: atm_tc_bind_filter
sch_atm.o: changed function: atm_tc_change
sch_atm.o: changed function: atm_tc_delete
sch_atm.o: changed function: atm_tc_destroy
sch_atm.o: changed function: atm_tc_enqueue
sch_atm.o: changed function: atm_tc_find
sch_atm.o: changed function: atm_tc_graft
sch_atm.o: changed function: atm_tc_leaf
sch_atm.o: changed function: atm_tc_peek
sch_atm.o: changed function: atm_tc_put
sch_atm.o: changed function: atm_tc_reset
sch_atm.o: changed function: atm_tc_tcf_block
sch_atm.o: changed function: sch_atm_dequeue
sch_drr.o: changed function: drr_dequeue
sch_dsmark.o: changed function: dsmark_bind_filter
sch_dsmark.o: changed function: dsmark_change
sch_dsmark.o: changed function: dsmark_destroy
sch_dsmark.o: changed function: dsmark_dump_class
sch_dsmark.o: changed function: dsmark_init
sch_dsmark.o: changed function: dsmark_peek
sch_dsmark.o: changed function: dsmark_reset
sch_hfsc.o: changed function: hfsc_change_class
sch_hfsc.o: changed function: hfsc_dequeue
sch_hfsc.o: changed function: hfsc_enqueue
sch_multiq.o: changed function: multiq_peek
sch_prio.o: changed function: prio_peek
sch_qfq.o: changed function: qfq_dequeue
sch_qfq.o: changed function: qfq_enqueue
sch_red.o: changed function: red_peek
sch_sfb.o: changed function: sfb_peek
sch_tbf.o: changed function: tbf_dequeue

---------------------------

Modifications:
- function l2cap_le_sig_cmd has no fentry/mcount call, so add a "klp_"
  prefix to the patched version and its callers
- for ppc64le, add __attribute__((optimize("-fno-optimize-sibling-calls")))
    l2cap_chan_hold()
    l2cap_disconn_cfm()
    l2cap_handle_rej()
    l2cap_handle_srej()
    l2cap_monitor_timeout()
    l2cap_pass_to_tx()
    l2cap_retransmit_all()
    l2cap_send_efs_conf_rsp()
    l2cap_send_sframe()

commit d8f15b60a96ba8ce5d3d55518eb939d9bebd87a9
Author: David Marlin <dmarlin@redhat.com>
Date:   Tue Jan 9 23:44:57 2024 -0600

    Bluetooth: L2CAP: Fix L2CAP_CR_SCID_IN_USE value

    JIRA: https://issues.redhat.com/browse/RHEL-2742
    CVE: CVE-2022-42896

    commit d8edd9ed156a1a840f1b1c2dbbf458684d6eea6e
    Author: Marcin Kraglak <marcin.kraglak@tieto.com>
    Date:   Wed Mar 8 14:09:41 2017 +0100

        Bluetooth: L2CAP: Fix L2CAP_CR_SCID_IN_USE value

        Fix issue found during L2CAP qualification test TP/LE/CFC/BV-20-C.

        Signed-off-by: Marcin Kraglak <marcin.kraglak@tieto.com>
        Signed-off-by: Marcel Holtmann <marcel@holtmann.org>

    Signed-off-by: David Marlin <dmarlin@redhat.com>

commit ae6cdce73d24b5cdccb89f88552bd6a9074f0aed
Author: David Marlin <dmarlin@redhat.com>
Date:   Tue Jan 9 23:45:05 2024 -0600

    Bluetooth: Use separate L2CAP LE credit based connection result values

    JIRA: https://issues.redhat.com/browse/RHEL-2742
    CVE: CVE-2022-42896

    commit 571f739083e2544b343b5998608de679519de4e9
    Author: Mallikarjun Phulari <mallikarjun.phulari@intel.com>
    Date:   Fri Oct 5 14:48:12 2018 +0530

        Bluetooth: Use separate L2CAP LE credit based connection result values

        Add the result values specific to L2CAP LE credit based connections
        and change the old result values wherever they were used.

        Signed-off-by: Mallikarjun Phulari <mallikarjun.phulari@intel.com>
        Signed-off-by: Marcel Holtmann <marcel@holtmann.org>

    Signed-off-by: David Marlin <dmarlin@redhat.com>

commit b45513e7819c6d7fe8bcd8bcf94670e0da9cc949
Author: David Marlin <dmarlin@redhat.com>
Date:   Tue Jan 9 23:46:25 2024 -0600

    Bluetooth: L2CAP: Fix accepting connection request for invalid SPSM

    JIRA: https://issues.redhat.com/browse/RHEL-2742

    CVE: CVE-2022-42896

    Conflicts:
    Our 3.10 tree does not include support for Bluetooth Enhanced Credit Based Mode,
    so omit hunk #2 of:
      711f8c3fb3db  Bluetooth: L2CAP: Fix accepting connection request for invalid SPSM

    commit 711f8c3fb3db61897080468586b970c87c61d9e4
    Author: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
    Date:   Mon Oct 31 16:10:32 2022 -0700

        Bluetooth: L2CAP: Fix accepting connection request for invalid SPSM

        The Bluetooth spec states that the valid range for SPSM is from
        0x0001-0x00ff so it is invalid to accept values outside of this range:

          BLUETOOTH CORE SPECIFICATION Version 5.3 | Vol 3, Part A
          page 1059:
          Table 4.15: L2CAP_LE_CREDIT_BASED_CONNECTION_REQ SPSM ranges

        CVE: CVE-2022-42896
        CC: stable@vger.kernel.org
        Reported-by: Tamás Koczka <poprdi@google.com>
        Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
        Reviewed-by: Tedd Ho-Jeong An <tedd.an@intel.com>

    Signed-off-by: David Marlin <dmarlin@redhat.com>

commit a766b7a5d576eb559319776f8fa400f00128937e
Author: David Marlin <dmarlin@redhat.com>
Date:   Tue Jan 9 23:47:13 2024 -0600

    Bluetooth: L2CAP: Fix l2cap_global_chan_by_psm

    JIRA: https://issues.redhat.com/browse/RHEL-2742
    CVE: CVE-2022-42896

    commit f937b758a188d6fd328a81367087eddbb2fce50f
    Author: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
    Date:   Mon Oct 31 16:10:33 2022 -0700

        Bluetooth: L2CAP: Fix l2cap_global_chan_by_psm

        l2cap_global_chan_by_psm shall not return fixed channels as they are not
        meant to be connected by (S)PSM.

        Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
        Reviewed-by: Tedd Ho-Jeong An <tedd.an@intel.com>

    Signed-off-by: David Marlin <dmarlin@redhat.com>

Signed-off-by: Joe Lawrence <joe.lawrence@redhat.com>
---
 include/net/bluetooth/l2cap.h | 17 +++++++----
 net/bluetooth/l2cap_core.c    | 55 +++++++++++++++++++++++++----------
 2 files changed, 50 insertions(+), 22 deletions(-)

diff --git a/include/net/bluetooth/l2cap.h b/include/net/bluetooth/l2cap.h
index 45f3a951974c..1b0dfbb0eb82 100644
--- a/include/net/bluetooth/l2cap.h
+++ b/include/net/bluetooth/l2cap.h
@@ -277,12 +277,17 @@ struct l2cap_conn_rsp {
 #define L2CAP_CR_SEC_BLOCK	0x0003
 #define L2CAP_CR_NO_MEM		0x0004
 #define L2CAP_CR_BAD_AMP	0x0005
-#define L2CAP_CR_AUTHENTICATION	0x0005
-#define L2CAP_CR_AUTHORIZATION	0x0006
-#define L2CAP_CR_BAD_KEY_SIZE	0x0007
-#define L2CAP_CR_ENCRYPTION	0x0008
-#define L2CAP_CR_INVALID_SCID	0x0009
-#define L2CAP_CR_SCID_IN_USE	0x0010
+
+/* credit based connect results */
+#define L2CAP_CR_LE_SUCCESS		0x0000
+#define L2CAP_CR_LE_BAD_PSM		0x0002
+#define L2CAP_CR_LE_NO_MEM		0x0004
+#define L2CAP_CR_LE_AUTHENTICATION	0x0005
+#define L2CAP_CR_LE_AUTHORIZATION	0x0006
+#define L2CAP_CR_LE_BAD_KEY_SIZE	0x0007
+#define L2CAP_CR_LE_ENCRYPTION		0x0008
+#define L2CAP_CR_LE_INVALID_SCID	0x0009
+#define L2CAP_CR_LE_SCID_IN_USE		0X000A
 
 /* connect/create channel status */
 #define L2CAP_CS_NO_INFO	0x0000
diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c
index 4338810b0d58..a3bed86517e7 100644
--- a/net/bluetooth/l2cap_core.c
+++ b/net/bluetooth/l2cap_core.c
@@ -480,6 +480,7 @@ static void l2cap_chan_destroy(struct kref *kref)
 	kfree(chan);
 }
 
+__attribute__((optimize("-fno-optimize-sibling-calls")))
 void l2cap_chan_hold(struct l2cap_chan *c)
 {
 	BT_DBG("chan %p orig refcnt %d", c, kref_read(&c->kref));
@@ -682,9 +683,9 @@ static void l2cap_chan_le_connect_reject(struct l2cap_chan *chan)
 	u16 result;
 
 	if (test_bit(FLAG_DEFER_SETUP, &chan->flags))
-		result = L2CAP_CR_AUTHORIZATION;
+		result = L2CAP_CR_LE_AUTHORIZATION;
 	else
-		result = L2CAP_CR_BAD_PSM;
+		result = L2CAP_CR_LE_BAD_PSM;
 
 	l2cap_state_change(chan, BT_DISCONN);
 
@@ -1067,6 +1068,7 @@ static struct sk_buff *l2cap_create_sframe_pdu(struct l2cap_chan *chan,
 	return skb;
 }
 
+__attribute__((optimize("-fno-optimize-sibling-calls")))
 static void l2cap_send_sframe(struct l2cap_chan *chan,
 			      struct l2cap_ctrl *control)
 {
@@ -1792,7 +1794,7 @@ static struct l2cap_chan *l2cap_global_chan_by_psm(int state, __le16 psm,
 		if (link_type == LE_LINK && c->src_type == BDADDR_BREDR)
 			continue;
 
-		if (c->psm == psm) {
+		if (c->chan_type != L2CAP_CHAN_FIXED && c->psm == psm) {
 			int src_match, dst_match;
 			int src_any, dst_any;
 
@@ -1822,6 +1824,7 @@ static struct l2cap_chan *l2cap_global_chan_by_psm(int state, __le16 psm,
 	return c1;
 }
 
+__attribute__((optimize("-fno-optimize-sibling-calls")))
 static void l2cap_monitor_timeout(struct work_struct *work)
 {
 	struct l2cap_chan *chan = container_of(work, struct l2cap_chan,
@@ -2062,6 +2065,7 @@ static void l2cap_retransmit(struct l2cap_chan *chan,
 	l2cap_ertm_resend(chan);
 }
 
+__attribute__((optimize("-fno-optimize-sibling-calls")))
 static void l2cap_retransmit_all(struct l2cap_chan *chan,
 				 struct l2cap_ctrl *control)
 {
@@ -2862,6 +2866,7 @@ static void l2cap_tx(struct l2cap_chan *chan, struct l2cap_ctrl *control,
 	}
 }
 
+__attribute__((optimize("-fno-optimize-sibling-calls")))
 static void l2cap_pass_to_tx(struct l2cap_chan *chan,
 			     struct l2cap_ctrl *control)
 {
@@ -3702,7 +3707,7 @@ void __l2cap_le_connect_rsp_defer(struct l2cap_chan *chan)
 	rsp.mtu     = cpu_to_le16(chan->imtu);
 	rsp.mps     = cpu_to_le16(chan->mps);
 	rsp.credits = cpu_to_le16(chan->rx_credits);
-	rsp.result  = cpu_to_le16(L2CAP_CR_SUCCESS);
+	rsp.result  = cpu_to_le16(L2CAP_CR_LE_SUCCESS);
 
 	l2cap_send_cmd(conn, chan->ident, L2CAP_LE_CONN_RSP, sizeof(rsp),
 		       &rsp);
@@ -4055,6 +4060,8 @@ static inline void set_default_fcs(struct l2cap_chan *chan)
 		chan->fcs = L2CAP_FCS_CRC16;
 }
 
+
+__attribute__((optimize("-fno-optimize-sibling-calls")))
 static void l2cap_send_efs_conf_rsp(struct l2cap_chan *chan, void *data,
 				    u8 ident, u16 flags)
 {
@@ -5318,7 +5325,7 @@ static int l2cap_le_connect_rsp(struct l2cap_conn *conn,
 	credits = __le16_to_cpu(rsp->credits);
 	result  = __le16_to_cpu(rsp->result);
 
-	if (result == L2CAP_CR_SUCCESS && (mtu < 23 || mps < 23 ||
+	if (result == L2CAP_CR_LE_SUCCESS && (mtu < 23 || mps < 23 ||
 					   dcid < L2CAP_CID_DYN_START ||
 					   dcid > L2CAP_CID_LE_DYN_END))
 		return -EPROTO;
@@ -5339,7 +5346,7 @@ static int l2cap_le_connect_rsp(struct l2cap_conn *conn,
 	l2cap_chan_lock(chan);
 
 	switch (result) {
-	case L2CAP_CR_SUCCESS:
+	case L2CAP_CR_LE_SUCCESS:
 		if (__l2cap_get_chan_by_dcid(conn, dcid)) {
 			err = -EBADSLT;
 			break;
@@ -5353,8 +5360,8 @@ static int l2cap_le_connect_rsp(struct l2cap_conn *conn,
 		l2cap_chan_ready(chan);
 		break;
 
-	case L2CAP_CR_AUTHENTICATION:
-	case L2CAP_CR_ENCRYPTION:
+	case L2CAP_CR_LE_AUTHENTICATION:
+	case L2CAP_CR_LE_ENCRYPTION:
 		/* If we already have MITM protection we can't do
 		 * anything.
 		 */
@@ -5493,11 +5500,24 @@ static int l2cap_le_connect_req(struct l2cap_conn *conn,
 	BT_DBG("psm 0x%2.2x scid 0x%4.4x mtu %u mps %u", __le16_to_cpu(psm),
 	       scid, mtu, mps);
 
+	/* BLUETOOTH CORE SPECIFICATION Version 5.3 | Vol 3, Part A
+	 * page 1059:
+	 *
+	 * Valid range: 0x0001-0x00ff
+	 *
+	 * Table 4.15: L2CAP_LE_CREDIT_BASED_CONNECTION_REQ SPSM ranges
+	 */
+	if (!psm || __le16_to_cpu(psm) > L2CAP_PSM_LE_DYN_END) {
+		result = L2CAP_CR_LE_BAD_PSM;
+		chan = NULL;
+		goto response;
+	}
+
 	/* Check if we have socket listening on psm */
 	pchan = l2cap_global_chan_by_psm(BT_LISTEN, psm, &conn->hcon->src,
 					 &conn->hcon->dst, LE_LINK);
 	if (!pchan) {
-		result = L2CAP_CR_BAD_PSM;
+		result = L2CAP_CR_LE_BAD_PSM;
 		chan = NULL;
 		goto response;
 	}
@@ -5507,28 +5527,28 @@ static int l2cap_le_connect_req(struct l2cap_conn *conn,
 
 	if (!smp_sufficient_security(conn->hcon, pchan->sec_level,
 				     SMP_ALLOW_STK)) {
-		result = L2CAP_CR_AUTHENTICATION;
+		result = L2CAP_CR_LE_AUTHENTICATION;
 		chan = NULL;
 		goto response_unlock;
 	}
 
 	/* Check for valid dynamic CID range */
 	if (scid < L2CAP_CID_DYN_START || scid > L2CAP_CID_LE_DYN_END) {
-		result = L2CAP_CR_INVALID_SCID;
+		result = L2CAP_CR_LE_INVALID_SCID;
 		chan = NULL;
 		goto response_unlock;
 	}
 
 	/* Check if we already have channel with that dcid */
 	if (__l2cap_get_chan_by_dcid(conn, scid)) {
-		result = L2CAP_CR_SCID_IN_USE;
+		result = L2CAP_CR_LE_SCID_IN_USE;
 		chan = NULL;
 		goto response_unlock;
 	}
 
 	chan = pchan->ops->new_connection(pchan);
 	if (!chan) {
-		result = L2CAP_CR_NO_MEM;
+		result = L2CAP_CR_LE_NO_MEM;
 		goto response_unlock;
 	}
 
@@ -5563,7 +5583,7 @@ static int l2cap_le_connect_req(struct l2cap_conn *conn,
 		chan->ops->defer(chan);
 	} else {
 		l2cap_chan_ready(chan);
-		result = L2CAP_CR_SUCCESS;
+		result = L2CAP_CR_LE_SUCCESS;
 	}
 
 response_unlock:
@@ -5665,7 +5685,7 @@ done:
 	return 0;
 }
 
-static inline int l2cap_le_sig_cmd(struct l2cap_conn *conn,
+static inline int klp_l2cap_le_sig_cmd(struct l2cap_conn *conn,
 				   struct l2cap_cmd_hdr *cmd, u16 cmd_len,
 				   u8 *data)
 {
@@ -5738,7 +5758,7 @@ static inline void l2cap_le_sig_channel(struct l2cap_conn *conn,
 		goto drop;
 	}
 
-	err = l2cap_le_sig_cmd(conn, cmd, len, skb->data);
+	err = klp_l2cap_le_sig_cmd(conn, cmd, len, skb->data);
 	if (err) {
 		struct l2cap_cmd_rej_unk rej;
 
@@ -6012,6 +6032,7 @@ static int l2cap_rx_queued_iframes(struct l2cap_chan *chan)
 	return err;
 }
 
+__attribute__((optimize("-fno-optimize-sibling-calls")))
 static void l2cap_handle_srej(struct l2cap_chan *chan,
 			      struct l2cap_ctrl *control)
 {
@@ -6070,6 +6091,7 @@ static void l2cap_handle_srej(struct l2cap_chan *chan,
 	}
 }
 
+__attribute__((optimize("-fno-optimize-sibling-calls")))
 static void l2cap_handle_rej(struct l2cap_chan *chan,
 			     struct l2cap_ctrl *control)
 {
@@ -7442,6 +7464,7 @@ int l2cap_disconn_ind(struct hci_conn *hcon)
 	return conn->disc_reason;
 }
 
+__attribute__((optimize("-fno-optimize-sibling-calls")))
 static void l2cap_disconn_cfm(struct hci_conn *hcon, u8 reason)
 {
 	if (hcon->type != ACL_LINK && hcon->type != LE_LINK)
-- 
2.44.0