mirror of
https://github.com/torvalds/linux.git
synced 2026-06-02 19:43:40 +02:00
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:
commit
f3be0c984e
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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)) {
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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)) {
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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)) {
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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),
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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 \
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user