Quick follow up, nothing super urgent here. Main reason I'm sending

this out is because the IPsec and Bluetooth PRs did not make it
 yesterday. I don't want to have to send you all of this + whatever
 comes next week, for rc7. The fixes under "Previous releases -
 regressions" are for real user-reported regressions from v7.0.
 
 Previous releases - regressions:
 
  - Revert "ipv6: preserve insertion order for same-scope addresses"
 
  - xfrm: move policy_bydst RCU sync, a fix which added a sync RCU
    on netns exit got backported to stable and was causing serious
    accumulation of dying netns's for real workloads
 
  - pcs-mtk-lynxi: fix bpi-r3 serdes configuration
 
 Previous releases - always broken:
 
  - usual grab bag of race, locking and leak fixes for Bluetooth
 
  - handful of page handling fixes for IPsec
 
 Signed-off-by: Jakub Kicinski <kuba@kernel.org>
 -----BEGIN PGP SIGNATURE-----
 
 iQIzBAABCgAdFiEE6jPA+I1ugmIBA4hXMUZtbf5SIrsFAmoZ+wAACgkQMUZtbf5S
 IrtXJQ/9Gwf702wvkRaeLdqrwQ/qLsvDfx5s+3ALIE0Xsm4z9g7V0XKrZ0cfiI1h
 aWGX8HugXEQuy9QvlFt09tgGEd76159g2WdlsBbh1raqiJRUw4GJKXYvwCmBZxsT
 o8bwfVTQ8CVmUTCKhYrpzJKroT6jR8dKHIrkRn5ZyBOBPMOhK8rnDs1OdseW5haI
 b/EkQrzzvTxd7/dJETIJszMQh/nbS5XIlKpQ+f7dfzR1gtO2GOJ24VWqrimonRTo
 qvMwyt+ca2axv7Af796I8mz7X9rqLjWVWzY2uSpd7Y5zITyQwHNbeNvxzr2Ivi4g
 2BcIi+ZHeeRbgQ9EL+rzapTnnIPIw0APPXnp5NnnNDj0RRG3G6PzulW9SmcdsmGD
 o6E7axSZPQT/KnCw1/N7uMfB9cPzgb1i0h8rbE6tCvtkDtJwECtey7Dc7RU9zLqP
 e0jWDv99+MyEqGPcu2LAg2IWLfsuQiV4priy4mM1NgOTQVgS1yw7+x0GiTqiClJ0
 GcOCTOdvYKlmzhLzsLo4I+AcKZq2uJi8wNXMUEP5pmuYByVeF5j+MmoFpQspzx+L
 gdUh9IctAjd47oX/uNaRtocOriU+JJEApToE9WekMb0XYd5Qx1jnt3WqB9ZFuDf4
 smjUirtAWYcT3d4SXR4wGzB5WEa8TITH07A7sa8noozzNmQRu1E=
 =ttPc
 -----END PGP SIGNATURE-----

Merge tag 'net-7.1-rc6-2' of git://git.kernel.org/pub/scm/linux/kernel/git/netdev/net

Pull more networking fixes from Jakub Kicinski:
 "Quick follow up, nothing super urgent here. Main reason I'm sending
  this out is because the IPsec and Bluetooth PRs did not make it
  yesterday. I don't want to have to send you all of this + whatever
  comes next week, for rc7. The fixes under "Previous releases -
  regressions" are for real user-reported regressions from v7.0.

  Previous releases - regressions:

   - Revert "ipv6: preserve insertion order for same-scope addresses"

   - xfrm: move policy_bydst RCU sync, a fix which added a sync RCU on
     netns exit got backported to stable and was causing serious
     accumulation of dying netns's for real workloads

   - pcs-mtk-lynxi: fix bpi-r3 serdes configuration

  Previous releases - always broken:

   - usual grab bag of race, locking and leak fixes for Bluetooth

   - handful of page handling fixes for IPsec"

* tag 'net-7.1-rc6-2' of git://git.kernel.org/pub/scm/linux/kernel/git/netdev/net: (36 commits)
  wireguard: send: append trailer after expanding head
  Revert "ipv6: preserve insertion order for same-scope addresses"
  net: skbuff: fix pskb_carve leaking zcopy pages
  ipv6: fix possible infinite loop in fib6_select_path()
  ipv6: fix possible infinite loop in rt6_fill_node()
  bpf: sockmap: fix tail fragment offset in bpf_msg_push_data
  vsock/virtio: bind uarg before filling zerocopy skb
  Revert "esp: fix page frag reference leak on skb_to_sgvec failure"
  net: pcs: pcs-mtk-lynxi: fix bpi-r3 serdes configuration
  sctp: fix race between sctp_wait_for_connect and peeloff
  net: mana: Skip redundant detach on already-detached port
  net: mana: Add NULL guards in teardown path to prevent panic on attach failure
  Bluetooth: hci_sync: Reset device counters in hci_dev_close_sync()
  Bluetooth: hci_sync: Set HCI_CMD_DRAIN_WORKQUEUE during device close
  Bluetooth: hci_core: Rework hci_dev_do_reset() to use hci_sync functions
  Bluetooth: ISO: serialize iso_sock_clear_timer with socket lock
  Bluetooth: ISO: fix UAF in iso_recv_frame
  Bluetooth: L2CAP: Fix possible crash on l2cap_ecred_conn_rsp
  Bluetooth: l2cap: clear chan->ident on ECRED reconfiguration success
  Bluetooth: hci_qca: Use 100 ms SSR delay for rampatch and NVM loading
  ...
This commit is contained in:
Linus Torvalds 2026-05-29 15:46:40 -07:00
commit f3be0c984e
32 changed files with 273 additions and 154 deletions

