Including fixes from bpf, can and netfilter.

Current release - regressions:
 
  - phy: fix null-deref in phy_attach_direct
 
  - mac802154: fix possible double free upon parsing error
 
 Previous releases - regressions:
 
  - bpf: preserve reg parent/live fields when copying range info,
    prevent mis-verification of programs as safe
 
  - ip6: fix GRE tunnels not generating IPv6 link local addresses
 
  - phy: dp83822: fix null-deref on DP83825/DP83826 devices
 
  - sctp: do not check hb_timer.expires when resetting hb_timer
 
  - eth: mtk_sock: fix SGMII configuration after phylink conversion
 
 Previous releases - always broken:
 
  - eth: xdp: execute xdp_do_flush() before napi_complete_done()
 
  - skb: do not mix page pool and page referenced frags in GRO
 
  - bpf:
    - fix a possible task gone issue with bpf_send_signal[_thread]()
    - fix an off-by-one bug in bpf_mem_cache_idx() to select
      the right cache
    - add missing btf_put to register_btf_id_dtor_kfuncs
    - sockmap: fon't let sock_map_{close,destroy,unhash} call itself
 
  - gso: fix null-deref in skb_segment_list()
 
  - mctp: purge receive queues on sk destruction
 
  - fix UaF caused by accept on already connected socket in exotic
    socket families
 
  - tls: don't treat list head as an entry in tls_is_tx_ready()
 
  - netfilter: br_netfilter: disable sabotage_in hook after first
    suppression
 
  - wwan: t7xx: fix runtime PM implementation
 
 Misc:
 
  - MAINTAINERS: spring cleanup of networking maintainers
 
 Signed-off-by: Jakub Kicinski <kuba@kernel.org>
 -----BEGIN PGP SIGNATURE-----
 
 iQIzBAABCAAdFiEE6jPA+I1ugmIBA4hXMUZtbf5SIrsFAmPcKlkACgkQMUZtbf5S
 IrtHgxAAxvuXeN9kQ+/gDYbxTa4Fc3gwCAA7SdJiBdfxP9xJAUEBs9TNfh5MPynb
 iIWl9tTe1OOQtWJTnp5CKMuegUj4hlJVYuLu4MK36hW56Q41cbCFvhsDk/1xoFTF
 2mtmEr5JiXZfgEdf9/tEITTGKgfANsbXOAzL4b5HcV9qtvwvEd2aFxll3VO9N2Xn
 k6o59Lr2mff7NnXQsrVkTLBxXRK9oir8VwyTnCs7j+T7E8Qe4hIkx2LDWcDiRC1e
 vSxfoWFoe+uOGTQMxlarMOAgAOt7nvOQngwCaaVpMBa/OLzGo51Clf98cpPm+cSi
 18ZjmA8r5owGghd75p2PtxcND8U1vXeeRJW+FKK60K8qznMc0D4s7HX+wHBfevnV
 U649F0OHsNsX0Y75Z5sqA1eSmJbTR9QeyiRbuS6nfOnT7ZKDw6vPJrKGJRN789y0
 erzG/JwrfnrCDavXfNNEgk0mMlP0squemffWjuH6FfL4Pt4/gUz63Nokr5vRFSns
 yskHZgXVs4gq++yrbZDZjKfQaPDkA1P/z6VADVRWh4Y5m1m6GtvDUy6vJxK7/hUs
 5giqmhbAAQq0U+2L5RIaoYGfjk2UaDcunNpqTCgjdCdMXx9Yz41QBloFgBjRshp/
 3kg6ElYPzflXXCYK4pGRrzqO4Gqz1Hrvr9YuT+kka+wrpZPDtWc=
 =OGU7
 -----END PGP SIGNATURE-----

Merge tag 'net-6.2-rc7' of git://git.kernel.org/pub/scm/linux/kernel/git/netdev/net

Pull networking fixes from Jakub Kicinski:
 "Including fixes from bpf, can and netfilter.

  Current release - regressions:

   - phy: fix null-deref in phy_attach_direct

   - mac802154: fix possible double free upon parsing error

  Previous releases - regressions:

   - bpf: preserve reg parent/live fields when copying range info,
     prevent mis-verification of programs as safe

   - ip6: fix GRE tunnels not generating IPv6 link local addresses

   - phy: dp83822: fix null-deref on DP83825/DP83826 devices

   - sctp: do not check hb_timer.expires when resetting hb_timer

   - eth: mtk_sock: fix SGMII configuration after phylink conversion

  Previous releases - always broken:

   - eth: xdp: execute xdp_do_flush() before napi_complete_done()

   - skb: do not mix page pool and page referenced frags in GRO

   - bpf:
      - fix a possible task gone issue with bpf_send_signal[_thread]()
      - fix an off-by-one bug in bpf_mem_cache_idx() to select the right
        cache
      - add missing btf_put to register_btf_id_dtor_kfuncs
      - sockmap: fon't let sock_map_{close,destroy,unhash} call itself

   - gso: fix null-deref in skb_segment_list()

   - mctp: purge receive queues on sk destruction

   - fix UaF caused by accept on already connected socket in exotic
     socket families

   - tls: don't treat list head as an entry in tls_is_tx_ready()

   - netfilter: br_netfilter: disable sabotage_in hook after first
     suppression

   - wwan: t7xx: fix runtime PM implementation

  Misc:

   - MAINTAINERS: spring cleanup of networking maintainers"

* tag 'net-6.2-rc7' of git://git.kernel.org/pub/scm/linux/kernel/git/netdev/net: (65 commits)
  mtk_sgmii: enable PCS polling to allow SFP work
  net: mediatek: sgmii: fix duplex configuration
  net: mediatek: sgmii: ensure the SGMII PHY is powered down on configuration
  MAINTAINERS: update SCTP maintainers
  MAINTAINERS: ipv6: retire Hideaki Yoshifuji
  mailmap: add John Crispin's entry
  MAINTAINERS: bonding: move Veaceslav Falico to CREDITS
  net: openvswitch: fix flow memory leak in ovs_flow_cmd_new
  net: ethernet: mtk_eth_soc: disable hardware DSA untagging for second MAC
  virtio-net: Keep stop() to follow mirror sequence of open()
  selftests: net: udpgso_bench_tx: Cater for pending datagrams zerocopy benchmarking
  selftests: net: udpgso_bench: Fix racing bug between the rx/tx programs
  selftests: net: udpgso_bench_rx/tx: Stop when wrong CLI args are provided
  selftests: net: udpgso_bench_rx: Fix 'used uninitialized' compiler warning
  can: mcp251xfd: mcp251xfd_ring_set_ringparam(): assign missing tx_obj_num_coalesce_irq
  can: isotp: split tx timer into transmission and timeout
  can: isotp: handle wait_event_interruptible() return values
  can: raw: fix CAN FD frame transmissions over CAN XL devices
  can: j1939: fix errant WARN_ON_ONCE in j1939_session_deactivate
  hv_netvsc: Fix missed pagebuf entries in netvsc_dma_map/unmap()
  ...
This commit is contained in:
Linus Torvalds 2023-02-02 14:03:31 -08:00
commit edb9b8f380
68 changed files with 599 additions and 272 deletions

View File

@ -214,6 +214,7 @@ Jisheng Zhang <jszhang@kernel.org> <jszhang@marvell.com>
Jisheng Zhang <jszhang@kernel.org> <Jisheng.Zhang@synaptics.com>
Johan Hovold <johan@kernel.org> <jhovold@gmail.com>
Johan Hovold <johan@kernel.org> <johan@hovoldconsulting.com>
John Crispin <john@phrozen.org> <blogic@openwrt.org>
John Paul Adrian Glaubitz <glaubitz@physik.fu-berlin.de>
John Stultz <johnstul@us.ibm.com>
Jordan Crouse <jordan@cosmicpenguin.net> <jcrouse@codeaurora.org>

View File

@ -1173,6 +1173,10 @@ D: Future Domain TMC-16x0 SCSI driver (author)
D: APM driver (early port)
D: DRM drivers (author of several)
N: Veaceslav Falico
E: vfalico@gmail.com
D: Co-maintainer and co-author of the network bonding driver.
N: János Farkas
E: chexum@shadow.banki.hu
D: romfs, various (mostly networking) fixes
@ -4179,6 +4183,10 @@ S: B-1206 Jingmao Guojigongyu
S: 16 Baliqiao Nanjie, Beijing 101100
S: People's Repulic of China
N: Vlad Yasevich
E: vyasevich@gmail.com
D: SCTP protocol maintainer.
N: Aviad Yehezkel
E: aviadye@nvidia.com
D: Kernel TLS implementation and offload support.

View File

@ -819,7 +819,7 @@ NAPI
----
This driver supports NAPI (Rx polling mode).
For more information on NAPI, see
https://www.linuxfoundation.org/collaborate/workgroups/networking/napi
https://wiki.linuxfoundation.org/networking/napi
MACVLAN

View File

@ -3771,7 +3771,6 @@ F: net/bluetooth/
BONDING DRIVER
M: Jay Vosburgh <j.vosburgh@gmail.com>
M: Veaceslav Falico <vfalico@gmail.com>
M: Andy Gospodarek <andy@greyhouse.net>
L: netdev@vger.kernel.org
S: Supported
@ -14609,7 +14608,6 @@ F: tools/testing/selftests/net/ipsec.c
NETWORKING [IPv4/IPv6]
M: "David S. Miller" <davem@davemloft.net>
M: Hideaki YOSHIFUJI <yoshfuji@linux-ipv6.org>
M: David Ahern <dsahern@kernel.org>
L: netdev@vger.kernel.org
S: Maintained
@ -18692,9 +18690,9 @@ F: drivers/target/
F: include/target/
SCTP PROTOCOL
M: Vlad Yasevich <vyasevich@gmail.com>
M: Neil Horman <nhorman@tuxdriver.com>
M: Marcelo Ricardo Leitner <marcelo.leitner@gmail.com>
M: Xin Long <lucien.xin@gmail.com>
L: linux-sctp@vger.kernel.org
S: Maintained
W: http://lksctp.sourceforge.net

View File

@ -48,6 +48,7 @@ mcp251xfd_ring_set_ringparam(struct net_device *ndev,
priv->rx_obj_num = layout.cur_rx;
priv->rx_obj_num_coalesce_irq = layout.rx_coalesce;
priv->tx->obj_num = layout.cur_tx;
priv->tx_obj_num_coalesce_irq = layout.tx_coalesce;
return 0;
}

View File

@ -35,12 +35,13 @@ config NET_DSA_LANTIQ_GSWIP
the xrx200 / VR9 SoC.
config NET_DSA_MT7530
tristate "MediaTek MT753x and MT7621 Ethernet switch support"
tristate "MediaTek MT7530 and MT7531 Ethernet switch support"
select NET_DSA_TAG_MTK
select MEDIATEK_GE_PHY
help
This enables support for the MediaTek MT7530, MT7531, and MT7621
Ethernet switch chips.
This enables support for the MediaTek MT7530 and MT7531 Ethernet
switch chips. Multi-chip module MT7530 in MT7621AT, MT7621DAT,
MT7621ST and MT7623AI SoCs is supported.
config NET_DSA_MV88E6060
tristate "Marvell 88E6060 ethernet switch chip support"

View File

