From: Sasha Levin Date: Sun, 25 Aug 2024 11:50:53 +0000 (-0400) Subject: Fixes for 5.15 X-Git-Tag: v6.1.107~70 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=137b128c20eddbecebba927eb6ddab2b88e5d74f;p=thirdparty%2Fkernel%2Fstable-queue.git Fixes for 5.15 Signed-off-by: Sasha Levin --- diff --git a/queue-5.15/bluetooth-hci_core-fix-le-quote-calculation.patch b/queue-5.15/bluetooth-hci_core-fix-le-quote-calculation.patch new file mode 100644 index 00000000000..4fd29cfcc85 --- /dev/null +++ b/queue-5.15/bluetooth-hci_core-fix-le-quote-calculation.patch @@ -0,0 +1,76 @@ +From 8fe5ac9a1582f17788f340db22af9dc8e467f6f0 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 12 Aug 2024 11:22:08 -0400 +Subject: Bluetooth: hci_core: Fix LE quote calculation + +From: Luiz Augusto von Dentz + +[ Upstream commit 932021a11805b9da4bd6abf66fe233cccd59fe0e ] + +Function hci_sched_le needs to update the respective counter variable +inplace other the likes of hci_quote_sent would attempt to use the +possible outdated value of conn->{le_cnt,acl_cnt}. + +Link: https://github.com/bluez/bluez/issues/915 +Fixes: 73d80deb7bdf ("Bluetooth: prioritizing data over HCI") +Signed-off-by: Luiz Augusto von Dentz +Signed-off-by: Sasha Levin +--- + net/bluetooth/hci_core.c | 19 +++++++------------ + 1 file changed, 7 insertions(+), 12 deletions(-) + +diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c +index fc4e02b3f26ad..7dff3f1a2a9eb 100644 +--- a/net/bluetooth/hci_core.c ++++ b/net/bluetooth/hci_core.c +@@ -4876,19 +4876,19 @@ static void hci_sched_le(struct hci_dev *hdev) + { + struct hci_chan *chan; + struct sk_buff *skb; +- int quote, cnt, tmp; ++ int quote, *cnt, tmp; + + BT_DBG("%s", hdev->name); + + if (!hci_conn_num(hdev, LE_LINK)) + return; + +- cnt = hdev->le_pkts ? hdev->le_cnt : hdev->acl_cnt; ++ cnt = hdev->le_pkts ? &hdev->le_cnt : &hdev->acl_cnt; + +- __check_timeout(hdev, cnt, LE_LINK); ++ __check_timeout(hdev, *cnt, LE_LINK); + +- tmp = cnt; +- while (cnt && (chan = hci_chan_sent(hdev, LE_LINK, "e))) { ++ tmp = *cnt; ++ while (*cnt && (chan = hci_chan_sent(hdev, LE_LINK, "e))) { + u32 priority = (skb_peek(&chan->data_q))->priority; + while (quote-- && (skb = skb_peek(&chan->data_q))) { + BT_DBG("chan %p skb %p len %d priority %u", chan, skb, +@@ -4903,7 +4903,7 @@ static void hci_sched_le(struct hci_dev *hdev) + hci_send_frame(hdev, skb); + hdev->le_last_tx = jiffies; + +- cnt--; ++ (*cnt)--; + chan->sent++; + chan->conn->sent++; + +@@ -4913,12 +4913,7 @@ static void hci_sched_le(struct hci_dev *hdev) + } + } + +- if (hdev->le_pkts) +- hdev->le_cnt = cnt; +- else +- hdev->acl_cnt = cnt; +- +- if (cnt != tmp) ++ if (*cnt != tmp) + hci_prio_recalculate(hdev, LE_LINK); + } + +-- +2.43.0 + diff --git a/queue-5.15/bluetooth-smp-fix-assumption-of-central-always-being.patch b/queue-5.15/bluetooth-smp-fix-assumption-of-central-always-being.patch new file mode 100644 index 00000000000..cf3918ff9a6 --- /dev/null +++ b/queue-5.15/bluetooth-smp-fix-assumption-of-central-always-being.patch @@ -0,0 +1,447 @@ +From cbaf7f005e45c39eb43c1a84ff634199d3d0094c Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 30 Aug 2023 15:08:06 -0700 +Subject: Bluetooth: SMP: Fix assumption of Central always being Initiator + +From: Luiz Augusto von Dentz + +[ Upstream commit 28cd47f75185c4818b0fb1b46f2f02faaba96376 ] + +SMP initiator role shall be considered the one that initiates the +pairing procedure with SMP_CMD_PAIRING_REQ: + +BLUETOOTH CORE SPECIFICATION Version 5.3 | Vol 3, Part H +page 1557: + +Figure 2.1: LE pairing phases + +Note that by sending SMP_CMD_SECURITY_REQ it doesn't change the role to +be Initiator. + +Link: https://github.com/bluez/bluez/issues/567 +Fixes: b28b4943660f ("Bluetooth: Add strict checks for allowed SMP PDUs") +Signed-off-by: Luiz Augusto von Dentz +Signed-off-by: Sasha Levin +--- + net/bluetooth/smp.c | 144 ++++++++++++++++++++++---------------------- + 1 file changed, 72 insertions(+), 72 deletions(-) + +diff --git a/net/bluetooth/smp.c b/net/bluetooth/smp.c +index f688f941c40c4..629d25bc7f671 100644 +--- a/net/bluetooth/smp.c ++++ b/net/bluetooth/smp.c +@@ -913,7 +913,7 @@ static int tk_request(struct l2cap_conn *conn, u8 remote_oob, u8 auth, + * Confirms and the responder Enters the passkey. + */ + if (smp->method == OVERLAP) { +- if (hcon->role == HCI_ROLE_MASTER) ++ if (test_bit(SMP_FLAG_INITIATOR, &smp->flags)) + smp->method = CFM_PASSKEY; + else + smp->method = REQ_PASSKEY; +@@ -963,7 +963,7 @@ static u8 smp_confirm(struct smp_chan *smp) + + smp_send_cmd(smp->conn, SMP_CMD_PAIRING_CONFIRM, sizeof(cp), &cp); + +- if (conn->hcon->out) ++ if (test_bit(SMP_FLAG_INITIATOR, &smp->flags)) + SMP_ALLOW_CMD(smp, SMP_CMD_PAIRING_CONFIRM); + else + SMP_ALLOW_CMD(smp, SMP_CMD_PAIRING_RANDOM); +@@ -979,7 +979,8 @@ static u8 smp_random(struct smp_chan *smp) + int ret; + + bt_dev_dbg(conn->hcon->hdev, "conn %p %s", conn, +- conn->hcon->out ? "initiator" : "responder"); ++ test_bit(SMP_FLAG_INITIATOR, &smp->flags) ? "initiator" : ++ "responder"); + + ret = smp_c1(smp->tk, smp->rrnd, smp->preq, smp->prsp, + hcon->init_addr_type, &hcon->init_addr, +@@ -993,7 +994,7 @@ static u8 smp_random(struct smp_chan *smp) + return SMP_CONFIRM_FAILED; + } + +- if (hcon->out) { ++ if (test_bit(SMP_FLAG_INITIATOR, &smp->flags)) { + u8 stk[16]; + __le64 rand = 0; + __le16 ediv = 0; +@@ -1250,14 +1251,15 @@ static void smp_distribute_keys(struct smp_chan *smp) + rsp = (void *) &smp->prsp[1]; + + /* The responder sends its keys first */ +- if (hcon->out && (smp->remote_key_dist & KEY_DIST_MASK)) { ++ if (test_bit(SMP_FLAG_INITIATOR, &smp->flags) && ++ (smp->remote_key_dist & KEY_DIST_MASK)) { + smp_allow_key_dist(smp); + return; + } + + req = (void *) &smp->preq[1]; + +- if (hcon->out) { ++ if (test_bit(SMP_FLAG_INITIATOR, &smp->flags)) { + keydist = &rsp->init_key_dist; + *keydist &= req->init_key_dist; + } else { +@@ -1426,7 +1428,7 @@ static int sc_mackey_and_ltk(struct smp_chan *smp, u8 mackey[16], u8 ltk[16]) + struct hci_conn *hcon = smp->conn->hcon; + u8 *na, *nb, a[7], b[7]; + +- if (hcon->out) { ++ if (test_bit(SMP_FLAG_INITIATOR, &smp->flags)) { + na = smp->prnd; + nb = smp->rrnd; + } else { +@@ -1454,7 +1456,7 @@ static void sc_dhkey_check(struct smp_chan *smp) + a[6] = hcon->init_addr_type; + b[6] = hcon->resp_addr_type; + +- if (hcon->out) { ++ if (test_bit(SMP_FLAG_INITIATOR, &smp->flags)) { + local_addr = a; + remote_addr = b; + memcpy(io_cap, &smp->preq[1], 3); +@@ -1533,7 +1535,7 @@ static u8 sc_passkey_round(struct smp_chan *smp, u8 smp_op) + /* The round is only complete when the initiator + * receives pairing random. + */ +- if (!hcon->out) { ++ if (!test_bit(SMP_FLAG_INITIATOR, &smp->flags)) { + smp_send_cmd(conn, SMP_CMD_PAIRING_RANDOM, + sizeof(smp->prnd), smp->prnd); + if (smp->passkey_round == 20) +@@ -1561,7 +1563,7 @@ static u8 sc_passkey_round(struct smp_chan *smp, u8 smp_op) + + SMP_ALLOW_CMD(smp, SMP_CMD_PAIRING_RANDOM); + +- if (hcon->out) { ++ if (test_bit(SMP_FLAG_INITIATOR, &smp->flags)) { + smp_send_cmd(conn, SMP_CMD_PAIRING_RANDOM, + sizeof(smp->prnd), smp->prnd); + return 0; +@@ -1572,7 +1574,7 @@ static u8 sc_passkey_round(struct smp_chan *smp, u8 smp_op) + case SMP_CMD_PUBLIC_KEY: + default: + /* Initiating device starts the round */ +- if (!hcon->out) ++ if (!test_bit(SMP_FLAG_INITIATOR, &smp->flags)) + return 0; + + bt_dev_dbg(hdev, "Starting passkey round %u", +@@ -1617,7 +1619,7 @@ static int sc_user_reply(struct smp_chan *smp, u16 mgmt_op, __le32 passkey) + } + + /* Initiator sends DHKey check first */ +- if (hcon->out) { ++ if (test_bit(SMP_FLAG_INITIATOR, &smp->flags)) { + sc_dhkey_check(smp); + SMP_ALLOW_CMD(smp, SMP_CMD_DHKEY_CHECK); + } else if (test_and_clear_bit(SMP_FLAG_DHKEY_PENDING, &smp->flags)) { +@@ -1740,7 +1742,7 @@ static u8 smp_cmd_pairing_req(struct l2cap_conn *conn, struct sk_buff *skb) + struct smp_cmd_pairing rsp, *req = (void *) skb->data; + struct l2cap_chan *chan = conn->smp; + struct hci_dev *hdev = conn->hcon->hdev; +- struct smp_chan *smp; ++ struct smp_chan *smp = chan->data; + u8 key_size, auth, sec_level; + int ret; + +@@ -1749,16 +1751,14 @@ static u8 smp_cmd_pairing_req(struct l2cap_conn *conn, struct sk_buff *skb) + if (skb->len < sizeof(*req)) + return SMP_INVALID_PARAMS; + +- if (conn->hcon->role != HCI_ROLE_SLAVE) ++ if (smp && test_bit(SMP_FLAG_INITIATOR, &smp->flags)) + return SMP_CMD_NOTSUPP; + +- if (!chan->data) ++ if (!smp) { + smp = smp_chan_create(conn); +- else +- smp = chan->data; +- +- if (!smp) +- return SMP_UNSPECIFIED; ++ if (!smp) ++ return SMP_UNSPECIFIED; ++ } + + /* We didn't start the pairing, so match remote */ + auth = req->auth_req & AUTH_REQ_MASK(hdev); +@@ -1940,7 +1940,7 @@ static u8 smp_cmd_pairing_rsp(struct l2cap_conn *conn, struct sk_buff *skb) + if (skb->len < sizeof(*rsp)) + return SMP_INVALID_PARAMS; + +- if (conn->hcon->role != HCI_ROLE_MASTER) ++ if (!test_bit(SMP_FLAG_INITIATOR, &smp->flags)) + return SMP_CMD_NOTSUPP; + + skb_pull(skb, sizeof(*rsp)); +@@ -2035,7 +2035,7 @@ static u8 sc_check_confirm(struct smp_chan *smp) + if (smp->method == REQ_PASSKEY || smp->method == DSP_PASSKEY) + return sc_passkey_round(smp, SMP_CMD_PAIRING_CONFIRM); + +- if (conn->hcon->out) { ++ if (test_bit(SMP_FLAG_INITIATOR, &smp->flags)) { + smp_send_cmd(conn, SMP_CMD_PAIRING_RANDOM, sizeof(smp->prnd), + smp->prnd); + SMP_ALLOW_CMD(smp, SMP_CMD_PAIRING_RANDOM); +@@ -2057,7 +2057,7 @@ static int fixup_sc_false_positive(struct smp_chan *smp) + u8 auth; + + /* The issue is only observed when we're in responder role */ +- if (hcon->out) ++ if (test_bit(SMP_FLAG_INITIATOR, &smp->flags)) + return SMP_UNSPECIFIED; + + if (hci_dev_test_flag(hdev, HCI_SC_ONLY)) { +@@ -2093,7 +2093,8 @@ static u8 smp_cmd_pairing_confirm(struct l2cap_conn *conn, struct sk_buff *skb) + struct hci_dev *hdev = hcon->hdev; + + bt_dev_dbg(hdev, "conn %p %s", conn, +- hcon->out ? "initiator" : "responder"); ++ test_bit(SMP_FLAG_INITIATOR, &smp->flags) ? "initiator" : ++ "responder"); + + if (skb->len < sizeof(smp->pcnf)) + return SMP_INVALID_PARAMS; +@@ -2115,7 +2116,7 @@ static u8 smp_cmd_pairing_confirm(struct l2cap_conn *conn, struct sk_buff *skb) + return ret; + } + +- if (conn->hcon->out) { ++ if (test_bit(SMP_FLAG_INITIATOR, &smp->flags)) { + smp_send_cmd(conn, SMP_CMD_PAIRING_RANDOM, sizeof(smp->prnd), + smp->prnd); + SMP_ALLOW_CMD(smp, SMP_CMD_PAIRING_RANDOM); +@@ -2150,7 +2151,7 @@ static u8 smp_cmd_pairing_random(struct l2cap_conn *conn, struct sk_buff *skb) + if (!test_bit(SMP_FLAG_SC, &smp->flags)) + return smp_random(smp); + +- if (hcon->out) { ++ if (test_bit(SMP_FLAG_INITIATOR, &smp->flags)) { + pkax = smp->local_pk; + pkbx = smp->remote_pk; + na = smp->prnd; +@@ -2163,7 +2164,7 @@ static u8 smp_cmd_pairing_random(struct l2cap_conn *conn, struct sk_buff *skb) + } + + if (smp->method == REQ_OOB) { +- if (!hcon->out) ++ if (!test_bit(SMP_FLAG_INITIATOR, &smp->flags)) + smp_send_cmd(conn, SMP_CMD_PAIRING_RANDOM, + sizeof(smp->prnd), smp->prnd); + SMP_ALLOW_CMD(smp, SMP_CMD_DHKEY_CHECK); +@@ -2174,7 +2175,7 @@ static u8 smp_cmd_pairing_random(struct l2cap_conn *conn, struct sk_buff *skb) + if (smp->method == REQ_PASSKEY || smp->method == DSP_PASSKEY) + return sc_passkey_round(smp, SMP_CMD_PAIRING_RANDOM); + +- if (hcon->out) { ++ if (test_bit(SMP_FLAG_INITIATOR, &smp->flags)) { + u8 cfm[16]; + + err = smp_f4(smp->tfm_cmac, smp->remote_pk, smp->local_pk, +@@ -2215,7 +2216,7 @@ static u8 smp_cmd_pairing_random(struct l2cap_conn *conn, struct sk_buff *skb) + return SMP_UNSPECIFIED; + + if (smp->method == REQ_OOB) { +- if (hcon->out) { ++ if (test_bit(SMP_FLAG_INITIATOR, &smp->flags)) { + sc_dhkey_check(smp); + SMP_ALLOW_CMD(smp, SMP_CMD_DHKEY_CHECK); + } +@@ -2289,10 +2290,27 @@ bool smp_sufficient_security(struct hci_conn *hcon, u8 sec_level, + return false; + } + ++static void smp_send_pairing_req(struct smp_chan *smp, __u8 auth) ++{ ++ struct smp_cmd_pairing cp; ++ ++ if (smp->conn->hcon->type == ACL_LINK) ++ build_bredr_pairing_cmd(smp, &cp, NULL); ++ else ++ build_pairing_cmd(smp->conn, &cp, NULL, auth); ++ ++ smp->preq[0] = SMP_CMD_PAIRING_REQ; ++ memcpy(&smp->preq[1], &cp, sizeof(cp)); ++ ++ smp_send_cmd(smp->conn, SMP_CMD_PAIRING_REQ, sizeof(cp), &cp); ++ SMP_ALLOW_CMD(smp, SMP_CMD_PAIRING_RSP); ++ ++ set_bit(SMP_FLAG_INITIATOR, &smp->flags); ++} ++ + static u8 smp_cmd_security_req(struct l2cap_conn *conn, struct sk_buff *skb) + { + struct smp_cmd_security_req *rp = (void *) skb->data; +- struct smp_cmd_pairing cp; + struct hci_conn *hcon = conn->hcon; + struct hci_dev *hdev = hcon->hdev; + struct smp_chan *smp; +@@ -2341,16 +2359,20 @@ static u8 smp_cmd_security_req(struct l2cap_conn *conn, struct sk_buff *skb) + + skb_pull(skb, sizeof(*rp)); + +- memset(&cp, 0, sizeof(cp)); +- build_pairing_cmd(conn, &cp, NULL, auth); ++ smp_send_pairing_req(smp, auth); + +- smp->preq[0] = SMP_CMD_PAIRING_REQ; +- memcpy(&smp->preq[1], &cp, sizeof(cp)); ++ return 0; ++} + +- smp_send_cmd(conn, SMP_CMD_PAIRING_REQ, sizeof(cp), &cp); +- SMP_ALLOW_CMD(smp, SMP_CMD_PAIRING_RSP); ++static void smp_send_security_req(struct smp_chan *smp, __u8 auth) ++{ ++ struct smp_cmd_security_req cp; + +- return 0; ++ cp.auth_req = auth; ++ smp_send_cmd(smp->conn, SMP_CMD_SECURITY_REQ, sizeof(cp), &cp); ++ SMP_ALLOW_CMD(smp, SMP_CMD_PAIRING_REQ); ++ ++ clear_bit(SMP_FLAG_INITIATOR, &smp->flags); + } + + int smp_conn_security(struct hci_conn *hcon, __u8 sec_level) +@@ -2421,23 +2443,11 @@ int smp_conn_security(struct hci_conn *hcon, __u8 sec_level) + authreq |= SMP_AUTH_MITM; + } + +- if (hcon->role == HCI_ROLE_MASTER) { +- struct smp_cmd_pairing cp; +- +- build_pairing_cmd(conn, &cp, NULL, authreq); +- smp->preq[0] = SMP_CMD_PAIRING_REQ; +- memcpy(&smp->preq[1], &cp, sizeof(cp)); +- +- smp_send_cmd(conn, SMP_CMD_PAIRING_REQ, sizeof(cp), &cp); +- SMP_ALLOW_CMD(smp, SMP_CMD_PAIRING_RSP); +- } else { +- struct smp_cmd_security_req cp; +- cp.auth_req = authreq; +- smp_send_cmd(conn, SMP_CMD_SECURITY_REQ, sizeof(cp), &cp); +- SMP_ALLOW_CMD(smp, SMP_CMD_PAIRING_REQ); +- } ++ if (hcon->role == HCI_ROLE_MASTER) ++ smp_send_pairing_req(smp, authreq); ++ else ++ smp_send_security_req(smp, authreq); + +- set_bit(SMP_FLAG_INITIATOR, &smp->flags); + ret = 0; + + unlock: +@@ -2688,8 +2698,6 @@ static int smp_cmd_sign_info(struct l2cap_conn *conn, struct sk_buff *skb) + + static u8 sc_select_method(struct smp_chan *smp) + { +- struct l2cap_conn *conn = smp->conn; +- struct hci_conn *hcon = conn->hcon; + struct smp_cmd_pairing *local, *remote; + u8 local_mitm, remote_mitm, local_io, remote_io, method; + +@@ -2702,7 +2710,7 @@ static u8 sc_select_method(struct smp_chan *smp) + * the "struct smp_cmd_pairing" from them we need to skip the + * first byte which contains the opcode. + */ +- if (hcon->out) { ++ if (test_bit(SMP_FLAG_INITIATOR, &smp->flags)) { + local = (void *) &smp->preq[1]; + remote = (void *) &smp->prsp[1]; + } else { +@@ -2771,7 +2779,7 @@ static int smp_cmd_public_key(struct l2cap_conn *conn, struct sk_buff *skb) + /* Non-initiating device sends its public key after receiving + * the key from the initiating device. + */ +- if (!hcon->out) { ++ if (!test_bit(SMP_FLAG_INITIATOR, &smp->flags)) { + err = sc_send_public_key(smp); + if (err) + return err; +@@ -2833,7 +2841,7 @@ static int smp_cmd_public_key(struct l2cap_conn *conn, struct sk_buff *skb) + } + + if (smp->method == REQ_OOB) { +- if (hcon->out) ++ if (test_bit(SMP_FLAG_INITIATOR, &smp->flags)) + smp_send_cmd(conn, SMP_CMD_PAIRING_RANDOM, + sizeof(smp->prnd), smp->prnd); + +@@ -2842,7 +2850,7 @@ static int smp_cmd_public_key(struct l2cap_conn *conn, struct sk_buff *skb) + return 0; + } + +- if (hcon->out) ++ if (test_bit(SMP_FLAG_INITIATOR, &smp->flags)) + SMP_ALLOW_CMD(smp, SMP_CMD_PAIRING_CONFIRM); + + if (smp->method == REQ_PASSKEY) { +@@ -2857,7 +2865,7 @@ static int smp_cmd_public_key(struct l2cap_conn *conn, struct sk_buff *skb) + /* The Initiating device waits for the non-initiating device to + * send the confirm value. + */ +- if (conn->hcon->out) ++ if (test_bit(SMP_FLAG_INITIATOR, &smp->flags)) + return 0; + + err = smp_f4(smp->tfm_cmac, smp->local_pk, smp->remote_pk, smp->prnd, +@@ -2891,7 +2899,7 @@ static int smp_cmd_dhkey_check(struct l2cap_conn *conn, struct sk_buff *skb) + a[6] = hcon->init_addr_type; + b[6] = hcon->resp_addr_type; + +- if (hcon->out) { ++ if (test_bit(SMP_FLAG_INITIATOR, &smp->flags)) { + local_addr = a; + remote_addr = b; + memcpy(io_cap, &smp->prsp[1], 3); +@@ -2916,7 +2924,7 @@ static int smp_cmd_dhkey_check(struct l2cap_conn *conn, struct sk_buff *skb) + if (crypto_memneq(check->e, e, 16)) + return SMP_DHKEY_CHECK_FAILED; + +- if (!hcon->out) { ++ if (!test_bit(SMP_FLAG_INITIATOR, &smp->flags)) { + if (test_bit(SMP_FLAG_WAIT_USER, &smp->flags)) { + set_bit(SMP_FLAG_DHKEY_PENDING, &smp->flags); + return 0; +@@ -2928,7 +2936,7 @@ static int smp_cmd_dhkey_check(struct l2cap_conn *conn, struct sk_buff *skb) + + sc_add_ltk(smp); + +- if (hcon->out) { ++ if (test_bit(SMP_FLAG_INITIATOR, &smp->flags)) { + hci_le_start_enc(hcon, 0, 0, smp->tk, smp->enc_key_size); + hcon->enc_key_size = smp->enc_key_size; + } +@@ -3077,7 +3085,6 @@ static void bredr_pairing(struct l2cap_chan *chan) + struct l2cap_conn *conn = chan->conn; + struct hci_conn *hcon = conn->hcon; + struct hci_dev *hdev = hcon->hdev; +- struct smp_cmd_pairing req; + struct smp_chan *smp; + + bt_dev_dbg(hdev, "chan %p", chan); +@@ -3129,14 +3136,7 @@ static void bredr_pairing(struct l2cap_chan *chan) + + bt_dev_dbg(hdev, "starting SMP over BR/EDR"); + +- /* Prepare and send the BR/EDR SMP Pairing Request */ +- build_bredr_pairing_cmd(smp, &req, NULL); +- +- smp->preq[0] = SMP_CMD_PAIRING_REQ; +- memcpy(&smp->preq[1], &req, sizeof(req)); +- +- smp_send_cmd(conn, SMP_CMD_PAIRING_REQ, sizeof(req), &req); +- SMP_ALLOW_CMD(smp, SMP_CMD_PAIRING_RSP); ++ smp_send_pairing_req(smp, 0x00); + } + + static void smp_resume_cb(struct l2cap_chan *chan) +-- +2.43.0 + diff --git a/queue-5.15/bonding-fix-bond_ipsec_offload_ok-return-type.patch b/queue-5.15/bonding-fix-bond_ipsec_offload_ok-return-type.patch new file mode 100644 index 00000000000..4d2f53b0b2c --- /dev/null +++ b/queue-5.15/bonding-fix-bond_ipsec_offload_ok-return-type.patch @@ -0,0 +1,68 @@ +From 8b9f59f340d4054266b677a4a44a74a207185d3a Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 16 Aug 2024 14:48:10 +0300 +Subject: bonding: fix bond_ipsec_offload_ok return type + +From: Nikolay Aleksandrov + +[ Upstream commit fc59b9a5f7201b9f7272944596113a82cc7773d5 ] + +Fix the return type which should be bool. + +Fixes: 955b785ec6b3 ("bonding: fix suspicious RCU usage in bond_ipsec_offload_ok()") +Signed-off-by: Nikolay Aleksandrov +Reviewed-by: Hangbin Liu +Signed-off-by: Paolo Abeni +Signed-off-by: Sasha Levin +--- + drivers/net/bonding/bond_main.c | 18 ++++++------------ + 1 file changed, 6 insertions(+), 12 deletions(-) + +diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c +index 6a91229b0e05b..61ff4bb22e647 100644 +--- a/drivers/net/bonding/bond_main.c ++++ b/drivers/net/bonding/bond_main.c +@@ -592,34 +592,28 @@ static bool bond_ipsec_offload_ok(struct sk_buff *skb, struct xfrm_state *xs) + struct net_device *real_dev; + struct slave *curr_active; + struct bonding *bond; +- int err; ++ bool ok = false; + + bond = netdev_priv(bond_dev); + rcu_read_lock(); + curr_active = rcu_dereference(bond->curr_active_slave); + real_dev = curr_active->dev; + +- if (BOND_MODE(bond) != BOND_MODE_ACTIVEBACKUP) { +- err = false; ++ if (BOND_MODE(bond) != BOND_MODE_ACTIVEBACKUP) + goto out; +- } + +- if (!xs->xso.real_dev) { +- err = false; ++ if (!xs->xso.real_dev) + goto out; +- } + + if (!real_dev->xfrmdev_ops || + !real_dev->xfrmdev_ops->xdo_dev_offload_ok || +- netif_is_bond_master(real_dev)) { +- err = false; ++ netif_is_bond_master(real_dev)) + goto out; +- } + +- err = real_dev->xfrmdev_ops->xdo_dev_offload_ok(skb, xs); ++ ok = real_dev->xfrmdev_ops->xdo_dev_offload_ok(skb, xs); + out: + rcu_read_unlock(); +- return err; ++ return ok; + } + + static const struct xfrmdev_ops bond_xfrmdev_ops = { +-- +2.43.0 + diff --git a/queue-5.15/bonding-fix-null-pointer-deref-in-bond_ipsec_offload.patch b/queue-5.15/bonding-fix-null-pointer-deref-in-bond_ipsec_offload.patch new file mode 100644 index 00000000000..f74b5ad143b --- /dev/null +++ b/queue-5.15/bonding-fix-null-pointer-deref-in-bond_ipsec_offload.patch @@ -0,0 +1,37 @@ +From bc38e9ec8063279f30428a46fee2d5f8b65bddc0 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 16 Aug 2024 14:48:11 +0300 +Subject: bonding: fix null pointer deref in bond_ipsec_offload_ok + +From: Nikolay Aleksandrov + +[ Upstream commit 95c90e4ad89d493a7a14fa200082e466e2548f9d ] + +We must check if there is an active slave before dereferencing the pointer. + +Fixes: 18cb261afd7b ("bonding: support hardware encryption offload to slaves") +Signed-off-by: Nikolay Aleksandrov +Reviewed-by: Hangbin Liu +Reviewed-by: Eric Dumazet +Signed-off-by: Paolo Abeni +Signed-off-by: Sasha Levin +--- + drivers/net/bonding/bond_main.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c +index 61ff4bb22e647..177c90e9a4685 100644 +--- a/drivers/net/bonding/bond_main.c ++++ b/drivers/net/bonding/bond_main.c +@@ -597,6 +597,8 @@ static bool bond_ipsec_offload_ok(struct sk_buff *skb, struct xfrm_state *xs) + bond = netdev_priv(bond_dev); + rcu_read_lock(); + curr_active = rcu_dereference(bond->curr_active_slave); ++ if (!curr_active) ++ goto out; + real_dev = curr_active->dev; + + if (BOND_MODE(bond) != BOND_MODE_ACTIVEBACKUP) +-- +2.43.0 + diff --git a/queue-5.15/bonding-fix-xfrm-real_dev-null-pointer-dereference.patch b/queue-5.15/bonding-fix-xfrm-real_dev-null-pointer-dereference.patch new file mode 100644 index 00000000000..3f9083b97ed --- /dev/null +++ b/queue-5.15/bonding-fix-xfrm-real_dev-null-pointer-dereference.patch @@ -0,0 +1,81 @@ +From 49fa20a3dfbf1d42674c572590c0d5334e8ea621 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 16 Aug 2024 14:48:12 +0300 +Subject: bonding: fix xfrm real_dev null pointer dereference + +From: Nikolay Aleksandrov + +[ Upstream commit f8cde9805981c50d0c029063dc7d82821806fc44 ] + +We shouldn't set real_dev to NULL because packets can be in transit and +xfrm might call xdo_dev_offload_ok() in parallel. All callbacks assume +real_dev is set. + + Example trace: + kernel: BUG: unable to handle page fault for address: 0000000000001030 + kernel: bond0: (slave eni0np1): making interface the new active one + kernel: #PF: supervisor write access in kernel mode + kernel: #PF: error_code(0x0002) - not-present page + kernel: PGD 0 P4D 0 + kernel: Oops: 0002 [#1] PREEMPT SMP + kernel: CPU: 4 PID: 2237 Comm: ping Not tainted 6.7.7+ #12 + kernel: Hardware name: QEMU Standard PC (Q35 + ICH9, 2009), BIOS 1.16.3-2.fc40 04/01/2014 + kernel: RIP: 0010:nsim_ipsec_offload_ok+0xc/0x20 [netdevsim] + kernel: bond0: (slave eni0np1): bond_ipsec_add_sa_all: failed to add SA + kernel: Code: e0 0f 0b 48 83 7f 38 00 74 de 0f 0b 48 8b 47 08 48 8b 37 48 8b 78 40 e9 b2 e5 9a d7 66 90 0f 1f 44 00 00 48 8b 86 80 02 00 00 <83> 80 30 10 00 00 01 b8 01 00 00 00 c3 0f 1f 80 00 00 00 00 0f 1f + kernel: bond0: (slave eni0np1): making interface the new active one + kernel: RSP: 0018:ffffabde81553b98 EFLAGS: 00010246 + kernel: bond0: (slave eni0np1): bond_ipsec_add_sa_all: failed to add SA + kernel: + kernel: RAX: 0000000000000000 RBX: ffff9eb404e74900 RCX: ffff9eb403d97c60 + kernel: RDX: ffffffffc090de10 RSI: ffff9eb404e74900 RDI: ffff9eb3c5de9e00 + kernel: RBP: ffff9eb3c0a42000 R08: 0000000000000010 R09: 0000000000000014 + kernel: R10: 7974203030303030 R11: 3030303030303030 R12: 0000000000000000 + kernel: R13: ffff9eb3c5de9e00 R14: ffffabde81553cc8 R15: ffff9eb404c53000 + kernel: FS: 00007f2a77a3ad00(0000) GS:ffff9eb43bd00000(0000) knlGS:0000000000000000 + kernel: CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 + kernel: CR2: 0000000000001030 CR3: 00000001122ab000 CR4: 0000000000350ef0 + kernel: bond0: (slave eni0np1): making interface the new active one + kernel: Call Trace: + kernel: + kernel: ? __die+0x1f/0x60 + kernel: bond0: (slave eni0np1): bond_ipsec_add_sa_all: failed to add SA + kernel: ? page_fault_oops+0x142/0x4c0 + kernel: ? do_user_addr_fault+0x65/0x670 + kernel: ? kvm_read_and_reset_apf_flags+0x3b/0x50 + kernel: bond0: (slave eni0np1): making interface the new active one + kernel: ? exc_page_fault+0x7b/0x180 + kernel: ? asm_exc_page_fault+0x22/0x30 + kernel: ? nsim_bpf_uninit+0x50/0x50 [netdevsim] + kernel: bond0: (slave eni0np1): bond_ipsec_add_sa_all: failed to add SA + kernel: ? nsim_ipsec_offload_ok+0xc/0x20 [netdevsim] + kernel: bond0: (slave eni0np1): making interface the new active one + kernel: bond_ipsec_offload_ok+0x7b/0x90 [bonding] + kernel: xfrm_output+0x61/0x3b0 + kernel: bond0: (slave eni0np1): bond_ipsec_add_sa_all: failed to add SA + kernel: ip_push_pending_frames+0x56/0x80 + +Fixes: 18cb261afd7b ("bonding: support hardware encryption offload to slaves") +Signed-off-by: Nikolay Aleksandrov +Reviewed-by: Hangbin Liu +Signed-off-by: Paolo Abeni +Signed-off-by: Sasha Levin +--- + drivers/net/bonding/bond_main.c | 1 - + 1 file changed, 1 deletion(-) + +diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c +index 177c90e9a4685..fd0667e1d10ab 100644 +--- a/drivers/net/bonding/bond_main.c ++++ b/drivers/net/bonding/bond_main.c +@@ -575,7 +575,6 @@ static void bond_ipsec_del_sa_all(struct bonding *bond) + } else { + slave->dev->xfrmdev_ops->xdo_dev_state_delete(ipsec->xs); + } +- ipsec->xs->xso.real_dev = NULL; + } + spin_unlock_bh(&bond->ipsec_lock); + rcu_read_unlock(); +-- +2.43.0 + diff --git a/queue-5.15/bonding-fix-xfrm-state-handling-when-clearing-active.patch b/queue-5.15/bonding-fix-xfrm-state-handling-when-clearing-active.patch new file mode 100644 index 00000000000..72a4ef0a7aa --- /dev/null +++ b/queue-5.15/bonding-fix-xfrm-state-handling-when-clearing-active.patch @@ -0,0 +1,43 @@ +From 2c9bafff042b6da7fbb4e69444f272ce2d959771 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 16 Aug 2024 14:48:13 +0300 +Subject: bonding: fix xfrm state handling when clearing active slave + +From: Nikolay Aleksandrov + +[ Upstream commit c4c5c5d2ef40a9f67a9241dc5422eac9ffe19547 ] + +If the active slave is cleared manually the xfrm state is not flushed. +This leads to xfrm add/del imbalance and adding the same state multiple +times. For example when the device cannot handle anymore states we get: + [ 1169.884811] bond0: (slave eni0np1): bond_ipsec_add_sa_all: failed to add SA +because it's filled with the same state after multiple active slave +clearings. This change also has a few nice side effects: user-space +gets a notification for the change, the old device gets its mac address +and promisc/mcast adjusted properly. + +Fixes: 18cb261afd7b ("bonding: support hardware encryption offload to slaves") +Signed-off-by: Nikolay Aleksandrov +Reviewed-by: Hangbin Liu +Signed-off-by: Paolo Abeni +Signed-off-by: Sasha Levin +--- + drivers/net/bonding/bond_options.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/net/bonding/bond_options.c b/drivers/net/bonding/bond_options.c +index 1f8f7537e8ebf..5da4599377e1e 100644 +--- a/drivers/net/bonding/bond_options.c ++++ b/drivers/net/bonding/bond_options.c +@@ -893,7 +893,7 @@ static int bond_option_active_slave_set(struct bonding *bond, + /* check to see if we are clearing active */ + if (!slave_dev) { + netdev_dbg(bond->dev, "Clearing current active slave\n"); +- RCU_INIT_POINTER(bond->curr_active_slave, NULL); ++ bond_change_active_slave(bond, NULL); + bond_select_active_slave(bond); + } else { + struct slave *old_active = rtnl_dereference(bond->curr_active_slave); +-- +2.43.0 + diff --git a/queue-5.15/dpaa2-switch-fix-error-checking-in-dpaa2_switch_seed.patch b/queue-5.15/dpaa2-switch-fix-error-checking-in-dpaa2_switch_seed.patch new file mode 100644 index 00000000000..b535af4cd2a --- /dev/null +++ b/queue-5.15/dpaa2-switch-fix-error-checking-in-dpaa2_switch_seed.patch @@ -0,0 +1,56 @@ +From 256cdced4f6026c9dda17dc1257b39c2bce2d466 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 17 Aug 2024 09:52:46 +0300 +Subject: dpaa2-switch: Fix error checking in dpaa2_switch_seed_bp() + +From: Dan Carpenter + +[ Upstream commit c50e7475961c36ec4d21d60af055b32f9436b431 ] + +The dpaa2_switch_add_bufs() function returns the number of bufs that it +was able to add. It returns BUFS_PER_CMD (7) for complete success or a +smaller number if there are not enough pages available. However, the +error checking is looking at the total number of bufs instead of the +number which were added on this iteration. Thus the error checking +only works correctly for the first iteration through the loop and +subsequent iterations are always counted as a success. + +Fix this by checking only the bufs added in the current iteration. + +Fixes: 0b1b71370458 ("staging: dpaa2-switch: handle Rx path on control interface") +Signed-off-by: Dan Carpenter +Reviewed-by: Simon Horman +Reviewed-by: Ioana Ciornei +Tested-by: Ioana Ciornei +Link: https://patch.msgid.link/eec27f30-b43f-42b6-b8ee-04a6f83423b6@stanley.mountain +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/freescale/dpaa2/dpaa2-switch.c | 7 ++++--- + 1 file changed, 4 insertions(+), 3 deletions(-) + +diff --git a/drivers/net/ethernet/freescale/dpaa2/dpaa2-switch.c b/drivers/net/ethernet/freescale/dpaa2/dpaa2-switch.c +index 175f15c46842e..2b6a6a997d75e 100644 +--- a/drivers/net/ethernet/freescale/dpaa2/dpaa2-switch.c ++++ b/drivers/net/ethernet/freescale/dpaa2/dpaa2-switch.c +@@ -2585,13 +2585,14 @@ static int dpaa2_switch_refill_bp(struct ethsw_core *ethsw) + + static int dpaa2_switch_seed_bp(struct ethsw_core *ethsw) + { +- int *count, i; ++ int *count, ret, i; + + for (i = 0; i < DPAA2_ETHSW_NUM_BUFS; i += BUFS_PER_CMD) { ++ ret = dpaa2_switch_add_bufs(ethsw, ethsw->bpid); + count = ðsw->buf_count; +- *count += dpaa2_switch_add_bufs(ethsw, ethsw->bpid); ++ *count += ret; + +- if (unlikely(*count < BUFS_PER_CMD)) ++ if (unlikely(ret < BUFS_PER_CMD)) + return -ENOMEM; + } + +-- +2.43.0 + diff --git a/queue-5.15/ice-fix-ice_last_offset-formula.patch b/queue-5.15/ice-fix-ice_last_offset-formula.patch new file mode 100644 index 00000000000..de3f9f7f6bf --- /dev/null +++ b/queue-5.15/ice-fix-ice_last_offset-formula.patch @@ -0,0 +1,39 @@ +From 210a03d04310f3be46040594cff617fcae1dcfa2 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 7 Aug 2024 12:53:25 +0200 +Subject: ice: fix ICE_LAST_OFFSET formula + +From: Maciej Fijalkowski + +[ Upstream commit b966ad832942b5a11e002f9b5ef102b08425b84a ] + +For bigger PAGE_SIZE archs, ice driver works on 3k Rx buffers. +Therefore, ICE_LAST_OFFSET should take into account ICE_RXBUF_3072, not +ICE_RXBUF_2048. + +Fixes: 7237f5b0dba4 ("ice: introduce legacy Rx flag") +Suggested-by: Luiz Capitulino +Signed-off-by: Maciej Fijalkowski +Tested-by: Chandan Kumar Rout (A Contingent Worker at Intel) +Signed-off-by: Tony Nguyen +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/intel/ice/ice_txrx.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/net/ethernet/intel/ice/ice_txrx.c b/drivers/net/ethernet/intel/ice/ice_txrx.c +index 6ee8e0032d52c..b09d89cdb001f 100644 +--- a/drivers/net/ethernet/intel/ice/ice_txrx.c ++++ b/drivers/net/ethernet/intel/ice/ice_txrx.c +@@ -765,7 +765,7 @@ ice_can_reuse_rx_page(struct ice_rx_buf *rx_buf, int rx_buf_pgcnt) + return false; + #else + #define ICE_LAST_OFFSET \ +- (SKB_WITH_OVERHEAD(PAGE_SIZE) - ICE_RXBUF_2048) ++ (SKB_WITH_OVERHEAD(PAGE_SIZE) - ICE_RXBUF_3072) + if (rx_buf->page_offset > ICE_LAST_OFFSET) + return false; + #endif /* PAGE_SIZE < 8192) */ +-- +2.43.0 + diff --git a/queue-5.15/ip6_tunnel-fix-broken-gro.patch b/queue-5.15/ip6_tunnel-fix-broken-gro.patch new file mode 100644 index 00000000000..b6224b83545 --- /dev/null +++ b/queue-5.15/ip6_tunnel-fix-broken-gro.patch @@ -0,0 +1,78 @@ +From 24193ca51f1ab13d3e3cad739335289f0a550f06 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 15 Aug 2024 17:14:16 +0200 +Subject: ip6_tunnel: Fix broken GRO + +From: Thomas Bogendoerfer + +[ Upstream commit 4b3e33fcc38f7750604b065c55a43e94c5bc3145 ] + +GRO code checks for matching layer 2 headers to see, if packet belongs +to the same flow and because ip6 tunnel set dev->hard_header_len +this check fails in cases, where it shouldn't. To fix this don't +set hard_header_len, but use needed_headroom like ipv4/ip_tunnel.c +does. + +Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2") +Signed-off-by: Thomas Bogendoerfer +Link: https://patch.msgid.link/20240815151419.109864-1-tbogendoerfer@suse.de +Signed-off-by: Paolo Abeni +Signed-off-by: Sasha Levin +--- + net/ipv6/ip6_tunnel.c | 12 +++++++----- + 1 file changed, 7 insertions(+), 5 deletions(-) + +diff --git a/net/ipv6/ip6_tunnel.c b/net/ipv6/ip6_tunnel.c +index d370a71c97520..5955fca601b3a 100644 +--- a/net/ipv6/ip6_tunnel.c ++++ b/net/ipv6/ip6_tunnel.c +@@ -1501,7 +1501,8 @@ static void ip6_tnl_link_config(struct ip6_tnl *t) + tdev = __dev_get_by_index(t->net, p->link); + + if (tdev) { +- dev->hard_header_len = tdev->hard_header_len + t_hlen; ++ dev->needed_headroom = tdev->hard_header_len + ++ tdev->needed_headroom + t_hlen; + mtu = min_t(unsigned int, tdev->mtu, IP6_MAX_MTU); + + mtu = mtu - t_hlen; +@@ -1729,7 +1730,9 @@ ip6_tnl_siocdevprivate(struct net_device *dev, struct ifreq *ifr, + int ip6_tnl_change_mtu(struct net_device *dev, int new_mtu) + { + struct ip6_tnl *tnl = netdev_priv(dev); ++ int t_hlen; + ++ t_hlen = tnl->hlen + sizeof(struct ipv6hdr); + if (tnl->parms.proto == IPPROTO_IPV6) { + if (new_mtu < IPV6_MIN_MTU) + return -EINVAL; +@@ -1738,10 +1741,10 @@ int ip6_tnl_change_mtu(struct net_device *dev, int new_mtu) + return -EINVAL; + } + if (tnl->parms.proto == IPPROTO_IPV6 || tnl->parms.proto == 0) { +- if (new_mtu > IP6_MAX_MTU - dev->hard_header_len) ++ if (new_mtu > IP6_MAX_MTU - dev->hard_header_len - t_hlen) + return -EINVAL; + } else { +- if (new_mtu > IP_MAX_MTU - dev->hard_header_len) ++ if (new_mtu > IP_MAX_MTU - dev->hard_header_len - t_hlen) + return -EINVAL; + } + dev->mtu = new_mtu; +@@ -1887,12 +1890,11 @@ ip6_tnl_dev_init_gen(struct net_device *dev) + t_hlen = t->hlen + sizeof(struct ipv6hdr); + + dev->type = ARPHRD_TUNNEL6; +- dev->hard_header_len = LL_MAX_HEADER + t_hlen; + dev->mtu = ETH_DATA_LEN - t_hlen; + if (!(t->parms.flags & IP6_TNL_F_IGN_ENCAP_LIMIT)) + dev->mtu -= 8; + dev->min_mtu = ETH_MIN_MTU; +- dev->max_mtu = IP6_MAX_MTU - dev->hard_header_len; ++ dev->max_mtu = IP6_MAX_MTU - dev->hard_header_len - t_hlen; + + dev_hold(dev); + return 0; +-- +2.43.0 + diff --git a/queue-5.15/ipv6-fix-possible-uaf-in-ip6_finish_output2.patch b/queue-5.15/ipv6-fix-possible-uaf-in-ip6_finish_output2.patch new file mode 100644 index 00000000000..cb8cfcd82c3 --- /dev/null +++ b/queue-5.15/ipv6-fix-possible-uaf-in-ip6_finish_output2.patch @@ -0,0 +1,49 @@ +From 119502bd558ef283df5ca4c7cf93d214e7123843 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 20 Aug 2024 16:08:58 +0000 +Subject: ipv6: fix possible UAF in ip6_finish_output2() + +From: Eric Dumazet + +[ Upstream commit da273b377ae0d9bd255281ed3c2adb228321687b ] + +If skb_expand_head() returns NULL, skb has been freed +and associated dst/idev could also have been freed. + +We need to hold rcu_read_lock() to make sure the dst and +associated idev are alive. + +Fixes: 5796015fa968 ("ipv6: allocate enough headroom in ip6_finish_output2()") +Signed-off-by: Eric Dumazet +Cc: Vasily Averin +Reviewed-by: David Ahern +Link: https://patch.msgid.link/20240820160859.3786976-3-edumazet@google.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + net/ipv6/ip6_output.c | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c +index 1d06b71c1adad..8054a4a2f2a5e 100644 +--- a/net/ipv6/ip6_output.c ++++ b/net/ipv6/ip6_output.c +@@ -69,11 +69,15 @@ static int ip6_finish_output2(struct net *net, struct sock *sk, struct sk_buff * + + /* Be paranoid, rather than too clever. */ + if (unlikely(hh_len > skb_headroom(skb)) && dev->header_ops) { ++ /* Make sure idev stays alive */ ++ rcu_read_lock(); + skb = skb_expand_head(skb, hh_len); + if (!skb) { + IP6_INC_STATS(net, idev, IPSTATS_MIB_OUTDISCARDS); ++ rcu_read_unlock(); + return -ENOMEM; + } ++ rcu_read_unlock(); + } + + hdr = ipv6_hdr(skb); +-- +2.43.0 + diff --git a/queue-5.15/ipv6-prevent-possible-uaf-in-ip6_xmit.patch b/queue-5.15/ipv6-prevent-possible-uaf-in-ip6_xmit.patch new file mode 100644 index 00000000000..3b5b855805c --- /dev/null +++ b/queue-5.15/ipv6-prevent-possible-uaf-in-ip6_xmit.patch @@ -0,0 +1,48 @@ +From 1ecc9670ed3dfd9baef486be569102ae9e5d245b Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 20 Aug 2024 16:08:59 +0000 +Subject: ipv6: prevent possible UAF in ip6_xmit() + +From: Eric Dumazet + +[ Upstream commit 2d5ff7e339d04622d8282661df36151906d0e1c7 ] + +If skb_expand_head() returns NULL, skb has been freed +and the associated dst/idev could also have been freed. + +We must use rcu_read_lock() to prevent a possible UAF. + +Fixes: 0c9f227bee11 ("ipv6: use skb_expand_head in ip6_xmit") +Signed-off-by: Eric Dumazet +Cc: Vasily Averin +Reviewed-by: David Ahern +Link: https://patch.msgid.link/20240820160859.3786976-4-edumazet@google.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + net/ipv6/ip6_output.c | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c +index 8054a4a2f2a5e..b37121f872bc9 100644 +--- a/net/ipv6/ip6_output.c ++++ b/net/ipv6/ip6_output.c +@@ -273,11 +273,15 @@ int ip6_xmit(const struct sock *sk, struct sk_buff *skb, struct flowi6 *fl6, + head_room += opt->opt_nflen + opt->opt_flen; + + if (unlikely(head_room > skb_headroom(skb))) { ++ /* Make sure idev stays alive */ ++ rcu_read_lock(); + skb = skb_expand_head(skb, head_room); + if (!skb) { + IP6_INC_STATS(net, idev, IPSTATS_MIB_OUTDISCARDS); ++ rcu_read_unlock(); + return -ENOBUFS; + } ++ rcu_read_unlock(); + } + + if (opt) { +-- +2.43.0 + diff --git a/queue-5.15/ipv6-prevent-uaf-in-ip6_send_skb.patch b/queue-5.15/ipv6-prevent-uaf-in-ip6_send_skb.patch new file mode 100644 index 00000000000..337bb0a3e18 --- /dev/null +++ b/queue-5.15/ipv6-prevent-uaf-in-ip6_send_skb.patch @@ -0,0 +1,158 @@ +From 82e8c35da22d3774a030f6e765896f59a92776ae Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 20 Aug 2024 16:08:57 +0000 +Subject: ipv6: prevent UAF in ip6_send_skb() + +From: Eric Dumazet + +[ Upstream commit faa389b2fbaaec7fd27a390b4896139f9da662e3 ] + +syzbot reported an UAF in ip6_send_skb() [1] + +After ip6_local_out() has returned, we no longer can safely +dereference rt, unless we hold rcu_read_lock(). + +A similar issue has been fixed in commit +a688caa34beb ("ipv6: take rcu lock in rawv6_send_hdrinc()") + +Another potential issue in ip6_finish_output2() is handled in a +separate patch. + +[1] + BUG: KASAN: slab-use-after-free in ip6_send_skb+0x18d/0x230 net/ipv6/ip6_output.c:1964 +Read of size 8 at addr ffff88806dde4858 by task syz.1.380/6530 + +CPU: 1 UID: 0 PID: 6530 Comm: syz.1.380 Not tainted 6.11.0-rc3-syzkaller-00306-gdf6cbc62cc9b #0 +Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 08/06/2024 +Call Trace: + + __dump_stack lib/dump_stack.c:93 [inline] + dump_stack_lvl+0x241/0x360 lib/dump_stack.c:119 + print_address_description mm/kasan/report.c:377 [inline] + print_report+0x169/0x550 mm/kasan/report.c:488 + kasan_report+0x143/0x180 mm/kasan/report.c:601 + ip6_send_skb+0x18d/0x230 net/ipv6/ip6_output.c:1964 + rawv6_push_pending_frames+0x75c/0x9e0 net/ipv6/raw.c:588 + rawv6_sendmsg+0x19c7/0x23c0 net/ipv6/raw.c:926 + sock_sendmsg_nosec net/socket.c:730 [inline] + __sock_sendmsg+0x1a6/0x270 net/socket.c:745 + sock_write_iter+0x2dd/0x400 net/socket.c:1160 + do_iter_readv_writev+0x60a/0x890 + vfs_writev+0x37c/0xbb0 fs/read_write.c:971 + do_writev+0x1b1/0x350 fs/read_write.c:1018 + do_syscall_x64 arch/x86/entry/common.c:52 [inline] + do_syscall_64+0xf3/0x230 arch/x86/entry/common.c:83 + entry_SYSCALL_64_after_hwframe+0x77/0x7f +RIP: 0033:0x7f936bf79e79 +Code: ff ff c3 66 2e 0f 1f 84 00 00 00 00 00 0f 1f 40 00 48 89 f8 48 89 f7 48 89 d6 48 89 ca 4d 89 c2 4d 89 c8 4c 8b 4c 24 08 0f 05 <48> 3d 01 f0 ff ff 73 01 c3 48 c7 c1 a8 ff ff ff f7 d8 64 89 01 48 +RSP: 002b:00007f936cd7f038 EFLAGS: 00000246 ORIG_RAX: 0000000000000014 +RAX: ffffffffffffffda RBX: 00007f936c115f80 RCX: 00007f936bf79e79 +RDX: 0000000000000001 RSI: 0000000020000040 RDI: 0000000000000004 +RBP: 00007f936bfe7916 R08: 0000000000000000 R09: 0000000000000000 +R10: 0000000000000000 R11: 0000000000000246 R12: 0000000000000000 +R13: 0000000000000000 R14: 00007f936c115f80 R15: 00007fff2860a7a8 + + +Allocated by task 6530: + kasan_save_stack mm/kasan/common.c:47 [inline] + kasan_save_track+0x3f/0x80 mm/kasan/common.c:68 + unpoison_slab_object mm/kasan/common.c:312 [inline] + __kasan_slab_alloc+0x66/0x80 mm/kasan/common.c:338 + kasan_slab_alloc include/linux/kasan.h:201 [inline] + slab_post_alloc_hook mm/slub.c:3988 [inline] + slab_alloc_node mm/slub.c:4037 [inline] + kmem_cache_alloc_noprof+0x135/0x2a0 mm/slub.c:4044 + dst_alloc+0x12b/0x190 net/core/dst.c:89 + ip6_blackhole_route+0x59/0x340 net/ipv6/route.c:2670 + make_blackhole net/xfrm/xfrm_policy.c:3120 [inline] + xfrm_lookup_route+0xd1/0x1c0 net/xfrm/xfrm_policy.c:3313 + ip6_dst_lookup_flow+0x13e/0x180 net/ipv6/ip6_output.c:1257 + rawv6_sendmsg+0x1283/0x23c0 net/ipv6/raw.c:898 + sock_sendmsg_nosec net/socket.c:730 [inline] + __sock_sendmsg+0x1a6/0x270 net/socket.c:745 + ____sys_sendmsg+0x525/0x7d0 net/socket.c:2597 + ___sys_sendmsg net/socket.c:2651 [inline] + __sys_sendmsg+0x2b0/0x3a0 net/socket.c:2680 + do_syscall_x64 arch/x86/entry/common.c:52 [inline] + do_syscall_64+0xf3/0x230 arch/x86/entry/common.c:83 + entry_SYSCALL_64_after_hwframe+0x77/0x7f + +Freed by task 45: + kasan_save_stack mm/kasan/common.c:47 [inline] + kasan_save_track+0x3f/0x80 mm/kasan/common.c:68 + kasan_save_free_info+0x40/0x50 mm/kasan/generic.c:579 + poison_slab_object+0xe0/0x150 mm/kasan/common.c:240 + __kasan_slab_free+0x37/0x60 mm/kasan/common.c:256 + kasan_slab_free include/linux/kasan.h:184 [inline] + slab_free_hook mm/slub.c:2252 [inline] + slab_free mm/slub.c:4473 [inline] + kmem_cache_free+0x145/0x350 mm/slub.c:4548 + dst_destroy+0x2ac/0x460 net/core/dst.c:124 + rcu_do_batch kernel/rcu/tree.c:2569 [inline] + rcu_core+0xafd/0x1830 kernel/rcu/tree.c:2843 + handle_softirqs+0x2c4/0x970 kernel/softirq.c:554 + __do_softirq kernel/softirq.c:588 [inline] + invoke_softirq kernel/softirq.c:428 [inline] + __irq_exit_rcu+0xf4/0x1c0 kernel/softirq.c:637 + irq_exit_rcu+0x9/0x30 kernel/softirq.c:649 + instr_sysvec_apic_timer_interrupt arch/x86/kernel/apic/apic.c:1043 [inline] + sysvec_apic_timer_interrupt+0xa6/0xc0 arch/x86/kernel/apic/apic.c:1043 + asm_sysvec_apic_timer_interrupt+0x1a/0x20 arch/x86/include/asm/idtentry.h:702 + +Last potentially related work creation: + kasan_save_stack+0x3f/0x60 mm/kasan/common.c:47 + __kasan_record_aux_stack+0xac/0xc0 mm/kasan/generic.c:541 + __call_rcu_common kernel/rcu/tree.c:3106 [inline] + call_rcu+0x167/0xa70 kernel/rcu/tree.c:3210 + refdst_drop include/net/dst.h:263 [inline] + skb_dst_drop include/net/dst.h:275 [inline] + nf_ct_frag6_queue net/ipv6/netfilter/nf_conntrack_reasm.c:306 [inline] + nf_ct_frag6_gather+0xb9a/0x2080 net/ipv6/netfilter/nf_conntrack_reasm.c:485 + ipv6_defrag+0x2c8/0x3c0 net/ipv6/netfilter/nf_defrag_ipv6_hooks.c:67 + nf_hook_entry_hookfn include/linux/netfilter.h:154 [inline] + nf_hook_slow+0xc3/0x220 net/netfilter/core.c:626 + nf_hook include/linux/netfilter.h:269 [inline] + __ip6_local_out+0x6fa/0x800 net/ipv6/output_core.c:143 + ip6_local_out+0x26/0x70 net/ipv6/output_core.c:153 + ip6_send_skb+0x112/0x230 net/ipv6/ip6_output.c:1959 + rawv6_push_pending_frames+0x75c/0x9e0 net/ipv6/raw.c:588 + rawv6_sendmsg+0x19c7/0x23c0 net/ipv6/raw.c:926 + sock_sendmsg_nosec net/socket.c:730 [inline] + __sock_sendmsg+0x1a6/0x270 net/socket.c:745 + sock_write_iter+0x2dd/0x400 net/socket.c:1160 + do_iter_readv_writev+0x60a/0x890 + +Fixes: 0625491493d9 ("ipv6: ip6_push_pending_frames() should increment IPSTATS_MIB_OUTDISCARDS") +Signed-off-by: Eric Dumazet +Reported-by: syzbot +Reviewed-by: David Ahern +Link: https://patch.msgid.link/20240820160859.3786976-2-edumazet@google.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + net/ipv6/ip6_output.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c +index ce37c83455796..1d06b71c1adad 100644 +--- a/net/ipv6/ip6_output.c ++++ b/net/ipv6/ip6_output.c +@@ -1940,6 +1940,7 @@ int ip6_send_skb(struct sk_buff *skb) + struct rt6_info *rt = (struct rt6_info *)skb_dst(skb); + int err; + ++ rcu_read_lock(); + err = ip6_local_out(net, skb->sk, skb); + if (err) { + if (err > 0) +@@ -1949,6 +1950,7 @@ int ip6_send_skb(struct sk_buff *skb) + IPSTATS_MIB_OUTDISCARDS); + } + ++ rcu_read_unlock(); + return err; + } + +-- +2.43.0 + diff --git a/queue-5.15/kcm-serialise-kcm_sendmsg-for-the-same-socket.patch b/queue-5.15/kcm-serialise-kcm_sendmsg-for-the-same-socket.patch new file mode 100644 index 00000000000..d9815a40078 --- /dev/null +++ b/queue-5.15/kcm-serialise-kcm_sendmsg-for-the-same-socket.patch @@ -0,0 +1,223 @@ +From c2fd1f443f3fc7488026ad20d07f7c36b35af76f Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 15 Aug 2024 15:04:37 -0700 +Subject: kcm: Serialise kcm_sendmsg() for the same socket. + +From: Kuniyuki Iwashima + +[ Upstream commit 807067bf014d4a3ae2cc55bd3de16f22a01eb580 ] + +syzkaller reported UAF in kcm_release(). [0] + +The scenario is + + 1. Thread A builds a skb with MSG_MORE and sets kcm->seq_skb. + + 2. Thread A resumes building skb from kcm->seq_skb but is blocked + by sk_stream_wait_memory() + + 3. Thread B calls sendmsg() concurrently, finishes building kcm->seq_skb + and puts the skb to the write queue + + 4. Thread A faces an error and finally frees skb that is already in the + write queue + + 5. kcm_release() does double-free the skb in the write queue + +When a thread is building a MSG_MORE skb, another thread must not touch it. + +Let's add a per-sk mutex and serialise kcm_sendmsg(). + +[0]: +BUG: KASAN: slab-use-after-free in __skb_unlink include/linux/skbuff.h:2366 [inline] +BUG: KASAN: slab-use-after-free in __skb_dequeue include/linux/skbuff.h:2385 [inline] +BUG: KASAN: slab-use-after-free in __skb_queue_purge_reason include/linux/skbuff.h:3175 [inline] +BUG: KASAN: slab-use-after-free in __skb_queue_purge include/linux/skbuff.h:3181 [inline] +BUG: KASAN: slab-use-after-free in kcm_release+0x170/0x4c8 net/kcm/kcmsock.c:1691 +Read of size 8 at addr ffff0000ced0fc80 by task syz-executor329/6167 + +CPU: 1 PID: 6167 Comm: syz-executor329 Tainted: G B 6.8.0-rc5-syzkaller-g9abbc24128bc #0 +Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 01/25/2024 +Call trace: + dump_backtrace+0x1b8/0x1e4 arch/arm64/kernel/stacktrace.c:291 + show_stack+0x2c/0x3c arch/arm64/kernel/stacktrace.c:298 + __dump_stack lib/dump_stack.c:88 [inline] + dump_stack_lvl+0xd0/0x124 lib/dump_stack.c:106 + print_address_description mm/kasan/report.c:377 [inline] + print_report+0x178/0x518 mm/kasan/report.c:488 + kasan_report+0xd8/0x138 mm/kasan/report.c:601 + __asan_report_load8_noabort+0x20/0x2c mm/kasan/report_generic.c:381 + __skb_unlink include/linux/skbuff.h:2366 [inline] + __skb_dequeue include/linux/skbuff.h:2385 [inline] + __skb_queue_purge_reason include/linux/skbuff.h:3175 [inline] + __skb_queue_purge include/linux/skbuff.h:3181 [inline] + kcm_release+0x170/0x4c8 net/kcm/kcmsock.c:1691 + __sock_release net/socket.c:659 [inline] + sock_close+0xa4/0x1e8 net/socket.c:1421 + __fput+0x30c/0x738 fs/file_table.c:376 + ____fput+0x20/0x30 fs/file_table.c:404 + task_work_run+0x230/0x2e0 kernel/task_work.c:180 + exit_task_work include/linux/task_work.h:38 [inline] + do_exit+0x618/0x1f64 kernel/exit.c:871 + do_group_exit+0x194/0x22c kernel/exit.c:1020 + get_signal+0x1500/0x15ec kernel/signal.c:2893 + do_signal+0x23c/0x3b44 arch/arm64/kernel/signal.c:1249 + do_notify_resume+0x74/0x1f4 arch/arm64/kernel/entry-common.c:148 + exit_to_user_mode_prepare arch/arm64/kernel/entry-common.c:169 [inline] + exit_to_user_mode arch/arm64/kernel/entry-common.c:178 [inline] + el0_svc+0xac/0x168 arch/arm64/kernel/entry-common.c:713 + el0t_64_sync_handler+0x84/0xfc arch/arm64/kernel/entry-common.c:730 + el0t_64_sync+0x190/0x194 arch/arm64/kernel/entry.S:598 + +Allocated by task 6166: + kasan_save_stack mm/kasan/common.c:47 [inline] + kasan_save_track+0x40/0x78 mm/kasan/common.c:68 + kasan_save_alloc_info+0x70/0x84 mm/kasan/generic.c:626 + unpoison_slab_object mm/kasan/common.c:314 [inline] + __kasan_slab_alloc+0x74/0x8c mm/kasan/common.c:340 + kasan_slab_alloc include/linux/kasan.h:201 [inline] + slab_post_alloc_hook mm/slub.c:3813 [inline] + slab_alloc_node mm/slub.c:3860 [inline] + kmem_cache_alloc_node+0x204/0x4c0 mm/slub.c:3903 + __alloc_skb+0x19c/0x3d8 net/core/skbuff.c:641 + alloc_skb include/linux/skbuff.h:1296 [inline] + kcm_sendmsg+0x1d3c/0x2124 net/kcm/kcmsock.c:783 + sock_sendmsg_nosec net/socket.c:730 [inline] + __sock_sendmsg net/socket.c:745 [inline] + sock_sendmsg+0x220/0x2c0 net/socket.c:768 + splice_to_socket+0x7cc/0xd58 fs/splice.c:889 + do_splice_from fs/splice.c:941 [inline] + direct_splice_actor+0xec/0x1d8 fs/splice.c:1164 + splice_direct_to_actor+0x438/0xa0c fs/splice.c:1108 + do_splice_direct_actor fs/splice.c:1207 [inline] + do_splice_direct+0x1e4/0x304 fs/splice.c:1233 + do_sendfile+0x460/0xb3c fs/read_write.c:1295 + __do_sys_sendfile64 fs/read_write.c:1362 [inline] + __se_sys_sendfile64 fs/read_write.c:1348 [inline] + __arm64_sys_sendfile64+0x160/0x3b4 fs/read_write.c:1348 + __invoke_syscall arch/arm64/kernel/syscall.c:37 [inline] + invoke_syscall+0x98/0x2b8 arch/arm64/kernel/syscall.c:51 + el0_svc_common+0x130/0x23c arch/arm64/kernel/syscall.c:136 + do_el0_svc+0x48/0x58 arch/arm64/kernel/syscall.c:155 + el0_svc+0x54/0x168 arch/arm64/kernel/entry-common.c:712 + el0t_64_sync_handler+0x84/0xfc arch/arm64/kernel/entry-common.c:730 + el0t_64_sync+0x190/0x194 arch/arm64/kernel/entry.S:598 + +Freed by task 6167: + kasan_save_stack mm/kasan/common.c:47 [inline] + kasan_save_track+0x40/0x78 mm/kasan/common.c:68 + kasan_save_free_info+0x5c/0x74 mm/kasan/generic.c:640 + poison_slab_object+0x124/0x18c mm/kasan/common.c:241 + __kasan_slab_free+0x3c/0x78 mm/kasan/common.c:257 + kasan_slab_free include/linux/kasan.h:184 [inline] + slab_free_hook mm/slub.c:2121 [inline] + slab_free mm/slub.c:4299 [inline] + kmem_cache_free+0x15c/0x3d4 mm/slub.c:4363 + kfree_skbmem+0x10c/0x19c + __kfree_skb net/core/skbuff.c:1109 [inline] + kfree_skb_reason+0x240/0x6f4 net/core/skbuff.c:1144 + kfree_skb include/linux/skbuff.h:1244 [inline] + kcm_release+0x104/0x4c8 net/kcm/kcmsock.c:1685 + __sock_release net/socket.c:659 [inline] + sock_close+0xa4/0x1e8 net/socket.c:1421 + __fput+0x30c/0x738 fs/file_table.c:376 + ____fput+0x20/0x30 fs/file_table.c:404 + task_work_run+0x230/0x2e0 kernel/task_work.c:180 + exit_task_work include/linux/task_work.h:38 [inline] + do_exit+0x618/0x1f64 kernel/exit.c:871 + do_group_exit+0x194/0x22c kernel/exit.c:1020 + get_signal+0x1500/0x15ec kernel/signal.c:2893 + do_signal+0x23c/0x3b44 arch/arm64/kernel/signal.c:1249 + do_notify_resume+0x74/0x1f4 arch/arm64/kernel/entry-common.c:148 + exit_to_user_mode_prepare arch/arm64/kernel/entry-common.c:169 [inline] + exit_to_user_mode arch/arm64/kernel/entry-common.c:178 [inline] + el0_svc+0xac/0x168 arch/arm64/kernel/entry-common.c:713 + el0t_64_sync_handler+0x84/0xfc arch/arm64/kernel/entry-common.c:730 + el0t_64_sync+0x190/0x194 arch/arm64/kernel/entry.S:598 + +The buggy address belongs to the object at ffff0000ced0fc80 + which belongs to the cache skbuff_head_cache of size 240 +The buggy address is located 0 bytes inside of + freed 240-byte region [ffff0000ced0fc80, ffff0000ced0fd70) + +The buggy address belongs to the physical page: +page:00000000d35f4ae4 refcount:1 mapcount:0 mapping:0000000000000000 index:0x0 pfn:0x10ed0f +flags: 0x5ffc00000000800(slab|node=0|zone=2|lastcpupid=0x7ff) +page_type: 0xffffffff() +raw: 05ffc00000000800 ffff0000c1cbf640 fffffdffc3423100 dead000000000004 +raw: 0000000000000000 00000000000c000c 00000001ffffffff 0000000000000000 +page dumped because: kasan: bad access detected + +Memory state around the buggy address: + ffff0000ced0fb80: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb + ffff0000ced0fc00: fb fb fb fb fb fb fc fc fc fc fc fc fc fc fc fc +>ffff0000ced0fc80: fa fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb + ^ + ffff0000ced0fd00: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fc fc + ffff0000ced0fd80: fc fc fc fc fc fc fc fc fa fb fb fb fb fb fb fb + +Fixes: ab7ac4eb9832 ("kcm: Kernel Connection Multiplexor module") +Reported-by: syzbot+b72d86aa5df17ce74c60@syzkaller.appspotmail.com +Closes: https://syzkaller.appspot.com/bug?extid=b72d86aa5df17ce74c60 +Tested-by: syzbot+b72d86aa5df17ce74c60@syzkaller.appspotmail.com +Signed-off-by: Kuniyuki Iwashima +Reviewed-by: Eric Dumazet +Link: https://patch.msgid.link/20240815220437.69511-1-kuniyu@amazon.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + include/net/kcm.h | 1 + + net/kcm/kcmsock.c | 4 ++++ + 2 files changed, 5 insertions(+) + +diff --git a/include/net/kcm.h b/include/net/kcm.h +index 2d704f8f49059..8e8252e08a9ce 100644 +--- a/include/net/kcm.h ++++ b/include/net/kcm.h +@@ -70,6 +70,7 @@ struct kcm_sock { + struct work_struct tx_work; + struct list_head wait_psock_list; + struct sk_buff *seq_skb; ++ struct mutex tx_mutex; + u32 tx_stopped : 1; + + /* Don't use bit fields here, these are set under different locks */ +diff --git a/net/kcm/kcmsock.c b/net/kcm/kcmsock.c +index 5457ca1909801..a3b281f7a99bc 100644 +--- a/net/kcm/kcmsock.c ++++ b/net/kcm/kcmsock.c +@@ -911,6 +911,7 @@ static int kcm_sendmsg(struct socket *sock, struct msghdr *msg, size_t len) + !(msg->msg_flags & MSG_MORE) : !!(msg->msg_flags & MSG_EOR); + int err = -EPIPE; + ++ mutex_lock(&kcm->tx_mutex); + lock_sock(sk); + + /* Per tcp_sendmsg this should be in poll */ +@@ -1059,6 +1060,7 @@ static int kcm_sendmsg(struct socket *sock, struct msghdr *msg, size_t len) + KCM_STATS_ADD(kcm->stats.tx_bytes, copied); + + release_sock(sk); ++ mutex_unlock(&kcm->tx_mutex); + return copied; + + out_error: +@@ -1084,6 +1086,7 @@ static int kcm_sendmsg(struct socket *sock, struct msghdr *msg, size_t len) + sk->sk_write_space(sk); + + release_sock(sk); ++ mutex_unlock(&kcm->tx_mutex); + return err; + } + +@@ -1326,6 +1329,7 @@ static void init_kcm_sock(struct kcm_sock *kcm, struct kcm_mux *mux) + spin_unlock_bh(&mux->lock); + + INIT_WORK(&kcm->tx_work, kcm_tx_work); ++ mutex_init(&kcm->tx_mutex); + + spin_lock_bh(&mux->rx_lock); + kcm_rcv_ready(kcm); +-- +2.43.0 + diff --git a/queue-5.15/net-dsa-mv88e6xxx-fix-out-of-bound-access.patch b/queue-5.15/net-dsa-mv88e6xxx-fix-out-of-bound-access.patch new file mode 100644 index 00000000000..9189c5bfbe5 --- /dev/null +++ b/queue-5.15/net-dsa-mv88e6xxx-fix-out-of-bound-access.patch @@ -0,0 +1,39 @@ +From a8c546f8380a6406eb97f169e2b506b031e373bd Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 19 Aug 2024 19:52:50 -0400 +Subject: net: dsa: mv88e6xxx: Fix out-of-bound access + +From: Joseph Huang + +[ Upstream commit 528876d867a23b5198022baf2e388052ca67c952 ] + +If an ATU violation was caused by a CPU Load operation, the SPID could +be larger than DSA_MAX_PORTS (the size of mv88e6xxx_chip.ports[] array). + +Fixes: 75c05a74e745 ("net: dsa: mv88e6xxx: Fix counting of ATU violations") +Signed-off-by: Joseph Huang +Reviewed-by: Andrew Lunn +Link: https://patch.msgid.link/20240819235251.1331763-1-Joseph.Huang@garmin.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/dsa/mv88e6xxx/global1_atu.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/drivers/net/dsa/mv88e6xxx/global1_atu.c b/drivers/net/dsa/mv88e6xxx/global1_atu.c +index 7c513a03789cf..17fd62616ce6d 100644 +--- a/drivers/net/dsa/mv88e6xxx/global1_atu.c ++++ b/drivers/net/dsa/mv88e6xxx/global1_atu.c +@@ -453,7 +453,8 @@ static irqreturn_t mv88e6xxx_g1_atu_prob_irq_thread_fn(int irq, void *dev_id) + trace_mv88e6xxx_atu_full_violation(chip->dev, spid, + entry.portvec, entry.mac, + fid); +- chip->ports[spid].atu_full_violation++; ++ if (spid < ARRAY_SIZE(chip->ports)) ++ chip->ports[spid].atu_full_violation++; + } + mv88e6xxx_reg_unlock(chip); + +-- +2.43.0 + diff --git a/queue-5.15/net-dsa-mv88e6xxx-read-fid-when-handling-atu-violati.patch b/queue-5.15/net-dsa-mv88e6xxx-read-fid-when-handling-atu-violati.patch new file mode 100644 index 00000000000..1c6f526fabd --- /dev/null +++ b/queue-5.15/net-dsa-mv88e6xxx-read-fid-when-handling-atu-violati.patch @@ -0,0 +1,175 @@ +From 468f4b15c33443fbca652358e6d1a0b521feca4b Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 9 Dec 2022 19:28:15 +0200 +Subject: net: dsa: mv88e6xxx: read FID when handling ATU violations + +From: Hans J. Schultz + +[ Upstream commit 4bf24ad09bc0b05e97fb48b962b2c9246fc76727 ] + +When an ATU violation occurs, the switch uses the ATU FID register to +report the FID of the MAC address that incurred the violation. It would +be good for the driver to know the FID value for purposes such as +logging and CPU-based authentication. + +Up until now, the driver has been calling the mv88e6xxx_g1_atu_op() +function to read ATU violations, but that doesn't do exactly what we +want, namely it calls mv88e6xxx_g1_atu_fid_write() with FID 0. +(side note, the documentation for the ATU Get/Clear Violation command +says that writes to the ATU FID register have no effect before the +operation starts, it's only that we disregard the value that this +register provides once the operation completes) + +So mv88e6xxx_g1_atu_fid_write() is not what we want, but rather +mv88e6xxx_g1_atu_fid_read(). However, the latter doesn't exist, we need +to write it. + +The remainder of mv88e6xxx_g1_atu_op() except for +mv88e6xxx_g1_atu_fid_write() is still needed, namely to send a +GET_CLR_VIOLATION command to the ATU. In principle we could have still +kept calling mv88e6xxx_g1_atu_op(), but the MDIO writes to the ATU FID +register are pointless, but in the interest of doing less CPU work per +interrupt, write a new function called mv88e6xxx_g1_read_atu_violation() +and call it. + +The FID will be the port default FID as set by mv88e6xxx_port_set_fid() +if the VID from the packet cannot be found in the VTU. Otherwise it is +the FID derived from the VTU entry associated with that VID. + +Signed-off-by: Hans J. Schultz +Signed-off-by: Vladimir Oltean +Reviewed-by: Florian Fainelli +Signed-off-by: Jakub Kicinski +Stable-dep-of: 528876d867a2 ("net: dsa: mv88e6xxx: Fix out-of-bound access") +Signed-off-by: Sasha Levin +--- + drivers/net/dsa/mv88e6xxx/global1_atu.c | 72 +++++++++++++++++++++---- + 1 file changed, 61 insertions(+), 11 deletions(-) + +diff --git a/drivers/net/dsa/mv88e6xxx/global1_atu.c b/drivers/net/dsa/mv88e6xxx/global1_atu.c +index 40bd67a5c8e93..4f689396fc402 100644 +--- a/drivers/net/dsa/mv88e6xxx/global1_atu.c ++++ b/drivers/net/dsa/mv88e6xxx/global1_atu.c +@@ -114,6 +114,19 @@ static int mv88e6xxx_g1_atu_op_wait(struct mv88e6xxx_chip *chip) + return mv88e6xxx_g1_wait_bit(chip, MV88E6XXX_G1_ATU_OP, bit, 0); + } + ++static int mv88e6xxx_g1_read_atu_violation(struct mv88e6xxx_chip *chip) ++{ ++ int err; ++ ++ err = mv88e6xxx_g1_write(chip, MV88E6XXX_G1_ATU_OP, ++ MV88E6XXX_G1_ATU_OP_BUSY | ++ MV88E6XXX_G1_ATU_OP_GET_CLR_VIOLATION); ++ if (err) ++ return err; ++ ++ return mv88e6xxx_g1_atu_op_wait(chip); ++} ++ + static int mv88e6xxx_g1_atu_op(struct mv88e6xxx_chip *chip, u16 fid, u16 op) + { + u16 val; +@@ -159,6 +172,41 @@ int mv88e6xxx_g1_atu_get_next(struct mv88e6xxx_chip *chip, u16 fid) + return mv88e6xxx_g1_atu_op(chip, fid, MV88E6XXX_G1_ATU_OP_GET_NEXT_DB); + } + ++static int mv88e6xxx_g1_atu_fid_read(struct mv88e6xxx_chip *chip, u16 *fid) ++{ ++ u16 val = 0, upper = 0, op = 0; ++ int err = -EOPNOTSUPP; ++ ++ if (mv88e6xxx_num_databases(chip) > 256) { ++ err = mv88e6xxx_g1_read(chip, MV88E6352_G1_ATU_FID, &val); ++ val &= 0xfff; ++ if (err) ++ return err; ++ } else { ++ err = mv88e6xxx_g1_read(chip, MV88E6XXX_G1_ATU_OP, &op); ++ if (err) ++ return err; ++ if (mv88e6xxx_num_databases(chip) > 64) { ++ /* ATU DBNum[7:4] are located in ATU Control 15:12 */ ++ err = mv88e6xxx_g1_read(chip, MV88E6XXX_G1_ATU_CTL, ++ &upper); ++ if (err) ++ return err; ++ ++ upper = (upper >> 8) & 0x00f0; ++ } else if (mv88e6xxx_num_databases(chip) > 16) { ++ /* ATU DBNum[5:4] are located in ATU Operation 9:8 */ ++ upper = (op >> 4) & 0x30; ++ } ++ ++ /* ATU DBNum[3:0] are located in ATU Operation 3:0 */ ++ val = (op & 0xf) | upper; ++ } ++ *fid = val; ++ ++ return err; ++} ++ + /* Offset 0x0C: ATU Data Register */ + + static int mv88e6xxx_g1_atu_data_read(struct mv88e6xxx_chip *chip, +@@ -353,14 +401,12 @@ static irqreturn_t mv88e6xxx_g1_atu_prob_irq_thread_fn(int irq, void *dev_id) + { + struct mv88e6xxx_chip *chip = dev_id; + struct mv88e6xxx_atu_entry entry; +- int spid; +- int err; +- u16 val; ++ int err, spid; ++ u16 val, fid; + + mv88e6xxx_reg_lock(chip); + +- err = mv88e6xxx_g1_atu_op(chip, 0, +- MV88E6XXX_G1_ATU_OP_GET_CLR_VIOLATION); ++ err = mv88e6xxx_g1_read_atu_violation(chip); + if (err) + goto out; + +@@ -368,6 +414,10 @@ static irqreturn_t mv88e6xxx_g1_atu_prob_irq_thread_fn(int irq, void *dev_id) + if (err) + goto out; + ++ err = mv88e6xxx_g1_atu_fid_read(chip, &fid); ++ if (err) ++ goto out; ++ + err = mv88e6xxx_g1_atu_data_read(chip, &entry); + if (err) + goto out; +@@ -386,22 +436,22 @@ static irqreturn_t mv88e6xxx_g1_atu_prob_irq_thread_fn(int irq, void *dev_id) + + if (val & MV88E6XXX_G1_ATU_OP_MEMBER_VIOLATION) { + dev_err_ratelimited(chip->dev, +- "ATU member violation for %pM portvec %x spid %d\n", +- entry.mac, entry.portvec, spid); ++ "ATU member violation for %pM fid %u portvec %x spid %d\n", ++ entry.mac, fid, entry.portvec, spid); + chip->ports[spid].atu_member_violation++; + } + + if (val & MV88E6XXX_G1_ATU_OP_MISS_VIOLATION) { + dev_err_ratelimited(chip->dev, +- "ATU miss violation for %pM portvec %x spid %d\n", +- entry.mac, entry.portvec, spid); ++ "ATU miss violation for %pM fid %u portvec %x spid %d\n", ++ entry.mac, fid, entry.portvec, spid); + chip->ports[spid].atu_miss_violation++; + } + + if (val & MV88E6XXX_G1_ATU_OP_FULL_VIOLATION) { + dev_err_ratelimited(chip->dev, +- "ATU full violation for %pM portvec %x spid %d\n", +- entry.mac, entry.portvec, spid); ++ "ATU full violation for %pM fid %u portvec %x spid %d\n", ++ entry.mac, fid, entry.portvec, spid); + chip->ports[spid].atu_full_violation++; + } + mv88e6xxx_reg_unlock(chip); +-- +2.43.0 + diff --git a/queue-5.15/net-dsa-mv88e6xxx-replace-atu-violation-prints-with-.patch b/queue-5.15/net-dsa-mv88e6xxx-replace-atu-violation-prints-with-.patch new file mode 100644 index 00000000000..88992a44a53 --- /dev/null +++ b/queue-5.15/net-dsa-mv88e6xxx-replace-atu-violation-prints-with-.patch @@ -0,0 +1,186 @@ +From e272d6bb7214e61309f4138d322cfb0894096083 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 9 Dec 2022 19:28:16 +0200 +Subject: net: dsa: mv88e6xxx: replace ATU violation prints with trace points + +From: Vladimir Oltean + +[ Upstream commit 8646384d80f3d3b4a66b3284dbbd8232d1b8799e ] + +In applications where the switch ports must perform 802.1X based +authentication and are therefore locked, ATU violation interrupts are +quite to be expected as part of normal operation. The problem is that +they currently spam the kernel log, even if rate limited. + +Create a series of trace points, all derived from the same event class, +which log these violations to the kernel's trace buffer, which is both +much faster and much easier to ignore than printing to a serial console. + +New usage model: + +$ trace-cmd list | grep mv88e6xxx +mv88e6xxx +mv88e6xxx:mv88e6xxx_atu_full_violation +mv88e6xxx:mv88e6xxx_atu_miss_violation +mv88e6xxx:mv88e6xxx_atu_member_violation +$ trace-cmd record -e mv88e6xxx sleep 10 + +Signed-off-by: Vladimir Oltean +Reviewed-by: Saeed Mahameed +Reviewed-by: Florian Fainelli +Signed-off-by: Jakub Kicinski +Stable-dep-of: 528876d867a2 ("net: dsa: mv88e6xxx: Fix out-of-bound access") +Signed-off-by: Sasha Levin +--- + drivers/net/dsa/mv88e6xxx/Makefile | 4 ++ + drivers/net/dsa/mv88e6xxx/global1_atu.c | 19 +++---- + drivers/net/dsa/mv88e6xxx/trace.c | 6 +++ + drivers/net/dsa/mv88e6xxx/trace.h | 66 +++++++++++++++++++++++++ + 4 files changed, 86 insertions(+), 9 deletions(-) + create mode 100644 drivers/net/dsa/mv88e6xxx/trace.c + create mode 100644 drivers/net/dsa/mv88e6xxx/trace.h + +diff --git a/drivers/net/dsa/mv88e6xxx/Makefile b/drivers/net/dsa/mv88e6xxx/Makefile +index c8eca2b6f9594..49bf358b9c4fa 100644 +--- a/drivers/net/dsa/mv88e6xxx/Makefile ++++ b/drivers/net/dsa/mv88e6xxx/Makefile +@@ -15,3 +15,7 @@ mv88e6xxx-objs += port_hidden.o + mv88e6xxx-$(CONFIG_NET_DSA_MV88E6XXX_PTP) += ptp.o + mv88e6xxx-objs += serdes.o + mv88e6xxx-objs += smi.o ++mv88e6xxx-objs += trace.o ++ ++# for tracing framework to find trace.h ++CFLAGS_trace.o := -I$(src) +diff --git a/drivers/net/dsa/mv88e6xxx/global1_atu.c b/drivers/net/dsa/mv88e6xxx/global1_atu.c +index 4f689396fc402..7c513a03789cf 100644 +--- a/drivers/net/dsa/mv88e6xxx/global1_atu.c ++++ b/drivers/net/dsa/mv88e6xxx/global1_atu.c +@@ -12,6 +12,7 @@ + + #include "chip.h" + #include "global1.h" ++#include "trace.h" + + /* Offset 0x01: ATU FID Register */ + +@@ -435,23 +436,23 @@ static irqreturn_t mv88e6xxx_g1_atu_prob_irq_thread_fn(int irq, void *dev_id) + } + + if (val & MV88E6XXX_G1_ATU_OP_MEMBER_VIOLATION) { +- dev_err_ratelimited(chip->dev, +- "ATU member violation for %pM fid %u portvec %x spid %d\n", +- entry.mac, fid, entry.portvec, spid); ++ trace_mv88e6xxx_atu_member_violation(chip->dev, spid, ++ entry.portvec, entry.mac, ++ fid); + chip->ports[spid].atu_member_violation++; + } + + if (val & MV88E6XXX_G1_ATU_OP_MISS_VIOLATION) { +- dev_err_ratelimited(chip->dev, +- "ATU miss violation for %pM fid %u portvec %x spid %d\n", +- entry.mac, fid, entry.portvec, spid); ++ trace_mv88e6xxx_atu_miss_violation(chip->dev, spid, ++ entry.portvec, entry.mac, ++ fid); + chip->ports[spid].atu_miss_violation++; + } + + if (val & MV88E6XXX_G1_ATU_OP_FULL_VIOLATION) { +- dev_err_ratelimited(chip->dev, +- "ATU full violation for %pM fid %u portvec %x spid %d\n", +- entry.mac, fid, entry.portvec, spid); ++ trace_mv88e6xxx_atu_full_violation(chip->dev, spid, ++ entry.portvec, entry.mac, ++ fid); + chip->ports[spid].atu_full_violation++; + } + mv88e6xxx_reg_unlock(chip); +diff --git a/drivers/net/dsa/mv88e6xxx/trace.c b/drivers/net/dsa/mv88e6xxx/trace.c +new file mode 100644 +index 0000000000000..7833cb50ca5d7 +--- /dev/null ++++ b/drivers/net/dsa/mv88e6xxx/trace.c +@@ -0,0 +1,6 @@ ++// SPDX-License-Identifier: GPL-2.0-or-later ++/* Copyright 2022 NXP ++ */ ++ ++#define CREATE_TRACE_POINTS ++#include "trace.h" +diff --git a/drivers/net/dsa/mv88e6xxx/trace.h b/drivers/net/dsa/mv88e6xxx/trace.h +new file mode 100644 +index 0000000000000..d9ab5c8dee55d +--- /dev/null ++++ b/drivers/net/dsa/mv88e6xxx/trace.h +@@ -0,0 +1,66 @@ ++/* SPDX-License-Identifier: GPL-2.0-or-later */ ++/* Copyright 2022 NXP ++ */ ++ ++#undef TRACE_SYSTEM ++#define TRACE_SYSTEM mv88e6xxx ++ ++#if !defined(_MV88E6XXX_TRACE_H) || defined(TRACE_HEADER_MULTI_READ) ++#define _MV88E6XXX_TRACE_H ++ ++#include ++#include ++#include ++ ++DECLARE_EVENT_CLASS(mv88e6xxx_atu_violation, ++ ++ TP_PROTO(const struct device *dev, int spid, u16 portvec, ++ const unsigned char *addr, u16 fid), ++ ++ TP_ARGS(dev, spid, portvec, addr, fid), ++ ++ TP_STRUCT__entry( ++ __string(name, dev_name(dev)) ++ __field(int, spid) ++ __field(u16, portvec) ++ __array(unsigned char, addr, ETH_ALEN) ++ __field(u16, fid) ++ ), ++ ++ TP_fast_assign( ++ __assign_str(name, dev_name(dev)); ++ __entry->spid = spid; ++ __entry->portvec = portvec; ++ memcpy(__entry->addr, addr, ETH_ALEN); ++ __entry->fid = fid; ++ ), ++ ++ TP_printk("dev %s spid %d portvec 0x%x addr %pM fid %u", ++ __get_str(name), __entry->spid, __entry->portvec, ++ __entry->addr, __entry->fid) ++); ++ ++DEFINE_EVENT(mv88e6xxx_atu_violation, mv88e6xxx_atu_member_violation, ++ TP_PROTO(const struct device *dev, int spid, u16 portvec, ++ const unsigned char *addr, u16 fid), ++ TP_ARGS(dev, spid, portvec, addr, fid)); ++ ++DEFINE_EVENT(mv88e6xxx_atu_violation, mv88e6xxx_atu_miss_violation, ++ TP_PROTO(const struct device *dev, int spid, u16 portvec, ++ const unsigned char *addr, u16 fid), ++ TP_ARGS(dev, spid, portvec, addr, fid)); ++ ++DEFINE_EVENT(mv88e6xxx_atu_violation, mv88e6xxx_atu_full_violation, ++ TP_PROTO(const struct device *dev, int spid, u16 portvec, ++ const unsigned char *addr, u16 fid), ++ TP_ARGS(dev, spid, portvec, addr, fid)); ++ ++#endif /* _MV88E6XXX_TRACE_H */ ++ ++/* We don't want to use include/trace/events */ ++#undef TRACE_INCLUDE_PATH ++#define TRACE_INCLUDE_PATH . ++#undef TRACE_INCLUDE_FILE ++#define TRACE_INCLUDE_FILE trace ++/* This part must be outside protection */ ++#include +-- +2.43.0 + diff --git a/queue-5.15/net-xilinx-axienet-always-disable-promiscuous-mode.patch b/queue-5.15/net-xilinx-axienet-always-disable-promiscuous-mode.patch new file mode 100644 index 00000000000..93b96bbee15 --- /dev/null +++ b/queue-5.15/net-xilinx-axienet-always-disable-promiscuous-mode.patch @@ -0,0 +1,42 @@ +From 1750fad1012e6e524fd0c4d372f5f6e95d5c7fa4 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 22 Aug 2024 11:40:55 -0400 +Subject: net: xilinx: axienet: Always disable promiscuous mode + +From: Sean Anderson + +[ Upstream commit 4ae738dfef2c0323752ab81786e2d298c9939321 ] + +If promiscuous mode is disabled when there are fewer than four multicast +addresses, then it will not be reflected in the hardware. Fix this by +always clearing the promiscuous mode flag even when we program multicast +addresses. + +Fixes: 8a3b7a252dca ("drivers/net/ethernet/xilinx: added Xilinx AXI Ethernet driver") +Signed-off-by: Sean Anderson +Reviewed-by: Simon Horman +Link: https://patch.msgid.link/20240822154059.1066595-2-sean.anderson@linux.dev +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/xilinx/xilinx_axienet_main.c | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/drivers/net/ethernet/xilinx/xilinx_axienet_main.c b/drivers/net/ethernet/xilinx/xilinx_axienet_main.c +index 63f33126d02fe..79f559178bb38 100644 +--- a/drivers/net/ethernet/xilinx/xilinx_axienet_main.c ++++ b/drivers/net/ethernet/xilinx/xilinx_axienet_main.c +@@ -427,6 +427,10 @@ static void axienet_set_multicast_list(struct net_device *ndev) + } else if (!netdev_mc_empty(ndev)) { + struct netdev_hw_addr *ha; + ++ reg = axienet_ior(lp, XAE_FMI_OFFSET); ++ reg &= ~XAE_FMI_PM_MASK; ++ axienet_iow(lp, XAE_FMI_OFFSET, reg); ++ + i = 0; + netdev_for_each_mc_addr(ha, ndev) { + if (i >= XAE_MULTICAST_CAM_TABLE_NUM) +-- +2.43.0 + diff --git a/queue-5.15/net-xilinx-axienet-fix-dangling-multicast-addresses.patch b/queue-5.15/net-xilinx-axienet-fix-dangling-multicast-addresses.patch new file mode 100644 index 00000000000..4c286f2462a --- /dev/null +++ b/queue-5.15/net-xilinx-axienet-fix-dangling-multicast-addresses.patch @@ -0,0 +1,94 @@ +From 4dfc9bd797dea5c903de44e115091b8cda93611b Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 22 Aug 2024 11:40:56 -0400 +Subject: net: xilinx: axienet: Fix dangling multicast addresses + +From: Sean Anderson + +[ Upstream commit 797a68c9de0f5a5447baf4bd3bb9c10a3993435b ] + +If a multicast address is removed but there are still some multicast +addresses, that address would remain programmed into the frame filter. +Fix this by explicitly setting the enable bit for each filter. + +Fixes: 8a3b7a252dca ("drivers/net/ethernet/xilinx: added Xilinx AXI Ethernet driver") +Signed-off-by: Sean Anderson +Reviewed-by: Simon Horman +Link: https://patch.msgid.link/20240822154059.1066595-3-sean.anderson@linux.dev +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/xilinx/xilinx_axienet.h | 1 + + .../net/ethernet/xilinx/xilinx_axienet_main.c | 21 ++++++++----------- + 2 files changed, 10 insertions(+), 12 deletions(-) + +diff --git a/drivers/net/ethernet/xilinx/xilinx_axienet.h b/drivers/net/ethernet/xilinx/xilinx_axienet.h +index cbf637078c38a..bdda836115095 100644 +--- a/drivers/net/ethernet/xilinx/xilinx_axienet.h ++++ b/drivers/net/ethernet/xilinx/xilinx_axienet.h +@@ -169,6 +169,7 @@ + #define XAE_UAW0_OFFSET 0x00000700 /* Unicast address word 0 */ + #define XAE_UAW1_OFFSET 0x00000704 /* Unicast address word 1 */ + #define XAE_FMI_OFFSET 0x00000708 /* Frame Filter Control */ ++#define XAE_FFE_OFFSET 0x0000070C /* Frame Filter Enable */ + #define XAE_AF0_OFFSET 0x00000710 /* Address Filter 0 */ + #define XAE_AF1_OFFSET 0x00000714 /* Address Filter 1 */ + +diff --git a/drivers/net/ethernet/xilinx/xilinx_axienet_main.c b/drivers/net/ethernet/xilinx/xilinx_axienet_main.c +index 79f559178bb38..0ca350faa4848 100644 +--- a/drivers/net/ethernet/xilinx/xilinx_axienet_main.c ++++ b/drivers/net/ethernet/xilinx/xilinx_axienet_main.c +@@ -409,7 +409,7 @@ static int netdev_set_mac_address(struct net_device *ndev, void *p) + */ + static void axienet_set_multicast_list(struct net_device *ndev) + { +- int i; ++ int i = 0; + u32 reg, af0reg, af1reg; + struct axienet_local *lp = netdev_priv(ndev); + +@@ -431,7 +431,6 @@ static void axienet_set_multicast_list(struct net_device *ndev) + reg &= ~XAE_FMI_PM_MASK; + axienet_iow(lp, XAE_FMI_OFFSET, reg); + +- i = 0; + netdev_for_each_mc_addr(ha, ndev) { + if (i >= XAE_MULTICAST_CAM_TABLE_NUM) + break; +@@ -450,6 +449,7 @@ static void axienet_set_multicast_list(struct net_device *ndev) + axienet_iow(lp, XAE_FMI_OFFSET, reg); + axienet_iow(lp, XAE_AF0_OFFSET, af0reg); + axienet_iow(lp, XAE_AF1_OFFSET, af1reg); ++ axienet_iow(lp, XAE_FFE_OFFSET, 1); + i++; + } + } else { +@@ -457,18 +457,15 @@ static void axienet_set_multicast_list(struct net_device *ndev) + reg &= ~XAE_FMI_PM_MASK; + + axienet_iow(lp, XAE_FMI_OFFSET, reg); +- +- for (i = 0; i < XAE_MULTICAST_CAM_TABLE_NUM; i++) { +- reg = axienet_ior(lp, XAE_FMI_OFFSET) & 0xFFFFFF00; +- reg |= i; +- +- axienet_iow(lp, XAE_FMI_OFFSET, reg); +- axienet_iow(lp, XAE_AF0_OFFSET, 0); +- axienet_iow(lp, XAE_AF1_OFFSET, 0); +- } +- + dev_info(&ndev->dev, "Promiscuous mode disabled.\n"); + } ++ ++ for (; i < XAE_MULTICAST_CAM_TABLE_NUM; i++) { ++ reg = axienet_ior(lp, XAE_FMI_OFFSET) & 0xFFFFFF00; ++ reg |= i; ++ axienet_iow(lp, XAE_FMI_OFFSET, reg); ++ axienet_iow(lp, XAE_FFE_OFFSET, 0); ++ } + } + + /** +-- +2.43.0 + diff --git a/queue-5.15/netem-fix-return-value-if-duplicate-enqueue-fails.patch b/queue-5.15/netem-fix-return-value-if-duplicate-enqueue-fails.patch new file mode 100644 index 00000000000..0aa5065aeef --- /dev/null +++ b/queue-5.15/netem-fix-return-value-if-duplicate-enqueue-fails.patch @@ -0,0 +1,138 @@ +From 3fcc323953552e78ca143f38f82da2b18f4b58da Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 19 Aug 2024 10:56:45 -0700 +Subject: netem: fix return value if duplicate enqueue fails + +From: Stephen Hemminger + +[ Upstream commit c07ff8592d57ed258afee5a5e04991a48dbaf382 ] + +There is a bug in netem_enqueue() introduced by +commit 5845f706388a ("net: netem: fix skb length BUG_ON in __skb_to_sgvec") +that can lead to a use-after-free. + +This commit made netem_enqueue() always return NET_XMIT_SUCCESS +when a packet is duplicated, which can cause the parent qdisc's q.qlen +to be mistakenly incremented. When this happens qlen_notify() may be +skipped on the parent during destruction, leaving a dangling pointer +for some classful qdiscs like DRR. + +There are two ways for the bug happen: + +- If the duplicated packet is dropped by rootq->enqueue() and then + the original packet is also dropped. +- If rootq->enqueue() sends the duplicated packet to a different qdisc + and the original packet is dropped. + +In both cases NET_XMIT_SUCCESS is returned even though no packets +are enqueued at the netem qdisc. + +The fix is to defer the enqueue of the duplicate packet until after +the original packet has been guaranteed to return NET_XMIT_SUCCESS. + +Fixes: 5845f706388a ("net: netem: fix skb length BUG_ON in __skb_to_sgvec") +Reported-by: Budimir Markovic +Signed-off-by: Stephen Hemminger +Reviewed-by: Simon Horman +Link: https://patch.msgid.link/20240819175753.5151-1-stephen@networkplumber.org +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + net/sched/sch_netem.c | 47 ++++++++++++++++++++++++++----------------- + 1 file changed, 29 insertions(+), 18 deletions(-) + +diff --git a/net/sched/sch_netem.c b/net/sched/sch_netem.c +index 08aaa6efc62c8..e0e16b0fdb179 100644 +--- a/net/sched/sch_netem.c ++++ b/net/sched/sch_netem.c +@@ -437,12 +437,10 @@ static int netem_enqueue(struct sk_buff *skb, struct Qdisc *sch, + struct netem_sched_data *q = qdisc_priv(sch); + /* We don't fill cb now as skb_unshare() may invalidate it */ + struct netem_skb_cb *cb; +- struct sk_buff *skb2; ++ struct sk_buff *skb2 = NULL; + struct sk_buff *segs = NULL; + unsigned int prev_len = qdisc_pkt_len(skb); + int count = 1; +- int rc = NET_XMIT_SUCCESS; +- int rc_drop = NET_XMIT_DROP; + + /* Do not fool qdisc_drop_all() */ + skb->prev = NULL; +@@ -471,19 +469,11 @@ static int netem_enqueue(struct sk_buff *skb, struct Qdisc *sch, + skb_orphan_partial(skb); + + /* +- * If we need to duplicate packet, then re-insert at top of the +- * qdisc tree, since parent queuer expects that only one +- * skb will be queued. ++ * If we need to duplicate packet, then clone it before ++ * original is modified. + */ +- if (count > 1 && (skb2 = skb_clone(skb, GFP_ATOMIC)) != NULL) { +- struct Qdisc *rootq = qdisc_root_bh(sch); +- u32 dupsave = q->duplicate; /* prevent duplicating a dup... */ +- +- q->duplicate = 0; +- rootq->enqueue(skb2, rootq, to_free); +- q->duplicate = dupsave; +- rc_drop = NET_XMIT_SUCCESS; +- } ++ if (count > 1) ++ skb2 = skb_clone(skb, GFP_ATOMIC); + + /* + * Randomized packet corruption. +@@ -495,7 +485,8 @@ static int netem_enqueue(struct sk_buff *skb, struct Qdisc *sch, + if (skb_is_gso(skb)) { + skb = netem_segment(skb, sch, to_free); + if (!skb) +- return rc_drop; ++ goto finish_segs; ++ + segs = skb->next; + skb_mark_not_on_list(skb); + qdisc_skb_cb(skb)->pkt_len = skb->len; +@@ -521,7 +512,24 @@ static int netem_enqueue(struct sk_buff *skb, struct Qdisc *sch, + /* re-link segs, so that qdisc_drop_all() frees them all */ + skb->next = segs; + qdisc_drop_all(skb, sch, to_free); +- return rc_drop; ++ if (skb2) ++ __qdisc_drop(skb2, to_free); ++ return NET_XMIT_DROP; ++ } ++ ++ /* ++ * If doing duplication then re-insert at top of the ++ * qdisc tree, since parent queuer expects that only one ++ * skb will be queued. ++ */ ++ if (skb2) { ++ struct Qdisc *rootq = qdisc_root_bh(sch); ++ u32 dupsave = q->duplicate; /* prevent duplicating a dup... */ ++ ++ q->duplicate = 0; ++ rootq->enqueue(skb2, rootq, to_free); ++ q->duplicate = dupsave; ++ skb2 = NULL; + } + + qdisc_qstats_backlog_inc(sch, skb); +@@ -592,9 +600,12 @@ static int netem_enqueue(struct sk_buff *skb, struct Qdisc *sch, + } + + finish_segs: ++ if (skb2) ++ __qdisc_drop(skb2, to_free); ++ + if (segs) { + unsigned int len, last_len; +- int nb; ++ int rc, nb; + + len = skb ? skb->len : 0; + nb = skb ? 1 : 0; +-- +2.43.0 + diff --git a/queue-5.15/netfilter-flowtable-validate-vlan-header.patch b/queue-5.15/netfilter-flowtable-validate-vlan-header.patch new file mode 100644 index 00000000000..87ef89b78cf --- /dev/null +++ b/queue-5.15/netfilter-flowtable-validate-vlan-header.patch @@ -0,0 +1,60 @@ +From e3aeb086f278e12ce93ad1a5cbaca4f71181cf15 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 13 Aug 2024 12:39:46 +0200 +Subject: netfilter: flowtable: validate vlan header + +From: Pablo Neira Ayuso + +[ Upstream commit 6ea14ccb60c8ab829349979b22b58a941ec4a3ee ] + +Ensure there is sufficient room to access the protocol field of the +VLAN header, validate it once before the flowtable lookup. + +===================================================== +BUG: KMSAN: uninit-value in nf_flow_offload_inet_hook+0x45a/0x5f0 net/netfilter/nf_flow_table_inet.c:32 + nf_flow_offload_inet_hook+0x45a/0x5f0 net/netfilter/nf_flow_table_inet.c:32 + nf_hook_entry_hookfn include/linux/netfilter.h:154 [inline] + nf_hook_slow+0xf4/0x400 net/netfilter/core.c:626 + nf_hook_ingress include/linux/netfilter_netdev.h:34 [inline] + nf_ingress net/core/dev.c:5440 [inline] + +Fixes: 4cd91f7c290f ("netfilter: flowtable: add vlan support") +Reported-by: syzbot+8407d9bb88cd4c6bf61a@syzkaller.appspotmail.com +Signed-off-by: Pablo Neira Ayuso +Signed-off-by: Sasha Levin +--- + net/netfilter/nf_flow_table_inet.c | 3 +++ + net/netfilter/nf_flow_table_ip.c | 3 +++ + 2 files changed, 6 insertions(+) + +diff --git a/net/netfilter/nf_flow_table_inet.c b/net/netfilter/nf_flow_table_inet.c +index 6783ea220f8fe..7f746acb4b027 100644 +--- a/net/netfilter/nf_flow_table_inet.c ++++ b/net/netfilter/nf_flow_table_inet.c +@@ -17,6 +17,9 @@ nf_flow_offload_inet_hook(void *priv, struct sk_buff *skb, + + switch (skb->protocol) { + case htons(ETH_P_8021Q): ++ if (!pskb_may_pull(skb, skb_mac_offset(skb) + sizeof(*veth))) ++ return NF_ACCEPT; ++ + veth = (struct vlan_ethhdr *)skb_mac_header(skb); + proto = veth->h_vlan_encapsulated_proto; + break; +diff --git a/net/netfilter/nf_flow_table_ip.c b/net/netfilter/nf_flow_table_ip.c +index f3227f9316969..8fa16be0def2a 100644 +--- a/net/netfilter/nf_flow_table_ip.c ++++ b/net/netfilter/nf_flow_table_ip.c +@@ -254,6 +254,9 @@ static bool nf_flow_skb_encap_protocol(struct sk_buff *skb, __be16 proto, + + switch (skb->protocol) { + case htons(ETH_P_8021Q): ++ if (!pskb_may_pull(skb, skb_mac_offset(skb) + sizeof(*veth))) ++ return false; ++ + veth = (struct vlan_ethhdr *)skb_mac_header(skb); + if (veth->h_vlan_encapsulated_proto == proto) { + *offset += VLAN_HLEN; +-- +2.43.0 + diff --git a/queue-5.15/netfilter-nft_counter-disable-bh-in-nft_counter_offl.patch b/queue-5.15/netfilter-nft_counter-disable-bh-in-nft_counter_offl.patch new file mode 100644 index 00000000000..585fc96235a --- /dev/null +++ b/queue-5.15/netfilter-nft_counter-disable-bh-in-nft_counter_offl.patch @@ -0,0 +1,55 @@ +From 003b800606c82615f4eecbf9ba9944e9073bcba9 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 20 Aug 2024 09:54:30 +0200 +Subject: netfilter: nft_counter: Disable BH in nft_counter_offload_stats(). + +From: Sebastian Andrzej Siewior + +[ Upstream commit 1eacdd71b3436b54d5fc8218c4bb0187d92a6892 ] + +The sequence counter nft_counter_seq is a per-CPU counter. There is no +lock associated with it. nft_counter_do_eval() is using the same counter +and disables BH which suggest that it can be invoked from a softirq. +This in turn means that nft_counter_offload_stats(), which disables only +preemption, can be interrupted by nft_counter_do_eval() leading to two +writer for one seqcount_t. +This can lead to loosing stats or reading statistics while they are +updated. + +Disable BH during stats update in nft_counter_offload_stats() to ensure +one writer at a time. + +Fixes: b72920f6e4a9d ("netfilter: nftables: counter hardware offload support") +Signed-off-by: Sebastian Andrzej Siewior +Reviewed-by: Florian Westphal +Signed-off-by: Pablo Neira Ayuso +Signed-off-by: Sasha Levin +--- + net/netfilter/nft_counter.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/net/netfilter/nft_counter.c b/net/netfilter/nft_counter.c +index 1b468a16b5237..f10d36c693b13 100644 +--- a/net/netfilter/nft_counter.c ++++ b/net/netfilter/nft_counter.c +@@ -264,7 +264,7 @@ static void nft_counter_offload_stats(struct nft_expr *expr, + struct nft_counter *this_cpu; + seqcount_t *myseq; + +- preempt_disable(); ++ local_bh_disable(); + this_cpu = this_cpu_ptr(priv->counter); + myseq = this_cpu_ptr(&nft_counter_seq); + +@@ -272,7 +272,7 @@ static void nft_counter_offload_stats(struct nft_expr *expr, + this_cpu->packets += stats->pkts; + this_cpu->bytes += stats->bytes; + write_seqcount_end(myseq); +- preempt_enable(); ++ local_bh_enable(); + } + + static struct nft_expr_type nft_counter_type; +-- +2.43.0 + diff --git a/queue-5.15/netfilter-nft_counter-synchronize-nft_counter_reset-.patch b/queue-5.15/netfilter-nft_counter-synchronize-nft_counter_reset-.patch new file mode 100644 index 00000000000..696fd253d40 --- /dev/null +++ b/queue-5.15/netfilter-nft_counter-synchronize-nft_counter_reset-.patch @@ -0,0 +1,50 @@ +From 7e577e6374b93a3098fc30d22d20116ecf24bee0 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 20 Aug 2024 09:54:31 +0200 +Subject: netfilter: nft_counter: Synchronize nft_counter_reset() against + reader. + +From: Sebastian Andrzej Siewior + +[ Upstream commit a0b39e2dc7017ac667b70bdeee5293e410fab2fb ] + +nft_counter_reset() resets the counter by subtracting the previously +retrieved value from the counter. This is a write operation on the +counter and as such it requires to be performed with a write sequence of +nft_counter_seq to serialize against its possible reader. + +Update the packets/ bytes within write-sequence of nft_counter_seq. + +Fixes: d84701ecbcd6a ("netfilter: nft_counter: rework atomic dump and reset") +Signed-off-by: Sebastian Andrzej Siewior +Reviewed-by: Florian Westphal +Signed-off-by: Pablo Neira Ayuso +Signed-off-by: Sasha Levin +--- + net/netfilter/nft_counter.c | 5 +++++ + 1 file changed, 5 insertions(+) + +diff --git a/net/netfilter/nft_counter.c b/net/netfilter/nft_counter.c +index f10d36c693b13..30b24d002c3d8 100644 +--- a/net/netfilter/nft_counter.c ++++ b/net/netfilter/nft_counter.c +@@ -106,11 +106,16 @@ static void nft_counter_reset(struct nft_counter_percpu_priv *priv, + struct nft_counter *total) + { + struct nft_counter *this_cpu; ++ seqcount_t *myseq; + + local_bh_disable(); + this_cpu = this_cpu_ptr(priv->counter); ++ myseq = this_cpu_ptr(&nft_counter_seq); ++ ++ write_seqcount_begin(myseq); + this_cpu->packets -= total->packets; + this_cpu->bytes -= total->bytes; ++ write_seqcount_end(myseq); + local_bh_enable(); + } + +-- +2.43.0 + diff --git a/queue-5.15/series b/queue-5.15/series index 7a6a1127006..de5f5830472 100644 --- a/queue-5.15/series +++ b/queue-5.15/series @@ -129,3 +129,26 @@ media-solo6x10-replace-max-a-min-b-c-by-clamp-b-a-c.patch dm-suspend-return-erestartsys-instead-of-eintr.patch net-mana-fix-doorbell-out-of-order-violation-and-avo.patch platform-surface-aggregator-fix-warning-when-control.patch +bluetooth-hci_core-fix-le-quote-calculation.patch +bluetooth-smp-fix-assumption-of-central-always-being.patch +tc-testing-don-t-access-non-existent-variable-on-exc.patch +kcm-serialise-kcm_sendmsg-for-the-same-socket.patch +netfilter-nft_counter-disable-bh-in-nft_counter_offl.patch +netfilter-nft_counter-synchronize-nft_counter_reset-.patch +ip6_tunnel-fix-broken-gro.patch +bonding-fix-bond_ipsec_offload_ok-return-type.patch +bonding-fix-null-pointer-deref-in-bond_ipsec_offload.patch +bonding-fix-xfrm-real_dev-null-pointer-dereference.patch +bonding-fix-xfrm-state-handling-when-clearing-active.patch +ice-fix-ice_last_offset-formula.patch +dpaa2-switch-fix-error-checking-in-dpaa2_switch_seed.patch +net-dsa-mv88e6xxx-read-fid-when-handling-atu-violati.patch +net-dsa-mv88e6xxx-replace-atu-violation-prints-with-.patch +net-dsa-mv88e6xxx-fix-out-of-bound-access.patch +netem-fix-return-value-if-duplicate-enqueue-fails.patch +ipv6-prevent-uaf-in-ip6_send_skb.patch +ipv6-fix-possible-uaf-in-ip6_finish_output2.patch +ipv6-prevent-possible-uaf-in-ip6_xmit.patch +netfilter-flowtable-validate-vlan-header.patch +net-xilinx-axienet-always-disable-promiscuous-mode.patch +net-xilinx-axienet-fix-dangling-multicast-addresses.patch diff --git a/queue-5.15/tc-testing-don-t-access-non-existent-variable-on-exc.patch b/queue-5.15/tc-testing-don-t-access-non-existent-variable-on-exc.patch new file mode 100644 index 00000000000..cd548134f76 --- /dev/null +++ b/queue-5.15/tc-testing-don-t-access-non-existent-variable-on-exc.patch @@ -0,0 +1,60 @@ +From a69418d2002a581a1245140fe0b87b59c58e193b Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 15 Aug 2024 16:37:13 +0100 +Subject: tc-testing: don't access non-existent variable on exception + +From: Simon Horman + +[ Upstream commit a0c9fe5eecc97680323ee83780ea3eaf440ba1b7 ] + +Since commit 255c1c7279ab ("tc-testing: Allow test cases to be skipped") +the variable test_ordinal doesn't exist in call_pre_case(). +So it should not be accessed when an exception occurs. + +This resolves the following splat: + + ... + During handling of the above exception, another exception occurred: + + Traceback (most recent call last): + File ".../tdc.py", line 1028, in + main() + File ".../tdc.py", line 1022, in main + set_operation_mode(pm, parser, args, remaining) + File ".../tdc.py", line 966, in set_operation_mode + catresults = test_runner_serial(pm, args, alltests) + File ".../tdc.py", line 642, in test_runner_serial + (index, tsr) = test_runner(pm, args, alltests) + File ".../tdc.py", line 536, in test_runner + res = run_one_test(pm, args, index, tidx) + File ".../tdc.py", line 419, in run_one_test + pm.call_pre_case(tidx) + File ".../tdc.py", line 146, in call_pre_case + print('test_ordinal is {}'.format(test_ordinal)) + NameError: name 'test_ordinal' is not defined + +Fixes: 255c1c7279ab ("tc-testing: Allow test cases to be skipped") +Signed-off-by: Simon Horman +Acked-by: Jamal Hadi Salim +Link: https://patch.msgid.link/20240815-tdc-test-ordinal-v1-1-0255c122a427@kernel.org +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + tools/testing/selftests/tc-testing/tdc.py | 1 - + 1 file changed, 1 deletion(-) + +diff --git a/tools/testing/selftests/tc-testing/tdc.py b/tools/testing/selftests/tc-testing/tdc.py +index a3e43189d9400..d6a9d97f73c24 100755 +--- a/tools/testing/selftests/tc-testing/tdc.py ++++ b/tools/testing/selftests/tc-testing/tdc.py +@@ -129,7 +129,6 @@ class PluginMgr: + except Exception as ee: + print('exception {} in call to pre_case for {} plugin'. + format(ee, pgn_inst.__class__)) +- print('test_ordinal is {}'.format(test_ordinal)) + print('testid is {}'.format(caseinfo['id'])) + raise + +-- +2.43.0 +