View File

@ -3540,7 +3540,13 @@ static int btusb_setup_qca_load_rampatch(struct hci_dev *hdev,
"firmware rome 0x%x build 0x%x",
rver_rom, rver_patch, ver_rom, ver_patch);
if (rver_rom != ver_rom || rver_patch <= ver_patch) {
/* Allow rampatch when the patch version equals the firmware version.
* A firmware download may be aborted by a transient USB error (e.g.
* disconnect) after the controller updates version info but before
* completion.
* Allowing equal versions enables re-flashing during recovery.
*/
if (rver_rom != ver_rom || rver_patch < ver_patch) {
bt_dev_err(hdev, "rampatch file version did not match with firmware");
err = -EINVAL;
goto done;

View File

@ -1680,8 +1680,8 @@ static void qca_hw_error(struct hci_dev *hdev, u8 code)
mod_timer(&qca->tx_idle_timer, jiffies +
msecs_to_jiffies(qca->tx_idle_delay));
/* Controller reset completion time is 50ms */
msleep(50);
/* Wait for the controller to load the rampatch and NVM. */
msleep(100);
clear_bit(QCA_SSR_TRIGGERED, &qca->flags);
clear_bit(QCA_IBS_DISABLED, &qca->flags);

View File

@ -1727,6 +1727,9 @@ static void mana_fence_rqs(struct mana_port_context *apc)
struct mana_rxq *rxq;
int err;
if (!apc->rxqs)
return;
for (rxq_idx = 0; rxq_idx < apc->num_queues; rxq_idx++) {
rxq = apc->rxqs[rxq_idx];
err = mana_fence_rq(apc, rxq);
@ -2858,13 +2861,16 @@ static void mana_destroy_vport(struct mana_port_context *apc)
struct mana_rxq *rxq;
u32 rxq_idx;
for (rxq_idx = 0; rxq_idx < apc->num_queues; rxq_idx++) {
rxq = apc->rxqs[rxq_idx];
if (!rxq)
continue;
if (apc->rxqs) {
mana_destroy_rxq(apc, rxq, true);
apc->rxqs[rxq_idx] = NULL;
for (rxq_idx = 0; rxq_idx < apc->num_queues; rxq_idx++) {
rxq = apc->rxqs[rxq_idx];
if (!rxq)
continue;
mana_destroy_rxq(apc, rxq, true);
apc->rxqs[rxq_idx] = NULL;
}
}
mana_destroy_txq(apc);
@ -3269,7 +3275,8 @@ static int mana_dealloc_queues(struct net_device *ndev)
if (apc->port_is_up)
return -EINVAL;
mana_chn_setxdp(apc, NULL);
if (apc->rxqs)
mana_chn_setxdp(apc, NULL);
if (gd->gdma_context->is_pf && !apc->ac->bm_hostmode)
mana_pf_deregister_filter(apc);
@ -3287,33 +3294,38 @@ static int mana_dealloc_queues(struct net_device *ndev)
* number of queues.
*/
for (i = 0; i < apc->num_queues; i++) {
txq = &apc->tx_qp[i].txq;
tsleep = 1000;
while (atomic_read(&txq->pending_sends) > 0 &&
time_before(jiffies, timeout)) {
usleep_range(tsleep, tsleep + 1000);
tsleep <<= 1;
}
if (atomic_read(&txq->pending_sends)) {
err = pcie_flr(to_pci_dev(gd->gdma_context->dev));
if (err) {
netdev_err(ndev, "flr failed %d with %d pkts pending in txq %u\n",
err, atomic_read(&txq->pending_sends),
txq->gdma_txq_id);
if (apc->tx_qp) {
for (i = 0; i < apc->num_queues; i++) {
txq = &apc->tx_qp[i].txq;
tsleep = 1000;
while (atomic_read(&txq->pending_sends) > 0 &&
time_before(jiffies, timeout)) {
usleep_range(tsleep, tsleep + 1000);
tsleep <<= 1;
}
break;
if (atomic_read(&txq->pending_sends)) {
err =
pcie_flr(to_pci_dev(gd->gdma_context->dev));
if (err) {
netdev_err(ndev, "flr failed %d with %d pkts pending in txq %u\n",
err,
atomic_read(&txq->pending_sends),
txq->gdma_txq_id);
}
break;
}
}
for (i = 0; i < apc->num_queues; i++) {
txq = &apc->tx_qp[i].txq;
while ((skb = skb_dequeue(&txq->pending_skbs))) {
mana_unmap_skb(skb, apc);
dev_kfree_skb_any(skb);
}
atomic_set(&txq->pending_sends, 0);
}
}
for (i = 0; i < apc->num_queues; i++) {
txq = &apc->tx_qp[i].txq;
while ((skb = skb_dequeue(&txq->pending_skbs))) {
mana_unmap_skb(skb, apc);
dev_kfree_skb_any(skb);
}
atomic_set(&txq->pending_sends, 0);
}
/* We're 100% sure the queues can no longer be woken up, because
* we're sure now mana_poll_tx_cq() can't be running.
*/
@ -3338,6 +3350,12 @@ int mana_detach(struct net_device *ndev, bool from_close)
ASSERT_RTNL();
/* If already detached (indicates detach succeeded but attach failed
* previously). Now skip mana detach and just retry mana_attach.
*/
if (!from_close && !netif_device_present(ndev))
return 0;
apc->port_st_save = apc->port_is_up;
apc->port_is_up = false;

View File

@ -129,6 +129,9 @@ static int mtk_pcs_config_polarity(struct mtk_pcs_lynxi *mpcs,
unsigned int val = 0;
int ret;
if (!fwnode)
return 0;
if (fwnode_property_read_bool(fwnode, "mediatek,pnswap"))
default_pol = PHY_POL_INVERT;

View File

@ -177,16 +177,6 @@ static bool encrypt_packet(struct sk_buff *skb, struct noise_keypair *keypair)
trailer_len = padding_len + noise_encrypted_len(0);
plaintext_len = skb->len + padding_len;
/* Expand data section to have room for padding and auth tag. */
num_frags = skb_cow_data(skb, trailer_len, &trailer);
if (unlikely(num_frags < 0 || num_frags > ARRAY_SIZE(sg)))
return false;
/* Set the padding to zeros, and make sure it and the auth tag are part
* of the skb.
*/
memset(skb_tail_pointer(trailer), 0, padding_len);
/* Expand head section to have room for our header and the network
* stack's headers.
*/
@ -198,6 +188,16 @@ static bool encrypt_packet(struct sk_buff *skb, struct noise_keypair *keypair)
skb_checksum_help(skb)))
return false;
/* Expand data section to have room for padding and auth tag. */
num_frags = skb_cow_data(skb, trailer_len, &trailer);
if (unlikely(num_frags < 0 || num_frags > ARRAY_SIZE(sg)))
return false;
/* Set the padding to zeros, and make sure it and the auth tag are part
* of the skb.
*/
memset(skb_tail_pointer(trailer), 0, padding_len);
/* Only after checksumming can we safely add on the padding at the end
* and the header.
*/

View File

@ -715,6 +715,7 @@ struct xfrm_mgr {
const struct xfrm_migrate *m,
int num_bundles,
const struct xfrm_kmaddress *k,
struct net *net,
const struct xfrm_encap_tmpl *encap);
bool (*is_alive)(const struct km_event *c);
};
@ -1891,7 +1892,7 @@ int xfrm_sk_policy_insert(struct sock *sk, int dir, struct xfrm_policy *pol);
#ifdef CONFIG_XFRM_MIGRATE
int km_migrate(const struct xfrm_selector *sel, u8 dir, u8 type,
const struct xfrm_migrate *m, int num_bundles,
const struct xfrm_kmaddress *k,
const struct xfrm_kmaddress *k, struct net *net,
const struct xfrm_encap_tmpl *encap);
struct xfrm_state *xfrm_migrate_state_find(struct xfrm_migrate *m, struct net *net,
u32 if_id);

View File

@ -486,6 +486,8 @@ static int send_mcast_pkt(struct sk_buff *skb, struct net_device *netdev)
int ret;
local_skb = skb_clone(skb, GFP_ATOMIC);
if (!local_skb)
continue;
BT_DBG("xmit %s to %pMR type %u IP %pI6c chan %p",
netdev->name,

View File

@ -870,8 +870,10 @@ static int hci_le_big_terminate(struct hci_dev *hdev, struct hci_conn *conn)
d->big_sync_term = true;
}
if (!d->pa_sync_term && !d->big_sync_term)
if (!d->pa_sync_term && !d->big_sync_term) {
kfree(d);
return 0;
}
ret = hci_cmd_sync_queue(hdev, big_terminate_sync, d,
terminate_big_destroy);

View File

@ -539,46 +539,9 @@ static int hci_dev_do_reset(struct hci_dev *hdev)
hci_req_sync_lock(hdev);
/* Drop queues */
skb_queue_purge(&hdev->rx_q);
skb_queue_purge(&hdev->cmd_q);
/* Cancel these to avoid queueing non-chained pending work */
hci_dev_set_flag(hdev, HCI_CMD_DRAIN_WORKQUEUE);
/* Wait for
*
* if (!hci_dev_test_flag(hdev, HCI_CMD_DRAIN_WORKQUEUE))
* queue_delayed_work(&hdev->{cmd,ncmd}_timer)
*
* inside RCU section to see the flag or complete scheduling.
*/
synchronize_rcu();
/* Explicitly cancel works in case scheduled after setting the flag. */
cancel_delayed_work(&hdev->cmd_timer);
cancel_delayed_work(&hdev->ncmd_timer);
/* Avoid potential lockdep warnings from the *_flush() calls by
* ensuring the workqueue is empty up front.
*/
drain_workqueue(hdev->workqueue);
hci_dev_lock(hdev);
hci_inquiry_cache_flush(hdev);
hci_conn_hash_flush(hdev);
hci_dev_unlock(hdev);
if (hdev->flush)
hdev->flush(hdev);
hci_dev_clear_flag(hdev, HCI_CMD_DRAIN_WORKQUEUE);
atomic_set(&hdev->cmd_cnt, 1);
hdev->acl_cnt = 0;
hdev->sco_cnt = 0;
hdev->le_cnt = 0;
hdev->iso_cnt = 0;
ret = hci_reset_sync(hdev);
ret = hci_dev_close_sync(hdev);
if (!ret)
ret = hci_dev_open_sync(hdev);
hci_req_sync_unlock(hdev);
return ret;

View File

@ -5301,6 +5301,12 @@ int hci_dev_close_sync(struct hci_dev *hdev)
bt_dev_dbg(hdev, "");
/* Set HCI_DRAIN_WORKQUEUE flag to prevent queuing work during
* reset/close. See hci_cmd_work() and handle_cmd_cnt_and_timer().
*/
hci_dev_set_flag(hdev, HCI_CMD_DRAIN_WORKQUEUE);
synchronize_rcu();
if (hci_dev_test_flag(hdev, HCI_UNREGISTER)) {
disable_delayed_work(&hdev->power_off);
disable_delayed_work(&hdev->ncmd_timer);
@ -5324,6 +5330,7 @@ int hci_dev_close_sync(struct hci_dev *hdev)
if (!test_and_clear_bit(HCI_UP, &hdev->flags)) {
cancel_delayed_work_sync(&hdev->cmd_timer);
hci_dev_clear_flag(hdev, HCI_CMD_DRAIN_WORKQUEUE);
return err;
}
@ -5386,6 +5393,10 @@ int hci_dev_close_sync(struct hci_dev *hdev)
/* Reset device */
skb_queue_purge(&hdev->cmd_q);
atomic_set(&hdev->cmd_cnt, 1);
hdev->acl_cnt = 0;
hdev->sco_cnt = 0;
hdev->le_cnt = 0;
hdev->iso_cnt = 0;
if (hci_test_quirk(hdev, HCI_QUIRK_RESET_ON_CLOSE) &&
!auto_off && !hci_dev_test_flag(hdev, HCI_UNCONFIGURED)) {
set_bit(HCI_INIT, &hdev->flags);
@ -5423,6 +5434,7 @@ int hci_dev_close_sync(struct hci_dev *hdev)
/* Clear flags */
hdev->flags &= BIT(HCI_RAW);
hci_dev_clear_volatile_flags(hdev);
hci_dev_clear_flag(hdev, HCI_CMD_DRAIN_WORKQUEUE);
memset(hdev->eir, 0, sizeof(hdev->eir));
memset(hdev->dev_class, 0, sizeof(hdev->dev_class));
@ -6699,6 +6711,7 @@ int hci_le_create_cis_sync(struct hci_dev *hdev)
DEFINE_FLEX(struct hci_cp_le_create_cis, cmd, cis, num_cis, 0x1f);
size_t aux_num_cis = 0;
struct hci_conn *conn;
u16 timeout = 0;
u8 cig = BT_ISO_QOS_CIG_UNSET;
/* The spec allows only one pending LE Create CIS command at a time. If
@ -6769,6 +6782,7 @@ int hci_le_create_cis_sync(struct hci_dev *hdev)
set_bit(HCI_CONN_CREATE_CIS, &conn->flags);
cis->acl_handle = cpu_to_le16(conn->parent->handle);
cis->cis_handle = cpu_to_le16(conn->handle);
timeout = conn->conn_timeout;
aux_num_cis++;
if (aux_num_cis >= cmd->num_cis)
@ -6788,7 +6802,7 @@ int hci_le_create_cis_sync(struct hci_dev *hdev)
return __hci_cmd_sync_status_sk(hdev, HCI_OP_LE_CREATE_CIS,
struct_size(cmd, cis, cmd->num_cis),
cmd, HCI_EVT_LE_CIS_ESTABLISHED,
conn->conn_timeout, NULL);
timeout, NULL);
}
int hci_le_remove_cig_sync(struct hci_dev *hdev, u8 handle)

View File

@ -179,12 +179,21 @@ static void hidp_input_report(struct hidp_session *session, struct sk_buff *skb)
{
struct input_dev *dev = session->input;
unsigned char *keys = session->keys;
unsigned char *udata = skb->data + 1;
signed char *sdata = skb->data + 1;
int i, size = skb->len - 1;
unsigned char *udata;
signed char *sdata;
u8 *hdr;
int i;
switch (skb->data[0]) {
hdr = skb_pull_data(skb, 1);
if (!hdr)
return;
switch (*hdr) {
case 0x01: /* Keyboard report */
udata = skb_pull_data(skb, 8);
if (!udata)
break;
for (i = 0; i < 8; i++)
input_report_key(dev, hidp_keycode[i + 224], (udata[0] >> i) & 1);
@ -213,6 +222,10 @@ static void hidp_input_report(struct hidp_session *session, struct sk_buff *skb)
break;
case 0x02: /* Mouse report */
sdata = skb_pull_data(skb, 3);
if (!sdata)
break;
input_report_key(dev, BTN_LEFT, sdata[0] & 0x01);
input_report_key(dev, BTN_RIGHT, sdata[0] & 0x02);
input_report_key(dev, BTN_MIDDLE, sdata[0] & 0x04);
@ -222,7 +235,7 @@ static void hidp_input_report(struct hidp_session *session, struct sk_buff *skb)
input_report_rel(dev, REL_X, sdata[1]);
input_report_rel(dev, REL_Y, sdata[2]);
if (size > 3)
if (skb->len > 0)
input_report_rel(dev, REL_WHEEL, sdata[3]);
break;
}

View File

@ -564,7 +564,7 @@ static void iso_recv_frame(struct iso_conn *conn, struct sk_buff *skb)
struct sock *sk;
iso_conn_lock(conn);
sk = conn->sk;
sk = iso_sock_hold(conn);
iso_conn_unlock(conn);
if (!sk)
@ -573,11 +573,15 @@ static void iso_recv_frame(struct iso_conn *conn, struct sk_buff *skb)
BT_DBG("sk %p len %d", sk, skb->len);
if (sk->sk_state != BT_CONNECTED)
goto drop;
goto drop_put;
if (!sock_queue_rcv_skb(sk, skb))
if (!sock_queue_rcv_skb(sk, skb)) {
sock_put(sk);
return;
}
drop_put:
sock_put(sk);
drop:
kfree_skb(skb);
}
@ -860,8 +864,8 @@ static void __iso_sock_close(struct sock *sk)
/* Must be called on unlocked socket. */
static void iso_sock_close(struct sock *sk)
{
iso_sock_clear_timer(sk);
lock_sock(sk);
iso_sock_clear_timer(sk);
__iso_sock_close(sk);
release_sock(sk);
iso_sock_kill(sk);

View File

@ -411,8 +411,10 @@ static void l2cap_chan_timeout(struct work_struct *work)
BT_DBG("chan %p state %s", chan, state_to_string(chan->state));
if (!conn)
if (!conn) {
l2cap_chan_put(chan);
return;
}
mutex_lock(&conn->lock);
/* __set_chan_timer() calls l2cap_chan_hold(chan) while scheduling
@ -5260,6 +5262,7 @@ static inline int l2cap_ecred_conn_rsp(struct l2cap_conn *conn,
cmd_len -= sizeof(*rsp);
list_for_each_entry_safe(chan, tmp, &conn->chan_l, list) {
struct l2cap_chan *orig;
u16 dcid;
if (chan->ident != cmd->ident ||
@ -5281,8 +5284,10 @@ static inline int l2cap_ecred_conn_rsp(struct l2cap_conn *conn,
BT_DBG("dcid[%d] 0x%4.4x", i, dcid);
orig = __l2cap_get_chan_by_dcid(conn, dcid);
/* Check if dcid is already in use */
if (dcid && __l2cap_get_chan_by_dcid(conn, dcid)) {
if (dcid && orig) {
/* If a device receives a
* L2CAP_CREDIT_BASED_CONNECTION_RSP packet with an
* already-assigned Destination CID, then both the
@ -5291,10 +5296,24 @@ static inline int l2cap_ecred_conn_rsp(struct l2cap_conn *conn,
*/
l2cap_chan_del(chan, ECONNREFUSED);
l2cap_chan_unlock(chan);
chan = __l2cap_get_chan_by_dcid(conn, dcid);
l2cap_chan_lock(chan);
l2cap_chan_del(chan, ECONNRESET);
l2cap_chan_unlock(chan);
/* Check that the dcid channel mode is
* L2CAP_MODE_EXT_FLOWCTL since this procedure is only
* valid for that mode and shouldn't disconnect a dcid
* in other modes.
*/
if (orig->mode == L2CAP_MODE_EXT_FLOWCTL) {
l2cap_chan_lock(orig);
/* Disconnect the original channel as it may be
* considered connected since dcid has already
* been assigned; don't call l2cap_chan_close
* directly since that could lead to
* l2cap_chan_del and then removing the channel
* from the list while we're iterating over it.
*/
__set_chan_timer(orig, 0);
l2cap_chan_unlock(orig);
}
continue;
}
@ -5458,14 +5477,20 @@ static inline int l2cap_ecred_reconf_rsp(struct l2cap_conn *conn,
BT_DBG("result 0x%4.4x", result);
if (!result)
if (!result) {
list_for_each_entry(chan, &conn->chan_l, list) {
if (chan->ident == cmd->ident)
chan->ident = 0;
}
return 0;
}
list_for_each_entry_safe(chan, tmp, &conn->chan_l, list) {
if (chan->ident != cmd->ident)
continue;
l2cap_chan_hold(chan);
if (!l2cap_chan_hold_unless_zero(chan))
continue;
l2cap_chan_lock(chan);
l2cap_chan_del(chan, ECONNRESET);

View File

@ -1499,6 +1499,10 @@ static void l2cap_sock_cleanup_listen(struct sock *parent)
* pin it (hold_unless_zero() additionally skips a chan already past
* its last reference). We then drop the sk lock before taking
* chan->lock, so sk and chan locks are never held together.
*
* Since we cannot call l2cap_chan_close() without conn->lock,
* schedule l2cap_chan_timeout to close the channel; it already
* acquires conn->lock -> chan->lock in the correct order.
*/
while ((sk = bt_accept_dequeue(parent, NULL))) {
struct l2cap_chan *chan;
@ -1516,14 +1520,12 @@ static void l2cap_sock_cleanup_listen(struct sock *parent)
state_to_string(chan->state));
l2cap_chan_lock(chan);
__clear_chan_timer(chan);
l2cap_chan_close(chan, ECONNRESET);
/* l2cap_conn_del() may already have killed this socket
* (it sets SOCK_DEAD); skip the duplicate to avoid a
* double sock_put()/l2cap_chan_put().
/* Since we cannot call l2cap_chan_close() without
* conn->lock, schedule its timer to trigger the close
* and cleanup of this channel.
*/
if (!sock_flag(sk, SOCK_DEAD))
l2cap_sock_kill(sk);
if (chan->conn)
__set_chan_timer(chan, 0);
l2cap_chan_unlock(chan);
l2cap_chan_put(chan);

View File

@ -2869,7 +2869,7 @@ BPF_CALL_4(bpf_msg_push_data, struct sk_msg *, msg, u32, start,
psge->length = start - offset;
rsge.length -= psge->length;
rsge.offset += start;
rsge.offset += start - offset;
sk_msg_iter_var_next(i);
sg_unmark_end(psge);

View File

@ -6823,6 +6823,11 @@ static int pskb_carve_inside_header(struct sk_buff *skb, const u32 off,
skb_copy_from_linear_data_offset(skb, off, data, new_hlen);
skb->len -= off;
/* Remove SKBFL_MANAGED_FRAG_REFS instead of trying to honour it
* while refcounting frags below.
*/
skb_zcopy_downgrade_managed(skb);
memcpy((struct skb_shared_info *)(data + size),
skb_shinfo(skb),
offsetof(struct skb_shared_info,
@ -6936,6 +6941,11 @@ static int pskb_carve_inside_nonlinear(struct sk_buff *skb, const u32 off,
return -ENOMEM;
size = SKB_WITH_OVERHEAD(size);
/* Remove SKBFL_MANAGED_FRAG_REFS instead of trying to honour it
* while refcounting frags below.
*/
skb_zcopy_downgrade_managed(skb);
memcpy((struct skb_shared_info *)(data + size),
skb_shinfo(skb), offsetof(struct skb_shared_info, frags[0]));
if (skb_orphan_frags(skb, gfp_mask)) {

View File

@ -143,7 +143,7 @@ static void ah_output_done(void *data, int err)
}
kfree(AH_SKB_CB(skb)->tmp);
xfrm_output_resume(skb->sk, skb, err);
xfrm_output_resume(skb_to_full_sk(skb), skb, err);
}
static int ah_output(struct xfrm_state *x, struct sk_buff *skb)

View File

@ -419,8 +419,8 @@ int esp_output_head(struct xfrm_state *x, struct sk_buff *skb, struct esp_info *
return err;
}
if (ALIGN(tailen, L1_CACHE_BYTES) > PAGE_SIZE ||
ALIGN(skb->data_len, L1_CACHE_BYTES) > PAGE_SIZE)
if (ALIGN(skb->data_len + tailen, L1_CACHE_BYTES) >
PAGE_SIZE)
goto cow;
if (!skb_cloned(skb)) {

View File

@ -1013,7 +1013,7 @@ ipv6_link_dev_addr(struct inet6_dev *idev, struct inet6_ifaddr *ifp)
list_for_each(p, &idev->addr_list) {
struct inet6_ifaddr *ifa
= list_entry(p, struct inet6_ifaddr, if_list);
if (ifp_scope > ipv6_addr_src_scope(&ifa->addr))
if (ifp_scope >= ipv6_addr_src_scope(&ifa->addr))
break;
}

View File

@ -337,7 +337,7 @@ static void ah6_output_done(void *data, int err)
ah6_restore_hdrs(top_iph, iph_ext, extlen);
kfree(AH_SKB_CB(skb)->tmp);
xfrm_output_resume(skb->sk, skb, err);
xfrm_output_resume(skb_to_full_sk(skb), skb, err);
}
static int ah6_output(struct xfrm_state *x, struct sk_buff *skb)

View File

@ -448,8 +448,8 @@ int esp6_output_head(struct xfrm_state *x, struct sk_buff *skb, struct esp_info
return err;
}
if (ALIGN(tailen, L1_CACHE_BYTES) > PAGE_SIZE ||
ALIGN(skb->data_len, L1_CACHE_BYTES) > PAGE_SIZE)
if (ALIGN(skb->data_len + tailen, L1_CACHE_BYTES) >
PAGE_SIZE)
goto cow;
if (!skb_cloned(skb)) {

View File

@ -481,6 +481,9 @@ void fib6_select_path(const struct net *net, struct fib6_result *res,
const struct fib6_nh *nh = sibling->fib6_nh;
int nh_upper_bound;
if (!READ_ONCE(first->fib6_nsiblings))
break;
nh_upper_bound = atomic_read(&nh->fib_nh_upper_bound);
if (hash > nh_upper_bound)
continue;
@ -5902,6 +5905,8 @@ static int rt6_fill_node(struct net *net, struct sk_buff *skb,
goto nla_put_failure;
}
if (!READ_ONCE(rt->fib6_nsiblings))
break;
}
rcu_read_unlock();

View File

@ -3564,7 +3564,7 @@ static int set_ipsecrequest(struct sk_buff *skb,
#ifdef CONFIG_NET_KEY_MIGRATE
static int pfkey_send_migrate(const struct xfrm_selector *sel, u8 dir, u8 type,
const struct xfrm_migrate *m, int num_bundles,
const struct xfrm_kmaddress *k,
const struct xfrm_kmaddress *k, struct net *net,
const struct xfrm_encap_tmpl *encap)
{
int i;
@ -3669,7 +3669,7 @@ static int pfkey_send_migrate(const struct xfrm_selector *sel, u8 dir, u8 type,
}
/* broadcast migrate message to sockets */
pfkey_broadcast(skb, GFP_ATOMIC, BROADCAST_ALL, NULL, &init_net);
pfkey_broadcast(skb, GFP_ATOMIC, BROADCAST_ALL, NULL, net);
return 0;
@ -3680,7 +3680,7 @@ static int pfkey_send_migrate(const struct xfrm_selector *sel, u8 dir, u8 type,
#else
static int pfkey_send_migrate(const struct xfrm_selector *sel, u8 dir, u8 type,
const struct xfrm_migrate *m, int num_bundles,
const struct xfrm_kmaddress *k,
const struct xfrm_kmaddress *k, struct net *net,
const struct xfrm_encap_tmpl *encap)
{
return -ENOPROTOOPT;

View File

@ -9403,6 +9403,8 @@ static int sctp_wait_for_connect(struct sctp_association *asoc, long *timeo_p)
release_sock(sk);
current_timeo = schedule_timeout(current_timeo);
lock_sock(sk);
if (sk != asoc->base.sk)
goto do_error;
*timeo_p = current_timeo;
}

View File

@ -205,6 +205,7 @@ static u16 virtio_transport_get_type(struct sock *sk)
static struct sk_buff *virtio_transport_alloc_skb(struct virtio_vsock_pkt_info *info,
size_t payload_len,
bool zcopy,
struct ubuf_info *uarg,
u32 src_cid,
u32 src_port,
u32 dst_cid,
@ -245,6 +246,12 @@ static struct sk_buff *virtio_transport_alloc_skb(struct virtio_vsock_pkt_info *
if (info->msg && payload_len > 0) {
int err;
/* Bind the zerocopy lifetime before filling frags so error
* rollback frees managed fixed-buffer pages through
* the uarg-aware path.
*/
skb_zcopy_set(skb, uarg, NULL);
err = virtio_transport_fill_skb(skb, info, payload_len, zcopy);
if (err)
goto out;
@ -364,6 +371,7 @@ static int virtio_transport_send_pkt_info(struct vsock_sock *vsk,
skb_len = min(max_skb_len, rest_len);
skb = virtio_transport_alloc_skb(info, skb_len, can_zcopy,
uarg,
src_cid, src_port,
dst_cid, dst_port);
if (!skb) {
@ -371,8 +379,6 @@ static int virtio_transport_send_pkt_info(struct vsock_sock *vsk,
break;
}
skb_zcopy_set(skb, uarg, NULL);
virtio_transport_inc_tx_pkt(vvs, skb);
ret = t_ops->send_pkt(skb, info->net);
@ -1183,7 +1189,7 @@ static int virtio_transport_reset_no_sock(const struct virtio_transport *t,
if (!t)
return -ENOTCONN;
reply = virtio_transport_alloc_skb(&info, 0, false,
reply = virtio_transport_alloc_skb(&info, 0, false, NULL,
le64_to_cpu(hdr->dst_cid),
le32_to_cpu(hdr->dst_port),
le64_to_cpu(hdr->src_cid),

View File

@ -797,9 +797,12 @@ static void xfrm_trans_reinject(struct work_struct *work)
spin_unlock_bh(&trans->queue_lock);
local_bh_disable();
while ((skb = __skb_dequeue(&queue)))
XFRM_TRANS_SKB_CB(skb)->finish(XFRM_TRANS_SKB_CB(skb)->net,
NULL, skb);
while ((skb = __skb_dequeue(&queue))) {
struct net *net = XFRM_TRANS_SKB_CB(skb)->net;
XFRM_TRANS_SKB_CB(skb)->finish(net, NULL, skb);
put_net(net);
}
local_bh_enable();
}
@ -808,6 +811,7 @@ int xfrm_trans_queue_net(struct net *net, struct sk_buff *skb,
struct sk_buff *))
{
struct xfrm_trans_tasklet *trans;
struct net *hold_net;
trans = this_cpu_ptr(&xfrm_trans_tasklet);
@ -816,8 +820,12 @@ int xfrm_trans_queue_net(struct net *net, struct sk_buff *skb,
BUILD_BUG_ON(sizeof(struct xfrm_trans_cb) > sizeof(skb->cb));
hold_net = maybe_get_net(net);
if (!hold_net)
return -ENODEV;
XFRM_TRANS_SKB_CB(skb)->finish = finish;
XFRM_TRANS_SKB_CB(skb)->net = net;
XFRM_TRANS_SKB_CB(skb)->net = hold_net;
spin_lock_bh(&trans->queue_lock);
__skb_queue_tail(&trans->queue, skb);
spin_unlock_bh(&trans->queue_lock);

View File

@ -51,11 +51,15 @@ static int ipcomp_post_acomp(struct sk_buff *skb, int err, int hlen)
struct scatterlist *dsg;
int len, dlen;
if (unlikely(err))
goto out_free_req;
if (unlikely(!req))
return err;
extra = acomp_request_extra(req);
dsg = extra->sg;
if (unlikely(err))
goto out_free_req;
dlen = req->dlen;
pskb_trim_unique(skb, 0);
@ -84,10 +88,10 @@ static int ipcomp_post_acomp(struct sk_buff *skb, int err, int hlen)
skb_shinfo(skb)->nr_frags++;
} while ((dlen -= len));
for (; dsg; dsg = sg_next(dsg))
out_free_req:
for (; dsg && sg_page(dsg); dsg = sg_next(dsg))
__free_page(sg_page(dsg));
out_free_req:
acomp_request_free(req);
return err;
}

View File

@ -2650,7 +2650,8 @@ static void __iptfs_init_state(struct xfrm_state *x,
x->props.enc_hdr_len = sizeof(struct ip_iptfs_hdr);
/* Always keep a module reference when x->mode_data is set */
__module_get(x->mode_cbs->owner);
if (x->mode_data != xtfs)
__module_get(x->mode_cbs->owner);
x->mode_data = xtfs;
xtfs->x = x;
@ -2658,22 +2659,39 @@ static void __iptfs_init_state(struct xfrm_state *x,
static int iptfs_clone_state(struct xfrm_state *x, struct xfrm_state *orig)
{
struct skb_wseq *w_saved = NULL;
struct xfrm_iptfs_data *xtfs;
xtfs = kmemdup(orig->mode_data, sizeof(*xtfs), GFP_KERNEL);
if (!xtfs)
return -ENOMEM;
xtfs->ra_newskb = NULL;
if (xtfs->cfg.reorder_win_size) {
xtfs->w_saved = kzalloc_objs(*xtfs->w_saved,
xtfs->cfg.reorder_win_size);
if (!xtfs->w_saved) {
w_saved = kzalloc_objs(*w_saved, xtfs->cfg.reorder_win_size);
if (!w_saved) {
kfree_sensitive(xtfs);
return -ENOMEM;
}
}
xtfs->w_saved = w_saved;
__skb_queue_head_init(&xtfs->queue);
xtfs->queue_size = 0;
hrtimer_setup(&xtfs->iptfs_timer, iptfs_delay_timer, CLOCK_MONOTONIC,
IPTFS_HRTIMER_MODE);
spin_lock_init(&xtfs->drop_lock);
hrtimer_setup(&xtfs->drop_timer, iptfs_drop_timer, CLOCK_MONOTONIC,
IPTFS_HRTIMER_MODE);
xtfs->w_seq_set = false;
xtfs->w_wantseq = 0;
xtfs->w_savedlen = 0;
xtfs->ra_newskb = NULL;
xtfs->ra_wantseq = 0;
xtfs->ra_runtlen = 0;
__module_get(x->mode_cbs->owner);
x->mode_data = xtfs;
xtfs->x = x;

View File

@ -4276,21 +4276,21 @@ static int __net_init xfrm_policy_init(struct net *net)
return -ENOMEM;
}
static void xfrm_policy_fini(struct net *net)
static void __net_exit xfrm_net_pre_exit(struct net *net)
{
struct xfrm_pol_inexact_bin *b, *t;
unsigned int sz;
int dir;
disable_work_sync(&net->xfrm.policy_hthresh.work);
flush_work(&net->xfrm.policy_hash_work);
#ifdef CONFIG_XFRM_SUB_POLICY
xfrm_policy_flush(net, XFRM_POLICY_TYPE_SUB, false);
#endif
xfrm_policy_flush(net, XFRM_POLICY_TYPE_MAIN, false);
}
synchronize_rcu();
static void xfrm_policy_fini(struct net *net)
{
struct xfrm_pol_inexact_bin *b, *t;
unsigned int sz;
int dir;
WARN_ON(!list_empty(&net->xfrm.policy_all));
@ -4368,6 +4368,7 @@ static void __net_exit xfrm_net_exit(struct net *net)
static struct pernet_operations __net_initdata xfrm_net_ops = {
.init = xfrm_net_init,
.pre_exit = xfrm_net_pre_exit,
.exit = xfrm_net_exit,
};
@ -4703,7 +4704,7 @@ int xfrm_migrate(const struct xfrm_selector *sel, u8 dir, u8 type,
}
/* Stage 5 - announce */
km_migrate(sel, dir, type, m, num_migrate, k, encap);
km_migrate(sel, dir, type, m, num_migrate, k, net, encap);
xfrm_pol_put(pol);

View File

@ -2837,7 +2837,7 @@ EXPORT_SYMBOL(km_policy_expired);
#ifdef CONFIG_XFRM_MIGRATE
int km_migrate(const struct xfrm_selector *sel, u8 dir, u8 type,
const struct xfrm_migrate *m, int num_migrate,
const struct xfrm_kmaddress *k,
const struct xfrm_kmaddress *k, struct net *net,
const struct xfrm_encap_tmpl *encap)
{
int err = -EINVAL;
@ -2848,7 +2848,7 @@ int km_migrate(const struct xfrm_selector *sel, u8 dir, u8 type,
list_for_each_entry_rcu(km, &xfrm_km_list, list) {
if (km->migrate) {
ret = km->migrate(sel, dir, type, m, num_migrate, k,
encap);
net, encap);
if (!ret)
err = ret;
}
@ -3114,10 +3114,14 @@ u32 xfrm_state_mtu(struct xfrm_state *x, int mtu)
const struct xfrm_type *type = READ_ONCE(x->type);
struct crypto_aead *aead;
u32 blksize, net_adj = 0;
u32 overhead, payload_mtu;
if (x->km.state != XFRM_STATE_VALID ||
!type || type->proto != IPPROTO_ESP)
!type || type->proto != IPPROTO_ESP) {
if (mtu <= x->props.header_len)
return 1;
return mtu - x->props.header_len;
}
aead = x->data;
blksize = ALIGN(crypto_aead_blocksize(aead), 4);
@ -3140,8 +3144,17 @@ u32 xfrm_state_mtu(struct xfrm_state *x, int mtu)
break;
}
return ((mtu - x->props.header_len - crypto_aead_authsize(aead) -
net_adj) & ~(blksize - 1)) + net_adj - 2;
overhead = x->props.header_len + crypto_aead_authsize(aead) + net_adj;
if (mtu <= overhead)
return 1;
payload_mtu = mtu - overhead;
payload_mtu &= ~(blksize - 1);
if (payload_mtu <= 2)
return 1;
return payload_mtu + net_adj - 2;
}
EXPORT_SYMBOL_GPL(xfrm_state_mtu);

View File

@ -3271,10 +3271,9 @@ static int build_migrate(struct sk_buff *skb, const struct xfrm_migrate *m,
static int xfrm_send_migrate(const struct xfrm_selector *sel, u8 dir, u8 type,
const struct xfrm_migrate *m, int num_migrate,
const struct xfrm_kmaddress *k,
const struct xfrm_kmaddress *k, struct net *net,
const struct xfrm_encap_tmpl *encap)
{
struct net *net = &init_net;
struct sk_buff *skb;
int err;
@ -3292,7 +3291,7 @@ static int xfrm_send_migrate(const struct xfrm_selector *sel, u8 dir, u8 type,
#else
static int xfrm_send_migrate(const struct xfrm_selector *sel, u8 dir, u8 type,
const struct xfrm_migrate *m, int num_migrate,
const struct xfrm_kmaddress *k,
const struct xfrm_kmaddress *k, struct net *net,
const struct xfrm_encap_tmpl *encap)
{
return -ENOPROTOOPT;

View File

@ -273,8 +273,8 @@ setup()
ip -netns $ioam_node_beta link set ioam-veth-betaR name veth1 &>/dev/null
ip -netns $ioam_node_gamma link set ioam-veth-gamma name veth0 &>/dev/null
ip -netns $ioam_node_alpha addr add 2001:db8:1::2/64 dev veth0 &>/dev/null
ip -netns $ioam_node_alpha addr add 2001:db8:1::50/64 dev veth0 &>/dev/null
ip -netns $ioam_node_alpha addr add 2001:db8:1::2/64 dev veth0 &>/dev/null
ip -netns $ioam_node_alpha link set veth0 up &>/dev/null
ip -netns $ioam_node_alpha link set lo up &>/dev/null
ip -netns $ioam_node_alpha route add 2001:db8:2::/64 \