@ -2410,6 +2410,9 @@ static int dpaa_eth_poll(struct napi_struct *napi, int budget)
cleaned = qman_p_poll_dqrr(np->p, budget);
if (np->xdp_act & XDP_REDIRECT)
xdp_do_flush();
if (cleaned < budget) {
napi_complete_done(napi, cleaned);
qman_p_irqsource_add(np->p, QM_PIRQ_DQRI);
@ -2417,9 +2420,6 @@ static int dpaa_eth_poll(struct napi_struct *napi, int budget)
qman_p_irqsource_add(np->p, QM_PIRQ_DQRI);
}
if (np->xdp_act & XDP_REDIRECT)
xdp_do_flush();
return cleaned;
}

View File

@ -1993,10 +1993,15 @@ static int dpaa2_eth_poll(struct napi_struct *napi, int budget)
if (rx_cleaned >= budget ||
txconf_cleaned >= DPAA2_ETH_TXCONF_PER_NAPI) {
work_done = budget;
if (ch->xdp.res & XDP_REDIRECT)
xdp_do_flush();
goto out;
}
} while (store_cleaned);
if (ch->xdp.res & XDP_REDIRECT)
xdp_do_flush();
/* Update NET DIM with the values for this CDAN */
dpaa2_io_update_net_dim(ch->dpio, ch->stats.frames_per_cdan,
ch->stats.bytes_per_cdan);
@ -2032,9 +2037,7 @@ out:
txc_fq->dq_bytes = 0;
}
if (ch->xdp.res & XDP_REDIRECT)
xdp_do_flush_map();
else if (rx_cleaned && ch->xdp.res & XDP_TX)
if (rx_cleaned && ch->xdp.res & XDP_TX)
dpaa2_eth_xdp_tx_flush(priv, ch, &priv->fq[flowid]);
return work_done;

View File

@ -1055,6 +1055,9 @@ static struct phylink_pcs *memac_pcs_create(struct device_node *mac_node,
return ERR_PTR(-EPROBE_DEFER);
pcs = lynx_pcs_create(mdiodev);
if (!pcs)
mdio_device_free(mdiodev);
return pcs;
}

View File

@ -880,7 +880,7 @@ void ice_set_ethtool_repr_ops(struct net_device *netdev);
void ice_set_ethtool_safe_mode_ops(struct net_device *netdev);
u16 ice_get_avail_txq_count(struct ice_pf *pf);
u16 ice_get_avail_rxq_count(struct ice_pf *pf);
int ice_vsi_recfg_qs(struct ice_vsi *vsi, int new_rx, int new_tx);
int ice_vsi_recfg_qs(struct ice_vsi *vsi, int new_rx, int new_tx, bool locked);
void ice_update_vsi_stats(struct ice_vsi *vsi);
void ice_update_pf_stats(struct ice_pf *pf);
void

View File

@ -441,7 +441,7 @@ int ice_pf_dcb_cfg(struct ice_pf *pf, struct ice_dcbx_cfg *new_cfg, bool locked)
goto out;
}
ice_pf_dcb_recfg(pf);
ice_pf_dcb_recfg(pf, false);
out:
/* enable previously downed VSIs */
@ -731,12 +731,13 @@ static int ice_dcb_noncontig_cfg(struct ice_pf *pf)
/**
* ice_pf_dcb_recfg - Reconfigure all VEBs and VSIs
* @pf: pointer to the PF struct
* @locked: is adev device lock held
*
* Assumed caller has already disabled all VSIs before
* calling this function. Reconfiguring DCB based on
* local_dcbx_cfg.
*/
void ice_pf_dcb_recfg(struct ice_pf *pf)
void ice_pf_dcb_recfg(struct ice_pf *pf, bool locked)
{
struct ice_dcbx_cfg *dcbcfg = &pf->hw.port_info->qos_cfg.local_dcbx_cfg;
struct iidc_event *event;
@ -783,14 +784,16 @@ void ice_pf_dcb_recfg(struct ice_pf *pf)
if (vsi->type == ICE_VSI_PF)
ice_dcbnl_set_all(vsi);
}
/* Notify the AUX drivers that TC change is finished */
event = kzalloc(sizeof(*event), GFP_KERNEL);
if (!event)
return;
if (!locked) {
/* Notify the AUX drivers that TC change is finished */
event = kzalloc(sizeof(*event), GFP_KERNEL);
if (!event)
return;
set_bit(IIDC_EVENT_AFTER_TC_CHANGE, event->type);
ice_send_event_to_aux(pf, event);
kfree(event);
set_bit(IIDC_EVENT_AFTER_TC_CHANGE, event->type);
ice_send_event_to_aux(pf, event);
kfree(event);
}
}
/**
@ -1044,7 +1047,7 @@ ice_dcb_process_lldp_set_mib_change(struct ice_pf *pf,
}
/* changes in configuration update VSI */
ice_pf_dcb_recfg(pf);
ice_pf_dcb_recfg(pf, false);
/* enable previously downed VSIs */
ice_dcb_ena_dis_vsi(pf, true, true);

View File

@ -23,7 +23,7 @@ u8 ice_dcb_get_tc(struct ice_vsi *vsi, int queue_index);
int
ice_pf_dcb_cfg(struct ice_pf *pf, struct ice_dcbx_cfg *new_cfg, bool locked);
int ice_dcb_bwchk(struct ice_pf *pf, struct ice_dcbx_cfg *dcbcfg);
void ice_pf_dcb_recfg(struct ice_pf *pf);
void ice_pf_dcb_recfg(struct ice_pf *pf, bool locked);
void ice_vsi_cfg_dcb_rings(struct ice_vsi *vsi);
int ice_init_pf_dcb(struct ice_pf *pf, bool locked);
void ice_update_dcb_stats(struct ice_pf *pf);
@ -128,7 +128,7 @@ static inline u8 ice_get_pfc_mode(struct ice_pf *pf)
return 0;
}
static inline void ice_pf_dcb_recfg(struct ice_pf *pf) { }
static inline void ice_pf_dcb_recfg(struct ice_pf *pf, bool locked) { }
static inline void ice_vsi_cfg_dcb_rings(struct ice_vsi *vsi) { }
static inline void ice_update_dcb_stats(struct ice_pf *pf) { }
static inline void

View File

@ -3641,7 +3641,9 @@ static int ice_set_channels(struct net_device *dev, struct ethtool_channels *ch)
struct ice_vsi *vsi = np->vsi;
struct ice_pf *pf = vsi->back;
int new_rx = 0, new_tx = 0;
bool locked = false;
u32 curr_combined;
int ret = 0;
/* do not support changing channels in Safe Mode */
if (ice_is_safe_mode(pf)) {
@ -3705,15 +3707,33 @@ static int ice_set_channels(struct net_device *dev, struct ethtool_channels *ch)
return -EINVAL;
}
ice_vsi_recfg_qs(vsi, new_rx, new_tx);
if (pf->adev) {
mutex_lock(&pf->adev_mutex);
device_lock(&pf->adev->dev);
locked = true;
if (pf->adev->dev.driver) {
netdev_err(dev, "Cannot change channels when RDMA is active\n");
ret = -EBUSY;
goto adev_unlock;
}
}
if (!netif_is_rxfh_configured(dev))
return ice_vsi_set_dflt_rss_lut(vsi, new_rx);
ice_vsi_recfg_qs(vsi, new_rx, new_tx, locked);
if (!netif_is_rxfh_configured(dev)) {
ret = ice_vsi_set_dflt_rss_lut(vsi, new_rx);
goto adev_unlock;
}
/* Update rss_size due to change in Rx queues */
vsi->rss_size = ice_get_valid_rss_size(&pf->hw, new_rx);
return 0;
adev_unlock:
if (locked) {
device_unlock(&pf->adev->dev);
mutex_unlock(&pf->adev_mutex);
}
return ret;
}
/**

View File

@ -4195,12 +4195,13 @@ bool ice_is_wol_supported(struct ice_hw *hw)
* @vsi: VSI being changed
* @new_rx: new number of Rx queues
* @new_tx: new number of Tx queues
* @locked: is adev device_lock held
*
* Only change the number of queues if new_tx, or new_rx is non-0.
*
* Returns 0 on success.
*/
int ice_vsi_recfg_qs(struct ice_vsi *vsi, int new_rx, int new_tx)
int ice_vsi_recfg_qs(struct ice_vsi *vsi, int new_rx, int new_tx, bool locked)
{
struct ice_pf *pf = vsi->back;
int err = 0, timeout = 50;
@ -4229,7 +4230,7 @@ int ice_vsi_recfg_qs(struct ice_vsi *vsi, int new_rx, int new_tx)
ice_vsi_close(vsi);
ice_vsi_rebuild(vsi, false);
ice_pf_dcb_recfg(pf);
ice_pf_dcb_recfg(pf, locked);
ice_vsi_open(vsi);
done:
clear_bit(ICE_CFG_BUSY, pf->state);

View File

@ -417,10 +417,12 @@ static int igc_ptp_verify_pin(struct ptp_clock_info *ptp, unsigned int pin,
*
* We need to convert the system time value stored in the RX/TXSTMP registers
* into a hwtstamp which can be used by the upper level timestamping functions.
*
* Returns 0 on success.
**/
static void igc_ptp_systim_to_hwtstamp(struct igc_adapter *adapter,
struct skb_shared_hwtstamps *hwtstamps,
u64 systim)
static int igc_ptp_systim_to_hwtstamp(struct igc_adapter *adapter,
struct skb_shared_hwtstamps *hwtstamps,
u64 systim)
{
switch (adapter->hw.mac.type) {
case igc_i225:
@ -430,8 +432,9 @@ static void igc_ptp_systim_to_hwtstamp(struct igc_adapter *adapter,
systim & 0xFFFFFFFF);
break;
default:
break;
return -EINVAL;
}
return 0;
}
/**
@ -652,7 +655,8 @@ static void igc_ptp_tx_hwtstamp(struct igc_adapter *adapter)
regval = rd32(IGC_TXSTMPL);
regval |= (u64)rd32(IGC_TXSTMPH) << 32;
igc_ptp_systim_to_hwtstamp(adapter, &shhwtstamps, regval);
if (igc_ptp_systim_to_hwtstamp(adapter, &shhwtstamps, regval))
return;
switch (adapter->link_speed) {
case SPEED_10:

View File

@ -1500,6 +1500,9 @@ static const struct devlink_param rvu_af_dl_params[] = {
BIT(DEVLINK_PARAM_CMODE_RUNTIME),
rvu_af_dl_dwrr_mtu_get, rvu_af_dl_dwrr_mtu_set,
rvu_af_dl_dwrr_mtu_validate),
};
static const struct devlink_param rvu_af_dl_param_exact_match[] = {
DEVLINK_PARAM_DRIVER(RVU_AF_DEVLINK_PARAM_ID_NPC_EXACT_FEATURE_DISABLE,
"npc_exact_feature_disable", DEVLINK_PARAM_TYPE_STRING,
BIT(DEVLINK_PARAM_CMODE_RUNTIME),
@ -1556,7 +1559,6 @@ int rvu_register_dl(struct rvu *rvu)
{
struct rvu_devlink *rvu_dl;
struct devlink *dl;
size_t size;
int err;
dl = devlink_alloc(&rvu_devlink_ops, sizeof(struct rvu_devlink),
@ -1578,21 +1580,32 @@ int rvu_register_dl(struct rvu *rvu)
goto err_dl_health;
}
/* Register exact match devlink only for CN10K-B */
size = ARRAY_SIZE(rvu_af_dl_params);
if (!rvu_npc_exact_has_match_table(rvu))
size -= 1;
err = devlink_params_register(dl, rvu_af_dl_params, size);
err = devlink_params_register(dl, rvu_af_dl_params, ARRAY_SIZE(rvu_af_dl_params));
if (err) {
dev_err(rvu->dev,
"devlink params register failed with error %d", err);
goto err_dl_health;
}
/* Register exact match devlink only for CN10K-B */
if (!rvu_npc_exact_has_match_table(rvu))
goto done;
err = devlink_params_register(dl, rvu_af_dl_param_exact_match,
ARRAY_SIZE(rvu_af_dl_param_exact_match));
if (err) {
dev_err(rvu->dev,
"devlink exact match params register failed with error %d", err);
goto err_dl_exact_match;
}
done:
devlink_register(dl);
return 0;
err_dl_exact_match:
devlink_params_unregister(dl, rvu_af_dl_params, ARRAY_SIZE(rvu_af_dl_params));
err_dl_health:
rvu_health_reporters_destroy(rvu);
devlink_free(dl);
@ -1605,8 +1618,14 @@ void rvu_unregister_dl(struct rvu *rvu)
struct devlink *dl = rvu_dl->dl;
devlink_unregister(dl);
devlink_params_unregister(dl, rvu_af_dl_params,
ARRAY_SIZE(rvu_af_dl_params));
devlink_params_unregister(dl, rvu_af_dl_params, ARRAY_SIZE(rvu_af_dl_params));
/* Unregister exact match devlink only for CN10K-B */
if (rvu_npc_exact_has_match_table(rvu))
devlink_params_unregister(dl, rvu_af_dl_param_exact_match,
ARRAY_SIZE(rvu_af_dl_param_exact_match));
rvu_health_reporters_destroy(rvu);
devlink_free(dl);
}

View File

@ -3177,7 +3177,8 @@ static int mtk_open(struct net_device *dev)
struct mtk_eth *eth = mac->hw;
int i, err;
if (mtk_uses_dsa(dev) && !eth->prog) {
if ((mtk_uses_dsa(dev) && !eth->prog) &&
!(mac->id == 1 && MTK_HAS_CAPS(eth->soc->caps, MTK_GMAC1_TRGMII))) {
for (i = 0; i < ARRAY_SIZE(eth->dsa_meta); i++) {
struct metadata_dst *md_dst = eth->dsa_meta[i];
@ -3194,7 +3195,8 @@ static int mtk_open(struct net_device *dev)
}
} else {
/* Hardware special tag parsing needs to be disabled if at least
* one MAC does not use DSA.
* one MAC does not use DSA, or the second MAC of the MT7621 and
* MT7623 SoCs is being used.
*/
u32 val = mtk_r32(eth, MTK_CDMP_IG_CTRL);
val &= ~MTK_CDMP_STAG_EN;

View File

@ -519,7 +519,7 @@
#define SGMII_SPEED_10 FIELD_PREP(SGMII_SPEED_MASK, 0)
#define SGMII_SPEED_100 FIELD_PREP(SGMII_SPEED_MASK, 1)
#define SGMII_SPEED_1000 FIELD_PREP(SGMII_SPEED_MASK, 2)
#define SGMII_DUPLEX_FULL BIT(4)
#define SGMII_DUPLEX_HALF BIT(4)
#define SGMII_IF_MODE_BIT5 BIT(5)
#define SGMII_REMOTE_FAULT_DIS BIT(8)
#define SGMII_CODE_SYNC_SET_VAL BIT(9)
@ -1036,11 +1036,13 @@ struct mtk_soc_data {
* @regmap: The register map pointing at the range used to setup
* SGMII modes
* @ana_rgc3: The offset refers to register ANA_RGC3 related to regmap
* @interface: Currently configured interface mode
* @pcs: Phylink PCS structure
*/
struct mtk_pcs {
struct regmap *regmap;
u32 ana_rgc3;
phy_interface_t interface;
struct phylink_pcs pcs;
};

View File

@ -615,8 +615,7 @@ mtk_foe_entry_commit_subflow(struct mtk_ppe *ppe, struct mtk_flow_entry *entry,
u32 ib1_mask = mtk_get_ib1_pkt_type_mask(ppe->eth) | MTK_FOE_IB1_UDP;
int type;
flow_info = kzalloc(offsetof(struct mtk_flow_entry, l2_data.end),
GFP_ATOMIC);
flow_info = kzalloc(sizeof(*flow_info), GFP_ATOMIC);
if (!flow_info)
return;

View File

@ -279,7 +279,6 @@ struct mtk_flow_entry {
struct {
struct mtk_flow_entry *base_flow;
struct hlist_node list;
struct {} end;
} l2_data;
};
struct rhash_head node;

View File

@ -43,11 +43,6 @@ static int mtk_pcs_config(struct phylink_pcs *pcs, unsigned int mode,
int advertise, link_timer;
bool changed, use_an;
if (interface == PHY_INTERFACE_MODE_2500BASEX)
rgc3 = RG_PHY_SPEED_3_125G;
else
rgc3 = 0;
advertise = phylink_mii_c22_pcs_encode_advertisement(interface,
advertising);
if (advertise < 0)
@ -88,9 +83,22 @@ static int mtk_pcs_config(struct phylink_pcs *pcs, unsigned int mode,
bmcr = 0;
}
/* Configure the underlying interface speed */
regmap_update_bits(mpcs->regmap, mpcs->ana_rgc3,
RG_PHY_SPEED_3_125G, rgc3);
if (mpcs->interface != interface) {
/* PHYA power down */
regmap_update_bits(mpcs->regmap, SGMSYS_QPHY_PWR_STATE_CTRL,
SGMII_PHYA_PWD, SGMII_PHYA_PWD);
if (interface == PHY_INTERFACE_MODE_2500BASEX)
rgc3 = RG_PHY_SPEED_3_125G;
else
rgc3 = 0;
/* Configure the underlying interface speed */
regmap_update_bits(mpcs->regmap, mpcs->ana_rgc3,
RG_PHY_SPEED_3_125G, rgc3);
mpcs->interface = interface;
}
/* Update the advertisement, noting whether it has changed */
regmap_update_bits_check(mpcs->regmap, SGMSYS_PCS_ADVERTISE,
@ -108,9 +116,17 @@ static int mtk_pcs_config(struct phylink_pcs *pcs, unsigned int mode,
regmap_update_bits(mpcs->regmap, SGMSYS_PCS_CONTROL_1,
SGMII_AN_RESTART | SGMII_AN_ENABLE, bmcr);
/* Release PHYA power down state */
regmap_update_bits(mpcs->regmap, SGMSYS_QPHY_PWR_STATE_CTRL,
SGMII_PHYA_PWD, 0);
/* Release PHYA power down state
* Only removing bit SGMII_PHYA_PWD isn't enough.
* There are cases when the SGMII_PHYA_PWD register contains 0x9 which
* prevents SGMII from working. The SGMII still shows link but no traffic
* can flow. Writing 0x0 to the PHYA_PWD register fix the issue. 0x0 was
* taken from a good working state of the SGMII interface.
* Unknown how much the QPHY needs but it is racy without a sleep.
* Tested on mt7622 & mt7986.
*/
usleep_range(50, 100);
regmap_write(mpcs->regmap, SGMSYS_QPHY_PWR_STATE_CTRL, 0);
return changed;
}
@ -138,11 +154,11 @@ static void mtk_pcs_link_up(struct phylink_pcs *pcs, unsigned int mode,
else
sgm_mode = SGMII_SPEED_1000;
if (duplex == DUPLEX_FULL)
sgm_mode |= SGMII_DUPLEX_FULL;
if (duplex != DUPLEX_FULL)
sgm_mode |= SGMII_DUPLEX_HALF;
regmap_update_bits(mpcs->regmap, SGMSYS_SGMII_MODE,
SGMII_DUPLEX_FULL | SGMII_SPEED_MASK,
SGMII_DUPLEX_HALF | SGMII_SPEED_MASK,
sgm_mode);
}
}
@ -171,6 +187,8 @@ int mtk_sgmii_init(struct mtk_sgmii *ss, struct device_node *r, u32 ana_rgc3)
return PTR_ERR(ss->pcs[i].regmap);
ss->pcs[i].pcs.ops = &mtk_pcs_ops;
ss->pcs[i].pcs.poll = true;
ss->pcs[i].interface = PHY_INTERFACE_MODE_NA;
}
return 0;

View File

@ -608,12 +608,12 @@ allocate_new:
lan966x_fdma_rx_reload(rx);
}
if (counter < weight && napi_complete_done(napi, counter))
lan_wr(0xff, lan966x, FDMA_INTR_DB_ENA);
if (redirect)
xdp_do_flush();
if (counter < weight && napi_complete_done(napi, counter))
lan_wr(0xff, lan966x, FDMA_INTR_DB_ENA);
return counter;
}

View File

@ -460,6 +460,7 @@ nfp_tun_write_neigh(struct net_device *netdev, struct nfp_app *app,
sizeof(struct nfp_tun_neigh_v4);
unsigned long cookie = (unsigned long)neigh;
struct nfp_flower_priv *priv = app->priv;
struct nfp_tun_neigh_lag lag_info;
struct nfp_neigh_entry *nn_entry;
u32 port_id;
u8 mtype;
@ -468,6 +469,11 @@ nfp_tun_write_neigh(struct net_device *netdev, struct nfp_app *app,
if (!port_id)
return;
if ((port_id & NFP_FL_LAG_OUT) == NFP_FL_LAG_OUT) {
memset(&lag_info, 0, sizeof(struct nfp_tun_neigh_lag));
nfp_flower_lag_get_info_from_netdev(app, netdev, &lag_info);
}
spin_lock_bh(&priv->predt_lock);
nn_entry = rhashtable_lookup_fast(&priv->neigh_table, &cookie,
neigh_table_params);
@ -515,7 +521,7 @@ nfp_tun_write_neigh(struct net_device *netdev, struct nfp_app *app,
neigh_ha_snapshot(common->dst_addr, neigh, netdev);
if ((port_id & NFP_FL_LAG_OUT) == NFP_FL_LAG_OUT)
nfp_flower_lag_get_info_from_netdev(app, netdev, lag);
memcpy(lag, &lag_info, sizeof(struct nfp_tun_neigh_lag));
common->port_id = cpu_to_be32(port_id);
if (rhashtable_insert_fast(&priv->neigh_table,

View File

@ -1438,6 +1438,10 @@ int qede_poll(struct napi_struct *napi, int budget)
rx_work_done = (likely(fp->type & QEDE_FASTPATH_RX) &&
qede_has_rx_work(fp->rxq)) ?
qede_rx_int(fp, budget) : 0;
if (fp->xdp_xmit & QEDE_XDP_REDIRECT)
xdp_do_flush();
/* Handle case where we are called by netpoll with a budget of 0 */
if (rx_work_done < budget || !budget) {
if (!qede_poll_is_more_work(fp)) {
@ -1457,9 +1461,6 @@ int qede_poll(struct napi_struct *napi, int budget)
qede_update_tx_producer(fp->xdp_tx);
}
if (fp->xdp_xmit & QEDE_XDP_REDIRECT)
xdp_do_flush_map();
return rx_work_done;
}

View File

@ -1003,8 +1003,11 @@ static int efx_pci_probe_post_io(struct efx_nic *efx)
/* Determine netdevice features */
net_dev->features |= (efx->type->offload_features | NETIF_F_SG |
NETIF_F_TSO | NETIF_F_RXCSUM | NETIF_F_RXALL);
if (efx->type->offload_features & (NETIF_F_IPV6_CSUM | NETIF_F_HW_CSUM))
if (efx->type->offload_features & (NETIF_F_IPV6_CSUM | NETIF_F_HW_CSUM)) {
net_dev->features |= NETIF_F_TSO6;
if (efx_has_cap(efx, TX_TSO_V2_ENCAP))
net_dev->hw_enc_features |= NETIF_F_TSO6;
}
/* Check whether device supports TSO */
if (!efx->type->tso_versions || !efx->type->tso_versions(efx))
net_dev->features &= ~NETIF_F_ALL_TSO;

View File

@ -560,6 +560,8 @@ static int qcom_ethqos_probe(struct platform_device *pdev)
plat_dat->has_gmac4 = 1;
plat_dat->pmt = 1;
plat_dat->tso_en = of_property_read_bool(np, "snps,tso");
if (of_device_is_compatible(np, "qcom,qcs404-ethqos"))
plat_dat->rx_clk_runs_in_lpi = 1;
ret = stmmac_dvr_probe(&pdev->dev, plat_dat, &stmmac_res);
if (ret)

View File

@ -1080,7 +1080,8 @@ static void stmmac_mac_link_up(struct phylink_config *config,
stmmac_mac_set(priv, priv->ioaddr, true);
if (phy && priv->dma_cap.eee) {
priv->eee_active = phy_init_eee(phy, 1) >= 0;
priv->eee_active =
phy_init_eee(phy, !priv->plat->rx_clk_runs_in_lpi) >= 0;
priv->eee_enabled = stmmac_eee_init(priv);
priv->tx_lpi_enabled = priv->eee_enabled;
stmmac_set_eee_pls(priv, priv->hw, true);

View File

@ -987,9 +987,6 @@ static void netvsc_copy_to_send_buf(struct netvsc_device *net_device,
void netvsc_dma_unmap(struct hv_device *hv_dev,
struct hv_netvsc_packet *packet)
{
u32 page_count = packet->cp_partial ?
packet->page_buf_cnt - packet->rmsg_pgcnt :
packet->page_buf_cnt;
int i;
if (!hv_is_isolation_supported())
@ -998,7 +995,7 @@ void netvsc_dma_unmap(struct hv_device *hv_dev,
if (!packet->dma_range)
return;
for (i = 0; i < page_count; i++)
for (i = 0; i < packet->page_buf_cnt; i++)
dma_unmap_single(&hv_dev->device, packet->dma_range[i].dma,
packet->dma_range[i].mapping_size,
DMA_TO_DEVICE);
@ -1028,9 +1025,7 @@ static int netvsc_dma_map(struct hv_device *hv_dev,
struct hv_netvsc_packet *packet,
struct hv_page_buffer *pb)
{
u32 page_count = packet->cp_partial ?
packet->page_buf_cnt - packet->rmsg_pgcnt :
packet->page_buf_cnt;
u32 page_count = packet->page_buf_cnt;
dma_addr_t dma;
int i;

View File

@ -233,7 +233,8 @@ static int dp83822_config_intr(struct phy_device *phydev)
DP83822_ENERGY_DET_INT_EN |
DP83822_LINK_QUAL_INT_EN);
if (!dp83822->fx_enabled)
/* Private data pointer is NULL on DP83825/26 */
if (!dp83822 || !dp83822->fx_enabled)
misr_status |= DP83822_ANEG_COMPLETE_INT_EN |
DP83822_DUP_MODE_CHANGE_INT_EN |
DP83822_SPEED_CHANGED_INT_EN;
@ -253,7 +254,8 @@ static int dp83822_config_intr(struct phy_device *phydev)
DP83822_PAGE_RX_INT_EN |
DP83822_EEE_ERROR_CHANGE_INT_EN);
if (!dp83822->fx_enabled)
/* Private data pointer is NULL on DP83825/26 */
if (!dp83822 || !dp83822->fx_enabled)
misr_status |= DP83822_ANEG_ERR_INT_EN |
DP83822_WOL_PKT_INT_EN;

View File

@ -271,6 +271,8 @@ static struct phy_driver meson_gxl_phy[] = {
.handle_interrupt = meson_gxl_handle_interrupt,
.suspend = genphy_suspend,
.resume = genphy_resume,
.read_mmd = genphy_read_mmd_unsupported,
.write_mmd = genphy_write_mmd_unsupported,
},
};

View File

@ -1517,7 +1517,7 @@ int phy_attach_direct(struct net_device *dev, struct phy_device *phydev,
* another mac interface, so we should create a device link between
* phy dev and mac dev.
*/
if (phydev->mdio.bus->parent && dev->dev.parent != phydev->mdio.bus->parent)
if (dev && phydev->mdio.bus->parent && dev->dev.parent != phydev->mdio.bus->parent)
phydev->devlink = device_link_add(dev->dev.parent, &phydev->mdio.dev,
DL_FLAG_PM_RUNTIME | DL_FLAG_STATELESS);

View File

@ -1677,13 +1677,13 @@ static int virtnet_poll(struct napi_struct *napi, int budget)
received = virtnet_receive(rq, budget, &xdp_xmit);
if (xdp_xmit & VIRTIO_XDP_REDIR)
xdp_do_flush();
/* Out of packets? */
if (received < budget)
virtqueue_napi_complete(napi, rq->vq, received);
if (xdp_xmit & VIRTIO_XDP_REDIR)
xdp_do_flush();
if (xdp_xmit & VIRTIO_XDP_TX) {
sq = virtnet_xdp_get_sq(vi);
if (virtqueue_kick_prepare(sq->vq) && virtqueue_notify(sq->vq)) {
@ -2158,8 +2158,8 @@ static int virtnet_close(struct net_device *dev)
cancel_delayed_work_sync(&vi->refill);
for (i = 0; i < vi->max_queue_pairs; i++) {
xdp_rxq_info_unreg(&vi->rq[i].xdp_rxq);
napi_disable(&vi->rq[i].napi);
xdp_rxq_info_unreg(&vi->rq[i].xdp_rxq);
virtnet_napi_tx_disable(&vi->sq[i].napi);
}

View File

@ -152,6 +152,15 @@ static irqreturn_t t7xx_dpmaif_isr_handler(int irq, void *data)
}
t7xx_pcie_mac_clear_int(dpmaif_ctrl->t7xx_dev, isr_para->pcie_int);
return IRQ_WAKE_THREAD;
}
static irqreturn_t t7xx_dpmaif_isr_thread(int irq, void *data)
{
struct dpmaif_isr_para *isr_para = data;
struct dpmaif_ctrl *dpmaif_ctrl = isr_para->dpmaif_ctrl;
t7xx_dpmaif_irq_cb(isr_para);
t7xx_pcie_mac_set_int(dpmaif_ctrl->t7xx_dev, isr_para->pcie_int);
return IRQ_HANDLED;
@ -188,7 +197,7 @@ static void t7xx_dpmaif_register_pcie_irq(struct dpmaif_ctrl *dpmaif_ctrl)
t7xx_pcie_mac_clear_int(t7xx_dev, int_type);
t7xx_dev->intr_handler[int_type] = t7xx_dpmaif_isr_handler;
t7xx_dev->intr_thread[int_type] = NULL;
t7xx_dev->intr_thread[int_type] = t7xx_dpmaif_isr_thread;
t7xx_dev->callback_param[int_type] = isr_para;
t7xx_pcie_mac_clear_int_status(t7xx_dev, int_type);

View File

@ -840,14 +840,13 @@ int t7xx_dpmaif_napi_rx_poll(struct napi_struct *napi, const int budget)
if (!rxq->que_started) {
atomic_set(&rxq->rx_processing, 0);
pm_runtime_put_autosuspend(rxq->dpmaif_ctrl->dev);
dev_err(rxq->dpmaif_ctrl->dev, "Work RXQ: %d has not been started\n", rxq->index);
return work_done;
}
if (!rxq->sleep_lock_pending) {
pm_runtime_get_noresume(rxq->dpmaif_ctrl->dev);
if (!rxq->sleep_lock_pending)
t7xx_pci_disable_sleep(t7xx_dev);
}
ret = try_wait_for_completion(&t7xx_dev->sleep_lock_acquire);
if (!ret) {
@ -876,22 +875,22 @@ int t7xx_dpmaif_napi_rx_poll(struct napi_struct *napi, const int budget)
napi_complete_done(napi, work_done);
t7xx_dpmaif_clr_ip_busy_sts(&rxq->dpmaif_ctrl->hw_info);
t7xx_dpmaif_dlq_unmask_rx_done(&rxq->dpmaif_ctrl->hw_info, rxq->index);
t7xx_pci_enable_sleep(rxq->dpmaif_ctrl->t7xx_dev);
pm_runtime_mark_last_busy(rxq->dpmaif_ctrl->dev);
pm_runtime_put_autosuspend(rxq->dpmaif_ctrl->dev);
atomic_set(&rxq->rx_processing, 0);
} else {
t7xx_dpmaif_clr_ip_busy_sts(&rxq->dpmaif_ctrl->hw_info);
}
t7xx_pci_enable_sleep(rxq->dpmaif_ctrl->t7xx_dev);
pm_runtime_mark_last_busy(rxq->dpmaif_ctrl->dev);
pm_runtime_put_noidle(rxq->dpmaif_ctrl->dev);
atomic_set(&rxq->rx_processing, 0);
return work_done;
}
void t7xx_dpmaif_irq_rx_done(struct dpmaif_ctrl *dpmaif_ctrl, const unsigned int que_mask)
{
struct dpmaif_rx_queue *rxq;
int qno;
struct dpmaif_ctrl *ctrl;
int qno, ret;
qno = ffs(que_mask) - 1;
if (qno < 0 || qno > DPMAIF_RXQ_NUM - 1) {
@ -900,6 +899,18 @@ void t7xx_dpmaif_irq_rx_done(struct dpmaif_ctrl *dpmaif_ctrl, const unsigned int
}
rxq = &dpmaif_ctrl->rxq[qno];
ctrl = rxq->dpmaif_ctrl;
/* We need to make sure that the modem has been resumed before
* calling napi. This can't be done inside the polling function
* as we could be blocked waiting for device to be resumed,
* which can't be done from softirq context the poll function
* is running in.
*/
ret = pm_runtime_resume_and_get(ctrl->dev);
if (ret < 0 && ret != -EACCES) {
dev_err(ctrl->dev, "Failed to resume device: %d\n", ret);
return;
}
napi_schedule(&rxq->napi);
}

View File

@ -27,6 +27,7 @@
#include <linux/list.h>
#include <linux/netdev_features.h>
#include <linux/netdevice.h>
#include <linux/pm_runtime.h>
#include <linux/skbuff.h>
#include <linux/types.h>
#include <linux/wwan.h>
@ -45,12 +46,25 @@
static void t7xx_ccmni_enable_napi(struct t7xx_ccmni_ctrl *ctlb)
{
int i;
struct dpmaif_ctrl *ctrl;
int i, ret;
ctrl = ctlb->hif_ctrl;
if (ctlb->is_napi_en)
return;
for (i = 0; i < RXQ_NUM; i++) {
/* The usage count has to be bumped every time before calling
* napi_schedule. It will be decresed in the poll routine,
* right after napi_complete_done is called.
*/
ret = pm_runtime_resume_and_get(ctrl->dev);
if (ret < 0) {
dev_err(ctrl->dev, "Failed to resume device: %d\n",
ret);
return;
}
napi_enable(ctlb->napi[i]);
napi_schedule(ctlb->napi[i]);
}

View File

@ -121,6 +121,8 @@ void t7xx_pci_pm_init_late(struct t7xx_pci_dev *t7xx_dev)
iowrite32(T7XX_L1_BIT(0), IREG_BASE(t7xx_dev) + ENABLE_ASPM_LOWPWR);
atomic_set(&t7xx_dev->md_pm_state, MTK_PM_RESUMED);
pm_runtime_mark_last_busy(&t7xx_dev->pdev->dev);
pm_runtime_allow(&t7xx_dev->pdev->dev);
pm_runtime_put_noidle(&t7xx_dev->pdev->dev);
}

View File

@ -252,6 +252,7 @@ struct plat_stmmacenet_data {
int rss_en;
int mac_port_sel_speed;
bool en_tx_lpi_clockgating;
bool rx_clk_runs_in_lpi;
int has_xgmac;
bool vlan_fail_q_en;
u8 vlan_fail_q;

View File

@ -38,4 +38,16 @@
*/
#define find_closest_descending(x, a, as) __find_closest(x, a, as, >=)
/**
* is_insidevar - check if the @ptr points inside the @var memory range.
* @ptr: the pointer to a memory address.
* @var: the variable which address and size identify the memory range.
*
* Evaluates to true if the address in @ptr lies within the memory
* range allocated to @var.
*/
#define is_insidevar(ptr, var) \
((uintptr_t)(ptr) >= (uintptr_t)(var) && \
(uintptr_t)(ptr) < (uintptr_t)(var) + sizeof(var))
#endif

View File

@ -51,7 +51,6 @@ BTF_SET_END(bpf_lsm_current_hooks)
*/
BTF_SET_START(bpf_lsm_locked_sockopt_hooks)
#ifdef CONFIG_SECURITY_NETWORK
BTF_ID(func, bpf_lsm_socket_sock_rcv_skb)
BTF_ID(func, bpf_lsm_sock_graft)
BTF_ID(func, bpf_lsm_inet_csk_clone)
BTF_ID(func, bpf_lsm_inet_conn_established)

View File

@ -7782,9 +7782,9 @@ int register_btf_id_dtor_kfuncs(const struct btf_id_dtor_kfunc *dtors, u32 add_c
sort(tab->dtors, tab->cnt, sizeof(tab->dtors[0]), btf_id_cmp_func, NULL);
return 0;
end:
btf_free_dtor_kfunc_tab(btf);
if (ret)
btf_free_dtor_kfunc_tab(btf);
btf_put(btf);
return ret;
}

View File

@ -71,7 +71,7 @@ static int bpf_mem_cache_idx(size_t size)
if (size <= 192)
return size_index[(size - 1) / 8] - 1;
return fls(size - 1) - 1;
return fls(size - 1) - 2;
}
#define NUM_CACHES 11

View File

@ -3243,13 +3243,24 @@ static bool __is_pointer_value(bool allow_ptr_leaks,
return reg->type != SCALAR_VALUE;
}
/* Copy src state preserving dst->parent and dst->live fields */
static void copy_register_state(struct bpf_reg_state *dst, const struct bpf_reg_state *src)
{
struct bpf_reg_state *parent = dst->parent;
enum bpf_reg_liveness live = dst->live;
*dst = *src;
dst->parent = parent;
dst->live = live;
}
static void save_register_state(struct bpf_func_state *state,
int spi, struct bpf_reg_state *reg,
int size)
{
int i;
state->stack[spi].spilled_ptr = *reg;
copy_register_state(&state->stack[spi].spilled_ptr, reg);
if (size == BPF_REG_SIZE)
state->stack[spi].spilled_ptr.live |= REG_LIVE_WRITTEN;
@ -3577,7 +3588,7 @@ static int check_stack_read_fixed_off(struct bpf_verifier_env *env,
*/
s32 subreg_def = state->regs[dst_regno].subreg_def;
state->regs[dst_regno] = *reg;
copy_register_state(&state->regs[dst_regno], reg);
state->regs[dst_regno].subreg_def = subreg_def;
} else {
for (i = 0; i < size; i++) {
@ -3598,7 +3609,7 @@ static int check_stack_read_fixed_off(struct bpf_verifier_env *env,
if (dst_regno >= 0) {
/* restore register state from stack */
state->regs[dst_regno] = *reg;
copy_register_state(&state->regs[dst_regno], reg);
/* mark reg as written since spilled pointer state likely
* has its liveness marks cleared by is_state_visited()
* which resets stack/reg liveness for state transitions
@ -9592,7 +9603,7 @@ do_sim:
*/
if (!ptr_is_dst_reg) {
tmp = *dst_reg;
*dst_reg = *ptr_reg;
copy_register_state(dst_reg, ptr_reg);
}
ret = sanitize_speculative_path(env, NULL, env->insn_idx + 1,
env->insn_idx);
@ -10845,7 +10856,7 @@ static int check_alu_op(struct bpf_verifier_env *env, struct bpf_insn *insn)
* to propagate min/max range.
*/
src_reg->id = ++env->id_gen;
*dst_reg = *src_reg;
copy_register_state(dst_reg, src_reg);
dst_reg->live |= REG_LIVE_WRITTEN;
dst_reg->subreg_def = DEF_NOT_SUBREG;
} else {
@ -10856,7 +10867,7 @@ static int check_alu_op(struct bpf_verifier_env *env, struct bpf_insn *insn)
insn->src_reg);
return -EACCES;
} else if (src_reg->type == SCALAR_VALUE) {
*dst_reg = *src_reg;
copy_register_state(dst_reg, src_reg);
/* Make sure ID is cleared otherwise
* dst_reg min/max could be incorrectly
* propagated into src_reg by find_equal_scalars()
@ -11655,7 +11666,7 @@ static void find_equal_scalars(struct bpf_verifier_state *vstate,
bpf_for_each_reg_in_vstate(vstate, state, reg, ({
if (reg->type == SCALAR_VALUE && reg->id == known_reg->id)
*reg = *known_reg;
copy_register_state(reg, known_reg);
}));
}

View File

@ -833,6 +833,7 @@ static void do_bpf_send_signal(struct irq_work *entry)
work = container_of(entry, struct send_signal_irq_work, irq_work);
group_send_sig_info(work->sig, SEND_SIG_PRIV, work->task, work->type);
put_task_struct(work->task);
}
static int bpf_send_signal_common(u32 sig, enum pid_type type)
@ -867,7 +868,7 @@ static int bpf_send_signal_common(u32 sig, enum pid_type type)
* to the irq_work. The current task may change when queued
* irq works get executed.
*/
work->task = current;
work->task = get_task_struct(current);
work->sig = sig;
work->type = type;
irq_work_queue(&work->irq_work);

View File

@ -871,6 +871,7 @@ static unsigned int ip_sabotage_in(void *priv,
if (nf_bridge && !nf_bridge->in_prerouting &&
!netif_is_l3_master(skb->dev) &&
!netif_is_l3_slave(skb->dev)) {
nf_bridge_info_free(skb);
state->okfn(state->net, state->sk, skb);
return NF_STOLEN;
}

View File

@ -140,7 +140,7 @@ struct isotp_sock {
canid_t rxid;
ktime_t tx_gap;
ktime_t lastrxcf_tstamp;
struct hrtimer rxtimer, txtimer;
struct hrtimer rxtimer, txtimer, txfrtimer;
struct can_isotp_options opt;
struct can_isotp_fc_options rxfc, txfc;
struct can_isotp_ll_options ll;
@ -871,7 +871,7 @@ static void isotp_rcv_echo(struct sk_buff *skb, void *data)
}
/* start timer to send next consecutive frame with correct delay */
hrtimer_start(&so->txtimer, so->tx_gap, HRTIMER_MODE_REL_SOFT);
hrtimer_start(&so->txfrtimer, so->tx_gap, HRTIMER_MODE_REL_SOFT);
}
static enum hrtimer_restart isotp_tx_timer_handler(struct hrtimer *hrtimer)
@ -879,49 +879,39 @@ static enum hrtimer_restart isotp_tx_timer_handler(struct hrtimer *hrtimer)
struct isotp_sock *so = container_of(hrtimer, struct isotp_sock,
txtimer);
struct sock *sk = &so->sk;
enum hrtimer_restart restart = HRTIMER_NORESTART;
switch (so->tx.state) {
case ISOTP_SENDING:
/* don't handle timeouts in IDLE state */
if (so->tx.state == ISOTP_IDLE)
return HRTIMER_NORESTART;
/* cfecho should be consumed by isotp_rcv_echo() here */
if (!so->cfecho) {
/* start timeout for unlikely lost echo skb */
hrtimer_set_expires(&so->txtimer,
ktime_add(ktime_get(),
ktime_set(ISOTP_ECHO_TIMEOUT, 0)));
restart = HRTIMER_RESTART;
/* we did not get any flow control or echo frame in time */
/* push out the next consecutive frame */
isotp_send_cframe(so);
break;
}
/* report 'communication error on send' */
sk->sk_err = ECOMM;
if (!sock_flag(sk, SOCK_DEAD))
sk_error_report(sk);
/* cfecho has not been cleared in isotp_rcv_echo() */
pr_notice_once("can-isotp: cfecho %08X timeout\n", so->cfecho);
fallthrough;
/* reset tx state */
so->tx.state = ISOTP_IDLE;
wake_up_interruptible(&so->wait);
case ISOTP_WAIT_FC:
case ISOTP_WAIT_FIRST_FC:
return HRTIMER_NORESTART;
}
/* we did not get any flow control frame in time */
static enum hrtimer_restart isotp_txfr_timer_handler(struct hrtimer *hrtimer)
{
struct isotp_sock *so = container_of(hrtimer, struct isotp_sock,
txfrtimer);
/* report 'communication error on send' */
sk->sk_err = ECOMM;
if (!sock_flag(sk, SOCK_DEAD))
sk_error_report(sk);
/* start echo timeout handling and cover below protocol error */
hrtimer_start(&so->txtimer, ktime_set(ISOTP_ECHO_TIMEOUT, 0),
HRTIMER_MODE_REL_SOFT);
/* reset tx state */
so->tx.state = ISOTP_IDLE;
wake_up_interruptible(&so->wait);
break;
/* cfecho should be consumed by isotp_rcv_echo() here */
if (so->tx.state == ISOTP_SENDING && !so->cfecho)
isotp_send_cframe(so);
default:
WARN_ONCE(1, "can-isotp: tx timer state %08X cfecho %08X\n",
so->tx.state, so->cfecho);
}
return restart;
return HRTIMER_NORESTART;
}
static int isotp_sendmsg(struct socket *sock, struct msghdr *msg, size_t size)
@ -1162,6 +1152,10 @@ static int isotp_release(struct socket *sock)
/* wait for complete transmission of current pdu */
wait_event_interruptible(so->wait, so->tx.state == ISOTP_IDLE);
/* force state machines to be idle also when a signal occurred */
so->tx.state = ISOTP_IDLE;
so->rx.state = ISOTP_IDLE;
spin_lock(&isotp_notifier_lock);
while (isotp_busy_notifier == so) {
spin_unlock(&isotp_notifier_lock);
@ -1194,6 +1188,7 @@ static int isotp_release(struct socket *sock)
}
}
hrtimer_cancel(&so->txfrtimer);
hrtimer_cancel(&so->txtimer);
hrtimer_cancel(&so->rxtimer);
@ -1597,6 +1592,8 @@ static int isotp_init(struct sock *sk)
so->rxtimer.function = isotp_rx_timer_handler;
hrtimer_init(&so->txtimer, CLOCK_MONOTONIC, HRTIMER_MODE_REL_SOFT);
so->txtimer.function = isotp_tx_timer_handler;
hrtimer_init(&so->txfrtimer, CLOCK_MONOTONIC, HRTIMER_MODE_REL_SOFT);
so->txfrtimer.function = isotp_txfr_timer_handler;
init_waitqueue_head(&so->wait);
spin_lock_init(&so->rx_lock);

View File

@ -1092,10 +1092,6 @@ static bool j1939_session_deactivate(struct j1939_session *session)
bool active;
j1939_session_list_lock(priv);
/* This function should be called with a session ref-count of at
* least 2.
*/
WARN_ON_ONCE(kref_read(&session->kref) < 2);
active = j1939_session_deactivate_locked(session);
j1939_session_list_unlock(priv);

View File

@ -132,8 +132,8 @@ static void raw_rcv(struct sk_buff *oskb, void *data)
return;
/* make sure to not pass oversized frames to the socket */
if ((can_is_canfd_skb(oskb) && !ro->fd_frames && !ro->xl_frames) ||
(can_is_canxl_skb(oskb) && !ro->xl_frames))
if ((!ro->fd_frames && can_is_canfd_skb(oskb)) ||
(!ro->xl_frames && can_is_canxl_skb(oskb)))
return;
/* eliminate multiple filter matches for the same skb */
@ -670,6 +670,11 @@ static int raw_setsockopt(struct socket *sock, int level, int optname,
if (copy_from_sockptr(&ro->fd_frames, optval, optlen))
return -EFAULT;
/* Enabling CAN XL includes CAN FD */
if (ro->xl_frames && !ro->fd_frames) {
ro->fd_frames = ro->xl_frames;
return -EINVAL;
}
break;
case CAN_RAW_XL_FRAMES:
@ -679,6 +684,9 @@ static int raw_setsockopt(struct socket *sock, int level, int optname,
if (copy_from_sockptr(&ro->xl_frames, optval, optlen))
return -EFAULT;
/* Enabling CAN XL includes CAN FD */
if (ro->xl_frames)
ro->fd_frames = ro->xl_frames;
break;
case CAN_RAW_JOIN_FILTERS:
@ -786,6 +794,25 @@ static int raw_getsockopt(struct socket *sock, int level, int optname,
return 0;
}
static bool raw_bad_txframe(struct raw_sock *ro, struct sk_buff *skb, int mtu)
{
/* Classical CAN -> no checks for flags and device capabilities */
if (can_is_can_skb(skb))
return false;
/* CAN FD -> needs to be enabled and a CAN FD or CAN XL device */
if (ro->fd_frames && can_is_canfd_skb(skb) &&
(mtu == CANFD_MTU || can_is_canxl_dev_mtu(mtu)))
return false;
/* CAN XL -> needs to be enabled and a CAN XL device */
if (ro->xl_frames && can_is_canxl_skb(skb) &&
can_is_canxl_dev_mtu(mtu))
return false;
return true;
}
static int raw_sendmsg(struct socket *sock, struct msghdr *msg, size_t size)
{
struct sock *sk = sock->sk;
@ -833,20 +860,8 @@ static int raw_sendmsg(struct socket *sock, struct msghdr *msg, size_t size)
goto free_skb;
err = -EINVAL;
if (ro->xl_frames && can_is_canxl_dev_mtu(dev->mtu)) {
/* CAN XL, CAN FD and Classical CAN */
if (!can_is_canxl_skb(skb) && !can_is_canfd_skb(skb) &&
!can_is_can_skb(skb))
goto free_skb;
} else if (ro->fd_frames && dev->mtu == CANFD_MTU) {
/* CAN FD and Classical CAN */
if (!can_is_canfd_skb(skb) && !can_is_can_skb(skb))
goto free_skb;
} else {
/* Classical CAN */
if (!can_is_can_skb(skb))
goto free_skb;
}
if (raw_bad_txframe(ro, skb, dev->mtu))
goto free_skb;
sockcm_init(&sockc, sk);
if (msg->msg_controllen) {

View File

@ -162,6 +162,15 @@ int skb_gro_receive(struct sk_buff *p, struct sk_buff *skb)
struct sk_buff *lp;
int segs;
/* Do not splice page pool based packets w/ non-page pool
* packets. This can result in reference count issues as page
* pool pages will not decrement the reference count and will
* instead be immediately returned to the pool or have frag
* count decremented.
*/
if (p->pp_recycle != skb->pp_recycle)
return -ETOOMANYREFS;
/* pairs with WRITE_ONCE() in netif_set_gro_max_size() */
gro_max_size = READ_ONCE(p->dev->gro_max_size);

View File

@ -4100,7 +4100,7 @@ struct sk_buff *skb_segment_list(struct sk_buff *skb,
skb_shinfo(skb)->frag_list = NULL;
do {
while (list_skb) {
nskb = list_skb;
list_skb = list_skb->next;
@ -4146,8 +4146,7 @@ struct sk_buff *skb_segment_list(struct sk_buff *skb,
if (skb_needs_linearize(nskb, features) &&
__skb_linearize(nskb))
goto err_linearize;
} while (list_skb);
}
skb->truesize = skb->truesize - delta_truesize;
skb->data_len = skb->data_len - delta_len;

View File

@ -1569,15 +1569,16 @@ void sock_map_unhash(struct sock *sk)
psock = sk_psock(sk);
if (unlikely(!psock)) {
rcu_read_unlock();
if (sk->sk_prot->unhash)
sk->sk_prot->unhash(sk);
return;
saved_unhash = READ_ONCE(sk->sk_prot)->unhash;
} else {
saved_unhash = psock->saved_unhash;
sock_map_remove_links(sk, psock);
rcu_read_unlock();
}
saved_unhash = psock->saved_unhash;
sock_map_remove_links(sk, psock);
rcu_read_unlock();
saved_unhash(sk);
if (WARN_ON_ONCE(saved_unhash == sock_map_unhash))
return;
if (saved_unhash)
saved_unhash(sk);
}
EXPORT_SYMBOL_GPL(sock_map_unhash);
@ -1590,17 +1591,18 @@ void sock_map_destroy(struct sock *sk)
psock = sk_psock_get(sk);
if (unlikely(!psock)) {
rcu_read_unlock();
if (sk->sk_prot->destroy)
sk->sk_prot->destroy(sk);
return;
saved_destroy = READ_ONCE(sk->sk_prot)->destroy;
} else {
saved_destroy = psock->saved_destroy;
sock_map_remove_links(sk, psock);
rcu_read_unlock();
sk_psock_stop(psock);
sk_psock_put(sk, psock);
}
saved_destroy = psock->saved_destroy;
sock_map_remove_links(sk, psock);
rcu_read_unlock();
sk_psock_stop(psock);
sk_psock_put(sk, psock);
saved_destroy(sk);
if (WARN_ON_ONCE(saved_destroy == sock_map_destroy))
return;
if (saved_destroy)
saved_destroy(sk);
}
EXPORT_SYMBOL_GPL(sock_map_destroy);
@ -1615,16 +1617,21 @@ void sock_map_close(struct sock *sk, long timeout)
if (unlikely(!psock)) {
rcu_read_unlock();
release_sock(sk);
return sk->sk_prot->close(sk, timeout);
saved_close = READ_ONCE(sk->sk_prot)->close;
} else {
saved_close = psock->saved_close;
sock_map_remove_links(sk, psock);
rcu_read_unlock();
sk_psock_stop(psock);
release_sock(sk);
cancel_work_sync(&psock->work);
sk_psock_put(sk, psock);
}
saved_close = psock->saved_close;
sock_map_remove_links(sk, psock);
rcu_read_unlock();
sk_psock_stop(psock);
release_sock(sk);
cancel_work_sync(&psock->work);
sk_psock_put(sk, psock);
/* Make sure we do not recurse. This is a bug.
* Leak the socket instead of crashing on a stack overflow.
*/
if (WARN_ON_ONCE(saved_close == sock_map_close))
return;
saved_close(sk, timeout);
}
EXPORT_SYMBOL_GPL(sock_map_close);

View File

@ -6,6 +6,7 @@
#include <linux/bpf.h>
#include <linux/init.h>
#include <linux/wait.h>
#include <linux/util_macros.h>
#include <net/inet_common.h>
#include <net/tls.h>
@ -639,10 +640,9 @@ EXPORT_SYMBOL_GPL(tcp_bpf_update_proto);
*/
void tcp_bpf_clone(const struct sock *sk, struct sock *newsk)
{
int family = sk->sk_family == AF_INET6 ? TCP_BPF_IPV6 : TCP_BPF_IPV4;
struct proto *prot = newsk->sk_prot;
if (prot == &tcp_bpf_prots[family][TCP_BPF_BASE])
if (is_insidevar(prot, tcp_bpf_prots))
newsk->sk_prot = sk->sk_prot_creator;
}
#endif /* CONFIG_BPF_SYSCALL */

View File

@ -3127,17 +3127,17 @@ static void add_v4_addrs(struct inet6_dev *idev)
offset = sizeof(struct in6_addr) - 4;
memcpy(&addr.s6_addr32[3], idev->dev->dev_addr + offset, 4);
if (idev->dev->flags&IFF_POINTOPOINT) {
if (!(idev->dev->flags & IFF_POINTOPOINT) && idev->dev->type == ARPHRD_SIT) {
scope = IPV6_ADDR_COMPATv4;
plen = 96;
pflags |= RTF_NONEXTHOP;
} else {
if (idev->cnf.addr_gen_mode == IN6_ADDR_GEN_MODE_NONE)
return;
addr.s6_addr32[0] = htonl(0xfe800000);
scope = IFA_LINK;
plen = 64;
} else {
scope = IPV6_ADDR_COMPATv4;
plen = 96;
pflags |= RTF_NONEXTHOP;
}
if (addr.s6_addr32[3]) {
@ -3447,6 +3447,30 @@ static void addrconf_gre_config(struct net_device *dev)
}
#endif
static void addrconf_init_auto_addrs(struct net_device *dev)
{
switch (dev->type) {
#if IS_ENABLED(CONFIG_IPV6_SIT)
case ARPHRD_SIT:
addrconf_sit_config(dev);
break;
#endif
#if IS_ENABLED(CONFIG_NET_IPGRE) || IS_ENABLED(CONFIG_IPV6_GRE)
case ARPHRD_IP6GRE:
case ARPHRD_IPGRE:
addrconf_gre_config(dev);
break;
#endif
case ARPHRD_LOOPBACK:
init_loopback(dev);
break;
default:
addrconf_dev_config(dev);
break;
}
}
static int fixup_permanent_addr(struct net *net,
struct inet6_dev *idev,
struct inet6_ifaddr *ifp)
@ -3615,26 +3639,7 @@ static int addrconf_notify(struct notifier_block *this, unsigned long event,
run_pending = 1;
}
switch (dev->type) {
#if IS_ENABLED(CONFIG_IPV6_SIT)
case ARPHRD_SIT:
addrconf_sit_config(dev);
break;
#endif
#if IS_ENABLED(CONFIG_NET_IPGRE) || IS_ENABLED(CONFIG_IPV6_GRE)
case ARPHRD_IP6GRE:
case ARPHRD_IPGRE:
addrconf_gre_config(dev);
break;
#endif
case ARPHRD_LOOPBACK:
init_loopback(dev);
break;
default:
addrconf_dev_config(dev);
break;
}
addrconf_init_auto_addrs(dev);
if (!IS_ERR_OR_NULL(idev)) {
if (run_pending)
@ -6397,7 +6402,7 @@ static int addrconf_sysctl_addr_gen_mode(struct ctl_table *ctl, int write,
if (idev->cnf.addr_gen_mode != new_val) {
idev->cnf.addr_gen_mode = new_val;
addrconf_dev_config(idev->dev);
addrconf_init_auto_addrs(idev->dev);
}
} else if (&net->ipv6.devconf_all->addr_gen_mode == ctl->data) {
struct net_device *dev;
@ -6408,7 +6413,7 @@ static int addrconf_sysctl_addr_gen_mode(struct ctl_table *ctl, int write,
if (idev &&
idev->cnf.addr_gen_mode != new_val) {
idev->cnf.addr_gen_mode = new_val;
addrconf_dev_config(idev->dev);
addrconf_init_auto_addrs(idev->dev);
}
}
}

View File

@ -213,7 +213,6 @@ __ieee802154_rx_handle_packet(struct ieee802154_local *local,
ret = ieee802154_parse_frame_start(skb, &hdr);
if (ret) {
pr_debug("got invalid frame\n");
kfree_skb(skb);
return;
}

View File

@ -587,6 +587,11 @@ static void mctp_sk_unhash(struct sock *sk)
del_timer_sync(&msk->key_expiry);
}
static void mctp_sk_destruct(struct sock *sk)
{
skb_queue_purge(&sk->sk_receive_queue);
}
static struct proto mctp_proto = {
.name = "MCTP",
.owner = THIS_MODULE,
@ -623,6 +628,7 @@ static int mctp_pf_create(struct net *net, struct socket *sock,
return -ENOMEM;
sock_init_data(sock, sk);
sk->sk_destruct = mctp_sk_destruct;
rc = 0;
if (sk->sk_prot->init)

View File

@ -142,10 +142,11 @@ static void sctp_print_conntrack(struct seq_file *s, struct nf_conn *ct)
}
#endif
/* do_basic_checks ensures sch->length > 0, do not use before */
#define for_each_sctp_chunk(skb, sch, _sch, offset, dataoff, count) \
for ((offset) = (dataoff) + sizeof(struct sctphdr), (count) = 0; \
((sch) = skb_header_pointer((skb), (offset), sizeof(_sch), &(_sch))) && \
(sch)->length; \
(offset) < (skb)->len && \
((sch) = skb_header_pointer((skb), (offset), sizeof(_sch), &(_sch))); \
(offset) += (ntohs((sch)->length) + 3) & ~3, (count)++)
/* Some validity checks to make sure the chunks are fine */

View File

@ -400,6 +400,11 @@ static int nr_listen(struct socket *sock, int backlog)
struct sock *sk = sock->sk;
lock_sock(sk);
if (sock->state != SS_UNCONNECTED) {
release_sock(sk);
return -EINVAL;
}
if (sk->sk_state != TCP_LISTEN) {
memset(&nr_sk(sk)->user_addr, 0, AX25_ADDR_LEN);
sk->sk_max_ack_backlog = backlog;

View File

@ -1004,14 +1004,14 @@ static int ovs_flow_cmd_new(struct sk_buff *skb, struct genl_info *info)
key = kzalloc(sizeof(*key), GFP_KERNEL);
if (!key) {
error = -ENOMEM;
goto err_kfree_key;
goto err_kfree_flow;
}
ovs_match_init(&match, key, false, &mask);
error = ovs_nla_get_match(net, &match, a[OVS_FLOW_ATTR_KEY],
a[OVS_FLOW_ATTR_MASK], log);
if (error)
goto err_kfree_flow;
goto err_kfree_key;
ovs_flow_mask_key(&new_flow->key, key, true, &mask);
@ -1019,14 +1019,14 @@ static int ovs_flow_cmd_new(struct sk_buff *skb, struct genl_info *info)
error = ovs_nla_get_identifier(&new_flow->id, a[OVS_FLOW_ATTR_UFID],
key, log);
if (error)
goto err_kfree_flow;
goto err_kfree_key;
/* Validate actions. */
error = ovs_nla_copy_actions(net, a[OVS_FLOW_ATTR_ACTIONS],
&new_flow->key, &acts, log);
if (error) {
OVS_NLERR(log, "Flow actions may not be safe on all matching packets.");
goto err_kfree_flow;
goto err_kfree_key;
}
reply = ovs_flow_cmd_alloc_info(acts, &new_flow->id, info, false,
@ -1126,10 +1126,10 @@ err_unlock_ovs:
kfree_skb(reply);
err_kfree_acts:
ovs_nla_free_flow_actions(acts);
err_kfree_flow:
ovs_flow_free(new_flow, false);
err_kfree_key:
kfree(key);
err_kfree_flow:
ovs_flow_free(new_flow, false);
error:
return error;
}

View File

@ -83,7 +83,10 @@ static struct qrtr_node *node_get(unsigned int node_id)
node->id = node_id;
radix_tree_insert(&nodes, node_id, node);
if (radix_tree_insert(&nodes, node_id, node)) {
kfree(node);
return NULL;
}
return node;
}

View File

@ -488,6 +488,12 @@ static int rose_listen(struct socket *sock, int backlog)
{
struct sock *sk = sock->sk;
lock_sock(sk);
if (sock->state != SS_UNCONNECTED) {
release_sock(sk);
return -EINVAL;
}
if (sk->sk_state != TCP_LISTEN) {
struct rose_sock *rose = rose_sk(sk);
@ -497,8 +503,10 @@ static int rose_listen(struct socket *sock, int backlog)
memset(rose->dest_digis, 0, AX25_ADDR_LEN * ROSE_MAX_DIGIS);
sk->sk_max_ack_backlog = backlog;
sk->sk_state = TCP_LISTEN;
release_sock(sk);
return 0;
}
release_sock(sk);
return -EOPNOTSUPP;
}

View File

@ -431,7 +431,10 @@ static void htb_activate_prios(struct htb_sched *q, struct htb_class *cl)
while (cl->cmode == HTB_MAY_BORROW && p && mask) {
m = mask;
while (m) {
int prio = ffz(~m);
unsigned int prio = ffz(~m);
if (WARN_ON_ONCE(prio > ARRAY_SIZE(p->inner.clprio)))
break;
m &= ~(1 << prio);
if (p->inner.clprio[prio].feed.rb_node)

View File

@ -196,9 +196,7 @@ void sctp_transport_reset_hb_timer(struct sctp_transport *transport)
/* When a data chunk is sent, reset the heartbeat interval. */
expires = jiffies + sctp_transport_timeout(transport);
if ((time_before(transport->hb_timer.expires, expires) ||
!timer_pending(&transport->hb_timer)) &&
!mod_timer(&transport->hb_timer,
if (!mod_timer(&transport->hb_timer,
expires + get_random_u32_below(transport->rto)))
sctp_transport_hold(transport);
}

View File

@ -2427,7 +2427,7 @@ static bool tls_is_tx_ready(struct tls_sw_context_tx *ctx)
{
struct tls_rec *rec;
rec = list_first_entry(&ctx->tx_list, struct tls_rec, list);
rec = list_first_entry_or_null(&ctx->tx_list, struct tls_rec, list);
if (!rec)
return false;

View File

@ -30,6 +30,8 @@
#define MAX_STRERR_LEN 256
#define MAX_TEST_NAME 80
#define __always_unused __attribute__((__unused__))
#define _FAIL(errnum, fmt...) \
({ \
error_at_line(0, (errnum), __func__, __LINE__, fmt); \
@ -321,7 +323,8 @@ static int socket_loopback(int family, int sotype)
return socket_loopback_reuseport(family, sotype, -1);
}
static void test_insert_invalid(int family, int sotype, int mapfd)
static void test_insert_invalid(struct test_sockmap_listen *skel __always_unused,
int family, int sotype, int mapfd)
{
u32 key = 0;
u64 value;
@ -338,7 +341,8 @@ static void test_insert_invalid(int family, int sotype, int mapfd)
FAIL_ERRNO("map_update: expected EBADF");
}
static void test_insert_opened(int family, int sotype, int mapfd)
static void test_insert_opened(struct test_sockmap_listen *skel __always_unused,
int family, int sotype, int mapfd)
{
u32 key = 0;
u64 value;
@ -359,7 +363,8 @@ static void test_insert_opened(int family, int sotype, int mapfd)
xclose(s);
}
static void test_insert_bound(int family, int sotype, int mapfd)
static void test_insert_bound(struct test_sockmap_listen *skel __always_unused,
int family, int sotype, int mapfd)
{
struct sockaddr_storage addr;
socklen_t len;
@ -386,7 +391,8 @@ close:
xclose(s);
}
static void test_insert(int family, int sotype, int mapfd)
static void test_insert(struct test_sockmap_listen *skel __always_unused,
int family, int sotype, int mapfd)
{
u64 value;
u32 key;
@ -402,7 +408,8 @@ static void test_insert(int family, int sotype, int mapfd)
xclose(s);
}
static void test_delete_after_insert(int family, int sotype, int mapfd)
static void test_delete_after_insert(struct test_sockmap_listen *skel __always_unused,
int family, int sotype, int mapfd)
{
u64 value;
u32 key;
@ -419,7 +426,8 @@ static void test_delete_after_insert(int family, int sotype, int mapfd)
xclose(s);
}
static void test_delete_after_close(int family, int sotype, int mapfd)
static void test_delete_after_close(struct test_sockmap_listen *skel __always_unused,
int family, int sotype, int mapfd)
{
int err, s;
u64 value;
@ -442,7 +450,8 @@ static void test_delete_after_close(int family, int sotype, int mapfd)
FAIL_ERRNO("map_delete: expected EINVAL/EINVAL");
}
static void test_lookup_after_insert(int family, int sotype, int mapfd)
static void test_lookup_after_insert(struct test_sockmap_listen *skel __always_unused,
int family, int sotype, int mapfd)
{
u64 cookie, value;
socklen_t len;
@ -470,7 +479,8 @@ static void test_lookup_after_insert(int family, int sotype, int mapfd)
xclose(s);
}
static void test_lookup_after_delete(int family, int sotype, int mapfd)
static void test_lookup_after_delete(struct test_sockmap_listen *skel __always_unused,
int family, int sotype, int mapfd)
{
int err, s;
u64 value;
@ -493,7 +503,8 @@ static void test_lookup_after_delete(int family, int sotype, int mapfd)
xclose(s);
}
static void test_lookup_32_bit_value(int family, int sotype, int mapfd)
static void test_lookup_32_bit_value(struct test_sockmap_listen *skel __always_unused,
int family, int sotype, int mapfd)
{
u32 key, value32;
int err, s;
@ -523,7 +534,8 @@ close:
xclose(s);
}
static void test_update_existing(int family, int sotype, int mapfd)
static void test_update_existing(struct test_sockmap_listen *skel __always_unused,
int family, int sotype, int mapfd)
{
int s1, s2;
u64 value;
@ -551,7 +563,7 @@ close_s1:
/* Exercise the code path where we destroy child sockets that never
* got accept()'ed, aka orphans, when parent socket gets closed.
*/
static void test_destroy_orphan_child(int family, int sotype, int mapfd)
static void do_destroy_orphan_child(int family, int sotype, int mapfd)
{
struct sockaddr_storage addr;
socklen_t len;
@ -582,10 +594,38 @@ close_srv:
xclose(s);
}
static void test_destroy_orphan_child(struct test_sockmap_listen *skel,
int family, int sotype, int mapfd)
{
int msg_verdict = bpf_program__fd(skel->progs.prog_msg_verdict);
int skb_verdict = bpf_program__fd(skel->progs.prog_skb_verdict);
const struct test {
int progfd;
enum bpf_attach_type atype;
} tests[] = {
{ -1, -1 },
{ msg_verdict, BPF_SK_MSG_VERDICT },
{ skb_verdict, BPF_SK_SKB_VERDICT },
};
const struct test *t;
for (t = tests; t < tests + ARRAY_SIZE(tests); t++) {
if (t->progfd != -1 &&
xbpf_prog_attach(t->progfd, mapfd, t->atype, 0) != 0)
return;
do_destroy_orphan_child(family, sotype, mapfd);
if (t->progfd != -1)
xbpf_prog_detach2(t->progfd, mapfd, t->atype);
}
}
/* Perform a passive open after removing listening socket from SOCKMAP
* to ensure that callbacks get restored properly.
*/
static void test_clone_after_delete(int family, int sotype, int mapfd)
static void test_clone_after_delete(struct test_sockmap_listen *skel __always_unused,
int family, int sotype, int mapfd)
{
struct sockaddr_storage addr;
socklen_t len;
@ -621,7 +661,8 @@ close_srv:
* SOCKMAP, but got accept()'ed only after the parent has been removed
* from SOCKMAP, gets cloned without parent psock state or callbacks.
*/
static void test_accept_after_delete(int family, int sotype, int mapfd)
static void test_accept_after_delete(struct test_sockmap_listen *skel __always_unused,
int family, int sotype, int mapfd)
{
struct sockaddr_storage addr;
const u32 zero = 0;
@ -675,7 +716,8 @@ close_srv:
/* Check that child socket that got created and accepted while parent
* was in a SOCKMAP is cloned without parent psock state or callbacks.
*/
static void test_accept_before_delete(int family, int sotype, int mapfd)
static void test_accept_before_delete(struct test_sockmap_listen *skel __always_unused,
int family, int sotype, int mapfd)
{
struct sockaddr_storage addr;
const u32 zero = 0, one = 1;
@ -784,7 +826,8 @@ done:
return NULL;
}
static void test_syn_recv_insert_delete(int family, int sotype, int mapfd)
static void test_syn_recv_insert_delete(struct test_sockmap_listen *skel __always_unused,
int family, int sotype, int mapfd)
{
struct connect_accept_ctx ctx = { 0 };
struct sockaddr_storage addr;
@ -847,7 +890,8 @@ static void *listen_thread(void *arg)
return NULL;
}
static void test_race_insert_listen(int family, int socktype, int mapfd)
static void test_race_insert_listen(struct test_sockmap_listen *skel __always_unused,
int family, int socktype, int mapfd)
{
struct connect_accept_ctx ctx = { 0 };
const u32 zero = 0;
@ -1473,7 +1517,8 @@ static void test_ops(struct test_sockmap_listen *skel, struct bpf_map *map,
int family, int sotype)
{
const struct op_test {
void (*fn)(int family, int sotype, int mapfd);
void (*fn)(struct test_sockmap_listen *skel,
int family, int sotype, int mapfd);
const char *name;
int sotype;
} tests[] = {
@ -1520,7 +1565,7 @@ static void test_ops(struct test_sockmap_listen *skel, struct bpf_map *map,
if (!test__start_subtest(s))
continue;
t->fn(family, sotype, map_fd);
t->fn(skel, family, sotype, map_fd);
test_ops_cleanup(map);
}
}

View File

@ -225,3 +225,39 @@
.result_unpriv = ACCEPT,
.insn_processed = 15,
},
/* The test performs a conditional 64-bit write to a stack location
* fp[-8], this is followed by an unconditional 8-bit write to fp[-8],
* then data is read from fp[-8]. This sequence is unsafe.
*
* The test would be mistakenly marked as safe w/o dst register parent
* preservation in verifier.c:copy_register_state() function.
*
* Note the usage of BPF_F_TEST_STATE_FREQ to force creation of the
* checkpoint state after conditional 64-bit assignment.
*/
{
"write tracking and register parent chain bug",
.insns = {
/* r6 = ktime_get_ns() */
BPF_EMIT_CALL(BPF_FUNC_ktime_get_ns),
BPF_MOV64_REG(BPF_REG_6, BPF_REG_0),
/* r0 = ktime_get_ns() */
BPF_EMIT_CALL(BPF_FUNC_ktime_get_ns),
/* if r0 > r6 goto +1 */
BPF_JMP_REG(BPF_JGT, BPF_REG_0, BPF_REG_6, 1),
/* *(u64 *)(r10 - 8) = 0xdeadbeef */
BPF_ST_MEM(BPF_DW, BPF_REG_FP, -8, 0xdeadbeef),
/* r1 = 42 */
BPF_MOV64_IMM(BPF_REG_1, 42),
/* *(u8 *)(r10 - 8) = r1 */
BPF_STX_MEM(BPF_B, BPF_REG_FP, BPF_REG_1, -8),
/* r2 = *(u64 *)(r10 - 8) */
BPF_LDX_MEM(BPF_DW, BPF_REG_2, BPF_REG_FP, -8),
/* exit(0) */
BPF_MOV64_IMM(BPF_REG_0, 0),
BPF_EXIT_INSN(),
},
.flags = BPF_F_TEST_STATE_FREQ,
.errstr = "invalid read from stack off -8+1 size 8",
.result = REJECT,
},

View File

@ -6,7 +6,7 @@ ksft_skip=4
NS=ns
IP6=2001:db8:1::1/64
TGT6=2001:db8:1::2
TMPF=`mktemp`
TMPF=$(mktemp --suffix ".pcap")
cleanup()
{

View File

@ -7,6 +7,7 @@ readonly GREEN='\033[0;92m'
readonly YELLOW='\033[0;33m'
readonly RED='\033[0;31m'
readonly NC='\033[0m' # No Color
readonly TESTPORT=8000
readonly KSFT_PASS=0
readonly KSFT_FAIL=1
@ -56,11 +57,26 @@ trap wake_children EXIT
run_one() {
local -r args=$@
local nr_socks=0
local i=0
local -r timeout=10
./udpgso_bench_rx &
./udpgso_bench_rx -t &
./udpgso_bench_rx -p "$TESTPORT" &
./udpgso_bench_rx -p "$TESTPORT" -t &
./udpgso_bench_tx ${args}
# Wait for the above test program to get ready to receive connections.
while [ "$i" -lt "$timeout" ]; do
nr_socks="$(ss -lnHi | grep -c "\*:${TESTPORT}")"
[ "$nr_socks" -eq 2 ] && break
i=$((i + 1))
sleep 1
done
if [ "$nr_socks" -ne 2 ]; then
echo "timed out while waiting for udpgso_bench_rx"
exit 1
fi
./udpgso_bench_tx -p "$TESTPORT" ${args}
}
run_in_netns() {

View File

@ -250,7 +250,7 @@ static int recv_msg(int fd, char *buf, int len, int *gso_size)
static void do_flush_udp(int fd)
{
static char rbuf[ETH_MAX_MTU];
int ret, len, gso_size, budget = 256;
int ret, len, gso_size = 0, budget = 256;
len = cfg_read_all ? sizeof(rbuf) : 0;
while (budget--) {
@ -336,6 +336,8 @@ static void parse_opts(int argc, char **argv)
cfg_verify = true;
cfg_read_all = true;
break;
default:
exit(1);
}
}

View File

@ -62,6 +62,7 @@ static int cfg_payload_len = (1472 * 42);
static int cfg_port = 8000;
static int cfg_runtime_ms = -1;
static bool cfg_poll;
static int cfg_poll_loop_timeout_ms = 2000;
static bool cfg_segment;
static bool cfg_sendmmsg;
static bool cfg_tcp;
@ -235,16 +236,17 @@ static void flush_errqueue_recv(int fd)
}
}
static void flush_errqueue(int fd, const bool do_poll)
static void flush_errqueue(int fd, const bool do_poll,
unsigned long poll_timeout, const bool poll_err)
{
if (do_poll) {
struct pollfd fds = {0};
int ret;
fds.fd = fd;
ret = poll(&fds, 1, 500);
ret = poll(&fds, 1, poll_timeout);
if (ret == 0) {
if (cfg_verbose)
if ((cfg_verbose) && (poll_err))
fprintf(stderr, "poll timeout\n");
} else if (ret < 0) {
error(1, errno, "poll");
@ -254,6 +256,20 @@ static void flush_errqueue(int fd, const bool do_poll)
flush_errqueue_recv(fd);
}
static void flush_errqueue_retry(int fd, unsigned long num_sends)
{
unsigned long tnow, tstop;
bool first_try = true;
tnow = gettimeofday_ms();
tstop = tnow + cfg_poll_loop_timeout_ms;
do {
flush_errqueue(fd, true, tstop - tnow, first_try);
first_try = false;
tnow = gettimeofday_ms();
} while ((stat_zcopies != num_sends) && (tnow < tstop));
}
static int send_tcp(int fd, char *data)
{
int ret, done = 0, count = 0;
@ -413,7 +429,8 @@ static int send_udp_segment(int fd, char *data)
static void usage(const char *filepath)
{
error(1, 0, "Usage: %s [-46acmHPtTuvz] [-C cpu] [-D dst ip] [-l secs] [-M messagenr] [-p port] [-s sendsize] [-S gsosize]",
error(1, 0, "Usage: %s [-46acmHPtTuvz] [-C cpu] [-D dst ip] [-l secs] "
"[-L secs] [-M messagenr] [-p port] [-s sendsize] [-S gsosize]",
filepath);
}
@ -423,7 +440,7 @@ static void parse_opts(int argc, char **argv)
int max_len, hdrlen;
int c;
while ((c = getopt(argc, argv, "46acC:D:Hl:mM:p:s:PS:tTuvz")) != -1) {
while ((c = getopt(argc, argv, "46acC:D:Hl:L:mM:p:s:PS:tTuvz")) != -1) {
switch (c) {
case '4':
if (cfg_family != PF_UNSPEC)
@ -452,6 +469,9 @@ static void parse_opts(int argc, char **argv)
case 'l':
cfg_runtime_ms = strtoul(optarg, NULL, 10) * 1000;
break;
case 'L':
cfg_poll_loop_timeout_ms = strtoul(optarg, NULL, 10) * 1000;
break;
case 'm':
cfg_sendmmsg = true;
break;
@ -490,6 +510,8 @@ static void parse_opts(int argc, char **argv)
case 'z':
cfg_zerocopy = true;
break;
default:
exit(1);
}
}
@ -677,7 +699,7 @@ int main(int argc, char **argv)
num_sends += send_udp(fd, buf[i]);
num_msgs++;
if ((cfg_zerocopy && ((num_msgs & 0xF) == 0)) || cfg_tx_tstamp)
flush_errqueue(fd, cfg_poll);
flush_errqueue(fd, cfg_poll, 500, true);
if (cfg_msg_nr && num_msgs >= cfg_msg_nr)
break;
@ -696,7 +718,7 @@ int main(int argc, char **argv)
} while (!interrupted && (cfg_runtime_ms == -1 || tnow < tstop));
if (cfg_zerocopy || cfg_tx_tstamp)
flush_errqueue(fd, true);
flush_errqueue_retry(fd, num_sends);
if (close(fd))
error(1, errno, "close");