7.0.10-rc1 review
Subsystems (6)
Greg Kroah-Hartman
maintainerPATCH 93/1146 wifi: mt76: mt7996: fix the behavior of radar detection
In reply to Greg Kroah-Hartman7.0-stable review patch. If anyone has any objections, please let me know.
------------------
From: StanleyYP Wang <[email protected]>
[ Upstream commit 45a09251d610f3b8a1fb02039146e42f1f4efe90 ]
RDD_DET_MODE is a firmware command intended for testing and does not pause TX after radar detection, so remove it from the normal flow; instead, use the MAC_ENABLE_CTRL firmware command to resume TX after the radar-triggered channel switch completes.
--- .../net/wireless/mediatek/mt76/mt7996/mac.c | 8 +-- .../net/wireless/mediatek/mt76/mt7996/main.c | 20 ++++++++ .../net/wireless/mediatek/mt76/mt7996/mcu.c | 49 ++++++++++++++++--- .../net/wireless/mediatek/mt76/mt7996/mcu.h | 1 + .../wireless/mediatek/mt76/mt7996/mt7996.h | 2 + 5 files changed, 68 insertions(+), 12 deletions(-)
drivers/net/wireless/mediatek/mt76/mt7996/mac.c +2 -6
@@ -2974,7 +2974,7 @@ static void mt7996_dfs_stop_radar_detector(struct mt7996_phy *phy)static int mt7996_dfs_start_rdd (struct mt7996_dev *dev,int rdd_idx) { -int err, region; +int region;switch (dev->mt76.region) {case NL80211_DFS_ETSI :
@@ -2989,11 +2989,7 @@ static int mt7996_dfs_start_rdd(struct mt7996_dev *dev, int rdd_idx)break ; } - err =mt7996_mcu_rdd_cmd (dev,RDD_START , rdd_idx, region); -if (err <0 ) -return err; - -return mt7996_mcu_rdd_cmd (dev,RDD_DET_MODE , rdd_idx,1 ); +return mt7996_mcu_rdd_cmd (dev,RDD_START , rdd_idx, region); }static int mt7996_dfs_start_radar_detector (struct mt7996_phy *phy)
drivers/net/wireless/mediatek/mt76/mt7996/main.c +20 -0
@@ -79,6 +79,7 @@ static void mt7996_stop_phy(struct mt7996_phy *phy)mutex_lock (&dev->mt76.mutex); +mt7996_mcu_rdd_resume_tx (phy);mt7996_mcu_set_radio_en (phy, false);clear_bit (MT76_STATE_RUNNING , &phy->mt76->state);
@@ -933,6 +934,24 @@ mt7996_channel_switch_beacon(struct ieee80211_hw *hw,mutex_unlock (&dev->mt76.mutex); } +static int +mt7996_post_channel_switch (struct ieee80211_hw *hw,struct ieee80211_vif *vif, +struct ieee80211_bss_conf *link_conf) +{ +struct cfg80211_chan_def *chandef = &link_conf->chanreq.oper; +struct mt7996_dev *dev =mt7996_hw_dev (hw); +struct mt7996_phy *phy =mt7996_band_phy (dev, chandef->chan->band); +int ret; + +mutex_lock (&dev->mt76.mutex); + + ret =mt7996_mcu_rdd_resume_tx (phy); + +mutex_unlock (&dev->mt76.mutex); + +return ret; +} + static int mt7996_mac_sta_init_link(struct mt7996_dev *dev, struct ieee80211_bss_conf *link_conf,
@@ -2306,6 +2325,7 @@ const struct ieee80211_ops mt7996_ops = { .release_buffered_frames = mt76_release_buffered_frames, .get_txpower = mt7996_get_txpower, .channel_switch_beacon = mt7996_channel_switch_beacon, + .post_channel_switch = mt7996_post_channel_switch, .get_stats = mt7996_get_stats, .get_et_sset_count = mt7996_get_et_sset_count, .get_et_stats = mt7996_get_et_stats,
drivers/net/wireless/mediatek/mt76/mt7996/mcu.c +43 -6
73 lines not on this page · raw message
drivers/net/wireless/mediatek/mt76/mt7996/mcu.h +1 -0
@@ -837,6 +837,7 @@ enum {enum {UNI_BAND_CONFIG_RADIO_ENABLE ,UNI_BAND_CONFIG_RTS_THRESHOLD =0x08 , +UNI_BAND_CONFIG_MAC_ENABLE_CTRL =0x0c , };enum {
drivers/net/wireless/mediatek/mt76/mt7996/mt7996.h +2 -0
@@ -377,6 +377,7 @@ struct mt7996_phy {bool has_aux_rx;bool counter_reset; +bool rdd_tx_paused; };struct mt7996_dev {
@@ -726,6 +727,7 @@ int mt7996_mcu_get_temperature(struct mt7996_phy *phy);int mt7996_mcu_set_thermal_throttling (struct mt7996_phy *phy,u8 state);int mt7996_mcu_set_thermal_protect (struct mt7996_phy *phy,bool enable);int mt7996_mcu_set_txpower_sku (struct mt7996_phy *phy); +int mt7996_mcu_rdd_resume_tx (struct mt7996_phy *phy);int mt7996_mcu_rdd_cmd (struct mt7996_dev *dev,int cmd,u8 rdd_idx,u8 val);int mt7996_mcu_rdd_background_enable (struct mt7996_phy *phy,struct cfg80211_chan_def *chandef);
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 94/1146 wifi: mt76: mt7996: fix iface combination for different chipsets
In reply to Greg Kroah-Hartman7.0-stable review patch. If anyone has any objections, please let me know.
------------------
From: Shayne Chen <[email protected]>
[ Upstream commit 5ef0e8e2653b1ba325eb883ffb94073f19cb669a ]
MT7992 and MT7990 support up to 19 interfaces per band and 32 in total.
--- .../net/wireless/mediatek/mt76/mt7996/init.c | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-)
drivers/net/wireless/mediatek/mt76/mt7996/init.c +16 -1
@@ -34,6 +34,20 @@ static const struct ieee80211_iface_combination if_comb_global = {BIT (NL80211_CHAN_WIDTH_40 ) |BIT (NL80211_CHAN_WIDTH_80 ) | BIT(NL80211_CHAN_WIDTH_160), + .beacon_int_min_gcd = 100, +}; + +static const struct ieee80211_iface_combination if_comb_global_7992 = { + .limits = &if_limits_global, + .n_limits =1 , + .max_interfaces =32 , + .num_different_channels =MT7996_MAX_RADIOS -1 , + .radar_detect_widths =BIT (NL80211_CHAN_WIDTH_20_NOHT ) | +BIT (NL80211_CHAN_WIDTH_20 ) | +BIT (NL80211_CHAN_WIDTH_40 ) | +BIT (NL80211_CHAN_WIDTH_80 ) | +BIT (NL80211_CHAN_WIDTH_160 ), + .beacon_int_min_gcd =100 , };static const struct ieee80211_iface_limit if_limits[] = {
@@ -485,7 +499,8 @@ mt7996_init_wiphy(struct ieee80211_hw *hw, struct mtk_wed_device *wed) hw->vif_data_size =sizeof (struct mt7996_vif ); hw->chanctx_data_size =sizeof (struct mt76_chanctx ); - wiphy->iface_combinations = &if_comb_global; + wiphy->iface_combinations =is_mt7996 (&dev->mt76) ? &if_comb_global : + &if_comb_global_7992; wiphy->n_iface_combinations =1 ; wiphy->radio = dev->radios;
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 95/1146 wifi: mt76: mt7996: Set mtxq->wcid just for primary link
In reply to Greg Kroah-Hartman7.0-stable review patch. If anyone has any objections, please let me know.
------------------
From: Lorenzo Bianconi <[email protected]>
[ Upstream commit 654abcbe4528f74428b69292fad5c4224414fa1b ]
Set WCID index in mt76_txq struct just for the primary link in mt7996_vif_link_add routine.
--- drivers/net/wireless/mediatek/mt76/mt7996/main.c | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-)
drivers/net/wireless/mediatek/mt76/mt7996/main.c +6 -8
@@ -301,7 +301,6 @@ int mt7996_vif_link_add(struct mt76_phy *mphy, struct ieee80211_vif *vif, .cmd = SET_KEY, .link_id = link_conf->link_id, }; -struct mt76_txq *mtxq;int mld_idx, idx, ret; mlink->idx =__ffs64 (~dev->mt76.vif_mask);
@@ -344,11 +343,6 @@ int mt7996_vif_link_add(struct mt76_phy *mphy, struct ieee80211_vif *vif,mt7996_mac_wtbl_update (dev, idx,MT_WTBL_UPDATE_ADM_COUNT_CLEAR ); -if (vif->txq) { - mtxq = (struct mt76_txq *)vif->txq->drv_priv; - mtxq->wcid = idx; - } -if (vif->type !=NL80211_IFTYPE_AP && (!mlink->omac_idx || mlink->omac_idx >3 )) vif->offload_flags =0 ;
@@ -371,9 +365,13 @@ int mt7996_vif_link_add(struct mt76_phy *mphy, struct ieee80211_vif *vif,ieee80211_iter_keys (mphy->hw, vif, mt7996_key_iter, &it); -if (!mlink->wcid->offchannel && - mvif->mt76.deflink_id ==IEEE80211_LINK_UNSPECIFIED ) +if (vif->txq && !mlink->wcid->offchannel && + mvif->mt76.deflink_id ==IEEE80211_LINK_UNSPECIFIED ) { +struct mt76_txq *mtxq = (struct mt76_txq *)vif->txq->drv_priv; + mvif->mt76.deflink_id = link_conf->link_id; + mtxq->wcid = idx; + }return 0 ; }
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 96/1146 wifi: mt76: mt7996: Reset mtxq->idx if primary link is removed in mt7996_vif_link_remove()
In reply to Greg Kroah-Hartman7.0-stable review patch. If anyone has any objections, please let me know.
------------------
From: Lorenzo Bianconi <[email protected]>
[ Upstream commit 751a2679b15e3a0fa8fc9175862f0ec40643db68 ]
Reset WCID index in mt76_txq struct if primary link is removed in mt7996_vif_link_remove routine.
--- .../net/wireless/mediatek/mt76/mt7996/main.c | 21 ++++++++++++++----- 1 file changed, 16 insertions(+), 5 deletions(-)
drivers/net/wireless/mediatek/mt76/mt7996/main.c +16 -5
@@ -402,17 +402,28 @@ void mt7996_vif_link_remove(struct mt76_phy *mphy, struct ieee80211_vif *vif,rcu_assign_pointer (dev->mt76.wcid[idx],NULL ); -if (!mlink->wcid->offchannel && +if (vif->txq && !mlink->wcid->offchannel && mvif->mt76.deflink_id == link_conf->link_id) {struct ieee80211_bss_conf *iter; +struct mt76_txq *mtxq;unsigned int link_id; mvif->mt76.deflink_id =IEEE80211_LINK_UNSPECIFIED ; + mtxq = (struct mt76_txq *)vif->txq->drv_priv; +/* Primary link will be removed, look for a new one */ for_each_vif_active_link (vif, iter, link_id) { -if (link_id !=IEEE80211_LINK_UNSPECIFIED ) { - mvif->mt76.deflink_id = link_id; -break ; - } +struct mt7996_vif_link *link; + +if (link_id == link_conf->link_id) +continue ; + + link =mt7996_vif_link (dev, vif, link_id); +if (!link) +continue ; + + mtxq->wcid = link->msta_link.wcid.idx; + mvif->mt76.deflink_id = link_id; +break ; } }
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 97/1146 wifi: mt76: mt7996: Switch to the secondary link if the default one is removed
In reply to Greg Kroah-Hartman7.0-stable review patch. If anyone has any objections, please let me know.
------------------
From: Lorenzo Bianconi <[email protected]>
[ Upstream commit 5ef44c200618430b004233cbfc1b0929a13d5ac8 ]
Switch to the secondary link if available in mt7996_mac_sta_remove_links routine if the primary one is removed.
Moreover reset secondary link index for single link scenario.
--- .../net/wireless/mediatek/mt76/mt7996/mac.c | 12 ++--- .../net/wireless/mediatek/mt76/mt7996/main.c | 51 +++++++++++++------ 2 files changed, 41 insertions(+), 22 deletions(-)
drivers/net/wireless/mediatek/mt76/mt7996/mac.c +5 -7
@@ -2404,14 +2404,12 @@ mt7996_mac_reset_sta_iter(void *data, struct ieee80211_sta *sta)continue ;mt7996_mac_sta_deinit_link (dev, msta_link); - -if (msta->deflink_id == i) { - msta->deflink_id =IEEE80211_LINK_UNSPECIFIED ; -continue ; - } - -kfree_rcu (msta_link, rcu_head); +if (msta_link != &msta->deflink) +kfree_rcu (msta_link, rcu_head); } + + msta->deflink_id =IEEE80211_LINK_UNSPECIFIED ; + msta->seclink_id = msta->deflink_id; } static void
drivers/net/wireless/mediatek/mt76/mt7996/main.c +36 -15
75 lines not on this page · raw message
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 98/1146 wifi: mt76: mt7996: Clear wcid pointer in mt7996_mac_sta_deinit_link()
In reply to Greg Kroah-Hartman7.0-stable review patch. If anyone has any objections, please let me know.
------------------
From: Lorenzo Bianconi <[email protected]>
[ Upstream commit 88973240dc7c976dd320b36a9e6d925c9be083ae ]
Clear WCID pointer removing the sta link in mt7996_mac_sta_deinit_link routine.
--- drivers/net/wireless/mediatek/mt76/mt7996/main.c | 1 + 1 file changed, 1 insertion(+)
drivers/net/wireless/mediatek/mt76/mt7996/main.c +1 -0
@@ -1043,6 +1043,7 @@ void mt7996_mac_sta_deinit_link(struct mt7996_dev *dev,list_del_init (&msta_link->rc_list);spin_unlock_bh (&dev->mt76.sta_poll_lock); +rcu_assign_pointer (dev->mt76.wcid[msta_link->wcid.idx],NULL );mt76_wcid_cleanup (&dev->mt76, &msta_link->wcid);mt76_wcid_mask_clear (dev->mt76.wcid_mask, msta_link->wcid.idx); }
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 99/1146 wifi: mt76: mt7996: Reset ampdu_state state in case of failure in mt7996_tx_check_aggr()
In reply to Greg Kroah-Hartman7.0-stable review patch. If anyone has any objections, please let me know.
------------------
From: Lorenzo Bianconi <[email protected]>
[ Upstream commit c0747db7c10c2dfbdcff0e8e97021e3df1f1e362 ]
Reset the ampdu_state configured state if ieee80211_start_tx_ba_session routine fails in mt7996_tx_check_aggr()
--- drivers/net/wireless/mediatek/mt76/mt7996/mac.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-)
drivers/net/wireless/mediatek/mt76/mt7996/mac.c +3 -2
@@ -1270,8 +1270,9 @@ mt7996_tx_check_aggr(struct ieee80211_link_sta *link_sta,if (unlikely (fc != (IEEE80211_FTYPE_DATA |IEEE80211_STYPE_QOS_DATA )))return ; -if (!test_and_set_bit (tid, &wcid->ampdu_state)) -ieee80211_start_tx_ba_session (link_sta->sta, tid,0 ); +if (!test_and_set_bit (tid, &wcid->ampdu_state) && +ieee80211_start_tx_ba_session (link_sta->sta, tid,0 )) +clear_bit (tid, &wcid->ampdu_state); } static void
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 100/1146 wifi: mt76: mt7921: Reset ampdu_state state in case of failure in mt76_connac2_tx_check_aggr()
In reply to Greg Kroah-Hartman7.0-stable review patch. If anyone has any objections, please let me know.
------------------
From: Sean Wang <[email protected]>
[ Upstream commit 53ffffeb9624ffab6d9a3b1da8635a23f1172b5e ]
Reset ampdu_state if ieee80211_start_tx_ba_session() fails in mt76_connac2_tx_check_aggr(), otherwise the driver may incorrectly assume aggregation is active and skip future BA setup attempts.
--- drivers/net/wireless/mediatek/mt76/mt76_connac_mac.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-)
drivers/net/wireless/mediatek/mt76/mt76_connac_mac.c +4 -2
@@ -1153,8 +1153,10 @@ void mt76_connac2_tx_check_aggr(struct ieee80211_sta *sta, __le32 *txwi)return ; wcid = (struct mt76_wcid *)sta->drv_priv; -if (!test_and_set_bit (tid, &wcid->ampdu_state)) -ieee80211_start_tx_ba_session (sta, tid,0 ); +if (!test_and_set_bit (tid, &wcid->ampdu_state)) { +if (ieee80211_start_tx_ba_session (sta, tid,0 )) +clear_bit (tid, &wcid->ampdu_state); + } }EXPORT_SYMBOL_GPL (mt76_connac2_tx_check_aggr);
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 101/1146 wifi: mt76: mt7925: Fix incorrect MLO mode in firmware control
In reply to Greg Kroah-Hartman7.0-stable review patch. If anyone has any objections, please let me know.
------------------
From: Leon Yen <[email protected]>
[ Upstream commit 1695f662329faa07c860c73453c097823852df28 ]
The selection of MLO mode should depend on the capabilities of the STA rather than those of the peer AP to avoid compatibility issues with certain APs, such as Xiaomi BE5000 WiFi7 router.
--- drivers/net/wireless/mediatek/mt76/mt7925/main.c | 2 +- drivers/net/wireless/mediatek/mt76/mt7925/mcu.c | 9 ++++++--- drivers/net/wireless/mediatek/mt76/mt7925/mt7925.h | 4 ++-- 3 files changed, 9 insertions(+), 6 deletions(-)
drivers/net/wireless/mediatek/mt76/mt7925/main.c +1 -1
@@ -541,7 +541,7 @@ static int mt7925_set_mlo_roc(struct mt792x_phy *phy, phy->roc_grant = false; - err =mt7925_mcu_set_mlo_roc (mconf, sel_links,5 , ++phy->roc_token_id); + err =mt7925_mcu_set_mlo_roc (phy, mconf, sel_links,5 , ++phy->roc_token_id);if (err <0 ) {clear_bit (MT76_STATE_ROC , &phy->mt76->state); goto out;
drivers/net/wireless/mediatek/mt76/mt7925/mcu.c +6 -3
@@ -1294,8 +1294,8 @@ int mt7925_mcu_add_key(struct mt76_dev *dev, struct ieee80211_vif *vif,return mt76_mcu_skb_send_msg (dev, skb, mcu_cmd, true); } -int mt7925_mcu_set_mlo_roc (struct mt792x_bss_conf *mconf,u16 sel_links, -int duration,u8 token_id) +int mt7925_mcu_set_mlo_roc (struct mt792x_phy *phy,struct mt792x_bss_conf *mconf, +u16 sel_links,int duration,u8 token_id) {struct mt792x_vif *mvif = mconf->vif; struct ieee80211_vif *vif = container_of((void *)mvif,
@@ -1330,6 +1330,8 @@ int mt7925_mcu_set_mlo_roc(struct mt792x_bss_conf *mconf, u16 sel_links, .roc[1].len = cpu_to_le16(sizeof(struct roc_acquire_tlv)) }; +struct wiphy *wiphy = phy->mt76->hw->wiphy; +if (!mconf ||hweight16 (vif->valid_links) <2 ||hweight16 (sel_links) !=2 )return -EPERM ;
@@ -1352,7 +1354,8 @@ int mt7925_mcu_set_mlo_roc(struct mt792x_bss_conf *mconf, u16 sel_links, is_AG_band |= links[i].chan->band ==NL80211_BAND_2GHZ ; } -if (vif->cfg.eml_cap &IEEE80211_EML_CAP_EMLSR_SUPP ) +if (!(wiphy->iftype_ext_capab[0 ].mld_capa_and_ops & +IEEE80211_MLD_CAP_OP_MAX_SIMUL_LINKS )) type = is_AG_band ?MT7925_ROC_REQ_MLSR_AG :MT7925_ROC_REQ_MLSR_AA ;else
drivers/net/wireless/mediatek/mt76/mt7925/mt7925.h +2 -2
@@ -349,8 +349,8 @@ int mt7925_set_tx_sar_pwr(struct ieee80211_hw *hw,int mt7925_mcu_regval (struct mt792x_dev *dev,u32 regidx,u32 *val,bool set);int mt7925_mcu_set_clc (struct mt792x_dev *dev,u8 *alpha2,enum environment_cap env_cap); -int mt7925_mcu_set_mlo_roc (struct mt792x_bss_conf *mconf,u16 sel_links, -int duration,u8 token_id); +int mt7925_mcu_set_mlo_roc (struct mt792x_phy *phy,struct mt792x_bss_conf *mconf, +u16 sel_links,int duration,u8 token_id);int mt7925_mcu_set_roc (struct mt792x_phy *phy,struct mt792x_bss_conf *mconf,struct ieee80211_channel *chan,int duration,enum mt7925_roc_req type,u8 token_id);
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 102/1146 wifi: mt76: mt7615: fix use_cts_prot support
In reply to Greg Kroah-Hartman7.0-stable review patch. If anyone has any objections, please let me know.
------------------
From: Ryder Lee <[email protected]>
[ Upstream commit 1974a67d9b65c29a0a9426e32e8cd8c056de48b7 ]
Driver should not directly write WTBL to prevent overwritten issues.
With this fix, when driver needs to adjust its behavior for compatibility, especially concerning older 11g/n devices, by enabling or disabling CTS protection frames, often for hidden SSIDs or to manage legacy clients.
--- .../net/wireless/mediatek/mt76/mt7615/mac.c | 15 ------ .../net/wireless/mediatek/mt76/mt7615/main.c | 7 +-- .../net/wireless/mediatek/mt76/mt7615/mcu.c | 47 +++++++++++++++++++ .../wireless/mediatek/mt76/mt7615/mt7615.h | 5 +- .../net/wireless/mediatek/mt76/mt7615/regs.h | 2 - 5 files changed, 53 insertions(+), 23 deletions(-)
drivers/net/wireless/mediatek/mt76/mt7615/mac.c +0 -15
@@ -1167,21 +1167,6 @@ void mt7615_mac_set_rates(struct mt7615_phy *phy, struct mt7615_sta *sta, }EXPORT_SYMBOL_GPL (mt7615_mac_set_rates); -void mt7615_mac_enable_rtscts (struct mt7615_dev *dev, -struct ieee80211_vif *vif,bool enable) -{ -struct mt7615_vif *mvif = (struct mt7615_vif *)vif->drv_priv; -u32 addr; - - addr =mt7615_mac_wtbl_addr (dev, mvif->sta.wcid.idx) +3 *4 ; - -if (enable) -mt76_set (dev, addr,MT_WTBL_W3_RTS ); -else -mt76_clear (dev, addr,MT_WTBL_W3_RTS ); -} -EXPORT_SYMBOL_GPL (mt7615_mac_enable_rtscts); - static int mt7615_mac_wtbl_update_key(struct mt7615_dev *dev, struct mt76_wcid *wcid, struct ieee80211_key_conf *key,
drivers/net/wireless/mediatek/mt76/mt7615/main.c +4 -3
@@ -583,9 +583,6 @@ static void mt7615_bss_info_changed(struct ieee80211_hw *hw, } } -if (changed &BSS_CHANGED_ERP_CTS_PROT ) -mt7615_mac_enable_rtscts (dev, vif, info->use_cts_prot); -if (changed &BSS_CHANGED_BEACON_ENABLED && info->enable_beacon) {mt7615_mcu_add_bss_info (phy, vif,NULL , true);mt7615_mcu_sta_add (phy, vif,NULL , true);
@@ -598,6 +595,10 @@ static void mt7615_bss_info_changed(struct ieee80211_hw *hw, BSS_CHANGED_BEACON_ENABLED)) mt7615_mcu_add_beacon(dev, hw, vif, info->enable_beacon); +if (changed &BSS_CHANGED_HT || changed &BSS_CHANGED_ERP_CTS_PROT ) +mt7615_mcu_set_protection (phy, vif, info->ht_operation_mode, + info->use_cts_prot); +if (changed &BSS_CHANGED_PS )mt76_connac_mcu_set_vif_ps (&dev->mt76, vif);
drivers/net/wireless/mediatek/mt76/mt7615/mcu.c +47 -0
50 lines not on this page · raw message
drivers/net/wireless/mediatek/mt76/mt7615/mt7615.h +2 -3
@@ -467,8 +467,6 @@ void mt7615_mac_reset_counters(struct mt7615_phy *phy);void mt7615_mac_cca_stats_reset (struct mt7615_phy *phy);void mt7615_mac_set_scs (struct mt7615_phy *phy,bool enable);void mt7615_mac_enable_nf (struct mt7615_dev *dev,bool ext_phy); -void mt7615_mac_enable_rtscts (struct mt7615_dev *dev, -struct ieee80211_vif *vif,bool enable);void mt7615_mac_sta_poll (struct mt7615_dev *dev); int mt7615_mac_write_txwi(struct mt7615_dev *dev, __le32 *txwi, struct sk_buff *skb, struct mt76_wcid *wcid,
@@ -523,7 +521,8 @@ int mt7615_mcu_set_sku_en(struct mt7615_phy *phy, bool enable);int mt7615_mcu_apply_rx_dcoc (struct mt7615_phy *phy);int mt7615_mcu_apply_tx_dpd (struct mt7615_phy *phy);int mt7615_dfs_init_radar_detector (struct mt7615_phy *phy); - +int mt7615_mcu_set_protection (struct mt7615_phy *phy,struct ieee80211_vif *vif, +u8 ht_mode,bool use_cts_prot);int mt7615_mcu_set_roc (struct mt7615_phy *phy,struct ieee80211_vif *vif,struct ieee80211_channel *chan,int duration);
drivers/net/wireless/mediatek/mt76/mt7615/regs.h +0 -2
@@ -455,8 +455,6 @@ enum mt7615_reg_base {#define MT_WTBL_RIUCR3_RATE6 GENMASK(19, 8)#define MT_WTBL_RIUCR3_RATE7 GENMASK(31, 20) -#define MT_WTBL_W3_RTS BIT(22) -#define MT_WTBL_W5_CHANGE_BW_RATE GENMASK(7, 5)#define MT_WTBL_W5_SHORT_GI_20 BIT(8)#define MT_WTBL_W5_SHORT_GI_40 BIT(9)
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 103/1146 wifi: mt76: mt7915: fix use_cts_prot support
In reply to Greg Kroah-Hartman7.0-stable review patch. If anyone has any objections, please let me know.
------------------
From: Ryder Lee <[email protected]>
[ Upstream commit 8b2c26562b95c6397e132d21f2bd3d73aaee0c0a ]
With this fix, when driver needs to adjust its behavior for compatibility, especially concerning older 11g/n devices, by enabling or disabling CTS protection frames, often for hidden SSIDs or to manage legacy clients.
--- .../net/wireless/mediatek/mt76/mt7915/mac.c | 13 ---- .../net/wireless/mediatek/mt76/mt7915/main.c | 7 ++- .../net/wireless/mediatek/mt76/mt7915/mcu.c | 62 +++++++++++++++++++ .../net/wireless/mediatek/mt76/mt7915/mcu.h | 11 ++++ .../wireless/mediatek/mt76/mt7915/mt7915.h | 4 ++ 5 files changed, 81 insertions(+), 16 deletions(-)
drivers/net/wireless/mediatek/mt76/mt7915/mac.c +0 -13
@@ -232,19 +232,6 @@ static void mt7915_mac_sta_poll(struct mt7915_dev *dev)rcu_read_unlock (); } -void mt7915_mac_enable_rtscts (struct mt7915_dev *dev, -struct ieee80211_vif *vif,bool enable) -{ -struct mt7915_vif *mvif = (struct mt7915_vif *)vif->drv_priv; -u32 addr; - - addr =mt7915_mac_wtbl_lmac_addr (dev, mvif->sta.wcid.idx,5 ); -if (enable) -mt76_set (dev, addr,BIT (5 )); -else -mt76_clear (dev, addr,BIT (5 )); -} - static void mt7915_wed_check_ppe(struct mt7915_dev *dev, struct mt76_queue *q, struct mt7915_sta *msta, struct sk_buff *skb,
drivers/net/wireless/mediatek/mt76/mt7915/main.c +4 -3
@@ -68,7 +68,7 @@ int mt7915_run(struct ieee80211_hw *hw)if (ret) goto out; - ret =mt76_connac_mcu_set_rts_thresh (&dev->mt76,0x92b , + ret =mt76_connac_mcu_set_rts_thresh (&dev->mt76,MT7915_RTS_LEN_THRES , phy->mt76->band_idx);if (ret) goto out;
@@ -633,8 +633,9 @@ static void mt7915_bss_info_changed(struct ieee80211_hw *hw,if (set_sta ==1 )mt7915_mcu_add_sta (dev, vif,NULL ,CONN_STATE_PORT_SECURE , false); -if (changed &BSS_CHANGED_ERP_CTS_PROT ) -mt7915_mac_enable_rtscts (dev, vif, info->use_cts_prot); +if (changed &BSS_CHANGED_HT || changed &BSS_CHANGED_ERP_CTS_PROT ) +mt7915_mcu_set_protection (phy, vif, info->ht_operation_mode, + info->use_cts_prot);if (changed &BSS_CHANGED_ERP_SLOT ) {int slottime =9 ;
drivers/net/wireless/mediatek/mt76/mt7915/mcu.c +62 -0
68 lines not on this page · raw message
drivers/net/wireless/mediatek/mt76/mt7915/mcu.h +11 -0
@@ -399,6 +399,17 @@ struct bss_info_inband_discovery {__le16 prob_rsp_len; } __packed__aligned(4) ; +struct bss_info_prot { +__le16 tag; +__le16 len; +__le32 prot_type; +__le32 prot_mode; +__le32 rts_len_thres; +__le16 he_rts_thres; +u8 rts_pkt_thres; +u8 rsv[5 ]; +} __packed; +enum {BSS_INFO_BCN_CSA ,BSS_INFO_BCN_BCC ,
drivers/net/wireless/mediatek/mt76/mt7915/mt7915.h +4 -0
@@ -84,6 +84,8 @@#define MT7915_CRIT_TEMP 110#define MT7915_MAX_TEMP 120 +#define MT7915_RTS_LEN_THRES 0x92b +struct mt7915_vif ;struct mt7915_sta ;struct mt7915_dfs_pulse ;
@@ -473,6 +475,8 @@ int mt7915_mcu_add_inband_discov(struct mt7915_dev *dev, struct ieee80211_vif *v u32 changed);int mt7915_mcu_add_beacon (struct ieee80211_hw *hw,struct ieee80211_vif *vif,int enable,u32 changed); +int mt7915_mcu_set_protection (struct mt7915_phy *phy,struct ieee80211_vif *vif, +u8 ht_mode,bool use_cts_prot);int mt7915_mcu_add_obss_spr (struct mt7915_phy *phy,struct ieee80211_vif *vif,struct ieee80211_he_obss_pd *he_obss_pd); int mt7915_mcu_add_rate_ctrl(struct mt7915_dev *dev, struct ieee80211_vif *vif,
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 104/1146 wifi: mt76: mt7925: prevent NULL pointer dereference in mt7925_tx_check_aggr()
In reply to Greg Kroah-Hartman7.0-stable review patch. If anyone has any objections, please let me know.
------------------
From: Ming Yen Hsieh <[email protected]>
[ Upstream commit 83ae3a18ba957257b4c406273d2da2caeea2b439 ]
Move the NULL check for 'sta' before dereferencing it to prevent a possible crash.
--- drivers/net/wireless/mediatek/mt76/mt7925/mac.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-)
drivers/net/wireless/mediatek/mt76/mt7925/mac.c +4 -1
@@ -846,11 +846,14 @@ static void mt7925_tx_check_aggr(struct ieee80211_sta *sta, struct sk_buff *skb,bool is_8023;u16 fc, tid; +if (!sta) +return ; + link_sta =rcu_dereference (sta->link[wcid->link_id]);if (!link_sta)return ; -if (!sta || !(link_sta->ht_cap.ht_supported || link_sta->he_cap.has_he)) +if (!(link_sta->ht_cap.ht_supported || link_sta->he_cap.has_he))return ; tid = skb->priority &IEEE80211_QOS_CTL_TID_MASK ;
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 105/1146 wifi: mt76: mt7925: prevent NULL vif dereference in mt7925_mac_write_txwi
In reply to Greg Kroah-Hartman7.0-stable review patch. If anyone has any objections, please let me know.
------------------
From: Ming Yen Hsieh <[email protected]>
[ Upstream commit 962eb04e67552be406c906c83099c1d736aae3b6 ]
Check for a NULL vif before accessing ieee80211_vif_is_mld(vif) to avoid a potential kernel panic in scenarios where vif might not be initialized.
--- drivers/net/wireless/mediatek/mt76/mt7925/mac.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
drivers/net/wireless/mediatek/mt76/mt7925/mac.c +2 -2
@@ -804,8 +804,8 @@ mt7925_mac_write_txwi(struct mt76_dev *dev, __le32 *txwi, txwi[5 ] =cpu_to_le32 (val); val =MT_TXD6_DAS |FIELD_PREP (MT_TXD6_MSDU_CNT ,1 ); -if (!ieee80211_vif_is_mld (vif) || - (q_idx >=MT_LMAC_ALTX0 && q_idx <=MT_LMAC_BCN0 )) +if (vif && (!ieee80211_vif_is_mld (vif) || + (q_idx >=MT_LMAC_ALTX0 && q_idx <=MT_LMAC_BCN0 ))) val |=MT_TXD6_DIS_MAT ; txwi[6 ] =cpu_to_le32 (val); txwi[7 ] =0 ;
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 106/1146 wifi: mt76: mt7996: fix FCS error flag check in RX descriptor
In reply to Greg Kroah-Hartman7.0-stable review patch. If anyone has any objections, please let me know.
------------------
From: Alok Tiwari <[email protected]>
[ Upstream commit d8db56142e531f060c938fa0b5175ed6c8cabb11 ]
The mt7996 driver currently checks the MT_RXD3_NORMAL_FCS_ERR bit in rxd1 whereas other Connac3-based drivers(mt7925) correctly check this bit in rxd3.
Since the MT_RXD3_NORMAL_FCS_ERR bit is defined in the fourth RX descriptor word (rxd3), update mt7996 to use the proper descriptor field. This change aligns mt7996 with mt7925 and the rest of the Connac3 family.
--- drivers/net/wireless/mediatek/mt76/mt7996/mac.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/net/wireless/mediatek/mt76/mt7996/mac.c +1 -1
@@ -527,7 +527,7 @@ mt7996_mac_fill_rx(struct mt7996_dev *dev, enum mt76_rxq_id q, !(csum_status & (BIT(0) | BIT(2) | BIT(3)))) skb->ip_summed = CHECKSUM_UNNECESSARY; -if (rxd1 &MT_RXD3_NORMAL_FCS_ERR ) +if (rxd3 &MT_RXD3_NORMAL_FCS_ERR ) status->flag |=RX_FLAG_FAILED_FCS_CRC ;if (rxd1 &MT_RXD1_NORMAL_TKIP_MIC_ERR )
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 107/1146 wifi: mt76: mt7921: Place upper limit on station AID
In reply to Greg Kroah-Hartman7.0-stable review patch. If anyone has any objections, please let me know.
------------------
From: Rory Little <[email protected]>
[ Upstream commit 4d0bf21e3e20619d51d06c0c36207aabab8b712c ]
Any station configured with an AID over 20 causes a firmware crash. This situation occurred in our testing using an AP interface on 7922 hardware, with a modified hostapd, sourced from Mediatek's OpenWRT feeds.
In stock hostapd, station AIDs begin counting at 1, and this configuration is prevented with an upper limit on associated stations. However, the modified hostapd began allocation at 65, which caused the firmware to crash. This fix does not allow these AIDs to work, but will prevent the firmware crash.
This crash was only seen on IFTYPE_AP interfaces, and the fix does not appear to have an effect on IFTYPE_STATION behavior.
--- drivers/net/wireless/mediatek/mt76/mt7921/main.c | 6 ++++++ drivers/net/wireless/mediatek/mt76/mt7921/mt7921.h | 2 ++ 2 files changed, 8 insertions(+)
drivers/net/wireless/mediatek/mt76/mt7921/main.c +6 -0
@@ -808,6 +808,9 @@ int mt7921_mac_sta_add(struct mt76_dev *mdev, struct ieee80211_vif *vif,struct mt792x_vif *mvif = (struct mt792x_vif *)vif->drv_priv;int ret, idx; +if (sta->aid >MT7921_MAX_AID ) +return -ENOENT ; + idx =mt76_wcid_alloc (dev->mt76.wcid_mask, MT792x_WTBL_STA -1 );if (idx <0 )return -ENOSPC ;
@@ -851,6 +854,9 @@ int mt7921_mac_sta_event(struct mt76_dev *mdev, struct ieee80211_vif *vif,struct mt792x_sta *msta = (struct mt792x_sta *)sta->drv_priv;struct mt792x_vif *mvif = (struct mt792x_vif *)vif->drv_priv; +if (sta->aid >MT7921_MAX_AID ) +return -ENOENT ; +if (ev !=MT76_STA_EVENT_ASSOC )return 0 ;
drivers/net/wireless/mediatek/mt76/mt7921/mt7921.h +2 -0
@@ -7,6 +7,8 @@#include "../mt792x.h" #include "regs.h" +#define MT7921_MAX_AID 20 +#define MT7921_TX_RING_SIZE 2048#define MT7921_TX_MCU_RING_SIZE 256#define MT7921_TX_FWDL_RING_SIZE 128
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 108/1146 wifi: mt76: Fix memory leak destroying device
In reply to Greg Kroah-Hartman7.0-stable review patch. If anyone has any objections, please let me know.
------------------
From: Lorenzo Bianconi <[email protected]>
[ Upstream commit 6b470f36616e3448d44b0ef4b1de2a3e3a31b5be ]
All MT76 rx queues have an associated page_pool even if the queue is not associated to a NAPI (e.g. WED RRO queues with WED enabled). Destroy the page_pool running mt76_dma_cleanup routine during module unload. Moreover returns pages to the page pool if WED is not enabled for WED RRO queues.
--- drivers/net/wireless/mediatek/mt76/dma.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-)
drivers/net/wireless/mediatek/mt76/dma.c +6 -5
@@ -874,7 +874,12 @@ mt76_dma_rx_cleanup(struct mt76_dev *dev, struct mt76_queue *q)if (!buf)break ; -if (!mt76_queue_is_wed_rro (q)) +if (mtk_wed_device_active (&dev->mmio.wed) && +mt76_queue_is_wed_rro (q)) +continue ; + +if (!mt76_queue_is_wed_rro_rxdmad_c (q) && + !mt76_queue_is_wed_rro_ind (q))mt76_put_page_pool_buf (buf, false); }while (1 );
@@ -1168,10 +1173,6 @@ void mt76_dma_cleanup(struct mt76_dev *dev)mt76_for_each_q_rx (dev, i) {struct mt76_queue *q = &dev->q_rx[i]; -if (mtk_wed_device_active (&dev->mmio.wed) && -mt76_queue_is_wed_rro (q)) -continue ; -netif_napi_del (&dev->napi[i]);mt76_dma_rx_cleanup (dev, q);
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 109/1146 wifi: mt76: mt7996: Fix NPU stop procedure
In reply to Greg Kroah-Hartman7.0-stable review patch. If anyone has any objections, please let me know.
------------------
From: Lorenzo Bianconi <[email protected]>
[ Upstream commit 7aed20bd9fe427b192cce80a164429584b298bbe ]
Move mt7996_npu_hw_stop routine before disabling rx NAPIs in order to fix NPU stop procedure used during device L1 SER recovery. Add missing usleep_range in mt7996_npu_hw_stop().
--- .../net/wireless/mediatek/mt76/mt7996/mac.c | 3 +-- .../net/wireless/mediatek/mt76/mt7996/npu.c | 23 +++++++++++-------- 2 files changed, 15 insertions(+), 11 deletions(-)
drivers/net/wireless/mediatek/mt76/mt7996/mac.c +1 -2
@@ -2543,6 +2543,7 @@ void mt7996_mac_reset_work(struct work_struct *work)if (mtk_wed_device_active (&dev->mt76.mmio.wed))mtk_wed_device_stop (&dev->mt76.mmio.wed); +mt7996_npu_hw_stop (dev);ieee80211_stop_queues (mt76_hw (dev));set_bit (MT76_RESET , &dev->mphy.state);
@@ -2569,8 +2570,6 @@ void mt7996_mac_reset_work(struct work_struct *work)mutex_lock (&dev->mt76.mutex); -mt7996_npu_hw_stop (dev); -mt76_wr (dev,MT_MCU_INT_EVENT ,MT_MCU_INT_EVENT_DMA_STOPPED );if (mt7996_wait_reset_state (dev,MT_MCU_CMD_RESET_DONE )) {
drivers/net/wireless/mediatek/mt76/mt7996/npu.c +14 -9
@@ -320,33 +320,38 @@ int mt7996_npu_hw_init(struct mt7996_dev *dev)int mt7996_npu_hw_stop (struct mt7996_dev *dev) {struct airoha_npu *npu; -int i, err; +int i, err =0 ;u32 info; +mutex_lock (&dev->mt76.mutex); + npu =rcu_dereference_protected (dev->mt76.mmio.npu, &dev->mt76.mutex);if (!npu) -return 0 ; + goto unlock; err =mt76_npu_send_msg (npu,4 ,WLAN_FUNC_SET_WAIT_INODE_TXRX_REG_ADDR ,0 ,GFP_KERNEL );if (err) -return err; + goto unlock;for (i =0 ; i <10 ; i++) { err =mt76_npu_get_msg (npu,3 ,WLAN_FUNC_GET_WAIT_NPU_INFO , &info,GFP_KERNEL ); -if (err) -continue ; +if (!err && !info) +break ; -if (info) { - err = -ETIMEDOUT ; -continue ; - } + err = -ETIMEDOUT ; +usleep_range (10000 ,15000 ); }if (!err) err =mt76_npu_send_msg (npu,6 ,WLAN_FUNC_SET_WAIT_INODE_TXRX_REG_ADDR ,0 ,GFP_KERNEL ); +else +dev_err (dev->mt76.dev,"npu stop failed\n" ); +unlock: +mutex_unlock (&dev->mt76.mutex); +return err; }
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 110/1146 wifi: mt76: npu: Add missing rx_token_size initialization
In reply to Greg Kroah-Hartman7.0-stable review patch. If anyone has any objections, please let me know.
------------------
From: Lorenzo Bianconi <[email protected]>
[ Upstream commit 25e3203a2192f2b0d697b2410126bad87e62d4f0 ]
Add missing rx_token_size initialization for NPU offloading.
--- drivers/net/wireless/mediatek/mt76/npu.c | 1 + 1 file changed, 1 insertion(+)
drivers/net/wireless/mediatek/mt76/npu.c +1 -0
@@ -457,6 +457,7 @@ int mt76_npu_init(struct mt76_dev *dev, phys_addr_t phy_addr, int type) dev->mmio.npu_type = type;/* NPU offloading requires HW-RRO for RX packet reordering. */ dev->hwrro_mode =MT76_HWRRO_V3_1 ; + dev->rx_token_size =32768 ;rcu_assign_pointer (dev->mmio.npu, npu);rcu_assign_pointer (dev->mmio.ppe_dev, ppe_dev);
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 111/1146 wifi: mt76: mt7925: drop puncturing handling from BSS change path
In reply to Greg Kroah-Hartman7.0-stable review patch. If anyone has any objections, please let me know.
------------------
From: Sean Wang <[email protected]>
[ Upstream commit 59a1864509d084a4b34117e693951c06b846b00a ]
IEEE80211_CHANCTX_CHANGE_PUNCTURING is a channel context change flag and should not be checked in the BSS change handler, where the changed mask represents enum ieee80211_bss_change.
Remove the puncturing handling from the BSS path and rely on mt7925_change_chanctx() to update puncturing configuration.
--- drivers/net/wireless/mediatek/mt76/mt7925/main.c | 6 ------ 1 file changed, 6 deletions(-)
drivers/net/wireless/mediatek/mt76/mt7925/main.c +0 -6
@@ -1894,10 +1894,8 @@ static void mt7925_link_info_changed(struct ieee80211_hw *hw,struct mt792x_phy *phy =mt792x_hw_phy (hw);struct mt792x_dev *dev =mt792x_hw_dev (hw);struct mt792x_bss_conf *mconf; -struct ieee80211_bss_conf *link_conf; mconf =mt792x_vif_to_link (mvif, info->link_id); - link_conf =mt792x_vif_to_bss_conf (vif, mconf->link_id);mt792x_mutex_acquire (dev);
@@ -1939,10 +1937,6 @@ static void mt7925_link_info_changed(struct ieee80211_hw *hw, mvif->mlo_pm_state = MT792x_MLO_CHANGED_PS; } -if (changed &IEEE80211_CHANCTX_CHANGE_PUNCTURING ) -mt7925_mcu_set_eht_pp (mvif->phy->mt76, &mconf->mt76, - link_conf,NULL ); -if (changed &BSS_CHANGED_CQM )mt7925_mcu_set_rssimonitor (dev, vif);
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 112/1146 wifi: mt76: mt7925: fix potential deadlock in mt7925_roc_abort_sync
In reply to Greg Kroah-Hartman7.0-stable review patch. If anyone has any objections, please let me know.
------------------
From: Sean Wang <[email protected]>
[ Upstream commit dd08ca3f092f4185ece69ce2a835c23198b1628a ]
roc_abort_sync() can deadlock with roc_work(). roc_work() holds dev->mt76.mutex, while cancel_work_sync() waits for roc_work() to finish. If the caller already owns the same mutex, both sides block and no progress is possible.
This deadlock can occur during station removal when mt76_sta_state() -> mt76_sta_remove() -> mt7925_mac_sta_remove_link() -> mt7925_mac_link_sta_remove() -> mt7925_roc_abort_sync() invokes cancel_work_sync() while roc_work() is still running and holding dev->mt76.mutex.
This avoids the mutex deadlock and preserves exactly-once work ownership.
--- drivers/net/wireless/mediatek/mt76/mt7925/main.c | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-)
drivers/net/wireless/mediatek/mt76/mt7925/main.c +9 -5
@@ -457,12 +457,16 @@ void mt7925_roc_abort_sync(struct mt792x_dev *dev) {struct mt792x_phy *phy = &dev->phy; +if (!test_and_clear_bit (MT76_STATE_ROC , &phy->mt76->state)) +return ; +timer_delete_sync (&phy->roc_timer); -cancel_work_sync (&phy->roc_work); -if (test_and_clear_bit (MT76_STATE_ROC , &phy->mt76->state)) -ieee80211_iterate_interfaces (mt76_hw (dev), -IEEE80211_IFACE_ITER_RESUME_ALL , - mt7925_roc_iter, (void *)phy); + +cancel_work (&phy->roc_work); + +ieee80211_iterate_interfaces (mt76_hw (dev), +IEEE80211_IFACE_ITER_RESUME_ALL , + mt7925_roc_iter, (void *)phy); }EXPORT_SYMBOL_GPL (mt7925_roc_abort_sync);
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 113/1146 wifi: mt76: Fix memory leak after mt76_connac_mcu_alloc_sta_req()
In reply to Greg Kroah-Hartman7.0-stable review patch. If anyone has any objections, please let me know.
------------------
From: Zilin Guan <[email protected]>
[ Upstream commit c41075ce8cf05ed8c0e7b7efef000dce548ffc42 ]
mt76_connac_mcu_alloc_sta_req() allocates an skb which is expected to be freed eventually by mt76_mcu_skb_send_msg(). However, currently if an intermediate function fails before sending, the allocated skb is leaked.
Specifically, mt76_connac_mcu_sta_wed_update() and mt76_connac_mcu_sta_key_tlv() may fail, leading to an immediate memory leak in the error path.
Fix this by explicitly freeing the skb in these error paths. Commit 7c0f63fe37a5 ("wifi: mt76: mt7996: fix memory leak on mt7996_mcu_sta_key_tlv error") made a similar change.
Compile tested only. Issue found using a prototype static analysis tool and code review.
--- .../net/wireless/mediatek/mt76/mt76_connac_mcu.c | 16 ++++++++++++---- drivers/net/wireless/mediatek/mt76/mt7915/mcu.c | 4 +++- drivers/net/wireless/mediatek/mt76/mt7925/mcu.c | 4 +++- 3 files changed, 18 insertions(+), 6 deletions(-)
drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.c +12 -4
@@ -1295,8 +1295,10 @@ int mt76_connac_mcu_sta_ba(struct mt76_dev *dev, struct mt76_vif_link *mvif, wtbl_hdr); ret =mt76_connac_mcu_sta_wed_update (dev, skb); -if (ret) +if (ret) { +dev_kfree_skb (skb);return ret; + } ret =mt76_mcu_skb_send_msg (dev, skb, cmd, true);if (ret)
@@ -1309,8 +1311,10 @@ int mt76_connac_mcu_sta_ba(struct mt76_dev *dev, struct mt76_vif_link *mvif,mt76_connac_mcu_sta_ba_tlv (skb, params, enable, tx); ret =mt76_connac_mcu_sta_wed_update (dev, skb); -if (ret) +if (ret) { +dev_kfree_skb (skb);return ret; + }return mt76_mcu_skb_send_msg (dev, skb, cmd, true); }
@@ -2764,12 +2768,16 @@ int mt76_connac_mcu_add_key(struct mt76_dev *dev, struct ieee80211_vif *vif,return PTR_ERR (skb); ret =mt76_connac_mcu_sta_key_tlv (sta_key_conf, skb, key, cmd); -if (ret) +if (ret) { +dev_kfree_skb (skb);return ret; + } ret =mt76_connac_mcu_sta_wed_update (dev, skb); -if (ret) +if (ret) { +dev_kfree_skb (skb);return ret; + }return mt76_mcu_skb_send_msg (dev, skb, mcu_cmd, true); }
drivers/net/wireless/mediatek/mt76/mt7915/mcu.c +3 -1
@@ -1765,8 +1765,10 @@ int mt7915_mcu_add_sta(struct mt7915_dev *dev, struct ieee80211_vif *vif, } out: ret =mt76_connac_mcu_sta_wed_update (&dev->mt76, skb); -if (ret) +if (ret) { +dev_kfree_skb (skb);return ret; + }return mt76_mcu_skb_send_msg (&dev->mt76, skb,MCU_EXT_CMD (STA_REC_UPDATE ), true);
drivers/net/wireless/mediatek/mt76/mt7925/mcu.c +3 -1
@@ -1288,8 +1288,10 @@ int mt7925_mcu_add_key(struct mt76_dev *dev, struct ieee80211_vif *vif,return PTR_ERR (skb); ret =mt7925_mcu_sta_key_tlv (wcid, sta_key_conf, skb, key, cmd, msta); -if (ret) +if (ret) { +dev_kfree_skb (skb);return ret; + }return mt76_mcu_skb_send_msg (dev, skb, mcu_cmd, true); }
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 114/1146 wifi: mt76: mt7925: fix tx power setting failure after chip reset
In reply to Greg Kroah-Hartman7.0-stable review patch. If anyone has any objections, please let me know.
------------------
From: Leon Yen <[email protected]>
[ Upstream commit aae89dc4a1608da9060bada757f650ac94b7f184 ]
After the chip reset, the procedure to set the tx power will not be successful because the previous region setting is still remains. Clear the region setting during MAC initialization and allow it to be reset to finalize the TX power setting.
--- drivers/net/wireless/mediatek/mt76/mt7925/init.c | 2 ++ drivers/net/wireless/mediatek/mt76/mt7925/regd.c | 3 ++- 2 files changed, 4 insertions(+), 1 deletion(-)
drivers/net/wireless/mediatek/mt76/mt7925/init.c +2 -0
@@ -91,6 +91,8 @@ int mt7925_mac_init(struct mt792x_dev *dev)mt7925_mac_init_basic_rates (dev); +memzero_explicit (&dev->mt76.alpha2,sizeof (dev->mt76.alpha2)); +return 0 ; }EXPORT_SYMBOL_GPL (mt7925_mac_init);
drivers/net/wireless/mediatek/mt76/mt7925/regd.c +2 -1
@@ -232,7 +232,8 @@ int mt7925_regd_change(struct mt792x_phy *phy, char *alpha2) dev->regd_user)return -EINVAL ; -if (mdev->alpha2[0 ] !='0' && mdev->alpha2[1 ] !='0' ) +if ((mdev->alpha2[0 ] && mdev->alpha2[0 ] !='0' ) && + (mdev->alpha2[1 ] && mdev->alpha2[1 ] !='0' ))return 0 ;/* do not need to update the same country twice */
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 115/1146 wifi: mt76: mt7921: fix potential deadlock in mt7921_roc_abort_sync
In reply to Greg Kroah-Hartman7.0-stable review patch. If anyone has any objections, please let me know.
------------------
From: Sean Wang <[email protected]>
[ Upstream commit d5059e52fd8bc624ec4255c9fa01a266513d126b ]
roc_abort_sync() can deadlock with roc_work(). roc_work() holds dev->mt76.mutex, while cancel_work_sync() waits for roc_work() to finish. If the caller already owns the same mutex, both sides block and no progress is possible.
This deadlock can occur during station removal when mt76_sta_state() -> mt76_sta_remove() -> mt7921_mac_sta_remove() -> mt7921_roc_abort_sync() invokes cancel_work_sync() while roc_work() is still running and holding dev->mt76.mutex.
This avoids the mutex deadlock and preserves exactly-once work ownership.
--- drivers/net/wireless/mediatek/mt76/mt7921/main.c | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-)
drivers/net/wireless/mediatek/mt76/mt7921/main.c +8 -5
@@ -371,12 +371,15 @@ void mt7921_roc_abort_sync(struct mt792x_dev *dev) {struct mt792x_phy *phy = &dev->phy; +if (!test_and_clear_bit (MT76_STATE_ROC , &phy->mt76->state)) +return ; +timer_delete_sync (&phy->roc_timer); -cancel_work_sync (&phy->roc_work); -if (test_and_clear_bit (MT76_STATE_ROC , &phy->mt76->state)) -ieee80211_iterate_interfaces (mt76_hw (dev), -IEEE80211_IFACE_ITER_RESUME_ALL , - mt7921_roc_iter, (void *)phy); +cancel_work (&phy->roc_work); + +ieee80211_iterate_interfaces (mt76_hw (dev), +IEEE80211_IFACE_ITER_RESUME_ALL , + mt7921_roc_iter, (void *)phy); }EXPORT_SYMBOL_GPL (mt7921_roc_abort_sync);
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 116/1146 wifi: mt76: fix deadlock in remain-on-channel
In reply to Greg Kroah-Hartman7.0-stable review patch. If anyone has any objections, please let me know.
------------------
From: Chad Monroe <[email protected]>
[ Upstream commit 6939b97ddad3cf3dfbb3b5a0a12ef79cb886747e ]
mt76_remain_on_channel() and mt76_roc_complete() call mt76_set_channel() while already holding dev->mutex. Since mt76_set_channel() also acquires dev->mutex, this results in a deadlock.
Use __mt76_set_channel() instead of mt76_set_channel().
Add cancel_delayed_work_sync() for mac_work before acquiring the mutex in mt76_remain_on_channel() to prevent a secondary deadlock with the mac_work workqueue.
--- drivers/net/wireless/mediatek/mt76/channel.c | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-)
drivers/net/wireless/mediatek/mt76/channel.c +11 -2
@@ -326,7 +326,7 @@ void mt76_roc_complete(struct mt76_phy *phy) mlink->mvif->roc_phy =NULL ;if (phy->main_chandef.chan && !test_bit (MT76_MCU_RESET , &dev->phy.state)) -mt76_set_channel (phy, &phy->main_chandef, false); +__mt76_set_channel (phy, &phy->main_chandef, false);mt76_put_vif_phy_link (phy, phy->roc_vif, phy->roc_link); phy->roc_vif =NULL ; phy->roc_link =NULL ;
@@ -370,6 +370,8 @@ int mt76_remain_on_channel(struct ieee80211_hw *hw, struct ieee80211_vif *vif,if (!phy)return -EINVAL ; +cancel_delayed_work_sync (&phy->mac_work); +mutex_lock (&dev->mutex); if (phy->roc_vif || dev->scan.phy == phy ||
@@ -388,7 +390,14 @@ int mt76_remain_on_channel(struct ieee80211_hw *hw, struct ieee80211_vif *vif, phy->roc_vif = vif; phy->roc_link = mlink;cfg80211_chandef_create (&chandef, chan,NL80211_CHAN_HT20 ); -mt76_set_channel (phy, &chandef, true); + ret =__mt76_set_channel (phy, &chandef, true); +if (ret) { + mlink->mvif->roc_phy =NULL ; + phy->roc_vif =NULL ; + phy->roc_link =NULL ; +mt76_put_vif_phy_link (phy, vif, mlink); + goto out; + }ieee80211_ready_on_channel (hw);ieee80211_queue_delayed_work (phy->hw, &phy->roc_work,msecs_to_jiffies (duration));
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 117/1146 wifi: mt76: fix backoff fields and max_power calculation
In reply to Greg Kroah-Hartman7.0-stable review patch. If anyone has any objections, please let me know.
------------------
From: Allen Ye <[email protected]>
[ Upstream commit 37d5b68ab57c5b4fb1c40e62c6b32376c6a2ca2c ]
The maximum power value may exist in either the data or backoff field. Previously, backoff power limits were not considered in txpower reporting. This patch ensures mt76 also considers backoff values in the SKU table.
Also, each RU entry (RU26, RU52, RU106, BW20, ...) in the DTS corresponds to 10 stream combinations (1T1ss, 2T1ss, 3T1ss, 4T1ss, 2T2ss, 3T2ss, 4T2ss, 3T3ss, 4T3ss, 4T4ss).
For beamforming tables:
- In connac2, beamforming entries for BW20~BW160, and OFDM do not include 1T1ss.
- In connac3, beamforming entries for BW20~BW160, and RU include 1T1ss, but OFDM beamforming does not include 1T1ss.
Non-beamforming and RU entries for both connac2 and connac3 include 1T1ss.
--- drivers/net/wireless/mediatek/mt76/eeprom.c | 154 ++++++++++++++------ drivers/net/wireless/mediatek/mt76/mt76.h | 1 - 2 files changed, 109 insertions(+), 46 deletions(-)
drivers/net/wireless/mediatek/mt76/eeprom.c +109 -45
@@ -9,6 +9,13 @@#include <linux/nvmem-consumer.h> #include <linux/etherdevice.h> #include "mt76.h" +#include "mt76_connac.h" + +enum mt76_sku_type { +MT76_SKU_RATE , +MT76_SKU_BACKOFF , +MT76_SKU_BACKOFF_BF_OFFSET , +};static int mt76_get_of_eeprom_data (struct mt76_dev *dev,void *eep,int len) {
@@ -292,7 +299,6 @@ mt76_find_channel_node(struct device_node *np, struct ieee80211_channel *chan) }EXPORT_SYMBOL_GPL (mt76_find_channel_node); -static s8 mt76_get_txs_delta (struct device_node *np,u8 nss) {
@@ -306,9 +312,24 @@ mt76_get_txs_delta(struct device_node *np, u8 nss)return be32_to_cpu (val[nss -1 ]); } +static inline u8 mt76_backoff_n_chains (struct mt76_dev *dev,u8 idx) +{ +/* 0:1T1ss, 1:2T1ss, ..., 14:5T5ss */ +static const u8 connac3_table[] = { +1 ,2 ,3 ,4 ,5 ,2 ,3 ,4 ,5 ,3 ,4 ,5 ,4 ,5 ,5 }; +static const u8 connac2_table[] = { +1 ,2 ,3 ,4 ,2 ,3 ,4 ,3 ,4 ,4 ,0 ,0 ,0 ,0 ,0 }; + +if (idx >=ARRAY_SIZE (connac3_table)) +return 0 ; + +return is_mt799x (dev) ? connac3_table[idx] : connac2_table[idx]; +} +static void -mt76_apply_array_limit (s8 *pwr,size_t pwr_len,const s8 *data, -s8 target_power,s8 nss_delta,s8 *max_power) +mt76_apply_array_limit (struct mt76_dev *dev,s8 *pwr,size_t pwr_len, +const s8 *data,s8 target_power,s8 nss_delta, +s8 *max_power,int n_chains,enum mt76_sku_type type) {int i;
@@ -316,18 +337,51 @@ mt76_apply_array_limit(s8 *pwr, size_t pwr_len, const s8 *data,return ;for (i =0 ; i < pwr_len; i++) { - pwr[i] =min_t (s8, target_power, data[i] + nss_delta); +u8 backoff_chain_idx = i; +int backoff_n_chains; +s8 backoff_delta; +s8 delta; + +switch (type) { +case MT76_SKU_RATE : + delta =0 ; + backoff_delta =0 ; + backoff_n_chains =0 ; +break ; +case MT76_SKU_BACKOFF_BF_OFFSET : + backoff_chain_idx +=1 ; + fallthrough; +case MT76_SKU_BACKOFF : + delta =mt76_tx_power_path_delta (n_chains); + backoff_n_chains =mt76_backoff_n_chains (dev, backoff_chain_idx); + backoff_delta =mt76_tx_power_path_delta (backoff_n_chains); +break ; +default : +return ; + } + + pwr[i] =min_t (s8, target_power + delta - backoff_delta, data[i] + nss_delta); + +/* used for padding, doesn't need to be considered */ +if (data[i] >=S8_MAX -1 ) +continue ; + +/* only consider backoff value for the configured chain number */ +if (type !=MT76_SKU_RATE && n_chains != backoff_n_chains) +continue ; + *max_power =max (*max_power, pwr[i]); } }static void -mt76_apply_multi_array_limit (s8 *pwr,size_t pwr_len,s8 pwr_num, -const s8 *data,size_t len,s8 target_power, -s8 nss_delta) +mt76_apply_multi_array_limit (struct mt76_dev *dev,s8 *pwr,size_t pwr_len, +s8 pwr_num,const s8 *data,size_t len, +s8 target_power,s8 nss_delta,s8 *max_power, +int n_chains,enum mt76_sku_type type) { +static const int connac2_backoff_ru_idx =2 ;int i, cur; -s8 max_power =-128 ;if (!data)return ;
@@ -337,8 +391,26 @@ mt76_apply_multi_array_limit(s8 *pwr, size_t pwr_len, s8 pwr_num,if (len < pwr_len +1 )break ; -mt76_apply_array_limit (pwr + pwr_len * i, pwr_len, data +1 , - target_power, nss_delta, &max_power); +/* Each RU entry (RU26, RU52, RU106, BW20, ...) in the DTS +* corresponds to 10 stream combinations (1T1ss, 2T1ss, 3T1ss, +* 4T1ss, 2T2ss, 3T2ss, 4T2ss, 3T3ss, 4T3ss, 4T4ss). +* +* For beamforming tables: +* - In connac2, beamforming entries for BW20~BW160 and OFDM +* do not include 1T1ss. +* - In connac3, beamforming entries for BW20~BW160 and RU +* include 1T1ss, but OFDM beamforming does not include 1T1ss. +* +* Non-beamforming and RU entries for both connac2 and connac3 +* include 1T1ss. +*/ +if (!is_mt799x (dev) && type ==MT76_SKU_BACKOFF && + i > connac2_backoff_ru_idx) + type =MT76_SKU_BACKOFF_BF_OFFSET ; + +mt76_apply_array_limit (dev, pwr + pwr_len * i, pwr_len, data +1 , + target_power, nss_delta, max_power, + n_chains, type);if (--cur >0 )continue ;
@@ -360,18 +432,11 @@ s8 mt76_get_rate_power_limits(struct mt76_phy *phy,struct device_node *np;const s8 *val;char name[16 ]; -u32 mcs_rates = dev->drv->mcs_rates; -u32 ru_rates =ARRAY_SIZE (dest->ru[0 ]);char band;size_t len; -s8 max_power =0 ; -s8 max_power_backoff =-127 ; +s8 max_power =-127 ;s8 txs_delta;int n_chains =hweight16 (phy->chainmask); -s8 target_power_combine = target_power +mt76_tx_power_path_delta (n_chains); - -if (!mcs_rates) - mcs_rates =10 ;memset (dest, target_power,sizeof (*dest) -sizeof (dest->path));memset (&dest->path,0 ,sizeof (dest->path));
@@ -409,46 +474,45 @@ s8 mt76_get_rate_power_limits(struct mt76_phy *phy, txs_delta =mt76_get_txs_delta (np,hweight16 (phy->chainmask)); val =mt76_get_of_array_s8 (np,"rates-cck" , &len,ARRAY_SIZE (dest->cck)); -mt76_apply_array_limit (dest->cck,ARRAY_SIZE (dest->cck), val, - target_power, txs_delta, &max_power); +mt76_apply_array_limit (dev, dest->cck,ARRAY_SIZE (dest->cck), val, + target_power, txs_delta, &max_power, n_chains,MT76_SKU_RATE ); - val =mt76_get_of_array_s8 (np,"rates-ofdm" , - &len,ARRAY_SIZE (dest->ofdm)); -mt76_apply_array_limit (dest->ofdm,ARRAY_SIZE (dest->ofdm), val, - target_power, txs_delta, &max_power); + val =mt76_get_of_array_s8 (np,"rates-ofdm" , &len,ARRAY_SIZE (dest->ofdm)); +mt76_apply_array_limit (dev, dest->ofdm,ARRAY_SIZE (dest->ofdm), val, + target_power, txs_delta, &max_power, n_chains,MT76_SKU_RATE ); - val =mt76_get_of_array_s8 (np,"rates-mcs" , &len, mcs_rates +1 ); -mt76_apply_multi_array_limit (dest->mcs[0 ],ARRAY_SIZE (dest->mcs[0 ]), -ARRAY_SIZE (dest->mcs), val, len, - target_power, txs_delta); + val =mt76_get_of_array_s8 (np,"rates-mcs" , &len,ARRAY_SIZE (dest->mcs[0 ]) +1 ); +mt76_apply_multi_array_limit (dev, dest->mcs[0 ],ARRAY_SIZE (dest->mcs[0 ]), +ARRAY_SIZE (dest->mcs), val, len, target_power, + txs_delta, &max_power, n_chains,MT76_SKU_RATE ); - val =mt76_get_of_array_s8 (np,"rates-ru" , &len, ru_rates +1 ); -mt76_apply_multi_array_limit (dest->ru[0 ],ARRAY_SIZE (dest->ru[0 ]), -ARRAY_SIZE (dest->ru), val, len, - target_power, txs_delta); + val =mt76_get_of_array_s8 (np,"rates-ru" , &len,ARRAY_SIZE (dest->ru[0 ]) +1 ); +mt76_apply_multi_array_limit (dev, dest->ru[0 ],ARRAY_SIZE (dest->ru[0 ]), +ARRAY_SIZE (dest->ru), val, len, target_power, + txs_delta, &max_power, n_chains,MT76_SKU_RATE ); - max_power_backoff = max_power; val =mt76_get_of_array_s8 (np,"paths-cck" , &len,ARRAY_SIZE (dest->path.cck)); -mt76_apply_array_limit (dest->path.cck,ARRAY_SIZE (dest->path.cck), val, - target_power_combine, txs_delta, &max_power_backoff); +mt76_apply_array_limit (dev, dest->path.cck,ARRAY_SIZE (dest->path.cck), val, + target_power, txs_delta, &max_power, n_chains,MT76_SKU_BACKOFF ); val =mt76_get_of_array_s8 (np,"paths-ofdm" , &len,ARRAY_SIZE (dest->path.ofdm)); -mt76_apply_array_limit (dest->path.ofdm,ARRAY_SIZE (dest->path.ofdm), val, - target_power_combine, txs_delta, &max_power_backoff); +mt76_apply_array_limit (dev, dest->path.ofdm,ARRAY_SIZE (dest->path.ofdm), val, + target_power, txs_delta, &max_power, n_chains,MT76_SKU_BACKOFF ); val =mt76_get_of_array_s8 (np,"paths-ofdm-bf" , &len,ARRAY_SIZE (dest->path.ofdm_bf)); -mt76_apply_array_limit (dest->path.ofdm_bf,ARRAY_SIZE (dest->path.ofdm_bf), val, - target_power_combine, txs_delta, &max_power_backoff); +mt76_apply_array_limit (dev, dest->path.ofdm_bf,ARRAY_SIZE (dest->path.ofdm_bf), val, + target_power, txs_delta, &max_power, n_chains, +MT76_SKU_BACKOFF_BF_OFFSET ); val =mt76_get_of_array_s8 (np,"paths-ru" , &len,ARRAY_SIZE (dest->path.ru[0 ]) +1 ); -mt76_apply_multi_array_limit (dest->path.ru[0 ],ARRAY_SIZE (dest->path.ru[0 ]), -ARRAY_SIZE (dest->path.ru), val, len, - target_power_combine, txs_delta); +mt76_apply_multi_array_limit (dev, dest->path.ru[0 ],ARRAY_SIZE (dest->path.ru[0 ]), +ARRAY_SIZE (dest->path.ru), val, len, target_power, + txs_delta, &max_power, n_chains,MT76_SKU_BACKOFF ); val =mt76_get_of_array_s8 (np,"paths-ru-bf" , &len,ARRAY_SIZE (dest->path.ru_bf[0 ]) +1 ); -mt76_apply_multi_array_limit (dest->path.ru_bf[0 ],ARRAY_SIZE (dest->path.ru_bf[0 ]), -ARRAY_SIZE (dest->path.ru_bf), val, len, - target_power_combine, txs_delta); +mt76_apply_multi_array_limit (dev, dest->path.ru_bf[0 ],ARRAY_SIZE (dest->path.ru_bf[0 ]), +ARRAY_SIZE (dest->path.ru_bf), val, len, target_power, + txs_delta, &max_power, n_chains,MT76_SKU_BACKOFF );return max_power; }
drivers/net/wireless/mediatek/mt76/mt76.h +0 -1
@@ -540,7 +540,6 @@ struct mt76_driver_ops {u32 survey_flags;u16 txwi_size;u16 token_size; -u8 mcs_rates;unsigned int link_data_size;
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 118/1146 arm64: cpufeature: Make PMUVer and PerfMon unsigned
In reply to Greg Kroah-Hartman7.0-stable review patch. If anyone has any objections, please let me know.
------------------
From: James Clark <[email protected]>
[ Upstream commit d1dcc20bcc40efe1f1c71639376c91dafa489222 ]
On the host, this change doesn't make a difference because the fields are defined as FTR_EXACT. However, KVM allows userspace to set these fields for a guest and overrides the type to be FTR_LOWER_SAFE. And while KVM used to do an unsigned comparison to validate that the new value is lower than what the hardware provides, since the linked commit it uses the generic sanitization framework which does a signed comparison.
Fix it by defining these fields as unsigned. In theory, without this fix, userspace could set a higher PMU version than the hardware supports by providing any value with the top bit set.
--- arch/arm64/kernel/cpufeature.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
arch/arm64/kernel/cpufeature.c +2 -2
@@ -565,7 +565,7 @@ static const struct arm64_ftr_bits ftr_id_aa64dfr0[] = {* We can instantiate multiple PMU instances with different levels * of support. */ -S_ARM64_FTR_BITS (FTR_HIDDEN ,FTR_NONSTRICT ,FTR_EXACT , ID_AA64DFR0_EL1_PMUVer_SHIFT,4 ,0 ), +ARM64_FTR_BITS (FTR_HIDDEN ,FTR_NONSTRICT ,FTR_EXACT , ID_AA64DFR0_EL1_PMUVer_SHIFT,4 ,0 ),ARM64_FTR_BITS (FTR_HIDDEN ,FTR_STRICT ,FTR_EXACT , ID_AA64DFR0_EL1_DebugVer_SHIFT,4 ,0x6 ), ARM64_FTR_END, };
@@ -709,7 +709,7 @@ static const struct arm64_ftr_bits ftr_id_pfr2[] = {static const struct arm64_ftr_bits ftr_id_dfr0[] = {/* [31:28] TraceFilt */ -S_ARM64_FTR_BITS (FTR_HIDDEN ,FTR_NONSTRICT ,FTR_EXACT , ID_DFR0_EL1_PerfMon_SHIFT,4 ,0 ), +ARM64_FTR_BITS (FTR_HIDDEN ,FTR_NONSTRICT ,FTR_EXACT , ID_DFR0_EL1_PerfMon_SHIFT,4 ,0 ),ARM64_FTR_BITS (FTR_HIDDEN ,FTR_STRICT ,FTR_LOWER_SAFE , ID_DFR0_EL1_MProfDbg_SHIFT,4 ,0 ),ARM64_FTR_BITS (FTR_HIDDEN ,FTR_STRICT ,FTR_LOWER_SAFE , ID_DFR0_EL1_MMapTrc_SHIFT,4 ,0 ),ARM64_FTR_BITS (FTR_HIDDEN ,FTR_STRICT ,FTR_LOWER_SAFE , ID_DFR0_EL1_CopTrc_SHIFT,4 ,0 ),
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 119/1146 bpf: Switch CONFIG_CFI_CLANG to CONFIG_CFI
In reply to Greg Kroah-Hartman7.0-stable review patch. If anyone has any objections, please let me know.
------------------
From: Carlos Llamas <[email protected]>
[ Upstream commit 9b0cf064ea0a6bac5e1a5fb43b004fd52fbe2b3b ]
This was renamed in commit 23ef9d439769 ("kcfi: Rename CONFIG_CFI_CLANG to CONFIG_CFI") as it is now a compiler-agnostic option. Using the wrong name results in the code getting compiled out. Meaning the CFI failures for btf_dtor_kfunc_t would still trigger.
--- kernel/bpf/btf.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
kernel/bpf/btf.c +1 -1
@@ -9019,7 +9019,7 @@ static int btf_check_dtor_kfuncs(struct btf *btf, const struct btf_id_dtor_kfuncif (!t || !btf_type_is_ptr (t))return -EINVAL ; -if (IS_ENABLED (CONFIG_CFI_CLANG )) { +if (IS_ENABLED (CONFIG_CFI )) {/* Ensure the destructor kfunc type matches btf_dtor_kfunc_t */ t =btf_type_by_id (btf, t->type);if (!btf_type_is_void (t))
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 120/1146 wifi: mt76: mt7996: fix wrong DMAD length when using MAC TXP
In reply to Greg Kroah-Hartman7.0-stable review patch. If anyone has any objections, please let me know.
------------------
From: Shayne Chen <[email protected]>
[ Upstream commit 97b9f9831bf297f3ffa62018721601ed2736f2c3 ]
The struct mt76_connac_fw_txp is used for HIF TXP. Change to use the struct mt76_connac_hw_txp to fix the wrong DMAD length for MAC TXP.
--- drivers/net/wireless/mediatek/mt76/mt7996/mac.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-)
drivers/net/wireless/mediatek/mt76/mt7996/mac.c +4 -2
@@ -1139,10 +1139,10 @@ int mt7996_tx_prepare_skb(struct mt76_dev *mdev, void *txwi_ptr,* req */ if (le32_to_cpu (ptr[7 ]) &MT_TXD7_MAC_TXD ) { -u32 val; +u32 val, mac_txp_size =sizeof (struct mt76_connac_hw_txp ); ptr = (__le32 *)(txwi +MT_TXD_SIZE ); -memset ((void *)ptr,0 ,sizeof (struct mt76_connac_fw_txp )); +memset ((void *)ptr,0 , mac_txp_size); val =FIELD_PREP (MT_TXP0_TOKEN_ID0 , id) |MT_TXP0_TOKEN_ID0_VALID_MASK ;
@@ -1161,6 +1161,8 @@ int mt7996_tx_prepare_skb(struct mt76_dev *mdev, void *txwi_ptr, tx_info->buf[1].addr >> 32);#endif ptr[3 ] =cpu_to_le32 (val); + + tx_info->buf[0 ].len =MT_TXD_SIZE + mac_txp_size; }else {struct mt76_connac_txp_common *txp;
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 121/1146 wifi: mt76: mt7996: fix struct mt7996_mcu_uni_event
In reply to Greg Kroah-Hartman7.0-stable review patch. If anyone has any objections, please let me know.
------------------
From: StanleyYP Wang <[email protected]>
[ Upstream commit efbd5bf395f4e6b45a87f3835d4c2e28170c77c5 ]
The cid field is defined as a two-byte value in the firmware.
--- drivers/net/wireless/mediatek/mt76/mt7996/mcu.c | 2 +- drivers/net/wireless/mediatek/mt76/mt7996/mcu.h | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-)
drivers/net/wireless/mediatek/mt76/mt7996/mcu.c +1 -1
@@ -233,7 +233,7 @@ mt7996_mcu_parse_response(struct mt76_dev *mdev, int cmd, event = (struct mt7996_mcu_uni_event *)skb->data; ret =le32_to_cpu (event->status);/* skip invalid event */ -if (mcu_cmd != event->cid) +if (mcu_cmd !=le16_to_cpu (event->cid)) ret = -EAGAIN ; }else {skb_pull (skb,sizeof (struct mt7996_mcu_rxd ));
drivers/net/wireless/mediatek/mt76/mt7996/mcu.h +2 -2
@@ -25,8 +25,8 @@ struct mt7996_mcu_rxd { };struct mt7996_mcu_uni_event { -u8 cid; -u8 __rsv[3 ]; +__le16 cid; +u8 __rsv[2 ];__le32 status;/* 0: success, others: fail */ } __packed;
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 122/1146 wifi: mt76: mt7915: fix use-after-free bugs in mt7915_mac_dump_work()
In reply to Greg Kroah-Hartman7.0-stable review patch. If anyone has any objections, please let me know.
------------------
From: Duoming Zhou <[email protected]>
[ Upstream commit 1146d0946b5358fad24812bd39d68f31cd40cc34 ]
When the mt7915 pci chip is detaching, the mt7915_crash_data is released in mt7915_coredump_unregister(). However, the work item dump_work may still be running or pending, leading to UAF bugs when the already freed crash_data is dereferenced again in mt7915_mac_dump_work().
The race condition can occur as follows:
CPU 0 (removal path) | CPU 1 (workqueue)
mt7915_pci_remove() | mt7915_sys_recovery_set()
mt7915_unregister_device() | mt7915_reset()
mt7915_coredump_unregister() | queue_work()
vfree(dev->coredump.crash_data) | mt7915_mac_dump_work()
| crash_data-> // UAFFix this by ensuring dump_work is properly canceled before the crash_data is deallocated. Add cancel_work_sync() in mt7915_unregister_device() to synchronize with any pending or executing dump work.
--- drivers/net/wireless/mediatek/mt76/mt7915/init.c | 1 + 1 file changed, 1 insertion(+)
drivers/net/wireless/mediatek/mt76/mt7915/init.c +1 -0
@@ -1294,6 +1294,7 @@ int mt7915_register_device(struct mt7915_dev *dev)void mt7915_unregister_device (struct mt7915_dev *dev) { +cancel_work_sync (&dev->dump_work);mt7915_unregister_ext_phy (dev);mt7915_coredump_unregister (dev);mt7915_unregister_thermal (&dev->phy);
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 123/1146 wifi: mt76: mt7996: fix use-after-free bugs in mt7996_mac_dump_work()
In reply to Greg Kroah-Hartman7.0-stable review patch. If anyone has any objections, please let me know.
------------------
From: Duoming Zhou <[email protected]>
[ Upstream commit c8f62f73bbced3a79894655bdb0b625462d956fc ]
When the mt7996 pci chip is detaching, the mt7996_crash_data is released in mt7996_coredump_unregister(). However, the work item dump_work may still be running or pending, leading to UAF bugs when the already freed crash_data is dereferenced again in mt7996_mac_dump_work().
The race condition can occur as follows:
CPU 0 (removal path) | CPU 1 (workqueue)
mt7996_pci_remove() | mt7996_sys_recovery_set()
mt7996_unregister_device() | mt7996_reset()
mt7996_coredump_unregister() | queue_work()
vfree(dev->coredump.crash_data) | mt7996_mac_dump_work()
| crash_data-> // UAFFix this by ensuring dump_work is properly canceled before the crash_data is deallocated. Add cancel_work_sync() in mt7996_unregister_device() to synchronize with any pending or executing dump work.
--- drivers/net/wireless/mediatek/mt76/mt7996/init.c | 1 + 1 file changed, 1 insertion(+)
drivers/net/wireless/mediatek/mt76/mt7996/init.c +1 -0
@@ -1741,6 +1741,7 @@ int mt7996_register_device(struct mt7996_dev *dev)void mt7996_unregister_device (struct mt7996_dev *dev) { +cancel_work_sync (&dev->dump_work);cancel_work_sync (&dev->wed_rro.work);mt7996_unregister_phy (mt7996_phy3 (dev));mt7996_unregister_phy (mt7996_phy2 (dev));
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 124/1146 wifi: mt76: mt7921: fix 6GHz regulatory update on connection
In reply to Greg Kroah-Hartman7.0-stable review patch. If anyone has any objections, please let me know.
------------------
From: Michael Lo <[email protected]>
[ Upstream commit 3dc0c40d7806c72cfe88cf4e1e2650c1673f9db4 ]
Call mt7921_regd_update() instead of mt7921_mcu_set_clc() when setting the 6GHz power type after connection, so that regulatory limits and SAR power are also applied.
--- drivers/net/wireless/mediatek/mt76/mt7921/main.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
drivers/net/wireless/mediatek/mt76/mt7921/main.c +2 -1
@@ -800,7 +800,8 @@ mt7921_regd_set_6ghz_power_type(struct ieee80211_vif *vif, bool is_add) } out: -mt7921_mcu_set_clc (dev, dev->mt76.alpha2, dev->country_ie_env); +if (vif->bss_conf.chanreq.oper.chan->band ==NL80211_BAND_6GHZ ) +mt7921_regd_update (dev); } int mt7921_mac_sta_add(struct mt76_dev *mdev, struct ieee80211_vif *vif,
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 125/1146 wifi: mt76: mt7996: Add missing CHANCTX_STA_CSA property
In reply to Greg Kroah-Hartman7.0-stable review patch. If anyone has any objections, please let me know.
------------------
From: Lorenzo Bianconi <[email protected]>
[ Upstream commit c0a47ffc4caaf5161955add553322112c3a211b0 ]
Enable missing CHANCTX_STA_CSA property required for MLO.
--- drivers/net/wireless/mediatek/mt76/mt7996/init.c | 1 + 1 file changed, 1 insertion(+)
drivers/net/wireless/mediatek/mt76/mt7996/init.c +1 -0
@@ -536,6 +536,7 @@ mt7996_init_wiphy(struct ieee80211_hw *hw, struct mtk_wed_device *wed)ieee80211_hw_set (hw,SUPPORTS_RX_DECAP_OFFLOAD );ieee80211_hw_set (hw,NO_VIRTUAL_MONITOR );ieee80211_hw_set (hw,SUPPORTS_MULTI_BSSID ); +ieee80211_hw_set (hw,CHANCTX_STA_CSA ); hw->max_tx_fragments =4 ;
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 126/1146 wifi: mt76: mt7996: Remove link pointer dependency in mt7996_mac_sta_remove_links()
In reply to Greg Kroah-Hartman7.0-stable review patch. If anyone has any objections, please let me know.
------------------
From: Lorenzo Bianconi <[email protected]>
[ Upstream commit 569ce4340268915911fc356ec9ad27e92fb82289 ]
Remove link pointer dependency in mt7996_mac_sta_remove_links routine to get the mt7996_phy pointer since the link can be already offchannel running mt7996_mac_sta_remove_links(). Rely on __mt7996_phy routine instead.
--- drivers/net/wireless/mediatek/mt76/mt7996/main.c | 14 ++++---------- 1 file changed, 4 insertions(+), 10 deletions(-)
drivers/net/wireless/mediatek/mt76/mt7996/main.c +4 -10
@@ -1058,8 +1058,7 @@ mt7996_mac_sta_remove_links(struct mt7996_dev *dev, struct ieee80211_vif *vif,for_each_set_bit (link_id, &links,IEEE80211_MLD_MAX_NUM_LINKS ) {struct mt7996_sta_link *msta_link =NULL ; -struct mt7996_vif_link *link; -struct mt76_phy *mphy; +struct mt7996_phy *phy; msta_link =rcu_replace_pointer (msta->link[link_id], msta_link,lockdep_is_held (&mdev->mutex));
@@ -1068,17 +1067,12 @@ mt7996_mac_sta_remove_links(struct mt7996_dev *dev, struct ieee80211_vif *vif,mt7996_mac_wtbl_update (dev, msta_link->wcid.idx,MT_WTBL_UPDATE_ADM_COUNT_CLEAR ); -mt7996_mac_sta_deinit_link (dev, msta_link); - link =mt7996_vif_link (dev, vif, link_id); -if (!link) -continue ; - mphy =mt76_vif_link_phy (&link->mt76); -if (!mphy) -continue ; + phy =__mt7996_phy (dev, msta_link->wcid.phy_idx); +if (phy) + phy->mt76->num_sta--; - mphy->num_sta--;if (msta->deflink_id == link_id) { msta->deflink_id =IEEE80211_LINK_UNSPECIFIED ;if (msta->seclink_id == link_id) {
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 127/1146 wifi: mt76: mt7996: Decrement sta counter removing the link in mt7996_mac_reset_sta_iter()
In reply to Greg Kroah-Hartman7.0-stable review patch. If anyone has any objections, please let me know.
------------------
From: Lorenzo Bianconi <[email protected]>
[ Upstream commit e648051d52afbdb360bd586218961f5fffff63e8 ]
Fixes tracking per-phy stations for offchannel switching.
--- drivers/net/wireless/mediatek/mt76/mt7996/mac.c | 5 +++++ 1 file changed, 5 insertions(+)
drivers/net/wireless/mediatek/mt76/mt7996/mac.c +5 -0
@@ -2400,6 +2400,7 @@ mt7996_mac_reset_sta_iter(void *data, struct ieee80211_sta *sta)for (i =0 ; i <ARRAY_SIZE (msta->link); i++) {struct mt7996_sta_link *msta_link =NULL ; +struct mt7996_phy *phy; msta_link =rcu_replace_pointer (msta->link[i], msta_link,lockdep_is_held (&dev->mt76.mutex));
@@ -2407,6 +2408,10 @@ mt7996_mac_reset_sta_iter(void *data, struct ieee80211_sta *sta)continue ;mt7996_mac_sta_deinit_link (dev, msta_link); + phy =__mt7996_phy (dev, msta_link->wcid.phy_idx); +if (phy) + phy->mt76->num_sta--; +if (msta_link != &msta->deflink)kfree_rcu (msta_link, rcu_head); }
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 128/1146 wifi: mt76: fix multi-radio on-channel scanning
In reply to Greg Kroah-Hartman7.0-stable review patch. If anyone has any objections, please let me know.
------------------
From: Chad Monroe <[email protected]>
[ Upstream commit 0420180df092419a96351fb2afec1e2a74d385c3 ]
avoid unnecessary channel switch when performing an on-channel scan using a multi-radio device.
--- drivers/net/wireless/mediatek/mt76/scan.c | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-)
drivers/net/wireless/mediatek/mt76/scan.c +12 -5
@@ -16,7 +16,7 @@ static void mt76_scan_complete(struct mt76_dev *dev, bool abort)clear_bit (MT76_SCANNING , &phy->state); -if (dev->scan.chan && phy->main_chandef.chan && +if (dev->scan.chan && phy->main_chandef.chan && phy->offchannel && !test_bit (MT76_MCU_RESET , &dev->phy.state))mt76_set_channel (phy, &phy->main_chandef, false);mt76_put_vif_phy_link (phy, dev->scan.vif, dev->scan.mlink);
@@ -85,6 +85,7 @@ void mt76_scan_work(struct work_struct *work)struct cfg80211_chan_def chandef = {};struct mt76_phy *phy = dev->scan.phy;int duration =HZ /9 ;/* ~110 ms */ +bool offchannel = true;int i;if (dev->scan.chan_idx >= req->n_channels) {
@@ -92,7 +93,7 @@ void mt76_scan_work(struct work_struct *work)return ; } -if (dev->scan.chan && phy->num_sta) { +if (dev->scan.chan && phy->num_sta && phy->offchannel) { dev->scan.chan =NULL ;mt76_set_channel (phy, &phy->main_chandef, false); goto out;
@@ -100,20 +101,26 @@ void mt76_scan_work(struct work_struct *work) dev->scan.chan = req->channels[dev->scan.chan_idx++];cfg80211_chandef_create (&chandef, dev->scan.chan,NL80211_CHAN_HT20 ); -mt76_set_channel (phy, &chandef, true); +if (phy->main_chandef.chan == dev->scan.chan) { + chandef = phy->main_chandef; + offchannel = false; + } + +mt76_set_channel (phy, &chandef, offchannel);if (!req->n_ssids || chandef.chan->flags & (IEEE80211_CHAN_NO_IR |IEEE80211_CHAN_RADAR )) goto out; - duration =HZ /16 ;/* ~60 ms */ +if (phy->offchannel) + duration =HZ /16 ;/* ~60 ms */ local_bh_disable ();for (i =0 ; i < req->n_ssids; i++)mt76_scan_send_probe (dev, &req->ssids[i]);local_bh_enable (); out: -if (dev->scan.chan) +if (dev->scan.chan && phy->offchannel) duration =max_t (int, duration,msecs_to_jiffies (req->duration + (req->duration >>5 )));
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 129/1146 wifi: mt76: support upgrading passive scans to active
In reply to Greg Kroah-Hartman7.0-stable review patch. If anyone has any objections, please let me know.
------------------
From: Chad Monroe <[email protected]>
[ Upstream commit 360552c8592dab3c69e0bbff786b55137f1a81bb ]
On channels with NO_IR or RADAR flags, wait for beacon before sending probe requests. Allows active scanning and WPS on restricted channels if another AP is already present.
--- drivers/net/wireless/mediatek/mt76/mac80211.c | 1 + drivers/net/wireless/mediatek/mt76/mt76.h | 4 ++ .../net/wireless/mediatek/mt76/mt7996/mac.c | 3 ++ drivers/net/wireless/mediatek/mt76/scan.c | 51 +++++++++++++++++-- 4 files changed, 56 insertions(+), 3 deletions(-)
drivers/net/wireless/mediatek/mt76/mac80211.c +1 -0
@@ -726,6 +726,7 @@ mt76_alloc_device(struct device *pdev, unsigned int size,INIT_LIST_HEAD (&dev->rxwi_cache); dev->token_size = dev->drv->token_size;INIT_DELAYED_WORK (&dev->scan_work, mt76_scan_work); +spin_lock_init (&dev->scan_lock);for (i =0 ; i <ARRAY_SIZE (dev->q_rx); i++)skb_queue_head_init (&dev->rx_skb[i]);
drivers/net/wireless/mediatek/mt76/mt76.h +4 -0
@@ -1001,6 +1001,7 @@ struct mt76_dev {u32 rxfilter;struct delayed_work scan_work; +spinlock_t scan_lock;struct {struct cfg80211_scan_request *req;struct ieee80211_channel *chan;
@@ -1008,6 +1009,8 @@ struct mt76_dev {struct mt76_vif_link *mlink;struct mt76_phy *phy;int chan_idx; +bool beacon_wait; +bool beacon_received; } scan;#ifdef CONFIG_NL80211_TESTMODE
@@ -1595,6 +1598,7 @@ int mt76_get_rate(struct mt76_dev *dev,int mt76_hw_scan (struct ieee80211_hw *hw,struct ieee80211_vif *vif,struct ieee80211_scan_request *hw_req);void mt76_cancel_hw_scan (struct ieee80211_hw *hw,struct ieee80211_vif *vif); +void mt76_scan_rx_beacon (struct mt76_dev *dev,struct ieee80211_channel *chan);void mt76_sw_scan (struct ieee80211_hw *hw,struct ieee80211_vif *vif,const u8 *mac); void mt76_sw_scan_complete(struct ieee80211_hw *hw,
drivers/net/wireless/mediatek/mt76/mt7996/mac.c +3 -0
@@ -554,6 +554,9 @@ mt7996_mac_fill_rx(struct mt7996_dev *dev, enum mt76_rxq_id q, qos_ctl =FIELD_GET (MT_RXD10_QOS_CTL , v2); seq_ctrl =FIELD_GET (MT_RXD10_SEQ_CTRL , v2); +if (ieee80211_is_beacon (fc)) +mt76_scan_rx_beacon (&dev->mt76, mphy->chandef.chan); + rxd +=4 ;if ((u8 *)rxd - skb->data >= skb->len)return -EINVAL ;
drivers/net/wireless/mediatek/mt76/scan.c +48 -3
79 lines not on this page · raw message
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 130/1146 wifi: mt76: mt7996: fix RRO EMU configuration
In reply to Greg Kroah-Hartman7.0-stable review patch. If anyone has any objections, please let me know.
------------------
From: Peter Chiu <[email protected]>
[ Upstream commit 73b46379e5231138025b271ce8e158d2a8aa0768 ]
Use the correct helper to update specific bitfields instead of overwriting the entire register.
--- drivers/net/wireless/mediatek/mt76/mt7996/init.c | 3 +-- drivers/net/wireless/mediatek/mt76/mt7996/mac.c | 2 +- 2 files changed, 2 insertions(+), 3 deletions(-)
drivers/net/wireless/mediatek/mt76/mt7996/init.c +1 -2
@@ -858,8 +858,7 @@ void mt7996_rro_hw_init(struct mt7996_dev *dev) } }else {/* set emul 3.0 function */ -mt76_wr (dev,MT_RRO_3_0_EMU_CONF , -MT_RRO_3_0_EMU_CONF_EN_MASK ); +mt76_set (dev,MT_RRO_3_0_EMU_CONF ,MT_RRO_3_0_EMU_CONF_EN_MASK );mt76_wr (dev,MT_RRO_ADDR_ARRAY_BASE0 , dev->wed_rro.addr_elem[0 ].phy_addr);
drivers/net/wireless/mediatek/mt76/mt7996/mac.c +1 -1
@@ -2599,7 +2599,7 @@ void mt7996_mac_reset_work(struct work_struct *work)mt7996_dma_start (dev, false, false);if (!is_mt7996 (&dev->mt76) && dev->mt76.hwrro_mode ==MT76_HWRRO_V3 ) -mt76_wr (dev,MT_RRO_3_0_EMU_CONF ,MT_RRO_3_0_EMU_CONF_EN_MASK ); +mt76_set (dev,MT_RRO_3_0_EMU_CONF ,MT_RRO_3_0_EMU_CONF_EN_MASK );if (mtk_wed_device_active (&dev->mt76.mmio.wed)) { u32 wed_irq_mask = MT_INT_TX_DONE_BAND2 |
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 131/1146 bpf: Fix refcount check in check_struct_ops_btf_id()
In reply to Greg Kroah-Hartman7.0-stable review patch. If anyone has any objections, please let me know.
------------------
From: Keisuke Nishimura <[email protected]>
[ Upstream commit 25e3e1f1096089a64901ae1faa7b7b13446653db ]
The current implementation only checks whether the first argument is refcounted. Fix this by iterating over all arguments.
--- kernel/bpf/verifier.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
kernel/bpf/verifier.c +1 -1
@@ -24897,7 +24897,7 @@ static int check_struct_ops_btf_id(struct bpf_verifier_env *env) }for (i =0 ; i < st_ops_desc->arg_info[member_idx].cnt; i++) { -if (st_ops_desc->arg_info[member_idx].info->refcounted) { +if (st_ops_desc->arg_info[member_idx].info[i].refcounted) { has_refcounted_arg = true;break ; }
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 132/1146 selftests/bpf: Fix sockmap_multi_channels reliability
In reply to Greg Kroah-Hartman7.0-stable review patch. If anyone has any objections, please let me know.
------------------
From: Jiayuan Chen <[email protected]>
[ Upstream commit d9d7125e445dc06c2d9bd3dbd070dcbcd41a540f ]
Previously I added a FIONREAD test for sockmap, but it can occasionally fail in CI [1].
The test sends 10 bytes in two segments (2 + 8). For UDP, FIONREAD only reports the length of the first datagram, not the total queued data. The original code used recv_timeout() expecting all 10 bytes, but under high system load, the second datagram may not yet be processed by the protocol stack, so recv would only return the first 2-byte datagram, causing a size mismatch failure.
Fix this by receiving exactly the expected bytes (matching FIONREAD) in the first recv. The remaining datagram is then consumed in a second recv block, which is only reachable for UDP since TCP's expected already equals sizeof(buf).
Test:
./test_progs -a sockmap_basic
410/1 sockmap_basic/sockmap create_update_free:OK
...
Summary: 1/35 PASSED, 0 SKIPPED, 0 FAILED
[1] https://github.com/kernel-patches/bpf/actions/runs/22919385910/job/66515395423
--- .../selftests/bpf/prog_tests/sockmap_basic.c | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-)
tools/testing/selftests/bpf/prog_tests/sockmap_basic.c +15 -2
@@ -1298,10 +1298,23 @@ static void test_sockmap_multi_channels(int sotype) avail =wait_for_fionread (p1, expected,IO_TIMEOUT_SEC );ASSERT_EQ (avail, expected,"ioctl(FIONREAD) full return" ); - recvd =recv_timeout (p1, rcv,sizeof (rcv),MSG_DONTWAIT ,1 ); -if (!ASSERT_EQ (recvd,sizeof (buf),"recv_timeout(p1)" ) || + recvd =recv_timeout (p1, rcv, expected,MSG_DONTWAIT ,1 ); +if (!ASSERT_EQ (recvd, expected,"recv_timeout(p1)" ) || !ASSERT_OK (memcmp (buf, rcv, recvd),"data mismatch" )) goto end; + +/* process remaining data for udp if secondary data is available */ + expected =sizeof (buf) - expected; +if (expected) { + avail =wait_for_fionread (p1, expected,IO_TIMEOUT_SEC ); +ASSERT_EQ (avail, expected,"second ioctl(FIONREAD) full return" ); + + recvd =recv_timeout (p1, rcv, expected,MSG_DONTWAIT ,1 ); +if (!ASSERT_EQ (recvd, expected,"second recv_timeout(p1)" ) || + !ASSERT_OK (memcmp (buf +sizeof (buf) - expected, rcv, recvd), +"second data mismatch" )) + goto end; + } end:if (c0 >=0 )close (c0);
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 133/1146 bpf: Use RCU-safe iteration in dev_map_redirect_multi() SKB path
In reply to Greg Kroah-Hartman7.0-stable review patch. If anyone has any objections, please let me know.
------------------
From: David Carlier <[email protected]>
[ Upstream commit 8ed82f807bb09d2c8455aaa665f2c6cb17bc6a19 ]
The DEVMAP_HASH branch in dev_map_redirect_multi() uses hlist_for_each_entry_safe() to iterate hash buckets, but this function runs under RCU protection (called from xdp_do_generic_redirect_map() in softirq context). Concurrent writers (__dev_map_hash_update_elem, dev_map_hash_delete_elem) modify the list using RCU primitives (hlist_add_head_rcu, hlist_del_rcu).
hlist_for_each_entry_safe() performs plain pointer dereferences without rcu_dereference(), missing the acquire barrier needed to pair with writers' rcu_assign_pointer(). On weakly-ordered architectures (ARM64, POWER), a reader can observe a partially-constructed node. It also defeats CONFIG_PROVE_RCU lockdep validation and KCSAN data-race detection.
Replace with hlist_for_each_entry_rcu() using rcu_read_lock_bh_held() as the lockdep condition, consistent with the rcu_dereference_check() used in the DEVMAP (non-hash) branch of the same functions. Also fix the same incorrect lockdep_is_held(&dtab->index_lock) condition in dev_map_enqueue_multi(), where the lock is not held either.
--- kernel/bpf/devmap.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-)
kernel/bpf/devmap.c +2 -3
@@ -665,7 +665,7 @@ int dev_map_enqueue_multi(struct xdp_frame *xdpf, struct net_device *dev_rx,for (i =0 ; i < dtab->n_buckets; i++) { head =dev_map_index_hash (dtab, i);hlist_for_each_entry_rcu (dst, head, index_hlist, -lockdep_is_held (&dtab->index_lock)) { +rcu_read_lock_bh_held ()) {if (!is_valid_dst (dst, xdpf))continue ;
@@ -747,7 +747,6 @@ int dev_map_redirect_multi(struct net_device *dev, struct sk_buff *skb,struct bpf_dtab_netdev *dst, *last_dst =NULL ;int excluded_devices[1 +MAX_NEST_DEV ];struct hlist_head *head; -struct hlist_node *next;int num_excluded =0 ;unsigned int i;int err;
@@ -787,7 +786,7 @@ int dev_map_redirect_multi(struct net_device *dev, struct sk_buff *skb, }else {/* BPF_MAP_TYPE_DEVMAP_HASH */ for (i =0 ; i < dtab->n_buckets; i++) { head =dev_map_index_hash (dtab, i); -hlist_for_each_entry_safe (dst, next, head, index_hlist) { +hlist_for_each_entry_rcu (dst, head, index_hlist,rcu_read_lock_bh_held ()) {if (is_ifindex_excluded (excluded_devices, num_excluded, dst->dev->ifindex))continue ;
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 134/1146 bpf: Fix variable length stack write over spilled pointers
In reply to Greg Kroah-Hartman7.0-stable review patch. If anyone has any objections, please let me know.
------------------
From: Alexei Starovoitov <[email protected]>
[ Upstream commit 4639eb9e30ab10c7935c7c19e872facf9a94713f ]
Scrub slots if variable-offset stack write goes over spilled pointers. Otherwise is_spilled_reg() may == true && spilled_ptr.type == NOT_INIT and valid program is rejected by check_stack_read_fixed_off() with obscure "invalid size of register fill" message.
--- kernel/bpf/verifier.c | 28 ++++++++++++++++++++-------- 1 file changed, 20 insertions(+), 8 deletions(-)
kernel/bpf/verifier.c +20 -8
@@ -5241,6 +5241,18 @@ static void check_fastcall_stack_contract(struct bpf_verifier_env *env, } } +static void scrub_special_slot (struct bpf_func_state *state,int spi) +{ +int i; + +/* regular write of data into stack destroys any spilled ptr */ + state->stack[spi].spilled_ptr.type =NOT_INIT ; +/* Mark slots as STACK_MISC if they belonged to spilled ptr/dynptr/iter. */ +if (is_stack_slot_special (&state->stack[spi])) +for (i =0 ; i <BPF_REG_SIZE ; i++) +scrub_spilled_slot (&state->stack[spi].slot_type[i]); +} +/* check_stack_{read,write}_fixed_off functions track spill/fill of registers, * stack boundary and alignment are checked in check_mem_access() */
@@ -5338,12 +5350,7 @@ static int check_stack_write_fixed_off(struct bpf_verifier_env *env, }else {u8 type =STACK_MISC ; -/* regular write of data into stack destroys any spilled ptr */ - state->stack[spi].spilled_ptr.type =NOT_INIT ; -/* Mark slots as STACK_MISC if they belonged to spilled ptr/dynptr/iter. */ -if (is_stack_slot_special (&state->stack[spi])) -for (i =0 ; i <BPF_REG_SIZE ; i++) -scrub_spilled_slot (&state->stack[spi].slot_type[i]); +scrub_special_slot (state, spi);/* when we zero initialize stack slots mark them as such */ if ((reg && register_is_null(reg)) ||
@@ -5467,8 +5474,13 @@ static int check_stack_write_var_off(struct bpf_verifier_env *env, } } -/* Erase all other spilled pointers. */ - state->stack[spi].spilled_ptr.type =NOT_INIT ; +/* +* Scrub slots if variable-offset stack write goes over spilled pointers. +* Otherwise is_spilled_reg() may == true && spilled_ptr.type == NOT_INIT +* and valid program is rejected by check_stack_read_fixed_off() +* with obscure "invalid size of register fill" message. +*/ +scrub_special_slot (state, spi);/* Update the slot type. */ new_type =STACK_MISC ;
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 135/1146 arm_mpam: Ensure in_reset_state is false after applying configuration
In reply to Greg Kroah-Hartman7.0-stable review patch. If anyone has any objections, please let me know.
------------------
From: Zeng Heng <[email protected]>
[ Upstream commit f91e913355f49c878fc77f995fd71b7800352bd2 ]
The per-RIS flag, in_reset_state, indicates whether or not the MSC registers are in reset state, and allows avoiding resetting when they are already in reset state. However, when mpam_apply_config() updates the configuration it doesn't update the in_reset_state flag and so even after the configuration update in_reset_state can be true and mpam_reset_ris() will skip the actual register restoration on subsequent resets.
Once resctrl has a MPAM backend it will use resctrl_arch_reset_all_ctrls() to reset the MSC configuration on unmount and, if the in_reset_state flag is bogusly true, fail to reset the MSC configuration. The resulting non-reset MSC configuration can lead to persistent performance restrictions even after resctrl is unmounted.
Fix by clearing in_reset_state to false immediately after successful configuration application, ensuring that the next reset operation properly restores MSC register defaults.
--- drivers/resctrl/mpam_devices.c | 1 + 1 file changed, 1 insertion(+)
drivers/resctrl/mpam_devices.c +1 -0
@@ -2694,6 +2694,7 @@ int mpam_apply_config(struct mpam_component *comp, u16 partid, srcu_read_lock_held(&mpam_srcu)) { arg.ris = ris;mpam_touch_msc (msc, __write_config, &arg); + ris->in_reset_state = false; }mutex_unlock (&msc->cfg_lock); }
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 136/1146 arm_mpam: Reset when feature configuration bit unset
In reply to Greg Kroah-Hartman7.0-stable review patch. If anyone has any objections, please let me know.
------------------
From: Ben Horgan <[email protected]>
[ Upstream commit a1cb6577f575ba5ec2583caf4f791a86754dbf69 ]
To indicate that the configuration, of the controls used by resctrl, in a RIS need resetting to driver defaults the reset flags in mpam_config are set. However, these flags are only ever set temporarily at RIS scope in mpam_reset_ris() and hence mpam_cpu_online() will never reset these controls to default. As the hardware reset is unknown this leads to unknown configuration when the control values haven't been configured away from the defaults.
Use the policy that an unset feature configuration bit means reset. In this way the mpam_config in the component can encode that it should be in reset state and mpam_reprogram_msc() will reset controls as needed.
--- drivers/resctrl/mpam_devices.c | 40 ++++++++++----------------------- drivers/resctrl/mpam_internal.h | 4 ---- 2 files changed, 12 insertions(+), 32 deletions(-)
drivers/resctrl/mpam_devices.c +12 -28
@@ -1364,17 +1364,15 @@ static void mpam_reprogram_ris_partid(struct mpam_msc_ris *ris, u16 partid,__mpam_intpart_sel (ris->ris_idx, partid, msc); } -if (mpam_has_feature (mpam_feat_cpor_part, rprops) && -mpam_has_feature (mpam_feat_cpor_part, cfg)) { -if (cfg->reset_cpbm) -mpam_reset_msc_bitmap (msc,MPAMCFG_CPBM , rprops->cpbm_wd); -else +if (mpam_has_feature (mpam_feat_cpor_part, rprops)) { +if (mpam_has_feature (mpam_feat_cpor_part, cfg))mpam_write_partsel_reg (msc,CPBM , cfg->cpbm); +else +mpam_reset_msc_bitmap (msc,MPAMCFG_CPBM , rprops->cpbm_wd); } -if (mpam_has_feature (mpam_feat_mbw_part, rprops) && -mpam_has_feature (mpam_feat_mbw_part, cfg)) { -if (cfg->reset_mbw_pbm) +if (mpam_has_feature (mpam_feat_mbw_part, rprops)) { +if (mpam_has_feature (mpam_feat_mbw_part, cfg))mpam_reset_msc_bitmap (msc,MPAMCFG_MBW_PBM , rprops->mbw_pbm_bits);else mpam_write_partsel_reg (msc,MBW_PBM , cfg->mbw_pbm);
@@ -1384,16 +1382,14 @@ static void mpam_reprogram_ris_partid(struct mpam_msc_ris *ris, u16 partid, mpam_has_feature(mpam_feat_mbw_min, cfg))mpam_write_partsel_reg (msc,MBW_MIN ,0 ); -if (mpam_has_feature (mpam_feat_mbw_max, rprops) && -mpam_has_feature (mpam_feat_mbw_max, cfg)) { -if (cfg->reset_mbw_max) -mpam_write_partsel_reg (msc,MBW_MAX ,MPAMCFG_MBW_MAX_MAX ); -else +if (mpam_has_feature (mpam_feat_mbw_max, rprops)) { +if (mpam_has_feature (mpam_feat_mbw_max, cfg))mpam_write_partsel_reg (msc,MBW_MAX , cfg->mbw_max); +else +mpam_write_partsel_reg (msc,MBW_MAX ,MPAMCFG_MBW_MAX_MAX ); } -if (mpam_has_feature (mpam_feat_mbw_prop, rprops) && -mpam_has_feature (mpam_feat_mbw_prop, cfg)) +if (mpam_has_feature (mpam_feat_mbw_prop, rprops))mpam_write_partsel_reg (msc,MBW_PROP ,0 );if (mpam_has_feature (mpam_feat_cmax_cmax, rprops))
@@ -1493,16 +1489,6 @@ static int mpam_save_mbwu_state(void *arg)return 0 ; } -static void mpam_init_reset_cfg (struct mpam_config *reset_cfg) -{ - *reset_cfg = (struct mpam_config ) { - .reset_cpbm = true, - .reset_mbw_pbm = true, - .reset_mbw_max = true, - }; -bitmap_fill (reset_cfg->features,MPAM_FEATURE_LAST ); -} -/* * Called via smp_call_on_cpu() to prevent migration, while still being * pre-emptible. Caller must hold mpam_srcu.
@@ -1510,14 +1496,12 @@ static void mpam_init_reset_cfg(struct mpam_config *reset_cfg)static int mpam_reset_ris (void *arg) {u16 partid, partid_max; -struct mpam_config reset_cfg; +struct mpam_config reset_cfg = {};struct mpam_msc_ris *ris = arg;if (ris->in_reset_state)return 0 ; -mpam_init_reset_cfg (&reset_cfg); -spin_lock (&partid_max_lock); partid_max = mpam_partid_max;spin_unlock (&partid_max_lock);
drivers/resctrl/mpam_internal.h +0 -4
@@ -266,10 +266,6 @@ struct mpam_config {u32 mbw_pbm;u16 mbw_max; -bool reset_cpbm; -bool reset_mbw_pbm; -bool reset_mbw_max; -struct mpam_garbage garbage; };
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 137/1146 bpf,arc_jit: Fix missing newline in pr_err messages
In reply to Greg Kroah-Hartman7.0-stable review patch. If anyone has any objections, please let me know.
------------------
From: haoyu.lu <[email protected]>
[ Upstream commit b6b5e0ebd429d66ce37ae5af649a74ea1f041d92 ]
Add missing newline to pr_err messages in ARC JIT.
--- arch/arc/net/bpf_jit_arcv2.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-)
arch/arc/net/bpf_jit_arcv2.c +4 -4
@@ -2427,7 +2427,7 @@ u8 arc_prologue(u8 *buf, u32 usage, u16 frame_size)#ifdef ARC_BPF_JIT_DEBUG if ((usage &BIT (ARC_R_FP )) && frame_size ==0 ) { -pr_err ("FP is being saved while there is no frame." ); +pr_err ("FP is being saved while there is no frame.\n" );BUG (); }#endif
@@ -2454,7 +2454,7 @@ u8 arc_epilogue(u8 *buf, u32 usage, u16 frame_size)#ifdef ARC_BPF_JIT_DEBUG if ((usage &BIT (ARC_R_FP )) && frame_size ==0 ) { -pr_err ("FP is being saved while there is no frame." ); +pr_err ("FP is being saved while there is no frame.\n" );BUG (); }#endif
@@ -2868,7 +2868,7 @@ u8 gen_jmp_64(u8 *buf, u8 rd, u8 rs, u8 cond, u32 curr_off, u32 targ_off)break ;default :#ifdef ARC_BPF_JIT_DEBUG -pr_err ("64-bit jump condition is not known." ); +pr_err ("64-bit jump condition is not known.\n" );BUG ();#endif }
@@ -2948,7 +2948,7 @@ u8 gen_jmp_32(u8 *buf, u8 rd, u8 rs, u8 cond, u32 curr_off, u32 targ_off)*/ if (cond >=ARC_CC_LAST ) {#ifdef ARC_BPF_JIT_DEBUG -pr_err ("32-bit jump condition is not known." ); +pr_err ("32-bit jump condition is not known.\n" );BUG ();#endif return 0 ;
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 138/1146 wifi: rtw89: phy: fix uninitialized variable access in rtw89_phy_cfo_set_crystal_cap()
In reply to Greg Kroah-Hartman7.0-stable review patch. If anyone has any objections, please let me know.
------------------
From: Alexey Velichayshiy <[email protected]>
[ Upstream commit 047cddf88c611e616d49a00311d4722e46286234 ]
In the rtw89_phy_cfo_set_crystal_cap() function, for chips other than RTL8852A/RTL8851B, the values read by rtw89_mac_read_xtal_si() are stored into the local variables sc_xi_val and sc_xo_val. If either read fails, these variables remain uninitialized, they are later used to update cfo->crystal_cap and in debug print statements. This can lead to undefined behavior.
Fix the issue by initializing sc_xi_val and sc_xo_val to zero, like is implemented in vendor driver.
Found by Linux Verification Center (linuxtesting.org) with SVACE.
--- drivers/net/wireless/realtek/rtw89/phy.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/net/wireless/realtek/rtw89/phy.c +1 -1
@@ -4860,7 +4860,7 @@ static void rtw89_phy_cfo_set_crystal_cap(struct rtw89_dev *rtwdev, {struct rtw89_cfo_tracking_info *cfo = &rtwdev->cfo_tracking;const struct rtw89_chip_info *chip = rtwdev->chip; -u8 sc_xi_val, sc_xo_val; +u8 sc_xi_val =0 , sc_xo_val =0 ;if (!force && cfo->crystal_cap == crystal_cap)return ;
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 139/1146 drivers/vfio_pci_core: Change PXD_ORDER check from switch case to if/else block
In reply to Greg Kroah-Hartman7.0-stable review patch. If anyone has any objections, please let me know.
------------------
From: Ritesh Harjani (IBM) <[email protected]>
[ Upstream commit 948b71aa81cd89b222942db6055e8d9c51c54e78 ]
Architectures like PowerPC uses runtime defined values for PMD_ORDER/PUD_ORDER. This is because it can use either RADIX or HASH MMU at runtime using kernel cmdline. So the pXd_index_size is not known at compile time. Without this fix, when we add huge pfn support on powerpc in the next patch, vfio_pci_core driver compilation can fail with the following errors.
CC [M] drivers/vfio/vfio_main.o
CC [M] drivers/vfio/group.o
CC [M] drivers/vfio/container.o
CC [M] drivers/vfio/virqfd.o
CC [M] drivers/vfio/vfio_iommu_spapr_tce.o
CC [M] drivers/vfio/pci/vfio_pci_core.o
CC [M] drivers/vfio/pci/vfio_pci_intrs.o
CC [M] drivers/vfio/pci/vfio_pci_rdwr.o
CC [M] drivers/vfio/pci/vfio_pci_config.o
CC [M] drivers/vfio/pci/vfio_pci.o
AR kernel/built-in.a
../drivers/vfio/pci/vfio_pci_core.c: In function ‘vfio_pci_vmf_insert_pfn’:
../drivers/vfio/pci/vfio_pci_core.c:1678:9: error: case label does not reduce to an integer constant
1678 | case PMD_ORDER:
| ^~~~
../drivers/vfio/pci/vfio_pci_core.c:1682:9: error: case label does not reduce to an integer constant
1682 | case PUD_ORDER:
| ^~~~make[6]: *** [../scripts/Makefile.build:289: drivers/vfio/pci/vfio_pci_core.o] Error 1 make[6]: *** Waiting for unfinished jobs....
make[5]: *** [../scripts/Makefile.build:546: drivers/vfio/pci] Error 2 make[5]: *** Waiting for unfinished jobs....
make[4]: *** [../scripts/Makefile.build:546: drivers/vfio] Error 2 make[3]: *** [../scripts/Makefile.build:546: drivers] Error 2
--- drivers/vfio/pci/vfio_pci_core.c | 19 +++++++------------ 1 file changed, 7 insertions(+), 12 deletions(-)
drivers/vfio/pci/vfio_pci_core.c +7 -12
@@ -1670,21 +1670,16 @@ vm_fault_t vfio_pci_vmf_insert_pfn(struct vfio_pci_core_device *vdev,if (vdev->pm_runtime_engaged || !__vfio_pci_memory_enabled (vdev))return VM_FAULT_SIGBUS ; -switch (order) { -case 0 : +if (!order)return vmf_insert_pfn (vmf->vma, vmf->address, pfn); -#ifdef CONFIG_ARCH_SUPPORTS_PMD_PFNMAP -case PMD_ORDER : + +if (IS_ENABLED (CONFIG_ARCH_SUPPORTS_PMD_PFNMAP ) && order ==PMD_ORDER )return vmf_insert_pfn_pmd (vmf, pfn, false); -#endif -#ifdef CONFIG_ARCH_SUPPORTS_PUD_PFNMAP -case PUD_ORDER : + +if (IS_ENABLED (CONFIG_ARCH_SUPPORTS_PUD_PFNMAP ) && order ==PUD_ORDER )return vmf_insert_pfn_pud (vmf, pfn, false); -break ; -#endif -default : -return VM_FAULT_FALLBACK ; - } + +return VM_FAULT_FALLBACK ; }EXPORT_SYMBOL_GPL (vfio_pci_vmf_insert_pfn);
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 140/1146 r8152: fix incorrect register write to USB_UPHY_XTAL
In reply to Greg Kroah-Hartman7.0-stable review patch. If anyone has any objections, please let me know.
------------------
From: Chih Kai Hsu <[email protected]>
[ Upstream commit 48afd5124fd6129c46fd12cb06155384b1c4a0c4 ]
The old code used ocp_write_byte() to clear the OOBS_POLLING bit (BIT(8)) in the USB_UPHY_XTAL register, but this doesn't correctly clear a bit in the upper byte of the 16-bit register.
Fix this by using ocp_write_word() instead.
--- drivers/net/usb/r8152.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/net/usb/r8152.c +1 -1
@@ -3890,7 +3890,7 @@ static void r8156_ups_en(struct r8152 *tp, bool enable)case RTL_VER_15 : ocp_data =ocp_read_word (tp,MCU_TYPE_USB ,USB_UPHY_XTAL ); ocp_data &= ~OOBS_POLLING ; -ocp_write_byte (tp,MCU_TYPE_USB ,USB_UPHY_XTAL , ocp_data); +ocp_write_word (tp,MCU_TYPE_USB ,USB_UPHY_XTAL , ocp_data);break ;default :break ;
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 141/1146 selftests/tracing: Fix to make --logdir option work again
In reply to Greg Kroah-Hartman7.0-stable review patch. If anyone has any objections, please let me know.
------------------
From: Masami Hiramatsu (Google) <[email protected]>
[ Upstream commit e011853dd78f97898ae8e0b0b949603987e24c4b ]
Since commit a0aa283c53a7 ("selftest/ftrace: Generalise ftracetest to use with RV") moved the default LOG_DIR setting after --logdir option parser, it overwrites the user given LOG_DIR.
This fixes it to check the --logdir option parameter when setting new default LOG_DIR with a new TOP_DIR.
--- tools/testing/selftests/ftrace/ftracetest | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-)
tools/testing/selftests/ftrace/ftracetest +12 -6
@@ -130,8 +130,7 @@ parse_opts() { # opts shift 1 ;; --logdir|-l) - LOG_DIR=$2 - LINK_PTR= + USER_LOG_DIR=$2 shift 2 ;; --rv)
@@ -199,6 +198,7 @@ fi TOP_DIR=`absdir $0` TEST_DIR=$TOP_DIR/test.d TEST_CASES=`find_testcases $TEST_DIR` +USER_LOG_DIR= KEEP_LOG=0 KTAP=0 DEBUG=0
@@ -210,12 +210,18 @@ RV_TEST=0 # Parse command-line options parse_opts $* +[ $DEBUG -ne 0 ] && set -x + +# TOP_DIR can be changed for rv. Setting log directory. LOG_TOP_DIR=$TOP_DIR/logs LOG_DATE=`date +%Y%m%d-%H%M%S` -LOG_DIR=$LOG_TOP_DIR/$LOG_DATE/ -LINK_PTR=$LOG_TOP_DIR/latest - -[ $DEBUG -ne 0 ] && set -x +if [ -n "$USER_LOG_DIR" ]; then + LOG_DIR=$USER_LOG_DIR + LINK_PTR= +else + LOG_DIR=$LOG_TOP_DIR/$LOG_DATE/ + LINK_PTR=$LOG_TOP_DIR/latest +fi if [ $RV_TEST -ne 0 ]; then TRACING_DIR=$TRACING_DIR/rv
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 142/1146 selftests/tracing: Fix to check awk supports non POSIX strtonum()
In reply to Greg Kroah-Hartman7.0-stable review patch. If anyone has any objections, please let me know.
------------------
From: Masami Hiramatsu (Google) <[email protected]>
[ Upstream commit 3d0b8e45075d398369eb07e11f529c17a63cf5e1 ]
Check the awk command supports non POSIX strtonum() function in the trace_marker_raw test case.
--- .../selftests/ftrace/test.d/00basic/trace_marker_raw.tc | 2 ++ tools/testing/selftests/ftrace/test.d/functions | 4 ++++ 2 files changed, 6 insertions(+)
tools/testing/selftests/ftrace/test.d/00basic/trace_marker_raw.tc +2 -0
@@ -4,6 +4,8 @@ # requires: trace_marker_raw # flags: instance +check_awk_strtonum || exit_unresolved + is_little_endian() { if lscpu | grep -q 'Little Endian'; then echo 1;
tools/testing/selftests/ftrace/test.d/functions +4 -0
@@ -173,6 +173,10 @@ check_requires() { # Check required files and tracers done } +check_awk_strtonum() { # strtonum is GNU awk extension + awk 'BEGIN{strtonum("0x1")}' +} + LOCALHOST=127.0.0.1 yield() {
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 143/1146 powerpc/crash: fix backup region offset update to elfcorehdr
In reply to Greg Kroah-Hartman7.0-stable review patch. If anyone has any objections, please let me know.
------------------
From: Sourabh Jain <[email protected]>
[ Upstream commit 789335cacdf37da93bb7c70322dff8c7e82881df ]
update_backup_region_phdr() in file_load_64.c iterates over all the program headers in the kdump kernel’s elfcorehdr and updates the p_offset of the program header whose physical address starts at 0.
However, the loop logic is incorrect because the program header pointer is not updated during iteration. Since elfcorehdr typically contains PT_NOTE entries first, the PT_LOAD program header with physical address 0 is never reached. As a result, its p_offset is not updated to point to the backup region.
Because of this behavior, the capture kernel exports the first 64 KB of the crashed kernel’s memory at offset 0, even though that memory actually lives in the backup region. When a crash happens, purgatory copies the first 64 KB of the crashed kernel’s memory into the backup region so the capture kernel can safely use it.
This has not caused problems so far because the first 64 KB is usually identical in both the crashed and capture kernels. However, this is just an assumption and is not guaranteed to always hold true.
Fix update_backup_region_phdr() to correctly update the p_offset of the program header with a starting physical address of 0 by correcting the logic used to iterate over the program headers.
--- arch/powerpc/kexec/file_load_64.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
arch/powerpc/kexec/file_load_64.c +1 -1
@@ -391,7 +391,7 @@ static void update_backup_region_phdr(struct kimage *image, Elf64_Ehdr *ehdr)unsigned int i; phdr = (Elf64_Phdr *)(ehdr +1 ); -for (i =0 ; i < ehdr->e_phnum; i++) { +for (i =0 ; i < ehdr->e_phnum; i++, phdr++) {if (phdr->p_paddr ==BACKUP_SRC_START ) { phdr->p_offset = image->arch.backup_start; kexec_dprintk("Backup region offset updated to 0x%lx\n",
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 144/1146 powerpc/crash: Update backup region offset in elfcorehdr on memory hotplug
In reply to Greg Kroah-Hartman7.0-stable review patch. If anyone has any objections, please let me know.
------------------
From: Sourabh Jain <[email protected]>
[ Upstream commit f53b24d1fa263f56155213eabab734c18d884aff ]
When elfcorehdr is prepared for kdump, the program header representing the first 64 KB of memory is expected to have its offset point to the backup region. This is required because purgatory copies the first 64 KB of the crashed kernel memory to this backup region following a kernel crash. This allows the capture kernel to use the first 64 KB of memory to place the exception vectors and other required data.
When elfcorehdr is recreated due to memory hotplug, the offset of the program header representing the first 64 KB is not updated. As a result, the capture kernel exports the first 64 KB at offset 0, even though the data actually resides in the backup region.
Fix this by calling sync_backup_region_phdr() to update the program header offset in the elfcorehdr created during memory hotplug.
sync_backup_region_phdr() works for images loaded via the kexec_file_load syscall. However, it does not work for kexec_load, because image->arch.backup_start is not initialized in that case. So introduce machine_kexec_post_load() to process the elfcorehdr prepared by kexec-tools and initialize image->arch.backup_start for kdump images loaded via kexec_load syscall.
Rename update_backup_region_phdr() to sync_backup_region_phdr() and extend it to synchronize the backup region offset between the kdump image and the ELF core header. The helper now supports updating either the kdump image from the ELF program header or updating the ELF program header from the kdump image, avoiding code duplication.
Define ARCH_HAS_KIMAGE_ARCH and struct kimage_arch when CONFIG_KEXEC_FILE or CONFIG_CRASH_DUMP is enabled so that kimage->arch.backup_start is available with the kexec_load system call.
This patch depends on the patch titled "powerpc/crash: fix backup region offset update to elfcorehdr".
--- arch/powerpc/include/asm/kexec.h | 14 +++++-- arch/powerpc/kexec/crash.c | 64 +++++++++++++++++++++++++++++++ arch/powerpc/kexec/file_load_64.c | 29 +------------- 3 files changed, 76 insertions(+), 31 deletions(-)
arch/powerpc/include/asm/kexec.h +11 -3
@@ -66,11 +66,9 @@ void relocate_new_kernel(unsigned long indirection_page, unsigned long reboot_co unsigned long start_address) __noreturn;void kexec_copy_flush (struct kimage *image); -#ifdef CONFIG_KEXEC_FILE -extern const struct kexec_file_ops kexec_elf64_ops; +#if defined(CONFIG_KEXEC_FILE) || defined(CONFIG_CRASH_DUMP) #define ARCH_HAS_KIMAGE_ARCH - struct kimage_arch { struct crash_mem *exclude_ranges;
@@ -78,6 +76,10 @@ struct kimage_arch {void *backup_buf; void *fdt; }; +#endif + +#ifdef CONFIG_KEXEC_FILE +extern const struct kexec_file_ops kexec_elf64_ops;char *setup_kdump_cmdline (struct kimage *image,char *cmdline,unsigned long cmdline_len);
@@ -145,6 +147,10 @@ int arch_crash_hotplug_support(struct kimage *image, unsigned long kexec_flags);unsigned int arch_crash_get_elfcorehdr_size (void );#define crash_get_elfcorehdr_size arch_crash_get_elfcorehdr_size + +int machine_kexec_post_load (struct kimage *image); +#define machine_kexec_post_load machine_kexec_post_load +#endif /* CONFIG_CRASH_HOTPLUG */ extern int crashing_cpu;
@@ -159,6 +165,8 @@ extern void default_machine_crash_shutdown(struct pt_regs *regs);extern void crash_kexec_prepare (void );extern void crash_kexec_secondary (struct pt_regs *regs); +extern void sync_backup_region_phdr (struct kimage *image,Elf64_Ehdr *ehdr, +bool phdr_to_kimage);static inline bool kdump_in_progress (void ) {return crashing_cpu >=0 ;
arch/powerpc/kexec/crash.c +64 -0
83 lines not on this page · raw message
arch/powerpc/kexec/file_load_64.c +1 -28
@@ -374,33 +374,6 @@ static int load_backup_segment(struct kimage *image, struct kexec_buf *kbuf)return 0 ; } -/** -* update_backup_region_phdr - Update backup region's offset for the core to -* export the region appropriately. -* @image: Kexec image. -* @ehdr: ELF core header. -* -* Assumes an exclusive program header is setup for the backup region -* in the ELF headers -* -* Returns nothing. -*/ -static void update_backup_region_phdr (struct kimage *image,Elf64_Ehdr *ehdr) -{ -Elf64_Phdr *phdr; -unsigned int i; - - phdr = (Elf64_Phdr *)(ehdr +1 ); -for (i =0 ; i < ehdr->e_phnum; i++, phdr++) { -if (phdr->p_paddr ==BACKUP_SRC_START ) { - phdr->p_offset = image->arch.backup_start; -kexec_dprintk ("Backup region offset updated to 0x%lx\n" , - image->arch.backup_start); -return ; - } - } -} -static unsigned int kdump_extra_elfcorehdr_size (struct crash_mem *cmem) {#if defined(CONFIG_CRASH_HOTPLUG ) && defined(CONFIG_MEMORY_HOTPLUG )
@@ -445,7 +418,7 @@ static int load_elfcorehdr_segment(struct kimage *image, struct kexec_buf *kbuf) }/* Fix the offset for backup region in the ELF header */ -update_backup_region_phdr (image, headers); +sync_backup_region_phdr (image, headers, false); kbuf->buffer = headers; kbuf->mem =KEXEC_BUF_MEM_UNKNOWN ;
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 145/1146 selftests/powerpc: Suppress -Wmaybe-uninitialized with GCC 15
In reply to Greg Kroah-Hartman7.0-stable review patch. If anyone has any objections, please let me know.
------------------
From: Amit Machhiwal <[email protected]>
[ Upstream commit 6e65886fceb23605eff952d6b1975737b4c4b154 ]
GCC 15 reports the below false positive '-Wmaybe-uninitialized' warning in vphn_unpack_associativity() when building the powerpc selftests.
# make -C tools/testing/selftests TARGETS="powerpc"
[...]
CC test-vphn
In file included from test-vphn.c:3:
In function ‘vphn_unpack_associativity’,
inlined from ‘test_one’ at test-vphn.c:371:2,
inlined from ‘test_vphn’ at test-vphn.c:399:9:
test-vphn.c:10:33: error: ‘be_packed’ may be used uninitialized [-Werror=maybe-uninitialized]
10 | #define be16_to_cpup(x) bswap_16(*x)
| ^~~~~~~~
vphn.c:42:27: note: in expansion of macro ‘be16_to_cpup’
42 | u16 new = be16_to_cpup(field++);
| ^~~~~~~~~~~~
In file included from test-vphn.c:19:
vphn.c: In function ‘test_vphn’:
vphn.c:27:16: note: ‘be_packed’ declared here
27 | __be64 be_packed[VPHN_REGISTER_COUNT];
| ^~~~~~~~~
cc1: all warnings being treated as errorsWhen vphn_unpack_associativity() is called from hcall_vphn() in kernel the error is not seen while building vphn.c during kernel compilation. This is because the top level Makefile includes '-fno-strict-aliasing' flag always.
The issue here is that GCC 15 emits '-Wmaybe-uninitialized' due to type punning between __be64[] and __b16* when accessing the buffer via be16_to_cpup(). The underlying object is fully initialized but GCC 15 fails to track the aliasing due to the strict aliasing violation here. Please refer [1] and [2]. This results in a false positive warning which is promoted to an error under '-Werror'. This problem is not seen when the compilation is performed with GCC 13 and 14. An issue [1] has also been created on GCC bugzilla.
The selftest compiles fine with '-fno-strict-aliasing'. Since this GCC flag is used to compile vphn.c in kernel too, the same flag should be used to build vphn tests when compiling vphn.c in the selftest as well.
Fix this by including '-fno-strict-aliasing' during vphn.c compilation in the selftest. This keeps the build working while limiting the scope of the suppression to building vphn tests.
[1] https://gcc.gnu.org/bugzilla/show_bug.cgi?id=124427
[2] https://gcc.gnu.org/bugzilla/show_bug.cgi?id=99768
--- tools/testing/selftests/powerpc/vphn/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
tools/testing/selftests/powerpc/vphn/Makefile +1 -1
@@ -5,7 +5,7 @@ top_srcdir = ../../../../.. include ../../lib.mk include ../flags.mk -CFLAGS += -m64 -I$(CURDIR) +CFLAGS += -m64 -I$(CURDIR) -fno-strict-aliasing $(TEST_GEN_PROGS): ../harness.c
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 146/1146 bpf: Fix abuse of kprobe_write_ctx via freplace
In reply to Greg Kroah-Hartman7.0-stable review patch. If anyone has any objections, please let me know.
------------------
From: Leon Hwang <[email protected]>
[ Upstream commit 611fe4b79af72d00d80f2223354284447daafae9 ]
uprobe programs are allowed to modify struct pt_regs.
Since the actual program type of uprobe is KPROBE, it can be abused to modify struct pt_regs via kprobe+freplace when the kprobe attaches to kernel functions.
For example,
SEC("?kprobe")
int kprobe(struct pt_regs *regs)
{
return 0;
}SEC("?freplace")
int freplace_kprobe(struct pt_regs *regs)
{
regs->di = 0;
return 0;
}freplace_kprobe prog will attach to kprobe prog.
kprobe prog will attach to a kernel function.
Without this patch, when the kernel function runs, its first arg will always be set as 0 via the freplace_kprobe prog.
To fix the abuse of kprobe_write_ctx=true via kprobe+freplace, disallow attaching freplace programs on kprobe programs with different kprobe_write_ctx values.
--- kernel/bpf/syscall.c | 17 +++++++++++++++++ 1 file changed, 17 insertions(+)
kernel/bpf/syscall.c +17 -0
@@ -3754,6 +3754,23 @@ static int bpf_tracing_prog_attach(struct bpf_prog *prog, tr = prog->aux->dst_trampoline; tgt_prog = prog->aux->dst_prog; } +/* +* It is to prevent modifying struct pt_regs via kprobe_write_ctx=true +* freplace prog. Without this check, kprobe_write_ctx=true freplace +* prog is allowed to attach to kprobe_write_ctx=false kprobe prog, and +* then modify the registers of the kprobe prog's target kernel +* function. +* +* This also blocks the combination of uprobe+freplace, because it is +* unable to recognize the use of the tgt_prog as an uprobe or a kprobe +* by tgt_prog itself. At attach time, uprobe/kprobe is recognized by +* the target perf event flags in __perf_event_set_bpf_prog(). +*/ +if (prog->type ==BPF_PROG_TYPE_EXT && + prog->aux->kprobe_write_ctx != tgt_prog->aux->kprobe_write_ctx) { + err = -EINVAL ; + goto out_unlock; + } err =bpf_link_prime (&link->link.link, &link_primer);if (err)
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 147/1146 macvlan: annotate data-races around port->bc_queue_len_used
In reply to Greg Kroah-Hartman7.0-stable review patch. If anyone has any objections, please let me know.
------------------
From: Eric Dumazet <[email protected]>
[ Upstream commit 1ef5789d9906df3771c99b7f413caaf2bf473ca5 ]
port->bc_queue_len_used is read and written locklessly, add READ_ONCE()/WRITE_ONCE() annotations.
While WRITE_ONCE() in macvlan_fill_info() is not yet needed, it is a prereq for future RTNL avoidance.
--- drivers/net/macvlan.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-)
drivers/net/macvlan.c +5 -3
@@ -352,6 +352,7 @@ static void macvlan_broadcast_enqueue(struct macvlan_port *port,const struct macvlan_dev *src, struct sk_buff *skb) { + u32 bc_queue_len_used = READ_ONCE(port->bc_queue_len_used);struct sk_buff *nskb;int err = -ENOMEM ;
@@ -362,7 +363,7 @@ static void macvlan_broadcast_enqueue(struct macvlan_port *port,MACVLAN_SKB_CB (nskb)->src = src;spin_lock (&port->bc_queue.lock); -if (skb_queue_len (&port->bc_queue) < port->bc_queue_len_used) { +if (skb_queue_len (&port->bc_queue) < bc_queue_len_used) {if (src)dev_hold (src->dev);__skb_queue_tail (&port->bc_queue, nskb);
@@ -1727,7 +1728,8 @@ static int macvlan_fill_info(struct sk_buff *skb, }if (nla_put_u32 (skb,IFLA_MACVLAN_BC_QUEUE_LEN , vlan->bc_queue_len_req)) goto nla_put_failure; -if (nla_put_u32 (skb,IFLA_MACVLAN_BC_QUEUE_LEN_USED , port->bc_queue_len_used)) +if (nla_put_u32 (skb,IFLA_MACVLAN_BC_QUEUE_LEN_USED , +READ_ONCE (port->bc_queue_len_used))) goto nla_put_failure;if (port->bc_cutoff !=1 &&nla_put_s32 (skb,IFLA_MACVLAN_BC_CUTOFF , port->bc_cutoff))
@@ -1787,7 +1789,7 @@ static void update_port_bc_queue_len(struct macvlan_port *port)if (vlan->bc_queue_len_req > max_bc_queue_len_req) max_bc_queue_len_req = vlan->bc_queue_len_req; } - port->bc_queue_len_used = max_bc_queue_len_req; +WRITE_ONCE (port->bc_queue_len_used, max_bc_queue_len_req); } static int macvlan_device_event(struct notifier_block *unused,
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 148/1146 bpf: Use copy_map_value_locked() in alloc_htab_elem() for BPF_F_LOCK
In reply to Greg Kroah-Hartman7.0-stable review patch. If anyone has any objections, please let me know.
------------------
From: Mykyta Yatsenko <[email protected]>
[ Upstream commit 07738bc566c38e0a8c82084e962890d1d59715c8 ]
When a BPF_F_LOCK update races with a concurrent delete, the freed element can be immediately recycled by alloc_htab_elem(). The fast path in htab_map_update_elem() performs a lockless lookup and then calls copy_map_value_locked() under the element's spin_lock. If alloc_htab_elem() recycles the same memory, it overwrites the value with plain copy_map_value(), without taking the spin_lock, causing torn writes.
Use copy_map_value_locked() when BPF_F_LOCK is set so the new element's value is written under the embedded spin_lock, serializing against any stale lock holders.
--- kernel/bpf/hashtab.c | 4 ++++ 1 file changed, 4 insertions(+)
kernel/bpf/hashtab.c +4 -0
@@ -1138,6 +1138,10 @@ static struct htab_elem *alloc_htab_elem(struct bpf_htab *htab, void *key, }else if (fd_htab_map_needs_adjust (htab)) { size =round_up (size,8 );memcpy (htab_elem_value (l_new, key_size), value, size); + }else if (map_flags &BPF_F_LOCK ) { +copy_map_value_locked (&htab->map, +htab_elem_value (l_new, key_size), + value, false); }else {copy_map_value (&htab->map,htab_elem_value (l_new, key_size), value); }
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 149/1146 bpf: fix end-of-list detection in cgroup_storage_get_next_key()
In reply to Greg Kroah-Hartman7.0-stable review patch. If anyone has any objections, please let me know.
------------------
From: Weiming Shi <[email protected]>
[ Upstream commit 5828b9e5b272ecff7cf5d345128d3de7324117f7 ]
list_next_entry() never returns NULL -- when the current element is the last entry it wraps to the list head via container_of(). The subsequent NULL check is therefore dead code and get_next_key() never returns -ENOENT for the last element, instead reading storage->key from a bogus pointer that aliases internal map fields and copying the result to userspace.
Replace it with list_entry_is_head() so the function correctly returns -ENOENT when there are no more entries.
--- kernel/bpf/local_storage.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
kernel/bpf/local_storage.c +1 -1
@@ -270,7 +270,7 @@ static int cgroup_storage_get_next_key(struct bpf_map *_map, void *key, goto enoent; storage =list_next_entry (storage, list_map); -if (!storage) +if (list_entry_is_head (storage, &map->list, list_map)) goto enoent; }else { storage = list_first_entry(&map->list,
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 150/1146 bpf: Fix stale offload->prog pointer after constant blinding
In reply to Greg Kroah-Hartman7.0-stable review patch. If anyone has any objections, please let me know.
------------------
From: MingTao Huang <[email protected]>
[ Upstream commit a1aa9ef47c299c5bbc30594d3c2f0589edf908e6 ]
When a dev-bound-only BPF program (BPF_F_XDP_DEV_BOUND_ONLY) undergoes JIT compilation with constant blinding enabled (bpf_jit_harden >= 2), bpf_jit_blind_constants() clones the program. The original prog is then freed in bpf_jit_prog_release_other(), which updates aux->prog to point to the surviving clone, but fails to update offload->prog.
This leaves offload->prog pointing to the freed original program. When the network namespace is subsequently destroyed, cleanup_net() triggers bpf_dev_bound_netdev_unregister(), which iterates ondev->progs and calls __bpf_prog_offload_destroy(offload->prog). Accessing the freed prog causes a page fault:
BUG: unable to handle page fault for address: ffffc900085f1038 Workqueue: netns cleanup_net RIP: 0010:__bpf_prog_offload_destroy+0xc/0x80 Call Trace: __bpf_offload_dev_netdev_unregister+0x257/0x350 bpf_dev_bound_netdev_unregister+0x4a/0x90 unregister_netdevice_many_notify+0x2a2/0x660
...cleanup_net+0x21a/0x320
The test sequence that triggers this reliably is:
1. Set net.core.bpf_jit_harden=2 (echo 2 > /proc/sys/net/core/bpf_jit_harden)
2. Run xdp_metadata selftest, which creates a dev-bound-only XDP program on a veth inside a netns (./test_progs -t xdp_metadata)
3. cleanup_net -> page fault in __bpf_prog_offload_destroy
Dev-bound-only programs are unique in that they have an offload structure but go through the normal JIT path instead of bpf_prog_offload_compile(). This means they are subject to constant blinding's prog clone-and-replace, while also having offload->prog that must stay in sync.
Fix this by updating offload->prog in bpf_jit_prog_release_other(), alongside the existing aux->prog update. Both are back-pointers to the prog that must be kept in sync when the prog is replaced.
--- kernel/bpf/core.c | 2 ++ 1 file changed, 2 insertions(+)
kernel/bpf/core.c +2 -0
@@ -1487,6 +1487,8 @@ void bpf_jit_prog_release_other(struct bpf_prog *fp, struct bpf_prog *fp_other)* know whether fp here is the clone or the original. */ fp->aux->prog = fp; +if (fp->aux->offload) + fp->aux->offload->prog = fp;bpf_prog_clone_free (fp_other); }
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 151/1146 net: ethernet: ti-cpsw:: rename soft_reset() function
In reply to Greg Kroah-Hartman7.0-stable review patch. If anyone has any objections, please let me know.
------------------
From: Arnd Bergmann <[email protected]>
[ Upstream commit 961f3c535608df64553f61d64ca086aa9f371bdd ]
While looking at the glob symbols shared between the cpsw drivers, I noticed that soft_reset() is the only one that is missing a proper namespace prefix, and will pollute the kernel namespace, so rename it to be consistent with the other symbols.
Stable-dep-of: df75bd552a87 ("net: ethernet: ti-cpsw: fix linking built-in code to modules")
--- drivers/net/ethernet/ti/cpsw.c | 2 +- drivers/net/ethernet/ti/cpsw_new.c | 2 +- drivers/net/ethernet/ti/cpsw_priv.c | 2 +- drivers/net/ethernet/ti/cpsw_priv.h | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-)
drivers/net/ethernet/ti/cpsw.c +1 -1
@@ -706,7 +706,7 @@ static void cpsw_init_host_port(struct cpsw_priv *priv)struct cpsw_common *cpsw = priv->cpsw;/* soft reset the controller and initialize ale */ -soft_reset ("cpsw" , &cpsw->regs->soft_reset); +cpsw_soft_reset ("cpsw" , &cpsw->regs->soft_reset);cpsw_ale_start (cpsw->ale);/* switch to vlan aware mode */
drivers/net/ethernet/ti/cpsw_new.c +1 -1
@@ -573,7 +573,7 @@ static void cpsw_init_host_port(struct cpsw_priv *priv)u32 control_reg;/* soft reset the controller and initialize ale */ -soft_reset ("cpsw" , &cpsw->regs->soft_reset); +cpsw_soft_reset ("cpsw" , &cpsw->regs->soft_reset);cpsw_ale_start (cpsw->ale);/* switch to vlan aware mode */
drivers/net/ethernet/ti/cpsw_priv.c +1 -1
@@ -275,7 +275,7 @@ void cpsw_set_slave_mac(struct cpsw_slave *slave, struct cpsw_priv *priv)slave_write (slave,mac_lo (priv->mac_addr),SA_LO ); } -void soft_reset (const char *module,void __iomem *reg) +void cpsw_soft_reset (const char *module,void __iomem *reg) {unsigned long timeout = jiffies +HZ ;
drivers/net/ethernet/ti/cpsw_priv.h +1 -1
@@ -458,7 +458,7 @@ int cpsw_tx_poll(struct napi_struct *napi_tx, int budget);int cpsw_rx_mq_poll (struct napi_struct *napi_rx,int budget);int cpsw_rx_poll (struct napi_struct *napi_rx,int budget);void cpsw_rx_vlan_encap (struct sk_buff *skb); -void soft_reset (const char *module,void __iomem *reg); +void cpsw_soft_reset (const char *module,void __iomem *reg);void cpsw_set_slave_mac (struct cpsw_slave *slave,struct cpsw_priv *priv);void cpsw_ndo_tx_timeout (struct net_device *ndev,unsigned int txqueue);int cpsw_need_resplit (struct cpsw_common *cpsw);
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 152/1146 net: ethernet: ti-cpsw: fix linking built-in code to modules
In reply to Greg Kroah-Hartman7.0-stable review patch. If anyone has any objections, please let me know.
------------------
From: Arnd Bergmann <[email protected]>
[ Upstream commit df75bd552a8790e83d4aeb5f112050cf3dc687bf ]
There are six variants of the cpsw driver, sharing various parts of the code: davinci-emac, cpsw, cpsw-switchdev, netcp, netcp_ethss and am65-cpsw-nuss.
I noticed that this means some files can be linked into more than one loadable module, or even part of vmlinux but also linked into a loadable module, both of which mess up assumptions of the build system, and causes warnings:
scripts/Makefile.build:279: cpsw_ale.o is added to multiple modules: ti-am65-cpsw-nuss ti_cpsw ti_cpsw_new scripts/Makefile.build:279: cpsw_priv.o is added to multiple modules: ti_cpsw ti_cpsw_new scripts/Makefile.build:279: cpsw_sl.o is added to multiple modules: ti-am65-cpsw-nuss ti_cpsw ti_cpsw_new scripts/Makefile.build:279: cpsw_ethtool.o is added to multiple modules: ti_cpsw ti_cpsw_new scripts/Makefile.build:279: davinci_cpdma.o is added to multiple modules: ti_cpsw ti_cpsw_new ti_davinci_emac
Change this back to having separate modules for each portion that can be linked standalone, exporting symbols as needed:
- ti-cpsw-common.ko now contains both cpsw-common.o and davinci_cpdma.o as they are always used together
- ti-cpsw-priv.ko contains cpsw_priv.o, cpsw_sl.o and cpsw_ethtool.o, which are the core of the cpsw and cpsw-new drivers.
- ti-cpsw-sl.ko contains the cpsw-sl.o object and is used on ti-am65-cpsw-nuss.ko in addition to the two other cpsw variants.
- ti-cpsw-ale.o is the one standalone module that is used by all except davinci_emac.
Each of these will be built-in if any of its users are built-in, otherwise it's a loadable module if there is at least one module using it. I did not bring back the separate Kconfig symbols for this, but just handle it using Makefile logic.
Note: ideally this is something that Kbuild complains about, but usually we just notice when something using THIS_MODULE misbehaves in a way that a user notices.
--- drivers/net/ethernet/ti/Makefile | 30 ++++++++++---------- drivers/net/ethernet/ti/cpsw_ale.c | 25 +++++++++++++++++ drivers/net/ethernet/ti/cpsw_ethtool.c | 24 ++++++++++++++++ drivers/net/ethernet/ti/cpsw_priv.c | 37 +++++++++++++++++++++++++ drivers/net/ethernet/ti/cpsw_sl.c | 11 ++++++++ drivers/net/ethernet/ti/davinci_cpdma.c | 27 ++++++++++++++++++ 6 files changed, 139 insertions(+), 15 deletions(-)
drivers/net/ethernet/ti/Makefile +15 -15
@@ -6,30 +6,30 @@ obj-$(CONFIG_TI_PRUETH) += icssm-prueth.o icssm-prueth-y := icssm/icssm_prueth.o icssm/icssm_prueth_switch.o icssm/icssm_switchdev.o -obj-$(CONFIG_TI_CPSW) += cpsw-common.o -obj-$(CONFIG_TI_DAVINCI_EMAC) += cpsw-common.o -obj-$(CONFIG_TI_CPSW_SWITCHDEV) += cpsw-common.o +ti-cpsw-common-y += cpsw-common.o davinci_cpdma.o +ti-cpsw-priv-y += cpsw_priv.o cpsw_ethtool.o +ti-cpsw-ale-y += cpsw_ale.o +ti-cpsw-sl-y += cpsw_sl.o obj-$(CONFIG_TLAN) += tlan.o -obj-$(CONFIG_TI_DAVINCI_EMAC) += ti_davinci_emac.o -ti_davinci_emac-y := davinci_emac.o davinci_cpdma.o +obj-$(CONFIG_TI_DAVINCI_EMAC) += davinci_emac.o ti-cpsw-common.o obj-$(CONFIG_TI_DAVINCI_MDIO) += davinci_mdio.o obj-$(CONFIG_TI_CPSW_PHY_SEL) += cpsw-phy-sel.o obj-$(CONFIG_TI_CPTS) += cpts.o -obj-$(CONFIG_TI_CPSW) += ti_cpsw.o -ti_cpsw-y := cpsw.o davinci_cpdma.o cpsw_ale.o cpsw_priv.o cpsw_sl.o cpsw_ethtool.o -obj-$(CONFIG_TI_CPSW_SWITCHDEV) += ti_cpsw_new.o -ti_cpsw_new-y := cpsw_switchdev.o cpsw_new.o davinci_cpdma.o cpsw_ale.o cpsw_sl.o cpsw_priv.o cpsw_ethtool.o +obj-$(CONFIG_TI_CPSW) += ti_cpsw.o ti-cpsw-common.o ti-cpsw-priv.o ti-cpsw-ale.o ti-cpsw-sl.o +ti_cpsw-y := cpsw.o +obj-$(CONFIG_TI_CPSW_SWITCHDEV) += ti_cpsw_new.o ti-cpsw-common.o ti-cpsw-priv.o ti-cpsw-ale.o ti-cpsw-sl.o +ti_cpsw_new-y := cpsw_switchdev.o cpsw_new.o -obj-$(CONFIG_TI_KEYSTONE_NETCP) += keystone_netcp.o -keystone_netcp-y := netcp_core.o cpsw_ale.o -obj-$(CONFIG_TI_KEYSTONE_NETCP_ETHSS) += keystone_netcp_ethss.o -keystone_netcp_ethss-y := netcp_ethss.o netcp_sgmii.o netcp_xgbepcsr.o cpsw_ale.o +obj-$(CONFIG_TI_KEYSTONE_NETCP) += keystone_netcp.o ti-cpsw-ale.o +keystone_netcp-y := netcp_core.o +obj-$(CONFIG_TI_KEYSTONE_NETCP_ETHSS) += keystone_netcp_ethss.o ti-cpsw-ale.o +keystone_netcp_ethss-y := netcp_ethss.o netcp_sgmii.o netcp_xgbepcsr.o obj-$(CONFIG_TI_K3_CPPI_DESC_POOL) += k3-cppi-desc-pool.o -obj-$(CONFIG_TI_K3_AM65_CPSW_NUSS) += ti-am65-cpsw-nuss.o -ti-am65-cpsw-nuss-y := am65-cpsw-nuss.o cpsw_sl.o am65-cpsw-ethtool.o cpsw_ale.o +obj-$(CONFIG_TI_K3_AM65_CPSW_NUSS) += ti-am65-cpsw-nuss.o ti-cpsw-sl.o ti-cpsw-ale.o +ti-am65-cpsw-nuss-y := am65-cpsw-nuss.o am65-cpsw-ethtool.o ti-am65-cpsw-nuss-$(CONFIG_TI_AM65_CPSW_QOS) += am65-cpsw-qos.o ti-am65-cpsw-nuss-$(CONFIG_TI_K3_AM65_CPSW_SWITCHDEV) += am65-cpsw-switchdev.o obj-$(CONFIG_TI_K3_AM65_CPTS) += am65-cpts.o
drivers/net/ethernet/ti/cpsw_ale.c +25 -0
@@ -493,6 +493,7 @@ int cpsw_ale_flush_multicast(struct cpsw_ale *ale, int port_mask, int vid) }return 0 ; } +EXPORT_SYMBOL_GPL (cpsw_ale_flush_multicast);static inline void cpsw_ale_set_vlan_entry_type (u32 *ale_entry,int flags,u16 vid)
@@ -530,6 +531,7 @@ int cpsw_ale_add_ucast(struct cpsw_ale *ale, const u8 *addr, int port,cpsw_ale_write (ale, idx, ale_entry);return 0 ; } +EXPORT_SYMBOL_GPL (cpsw_ale_add_ucast);int cpsw_ale_del_ucast (struct cpsw_ale *ale,const u8 *addr,int port,int flags,u16 vid)
@@ -545,6 +547,7 @@ int cpsw_ale_del_ucast(struct cpsw_ale *ale, const u8 *addr, int port,cpsw_ale_write (ale, idx, ale_entry);return 0 ; } +EXPORT_SYMBOL_GPL (cpsw_ale_del_ucast);int cpsw_ale_add_mcast (struct cpsw_ale *ale,const u8 *addr,int port_mask,int flags,u16 vid,int mcast_state)
@@ -578,6 +581,7 @@ int cpsw_ale_add_mcast(struct cpsw_ale *ale, const u8 *addr, int port_mask,cpsw_ale_write (ale, idx, ale_entry);return 0 ; } +EXPORT_SYMBOL_GPL (cpsw_ale_add_mcast);int cpsw_ale_del_mcast (struct cpsw_ale *ale,const u8 *addr,int port_mask,int flags,u16 vid)
@@ -607,6 +611,7 @@ int cpsw_ale_del_mcast(struct cpsw_ale *ale, const u8 *addr, int port_mask,cpsw_ale_write (ale, idx, ale_entry);return 0 ; } +EXPORT_SYMBOL_GPL (cpsw_ale_del_mcast);/* ALE NetCP NU switch specific vlan functions */ static void cpsw_ale_set_vlan_mcast(struct cpsw_ale *ale, u32 *ale_entry,
@@ -676,6 +681,7 @@ int cpsw_ale_add_vlan(struct cpsw_ale *ale, u16 vid, int port_mask, int untag,cpsw_ale_write (ale, idx, ale_entry);return 0 ; } +EXPORT_SYMBOL_GPL (cpsw_ale_add_vlan);static void cpsw_ale_vlan_del_modify_int (struct cpsw_ale *ale,u32 *ale_entry,u16 vid,int port_mask)
@@ -733,6 +739,7 @@ int cpsw_ale_vlan_del_modify(struct cpsw_ale *ale, u16 vid, int port_mask)return 0 ; } +EXPORT_SYMBOL_GPL (cpsw_ale_vlan_del_modify);int cpsw_ale_del_vlan (struct cpsw_ale *ale,u16 vid,int port_mask) {
@@ -767,6 +774,7 @@ int cpsw_ale_del_vlan(struct cpsw_ale *ale, u16 vid, int port_mask)return 0 ; } +EXPORT_SYMBOL_GPL (cpsw_ale_del_vlan);int cpsw_ale_vlan_add_modify (struct cpsw_ale *ale,u16 vid,int port_mask,int untag_mask,int reg_mask,int unreg_mask)
@@ -806,6 +814,7 @@ int cpsw_ale_vlan_add_modify(struct cpsw_ale *ale, u16 vid, int port_mask,return ret; } +EXPORT_SYMBOL_GPL (cpsw_ale_vlan_add_modify);void cpsw_ale_set_unreg_mcast (struct cpsw_ale *ale,int unreg_mcast_mask,bool add)
@@ -833,6 +842,7 @@ void cpsw_ale_set_unreg_mcast(struct cpsw_ale *ale, int unreg_mcast_mask,cpsw_ale_write (ale, idx, ale_entry); } } +EXPORT_SYMBOL_GPL (cpsw_ale_set_unreg_mcast);static void cpsw_ale_vlan_set_unreg_mcast (struct cpsw_ale *ale,u32 *ale_entry,int allmulti)
@@ -898,6 +908,7 @@ void cpsw_ale_set_allmulti(struct cpsw_ale *ale, int allmulti, int port)cpsw_ale_write (ale, idx, ale_entry); } } +EXPORT_SYMBOL_GPL (cpsw_ale_set_allmulti);struct ale_control_info {const char *name;
@@ -1155,6 +1166,7 @@ int cpsw_ale_control_set(struct cpsw_ale *ale, int port, int control,return 0 ; } +EXPORT_SYMBOL_GPL (cpsw_ale_control_set);int cpsw_ale_control_get (struct cpsw_ale *ale,int port,int control) {
@@ -1178,6 +1190,7 @@ int cpsw_ale_control_get(struct cpsw_ale *ale, int port, int control) tmp =readl_relaxed (ale->params.ale_regs + offset) >> shift;return tmp &BITMASK (info->bits); } +EXPORT_SYMBOL_GPL (cpsw_ale_control_get);int cpsw_ale_rx_ratelimit_mc (struct cpsw_ale *ale,int port,unsigned int ratelimit_pps)
@@ -1200,6 +1213,7 @@ int cpsw_ale_rx_ratelimit_mc(struct cpsw_ale *ale, int port, unsigned int rateli port, val * ALE_RATE_LIMIT_MIN_PPS);return 0 ; } +EXPORT_SYMBOL_GPL (cpsw_ale_rx_ratelimit_mc);int cpsw_ale_rx_ratelimit_bc (struct cpsw_ale *ale,int port,unsigned int ratelimit_pps)
@@ -1222,6 +1236,7 @@ int cpsw_ale_rx_ratelimit_bc(struct cpsw_ale *ale, int port, unsigned int rateli port, val * ALE_RATE_LIMIT_MIN_PPS);return 0 ; } +EXPORT_SYMBOL_GPL (cpsw_ale_rx_ratelimit_bc);static void cpsw_ale_timer (struct timer_list *t) {
@@ -1311,6 +1326,7 @@ void cpsw_ale_start(struct cpsw_ale *ale)cpsw_ale_aging_start (ale); } +EXPORT_SYMBOL_GPL (cpsw_ale_start);void cpsw_ale_stop (struct cpsw_ale *ale) {
@@ -1318,6 +1334,7 @@ void cpsw_ale_stop(struct cpsw_ale *ale)cpsw_ale_control_set (ale,0 ,ALE_CLEAR ,1 );cpsw_ale_control_set (ale,0 ,ALE_ENABLE ,0 ); } +EXPORT_SYMBOL_GPL (cpsw_ale_stop);static const struct reg_field ale_fields_cpsw[] = {/* CPSW_ALE_IDVER_REG */
@@ -1618,6 +1635,7 @@ struct cpsw_ale *cpsw_ale_create(struct cpsw_ale_params *params)cpsw_ale_control_set (ale,0 ,ALE_CLEAR ,1 );return ale; } +EXPORT_SYMBOL_GPL (cpsw_ale_create);void cpsw_ale_dump (struct cpsw_ale *ale,u32 *data) {
@@ -1628,6 +1646,7 @@ void cpsw_ale_dump(struct cpsw_ale *ale, u32 *data) data +=ALE_ENTRY_WORDS ; } } +EXPORT_SYMBOL_GPL (cpsw_ale_dump);void cpsw_ale_restore (struct cpsw_ale *ale,u32 *data) {
@@ -1638,11 +1657,13 @@ void cpsw_ale_restore(struct cpsw_ale *ale, u32 *data) data +=ALE_ENTRY_WORDS ; } } +EXPORT_SYMBOL_GPL (cpsw_ale_restore);u32 cpsw_ale_get_num_entries (struct cpsw_ale *ale) {return ale ? ale->params.ale_entries :0 ; } +EXPORT_SYMBOL_GPL (cpsw_ale_get_num_entries);/* Reads the specified policer index into ALE POLICER registers */ static void cpsw_ale_policer_read_idx (struct cpsw_ale *ale,u32 idx)
@@ -1745,3 +1766,7 @@ void cpsw_ale_classifier_setup_default(struct cpsw_ale *ale, int num_rx_ch) 1); } } +EXPORT_SYMBOL_GPL (cpsw_ale_classifier_setup_default); + +MODULE_LICENSE ("GPL" ); +MODULE_DESCRIPTION ("TI N-Port Ethernet Switch Address Lookup Engine" );
drivers/net/ethernet/ti/cpsw_ethtool.c +24 -0
@@ -144,6 +144,7 @@ u32 cpsw_get_msglevel(struct net_device *ndev)return priv->msg_enable; } +EXPORT_SYMBOL_GPL (cpsw_get_msglevel);void cpsw_set_msglevel (struct net_device *ndev,u32 value) {
@@ -151,6 +152,7 @@ void cpsw_set_msglevel(struct net_device *ndev, u32 value) priv->msg_enable = value; } +EXPORT_SYMBOL_GPL (cpsw_set_msglevel); int cpsw_get_coalesce(struct net_device *ndev, struct ethtool_coalesce *coal, struct kernel_ethtool_coalesce *kernel_coal,
@@ -161,6 +163,7 @@ int cpsw_get_coalesce(struct net_device *ndev, struct ethtool_coalesce *coal, coal->rx_coalesce_usecs = cpsw->coal_intvl;return 0 ; } +EXPORT_SYMBOL_GPL (cpsw_get_coalesce); int cpsw_set_coalesce(struct net_device *ndev, struct ethtool_coalesce *coal, struct kernel_ethtool_coalesce *kernel_coal,
@@ -220,6 +223,7 @@ int cpsw_set_coalesce(struct net_device *ndev, struct ethtool_coalesce *coal,return 0 ; } +EXPORT_SYMBOL_GPL (cpsw_set_coalesce);int cpsw_get_sset_count (struct net_device *ndev,int sset) {
@@ -234,6 +238,7 @@ int cpsw_get_sset_count(struct net_device *ndev, int sset)return -EOPNOTSUPP ; } } +EXPORT_SYMBOL_GPL (cpsw_get_sset_count);static void cpsw_add_ch_strings (u8 **p,int ch_num,int rx_dir) {
@@ -271,6 +276,7 @@ void cpsw_get_strings(struct net_device *ndev, u32 stringset, u8 *data)break ; } } +EXPORT_SYMBOL_GPL (cpsw_get_strings);void cpsw_get_ethtool_stats (struct net_device *ndev,struct ethtool_stats *stats,u64 *data)
@@ -303,6 +309,7 @@ void cpsw_get_ethtool_stats(struct net_device *ndev, } } } +EXPORT_SYMBOL_GPL (cpsw_get_ethtool_stats);void cpsw_get_pauseparam (struct net_device *ndev,struct ethtool_pauseparam *pause)
@@ -313,6 +320,7 @@ void cpsw_get_pauseparam(struct net_device *ndev, pause->rx_pause = priv->rx_pause ? true : false; pause->tx_pause = priv->tx_pause ? true : false; } +EXPORT_SYMBOL_GPL (cpsw_get_pauseparam);void cpsw_get_wol (struct net_device *ndev,struct ethtool_wolinfo *wol) {
@@ -326,6 +334,7 @@ void cpsw_get_wol(struct net_device *ndev, struct ethtool_wolinfo *wol)if (cpsw->slaves[slave_no].phy)phy_ethtool_get_wol (cpsw->slaves[slave_no].phy, wol); } +EXPORT_SYMBOL_GPL (cpsw_get_wol);int cpsw_set_wol (struct net_device *ndev,struct ethtool_wolinfo *wol) {
@@ -338,6 +347,7 @@ int cpsw_set_wol(struct net_device *ndev, struct ethtool_wolinfo *wol)else return -EOPNOTSUPP ; } +EXPORT_SYMBOL_GPL (cpsw_set_wol);int cpsw_get_regs_len (struct net_device *ndev) {
@@ -346,6 +356,7 @@ int cpsw_get_regs_len(struct net_device *ndev)return cpsw_ale_get_num_entries (cpsw->ale) *ALE_ENTRY_WORDS *sizeof (u32); } +EXPORT_SYMBOL_GPL (cpsw_get_regs_len);void cpsw_get_regs (struct net_device *ndev,struct ethtool_regs *regs,void *p) {
@@ -357,6 +368,7 @@ void cpsw_get_regs(struct net_device *ndev, struct ethtool_regs *regs, void *p)cpsw_ale_dump (cpsw->ale, reg); } +EXPORT_SYMBOL_GPL (cpsw_get_regs);int cpsw_ethtool_op_begin (struct net_device *ndev) {
@@ -370,6 +382,7 @@ int cpsw_ethtool_op_begin(struct net_device *ndev)return ret; } +EXPORT_SYMBOL_GPL (cpsw_ethtool_op_begin);void cpsw_ethtool_op_complete (struct net_device *ndev) {
@@ -377,6 +390,7 @@ void cpsw_ethtool_op_complete(struct net_device *ndev)pm_runtime_put (priv->cpsw->dev); } +EXPORT_SYMBOL_GPL (cpsw_ethtool_op_complete);void cpsw_get_channels (struct net_device *ndev,struct ethtool_channels *ch) {
@@ -391,6 +405,7 @@ void cpsw_get_channels(struct net_device *ndev, struct ethtool_channels *ch) ch->tx_count = cpsw->tx_ch_num; ch->combined_count =0 ; } +EXPORT_SYMBOL_GPL (cpsw_get_channels);int cpsw_get_link_ksettings (struct net_device *ndev,struct ethtool_link_ksettings *ecmd)
@@ -405,6 +420,7 @@ int cpsw_get_link_ksettings(struct net_device *ndev,phy_ethtool_ksettings_get (cpsw->slaves[slave_no].phy, ecmd);return 0 ; } +EXPORT_SYMBOL_GPL (cpsw_get_link_ksettings);int cpsw_set_link_ksettings (struct net_device *ndev,const struct ethtool_link_ksettings *ecmd)
@@ -418,6 +434,7 @@ int cpsw_set_link_ksettings(struct net_device *ndev,return phy_ethtool_ksettings_set (cpsw->slaves[slave_no].phy, ecmd); } +EXPORT_SYMBOL_GPL (cpsw_set_link_ksettings);int cpsw_get_eee (struct net_device *ndev,struct ethtool_keee *edata) {
@@ -430,6 +447,7 @@ int cpsw_get_eee(struct net_device *ndev, struct ethtool_keee *edata)else return -EOPNOTSUPP ; } +EXPORT_SYMBOL_GPL (cpsw_get_eee);int cpsw_nway_reset (struct net_device *ndev) {
@@ -442,6 +460,7 @@ int cpsw_nway_reset(struct net_device *ndev)else return -EOPNOTSUPP ; } +EXPORT_SYMBOL_GPL (cpsw_nway_reset);static void cpsw_suspend_data_pass (struct net_device *ndev) {
@@ -639,6 +658,7 @@ int cpsw_set_channels_common(struct net_device *ndev,cpsw_fail (cpsw);return ret; } +EXPORT_SYMBOL_GPL (cpsw_set_channels_common); void cpsw_get_ringparam(struct net_device *ndev, struct ethtool_ringparam *ering,
@@ -654,6 +674,7 @@ void cpsw_get_ringparam(struct net_device *ndev, ering->rx_max_pending = cpsw->descs_pool_size -CPSW_MAX_QUEUES ; ering->rx_pending =cpdma_get_num_rx_descs (cpsw->dma); } +EXPORT_SYMBOL_GPL (cpsw_get_ringparam); int cpsw_set_ringparam(struct net_device *ndev, struct ethtool_ringparam *ering,
@@ -700,6 +721,7 @@ int cpsw_set_ringparam(struct net_device *ndev,cpsw_fail (cpsw);return ret; } +EXPORT_SYMBOL_GPL (cpsw_set_ringparam);#if IS_ENABLED (CONFIG_TI_CPTS )int cpsw_get_ts_info (struct net_device *ndev,struct kernel_ethtool_ts_info *info)
@@ -720,6 +742,7 @@ int cpsw_get_ts_info(struct net_device *ndev, struct kernel_ethtool_ts_info *inf (1 <<HWTSTAMP_FILTER_PTP_V2_EVENT ); return 0; } +EXPORT_SYMBOL_GPL (cpsw_get_ts_info);#else int cpsw_get_ts_info (struct net_device *ndev,struct kernel_ethtool_ts_info *info) {
@@ -729,4 +752,5 @@ int cpsw_get_ts_info(struct net_device *ndev, struct kernel_ethtool_ts_info *inf info->rx_filters =0 ; return 0; } +EXPORT_SYMBOL_GPL (cpsw_get_ts_info);#endif
drivers/net/ethernet/ti/cpsw_priv.c +37 -0
@@ -32,6 +32,7 @@#define CPTS_N_ETX_TS 4int (*cpsw_slave_index)(struct cpsw_common *cpsw,struct cpsw_priv *priv); +EXPORT_SYMBOL_GPL (cpsw_slave_index);void cpsw_intr_enable (struct cpsw_common *cpsw) {
@@ -40,6 +41,7 @@ void cpsw_intr_enable(struct cpsw_common *cpsw)cpdma_ctlr_int_ctrl (cpsw->dma, true); } +EXPORT_SYMBOL_GPL (cpsw_intr_enable);void cpsw_intr_disable (struct cpsw_common *cpsw) {
@@ -48,6 +50,7 @@ void cpsw_intr_disable(struct cpsw_common *cpsw)cpdma_ctlr_int_ctrl (cpsw->dma, false); } +EXPORT_SYMBOL_GPL (cpsw_intr_disable);void cpsw_tx_handler (void *token,int len,int status) {
@@ -82,6 +85,7 @@ void cpsw_tx_handler(void *token, int len, int status) ndev->stats.tx_packets++; ndev->stats.tx_bytes += len; } +EXPORT_SYMBOL_GPL (cpsw_tx_handler);irqreturn_t cpsw_tx_interrupt (int irq,void *dev_id) {
@@ -98,6 +102,7 @@ irqreturn_t cpsw_tx_interrupt(int irq, void *dev_id)napi_schedule (&cpsw->napi_tx);return IRQ_HANDLED ; } +EXPORT_SYMBOL_GPL (cpsw_tx_interrupt);irqreturn_t cpsw_rx_interrupt (int irq,void *dev_id) {
@@ -114,6 +119,7 @@ irqreturn_t cpsw_rx_interrupt(int irq, void *dev_id)napi_schedule (&cpsw->napi_rx);return IRQ_HANDLED ; } +EXPORT_SYMBOL_GPL (cpsw_rx_interrupt);irqreturn_t cpsw_misc_interrupt (int irq,void *dev_id) {
@@ -126,6 +132,7 @@ irqreturn_t cpsw_misc_interrupt(int irq, void *dev_id)return IRQ_HANDLED ; } +EXPORT_SYMBOL_GPL (cpsw_misc_interrupt);int cpsw_tx_mq_poll (struct napi_struct *napi_tx,int budget) {
@@ -158,6 +165,7 @@ int cpsw_tx_mq_poll(struct napi_struct *napi_tx, int budget)return num_tx; } +EXPORT_SYMBOL_GPL (cpsw_tx_mq_poll);int cpsw_tx_poll (struct napi_struct *napi_tx,int budget) {
@@ -176,6 +184,7 @@ int cpsw_tx_poll(struct napi_struct *napi_tx, int budget)return num_tx; } +EXPORT_SYMBOL_GPL (cpsw_tx_poll);int cpsw_rx_mq_poll (struct napi_struct *napi_rx,int budget) {
@@ -208,6 +217,7 @@ int cpsw_rx_mq_poll(struct napi_struct *napi_rx, int budget)return num_rx; } +EXPORT_SYMBOL_GPL (cpsw_rx_mq_poll);int cpsw_rx_poll (struct napi_struct *napi_rx,int budget) {
@@ -226,6 +236,7 @@ int cpsw_rx_poll(struct napi_struct *napi_rx, int budget)return num_rx; } +EXPORT_SYMBOL_GPL (cpsw_rx_poll);void cpsw_rx_vlan_encap (struct sk_buff *skb) {
@@ -268,12 +279,14 @@ void cpsw_rx_vlan_encap(struct sk_buff *skb)skb_pull (skb,VLAN_HLEN ); } } +EXPORT_SYMBOL_GPL (cpsw_rx_vlan_encap);void cpsw_set_slave_mac (struct cpsw_slave *slave,struct cpsw_priv *priv) {slave_write (slave,mac_hi (priv->mac_addr),SA_HI );slave_write (slave,mac_lo (priv->mac_addr),SA_LO ); } +EXPORT_SYMBOL_GPL (cpsw_set_slave_mac);void cpsw_soft_reset (const char *module,void __iomem *reg) {
@@ -286,6 +299,7 @@ void cpsw_soft_reset(const char *module, void __iomem *reg)WARN (readl_relaxed (reg) &1 ,"failed to soft-reset %s\n" , module); } +EXPORT_SYMBOL_GPL (cpsw_soft_reset);void cpsw_ndo_tx_timeout (struct net_device *ndev,unsigned int txqueue) {
@@ -305,6 +319,7 @@ void cpsw_ndo_tx_timeout(struct net_device *ndev, unsigned int txqueue)netif_trans_update (ndev);netif_tx_wake_all_queues (ndev); } +EXPORT_SYMBOL_GPL (cpsw_ndo_tx_timeout);static int cpsw_get_common_speed (struct cpsw_common *cpsw) {
@@ -343,6 +358,7 @@ int cpsw_need_resplit(struct cpsw_common *cpsw)return 1 ; } +EXPORT_SYMBOL_GPL (cpsw_need_resplit);void cpsw_split_res (struct cpsw_common *cpsw) {
@@ -428,6 +444,7 @@ void cpsw_split_res(struct cpsw_common *cpsw)if (budget) cpsw->rxv[0 ].budget += budget; } +EXPORT_SYMBOL_GPL (cpsw_split_res); int cpsw_init_common(struct cpsw_common *cpsw, void __iomem *ss_regs, int ale_ageout, phys_addr_t desc_mem_phys,
@@ -548,6 +565,7 @@ int cpsw_init_common(struct cpsw_common *cpsw, void __iomem *ss_regs,return ret; } +EXPORT_SYMBOL_GPL (cpsw_init_common);#if IS_ENABLED (CONFIG_TI_CPTS )
@@ -678,6 +696,7 @@ int cpsw_hwtstamp_set(struct net_device *dev,return 0 ; } +EXPORT_SYMBOL_GPL (cpsw_hwtstamp_set);int cpsw_hwtstamp_get (struct net_device *dev,struct kernel_hwtstamp_config *cfg)
@@ -695,12 +714,14 @@ int cpsw_hwtstamp_get(struct net_device *dev,return 0 ; } +EXPORT_SYMBOL_GPL (cpsw_hwtstamp_get);#else int cpsw_hwtstamp_get (struct net_device *dev,struct kernel_hwtstamp_config *cfg) {return -EOPNOTSUPP ; } +EXPORT_SYMBOL_GPL (cpsw_hwtstamp_set); int cpsw_hwtstamp_set(struct net_device *dev, struct kernel_hwtstamp_config *cfg,
@@ -708,6 +729,7 @@ int cpsw_hwtstamp_set(struct net_device *dev, {return -EOPNOTSUPP ; } +EXPORT_SYMBOL_GPL (cpsw_hwtstamp_get);#endif /*CONFIG_TI_CPTS*/ int cpsw_ndo_set_tx_maxrate (struct net_device *ndev,int queue,u32 rate)
@@ -758,6 +780,7 @@ int cpsw_ndo_set_tx_maxrate(struct net_device *ndev, int queue, u32 rate)cpsw_split_res (cpsw);return ret; } +EXPORT_SYMBOL_GPL (cpsw_ndo_set_tx_maxrate);static int cpsw_tc_to_fifo (int tc,int num_tc) {
@@ -782,6 +805,7 @@ bool cpsw_shp_is_off(struct cpsw_priv *priv)return !val; } +EXPORT_SYMBOL_GPL (cpsw_shp_is_off);static void cpsw_fifo_shp_on (struct cpsw_priv *priv,int fifo,int on) {
@@ -1043,6 +1067,7 @@ int cpsw_ndo_setup_tc(struct net_device *ndev, enum tc_setup_type type,return -EOPNOTSUPP ; } } +EXPORT_SYMBOL_GPL (cpsw_ndo_setup_tc);void cpsw_cbs_resume (struct cpsw_slave *slave,struct cpsw_priv *priv) {
@@ -1056,6 +1081,7 @@ void cpsw_cbs_resume(struct cpsw_slave *slave, struct cpsw_priv *priv)cpsw_set_fifo_rlimit (priv, fifo, bw); } } +EXPORT_SYMBOL_GPL (cpsw_cbs_resume);void cpsw_mqprio_resume (struct cpsw_slave *slave,struct cpsw_priv *priv) {
@@ -1078,6 +1104,7 @@ void cpsw_mqprio_resume(struct cpsw_slave *slave, struct cpsw_priv *priv)slave_write (slave, tx_prio_map, tx_prio_rg); } +EXPORT_SYMBOL_GPL (cpsw_mqprio_resume);int cpsw_fill_rx_channels (struct cpsw_priv *priv) {
@@ -1123,6 +1150,7 @@ int cpsw_fill_rx_channels(struct cpsw_priv *priv)return 0 ; } +EXPORT_SYMBOL_GPL (cpsw_fill_rx_channels);static struct page_pool *cpsw_create_page_pool (struct cpsw_common *cpsw,int size)
@@ -1208,6 +1236,7 @@ void cpsw_destroy_xdp_rxqs(struct cpsw_common *cpsw) cpsw->page_pool[ch] =NULL ; } } +EXPORT_SYMBOL_GPL (cpsw_destroy_xdp_rxqs);int cpsw_create_xdp_rxqs (struct cpsw_common *cpsw) {
@@ -1240,6 +1269,7 @@ int cpsw_create_xdp_rxqs(struct cpsw_common *cpsw)return ret; } +EXPORT_SYMBOL_GPL (cpsw_create_xdp_rxqs);static int cpsw_xdp_prog_setup (struct cpsw_priv *priv,struct netdev_bpf *bpf) {
@@ -1267,6 +1297,7 @@ int cpsw_ndo_bpf(struct net_device *ndev, struct netdev_bpf *bpf)return -EINVAL ; } } +EXPORT_SYMBOL_GPL (cpsw_ndo_bpf);int cpsw_xdp_tx_frame (struct cpsw_priv *priv,struct xdp_frame *xdpf,struct page *page,int port)
@@ -1300,6 +1331,7 @@ int cpsw_xdp_tx_frame(struct cpsw_priv *priv, struct xdp_frame *xdpf,return ret; } +EXPORT_SYMBOL_GPL (cpsw_xdp_tx_frame);int cpsw_run_xdp (struct cpsw_priv *priv,int ch,struct xdp_buff *xdp,struct page *page,int port,int *len)
@@ -1362,6 +1394,7 @@ int cpsw_run_xdp(struct cpsw_priv *priv, int ch, struct xdp_buff *xdp,page_pool_recycle_direct (cpsw->page_pool[ch], page);return ret; } +EXPORT_SYMBOL_GPL (cpsw_run_xdp); static int cpsw_qos_clsflower_add_policer(struct cpsw_priv *priv, struct netlink_ext_ack *extack,
@@ -1564,3 +1597,7 @@ void cpsw_qos_clsflower_resume(struct cpsw_priv *priv)cpsw_ale_rx_ratelimit_mc (priv->cpsw->ale, port_id, priv->ale_mc_ratelimit.rate_packet_ps); } +EXPORT_SYMBOL_GPL (cpsw_qos_clsflower_resume); + +MODULE_LICENSE ("GPL" ); +MODULE_DESCRIPTION ("TI CPSW Ethernet Switch Driver" );
drivers/net/ethernet/ti/cpsw_sl.c +11 -0
@@ -200,6 +200,7 @@ u32 cpsw_sl_reg_read(struct cpsw_sl *sl, enum cpsw_sl_regs reg)dev_dbg (sl->dev,"cpsw_sl: reg: %04X r 0x%08X\n" , sl->regs[reg], val);return val; } +EXPORT_SYMBOL_GPL (cpsw_sl_reg_read);void cpsw_sl_reg_write (struct cpsw_sl *sl,enum cpsw_sl_regs reg,u32 val) {
@@ -212,6 +213,7 @@ void cpsw_sl_reg_write(struct cpsw_sl *sl, enum cpsw_sl_regs reg, u32 val)dev_dbg (sl->dev,"cpsw_sl: reg: %04X w 0x%08X\n" , sl->regs[reg], val);writel (val, sl->sl_base + sl->regs[reg]); } +EXPORT_SYMBOL_GPL (cpsw_sl_reg_write); static const struct cpsw_sl_dev_id *cpsw_sl_match_id( const struct cpsw_sl_dev_id *id,
@@ -252,6 +254,7 @@ struct cpsw_sl *cpsw_sl_get(const char *device_id, struct device *dev,return sl; } +EXPORT_SYMBOL_GPL (cpsw_sl_get);void cpsw_sl_reset (struct cpsw_sl *sl,unsigned long tmo) {
@@ -270,6 +273,7 @@ void cpsw_sl_reset(struct cpsw_sl *sl, unsigned long tmo)if (cpsw_sl_reg_read (sl,CPSW_SL_SOFT_RESET ) &CPSW_SL_SOFT_RESET_BIT )dev_err (sl->dev,"cpsw_sl failed to soft-reset.\n" ); } +EXPORT_SYMBOL_GPL (cpsw_sl_reset);u32 cpsw_sl_ctl_set (struct cpsw_sl *sl,u32 ctl_funcs) {
@@ -287,6 +291,7 @@ u32 cpsw_sl_ctl_set(struct cpsw_sl *sl, u32 ctl_funcs)return 0 ; } +EXPORT_SYMBOL_GPL (cpsw_sl_ctl_set);u32 cpsw_sl_ctl_clr (struct cpsw_sl *sl,u32 ctl_funcs) {
@@ -304,11 +309,13 @@ u32 cpsw_sl_ctl_clr(struct cpsw_sl *sl, u32 ctl_funcs)return 0 ; } +EXPORT_SYMBOL_GPL (cpsw_sl_ctl_clr);void cpsw_sl_ctl_reset (struct cpsw_sl *sl) {cpsw_sl_reg_write (sl,CPSW_SL_MACCONTROL ,0 ); } +EXPORT_SYMBOL_GPL (cpsw_sl_ctl_reset);int cpsw_sl_wait_for_idle (struct cpsw_sl *sl,unsigned long tmo) {
@@ -326,3 +333,7 @@ int cpsw_sl_wait_for_idle(struct cpsw_sl *sl, unsigned long tmo)return 0 ; } +EXPORT_SYMBOL_GPL (cpsw_sl_wait_for_idle); + +MODULE_LICENSE ("GPL" ); +MODULE_DESCRIPTION ("TI Ethernet Switch media-access-controller (MAC) submodule" );
drivers/net/ethernet/ti/davinci_cpdma.c +27 -0
@@ -531,6 +531,7 @@ struct cpdma_ctlr *cpdma_ctlr_create(struct cpdma_params *params) ctlr->num_chan =CPDMA_MAX_CHANNELS ;return ctlr; } +EXPORT_SYMBOL_GPL (cpdma_ctlr_create);int cpdma_ctlr_start (struct cpdma_ctlr *ctlr) {
@@ -591,6 +592,7 @@ int cpdma_ctlr_start(struct cpdma_ctlr *ctlr)spin_unlock_irqrestore (&ctlr->lock, flags);return 0 ; } +EXPORT_SYMBOL_GPL (cpdma_ctlr_start);int cpdma_ctlr_stop (struct cpdma_ctlr *ctlr) {
@@ -623,6 +625,7 @@ int cpdma_ctlr_stop(struct cpdma_ctlr *ctlr)spin_unlock_irqrestore (&ctlr->lock, flags);return 0 ; } +EXPORT_SYMBOL_GPL (cpdma_ctlr_stop);int cpdma_ctlr_destroy (struct cpdma_ctlr *ctlr) {
@@ -640,6 +643,7 @@ int cpdma_ctlr_destroy(struct cpdma_ctlr *ctlr)cpdma_desc_pool_destroy (ctlr);return ret; } +EXPORT_SYMBOL_GPL (cpdma_ctlr_destroy);int cpdma_ctlr_int_ctrl (struct cpdma_ctlr *ctlr,bool enable) {
@@ -660,21 +664,25 @@ int cpdma_ctlr_int_ctrl(struct cpdma_ctlr *ctlr, bool enable)spin_unlock_irqrestore (&ctlr->lock, flags);return 0 ; } +EXPORT_SYMBOL_GPL (cpdma_ctlr_int_ctrl);void cpdma_ctlr_eoi (struct cpdma_ctlr *ctlr,u32 value) {dma_reg_write (ctlr,CPDMA_MACEOIVECTOR , value); } +EXPORT_SYMBOL_GPL (cpdma_ctlr_eoi);u32 cpdma_ctrl_rxchs_state (struct cpdma_ctlr *ctlr) {return dma_reg_read (ctlr,CPDMA_RXINTSTATMASKED ); } +EXPORT_SYMBOL_GPL (cpdma_ctrl_rxchs_state);u32 cpdma_ctrl_txchs_state (struct cpdma_ctlr *ctlr) {return dma_reg_read (ctlr,CPDMA_TXINTSTATMASKED ); } +EXPORT_SYMBOL_GPL (cpdma_ctrl_txchs_state); static void cpdma_chan_set_descs(struct cpdma_ctlr *ctlr, int rx, int desc_num,
@@ -802,6 +810,7 @@ int cpdma_chan_set_weight(struct cpdma_chan *ch, int weight)spin_unlock_irqrestore (&ctlr->lock, flags);return ret; } +EXPORT_SYMBOL_GPL (cpdma_chan_set_weight);/* cpdma_chan_get_min_rate - get minimum allowed rate for channel * Should be called before cpdma_chan_set_rate.
@@ -816,6 +825,7 @@ u32 cpdma_chan_get_min_rate(struct cpdma_ctlr *ctlr)return DIV_ROUND_UP (divident, divisor); } +EXPORT_SYMBOL_GPL (cpdma_chan_get_min_rate);/* cpdma_chan_set_rate - limits bandwidth for transmit channel. * The bandwidth * limited channels have to be in order beginning from lowest.
@@ -860,6 +870,7 @@ int cpdma_chan_set_rate(struct cpdma_chan *ch, u32 rate)spin_unlock_irqrestore (&ctlr->lock, flags);return ret; } +EXPORT_SYMBOL_GPL (cpdma_chan_set_rate);u32 cpdma_chan_get_rate (struct cpdma_chan *ch) {
@@ -872,6 +883,7 @@ u32 cpdma_chan_get_rate(struct cpdma_chan *ch)return rate; } +EXPORT_SYMBOL_GPL (cpdma_chan_get_rate);struct cpdma_chan *cpdma_chan_create (struct cpdma_ctlr *ctlr,int chan_num,cpdma_handler_fn handler,int rx_type)
@@ -931,6 +943,7 @@ struct cpdma_chan *cpdma_chan_create(struct cpdma_ctlr *ctlr, int chan_num,spin_unlock_irqrestore (&ctlr->lock, flags);return chan; } +EXPORT_SYMBOL_GPL (cpdma_chan_create);int cpdma_chan_get_rx_buf_num (struct cpdma_chan *chan) {
@@ -943,6 +956,7 @@ int cpdma_chan_get_rx_buf_num(struct cpdma_chan *chan)return desc_num; } +EXPORT_SYMBOL_GPL (cpdma_chan_get_rx_buf_num);int cpdma_chan_destroy (struct cpdma_chan *chan) {
@@ -964,6 +978,7 @@ int cpdma_chan_destroy(struct cpdma_chan *chan)spin_unlock_irqrestore (&ctlr->lock, flags);return 0 ; } +EXPORT_SYMBOL_GPL (cpdma_chan_destroy);int cpdma_chan_get_stats (struct cpdma_chan *chan,struct cpdma_chan_stats *stats)
@@ -976,6 +991,7 @@ int cpdma_chan_get_stats(struct cpdma_chan *chan,spin_unlock_irqrestore (&chan->lock, flags);return 0 ; } +EXPORT_SYMBOL_GPL (cpdma_chan_get_stats);static void __cpdma_chan_submit (struct cpdma_chan *chan,struct cpdma_desc __iomem *desc)
@@ -1100,6 +1116,7 @@ int cpdma_chan_idle_submit(struct cpdma_chan *chan, void *token, void *data,spin_unlock_irqrestore (&chan->lock, flags);return ret; } +EXPORT_SYMBOL_GPL (cpdma_chan_idle_submit);int cpdma_chan_idle_submit_mapped (struct cpdma_chan *chan,void *token,dma_addr_t data,int len,int directed)
@@ -1125,6 +1142,7 @@ int cpdma_chan_idle_submit_mapped(struct cpdma_chan *chan, void *token,spin_unlock_irqrestore (&chan->lock, flags);return ret; } +EXPORT_SYMBOL_GPL (cpdma_chan_idle_submit_mapped);int cpdma_chan_submit (struct cpdma_chan *chan,void *token,void *data,int len,int directed)
@@ -1150,6 +1168,7 @@ int cpdma_chan_submit(struct cpdma_chan *chan, void *token, void *data,spin_unlock_irqrestore (&chan->lock, flags);return ret; } +EXPORT_SYMBOL_GPL (cpdma_chan_submit);int cpdma_chan_submit_mapped (struct cpdma_chan *chan,void *token,dma_addr_t data,int len,int directed)
@@ -1175,6 +1194,7 @@ int cpdma_chan_submit_mapped(struct cpdma_chan *chan, void *token,spin_unlock_irqrestore (&chan->lock, flags);return ret; } +EXPORT_SYMBOL_GPL (cpdma_chan_submit_mapped);bool cpdma_check_free_tx_desc (struct cpdma_chan *chan) {
@@ -1189,6 +1209,7 @@ bool cpdma_check_free_tx_desc(struct cpdma_chan *chan)spin_unlock_irqrestore (&chan->lock, flags);return free_tx_desc; } +EXPORT_SYMBOL_GPL (cpdma_check_free_tx_desc); static void __cpdma_chan_free(struct cpdma_chan *chan, struct cpdma_desc __iomem *desc,
@@ -1289,6 +1310,7 @@ int cpdma_chan_process(struct cpdma_chan *chan, int quota) }return used; } +EXPORT_SYMBOL_GPL (cpdma_chan_process);int cpdma_chan_start (struct cpdma_chan *chan) {
@@ -1308,6 +1330,7 @@ int cpdma_chan_start(struct cpdma_chan *chan)return 0 ; } +EXPORT_SYMBOL_GPL (cpdma_chan_start);int cpdma_chan_stop (struct cpdma_chan *chan) {
@@ -1370,6 +1393,7 @@ int cpdma_chan_stop(struct cpdma_chan *chan)spin_unlock_irqrestore (&chan->lock, flags);return 0 ; } +EXPORT_SYMBOL_GPL (cpdma_chan_stop);int cpdma_chan_int_ctrl (struct cpdma_chan *chan,bool enable) {
@@ -1416,11 +1440,13 @@ int cpdma_get_num_rx_descs(struct cpdma_ctlr *ctlr) {return ctlr->num_rx_desc; } +EXPORT_SYMBOL_GPL (cpdma_get_num_rx_descs);int cpdma_get_num_tx_descs (struct cpdma_ctlr *ctlr) {return ctlr->num_tx_desc; } +EXPORT_SYMBOL_GPL (cpdma_get_num_tx_descs);int cpdma_set_num_rx_descs (struct cpdma_ctlr *ctlr,int num_rx_desc) {
@@ -1442,3 +1468,4 @@ int cpdma_set_num_rx_descs(struct cpdma_ctlr *ctlr, int num_rx_desc)return ret; } +EXPORT_SYMBOL_GPL (cpdma_set_num_rx_descs);
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 153/1146 wifi: brcmfmac: Fix error pointer dereference
In reply to Greg Kroah-Hartman7.0-stable review patch. If anyone has any objections, please let me know.
------------------
From: Ethan Tidmore <[email protected]>
[ Upstream commit dd8592fc6007a451c3e4b9025de365e39de8178a ]
The function brcmf_chip_add_core() can return an error pointer and is not checked. Add checks for error pointer.
Detected by Smatch:drivers/net/wireless/broadcom/brcm80211/brcmfmac/chip.c:1010 brcmf_chip_recognition() error:
'core' dereferencing possible ERR_PTR()
drivers/net/wireless/broadcom/brcm80211/brcmfmac/chip.c:1013 brcmf_chip_recognition() error:
'core' dereferencing possible ERR_PTR()
drivers/net/wireless/broadcom/brcm80211/brcmfmac/chip.c:1016 brcmf_chip_recognition() error:
'core' dereferencing possible ERR_PTR()
drivers/net/wireless/broadcom/brcm80211/brcmfmac/chip.c:1019 brcmf_chip_recognition() error:
'core' dereferencing possible ERR_PTR()
drivers/net/wireless/broadcom/brcm80211/brcmfmac/chip.c:1022 brcmf_chip_recognition() error:
'core' dereferencing possible ERR_PTR()
--- .../wireless/broadcom/brcm80211/brcmfmac/chip.c | 15 +++++++++++++++ 1 file changed, 15 insertions(+)
drivers/net/wireless/broadcom/brcm80211/brcmfmac/chip.c +15 -0
@@ -1007,18 +1007,33 @@ static int brcmf_chip_recognition(struct brcmf_chip_priv *ci) core =brcmf_chip_add_core (ci,BCMA_CORE_CHIPCOMMON ,SI_ENUM_BASE_DEFAULT ,0 ); +if (IS_ERR (core)) +return PTR_ERR (core); +brcmf_chip_sb_corerev (ci, core); core =brcmf_chip_add_core (ci,BCMA_CORE_SDIO_DEV ,BCM4329_CORE_BUS_BASE ,0 ); +if (IS_ERR (core)) +return PTR_ERR (core); +brcmf_chip_sb_corerev (ci, core); core =brcmf_chip_add_core (ci,BCMA_CORE_INTERNAL_MEM ,BCM4329_CORE_SOCRAM_BASE ,0 ); +if (IS_ERR (core)) +return PTR_ERR (core); +brcmf_chip_sb_corerev (ci, core); core =brcmf_chip_add_core (ci,BCMA_CORE_ARM_CM3 ,BCM4329_CORE_ARM_BASE ,0 ); +if (IS_ERR (core)) +return PTR_ERR (core); +brcmf_chip_sb_corerev (ci, core); core =brcmf_chip_add_core (ci,BCMA_CORE_80211 ,0x18001000 ,0 ); +if (IS_ERR (core)) +return PTR_ERR (core); +brcmf_chip_sb_corerev (ci, core); }else if (socitype ==SOCI_AI ) { ci->iscoreup = brcmf_chip_ai_iscoreup;
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 154/1146 wifi: mac80211: handle VHT EXT NSS in ieee80211_determine_our_sta_mode()
In reply to Greg Kroah-Hartman7.0-stable review patch. If anyone has any objections, please let me know.
------------------
From: Nicolas Escande <[email protected]>
[ Upstream commit b5b8e295973083abf823fb66647a7c702a8db8a7 ]
A station which has a NSS ratio on the number of streams it is capable of in 160MHz VHT operation is supposed to use the 'Extended NSS BW Support' as defined by section '9.4.2.156.2 VHT Capabilities Information field'.
This was missing in ieee80211_determine_our_sta_mode() and so we would wrongfully downgrade our bandwidth when connecting to an AP that supported 160MHz with messages such as:
[ 37.638346] wlan1: AP XX:XX:XX:XX:XX:XX changed bandwidth in assoc response, new used config is 5280.000 MHz, width 3 (5290.000/0 MHz)
--- net/mac80211/mlme.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
net/mac80211/mlme.c +2 -1
@@ -6009,7 +6009,8 @@ ieee80211_determine_our_sta_mode(struct ieee80211_sub_if_data *sdata,if (is_5ghz && !(vht_cap.cap & (IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160MHZ | -IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160_80PLUS80MHZ ))) { +IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160_80PLUS80MHZ | +IEEE80211_VHT_CAP_EXT_NSS_BW_MASK ))) { conn->bw_limit =IEEE80211_CONN_BW_LIMIT_80 ;mlme_link_id_dbg (sdata, link_id,"no VHT 160 MHz capability on 5 GHz, limiting to 80 MHz" );
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 155/1146 bpf: Drop task_to_inode and inet_conn_established from lsm sleepable hooks
In reply to Greg Kroah-Hartman7.0-stable review patch. If anyone has any objections, please let me know.
------------------
From: Jiayuan Chen <[email protected]>
[ Upstream commit beaf0e96b1da74549a6cabd040f9667d83b2e97e ]
bpf_lsm_task_to_inode() is called under rcu_read_lock() and bpf_lsm_inet_conn_established() is called from softirq context, so neither hook can be used by sleepable LSM programs.
--- kernel/bpf/bpf_lsm.c | 3 --- 1 file changed, 3 deletions(-)
kernel/bpf/bpf_lsm.c +0 -3
@@ -359,8 +359,6 @@ BTF_ID(func, bpf_lsm_sb_umount) BTF_ID(func, bpf_lsm_settime)#ifdef CONFIG_SECURITY_NETWORK -BTF_ID(func, bpf_lsm_inet_conn_established) - BTF_ID(func, bpf_lsm_socket_accept) BTF_ID(func, bpf_lsm_socket_bind)BTF_ID (func, bpf_lsm_socket_connect)
@@ -381,7 +379,6 @@ BTF_ID(func, bpf_lsm_syslog) BTF_ID(func, bpf_lsm_task_alloc) BTF_ID(func, bpf_lsm_task_prctl) BTF_ID(func, bpf_lsm_task_setscheduler) -BTF_ID(func, bpf_lsm_task_to_inode) BTF_ID(func, bpf_lsm_userns_create)BTF_SET_END (sleepable_lsm_hooks)
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 156/1146 bpf: reject negative CO-RE accessor indices in bpf_core_parse_spec()
In reply to Greg Kroah-Hartman7.0-stable review patch. If anyone has any objections, please let me know.
------------------
From: Weiming Shi <[email protected]>
[ Upstream commit 1c22483a2c4bbf747787f328392ca3e68619c4dc ]
CO-RE accessor strings are colon-separated indices that describe a path from a root BTF type to a target field, e.g. "0:1:2" walks through nested struct members. bpf_core_parse_spec() parses each component with sscanf("%d"), so negative values like -1 are silently accepted. The subsequent bounds checks (access_idx >= btf_vlen(t)) only guard the upper bound and always pass for negative values because C integer promotion converts the __u16 btf_vlen result to int, making the comparison (int)(-1) >= (int)(N) false for any positive N.
When -1 reaches btf_member_bit_offset() it gets cast to u32 0xffffffff, producing an out-of-bounds read far past the members array. A crafted BPF program with a negative CO-RE accessor on any struct that exists in vmlinux BTF (e.g. task_struct) crashes the kernel deterministically during BPF_PROG_LOAD on any system with CONFIG_DEBUG_INFO_BTF=y (default on major distributions). The bug is reachable with CAP_BPF:
BUG: unable to handle page fault for address: ffffed11818b6626 #PF: supervisor read access in kernel mode #PF: error_code(0x0000) - not-present page Oops: Oops: 0000 [#1] SMP KASAN NOPTI CPU: 0 UID: 0 PID: 85 Comm: poc Not tainted 7.0.0-rc6 #18 PREEMPT(full) RIP: 0010:bpf_core_parse_spec (tools/lib/bpf/relo_core.c:354) RAX: 00000000ffffffff Call Trace: <TASK> bpf_core_calc_relo_insn (tools/lib/bpf/relo_core.c:1321) bpf_core_apply (kernel/bpf/btf.c:9507) check_core_relo (kernel/bpf/verifier.c:19475) bpf_check (kernel/bpf/verifier.c:26031) bpf_prog_load (kernel/bpf/syscall.c:3089) __sys_bpf (kernel/bpf/syscall.c:6228) </TASK>
CO-RE accessor indices are inherently non-negative (struct member index, array element index, or enumerator index), so reject them immediately after parsing.
--- tools/lib/bpf/relo_core.c | 2 ++ 1 file changed, 2 insertions(+)
tools/lib/bpf/relo_core.c +2 -0
@@ -292,6 +292,8 @@ int bpf_core_parse_spec(const char *prog_name, const struct btf *btf, ++spec_str;if (sscanf (spec_str,"%d%n" , &access_idx, &parsed_len) !=1 )return -EINVAL ; +if (access_idx <0 ) +return -EINVAL ;if (spec->raw_len ==BPF_CORE_SPEC_MAX_LEN )return -E2BIG ; spec_str += parsed_len;
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 157/1146 bpf: Prefer vmlinux symbols over module symbols for unqualified kprobes
In reply to Greg Kroah-Hartman7.0-stable review patch. If anyone has any objections, please let me know.
------------------
From: Andrey Grodzovsky <[email protected]>
[ Upstream commit 1870ddcd94b061f54613b90d6300a350f29fc2f4 ]
When an unqualified kprobe target exists in both vmlinux and a loaded module, number_of_same_symbols() returns a count greater than 1, causing kprobe attachment to fail with -EADDRNOTAVAIL even though the vmlinux symbol is unambiguous.
When no module qualifier is given and the symbol is found in vmlinux, return the vmlinux-only count without scanning loaded modules. This preserves the existing behavior for all other cases:
- Symbol only in a module: vmlinux count is 0, falls through to module scan as before.
- Symbol qualified with MOD:SYM: mod != NULL, unchanged path.
- Symbol ambiguous within vmlinux itself: count > 1 is returned as-is.
--- kernel/trace/trace_kprobe.c | 8 ++++++++ 1 file changed, 8 insertions(+)
kernel/trace/trace_kprobe.c +8 -0
@@ -765,6 +765,14 @@ static unsigned int number_of_same_symbols(const char *mod, const char *func_namif (!mod)kallsyms_on_each_match_symbol (count_symbols, func_name, &ctx.count); +/* +* If the symbol is found in vmlinux, use vmlinux resolution only. +* This prevents module symbols from shadowing vmlinux symbols +* and causing -EADDRNOTAVAIL for unqualified kprobe targets. +*/ +if (!mod && ctx.count >0 ) +return ctx.count; +module_kallsyms_on_each_symbol (mod, count_mod_symbols, &ctx);return ctx.count;
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 158/1146 wifi: ath10k: fix station lookup failure during disconnect
In reply to Greg Kroah-Hartman7.0-stable review patch. If anyone has any objections, please let me know.
------------------
From: Baochen Qiang <[email protected]>
[ Upstream commit 9a34a59c6086ae731a06b3e61b0951feef758648 ]
Recent commit [1] moved station statistics collection to an earlier stage of the disconnect flow. With this change in place, ath10k fails to resolve the station entry when handling a peer stats event triggered during disconnect, resulting in log messages such as:
wlp58s0: deauthenticating from 74:1a:e0:e7:b4:c8 by local choice (Reason: 3=DEAUTH_LEAVING) ath10k_pci 0000:3a:00.0: not found station for peer statsath10k_pci 0000:3a:00.0: failed to parse stats info tlv: -22
The failure occurs because ath10k relies on ieee80211_find_sta_by_ifaddr() for station lookup. That function uses local->sta_hash, but by the time the peer stats request is triggered during disconnect, mac80211 has already removed the station from that hash table, leading to lookup failure.
Before commit [1], this issue was not visible because the transition from IEEE80211_STA_NONE to IEEE80211_STA_NOTEXIST prevented ath10k from sending a peer stats request at all: ath10k_mac_sta_get_peer_stats_info() would fail early to find the peer and skip requesting statistics.
Fix this by switching the lookup path to ath10k_peer_find(), which queries ath10k's internal peer table. At the point where the firmware emits the peer stats event, the peer entry is still present in the driver's list, ensuring lookup succeeds.
Tested-on: QCA6174 hw3.2 PCI WLAN.RM.4.4.1-00309-QCARMSWPZ-1
--- drivers/net/wireless/ath/ath10k/wmi-tlv.c | 26 +++++++++++++---------- 1 file changed, 15 insertions(+), 11 deletions(-)
drivers/net/wireless/ath/ath10k/wmi-tlv.c +15 -11
@@ -3,7 +3,7 @@* Copyright (c) 2005-2011 Atheros Communications Inc. * Copyright (c) 2011-2017 Qualcomm Atheros, Inc. * Copyright (c) 2018-2019, The Linux Foundation. All rights reserved. -* Copyright (c) 2024 Qualcomm Innovation Center, Inc. All rights reserved. +* Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. */ #include "core.h" #include "debug.h"
@@ -14,6 +14,7 @@#include "wmi-tlv.h" #include "p2p.h" #include "testmode.h" +#include "txrx.h" #include <linux/bitfield.h> /***************/
@@ -224,8 +225,9 @@ static int ath10k_wmi_tlv_parse_peer_stats_info(struct ath10k *ar, u16 tag, u16 const void *ptr, void *data) { const struct wmi_tlv_peer_stats_info *stat = ptr; -struct ieee80211_sta *sta; +u32 vdev_id = *(u32 *)data;struct ath10k_sta *arsta; +struct ath10k_peer *peer;if (tag !=WMI_TLV_TAG_STRUCT_PEER_STATS_INFO )return -EPROTO ;
@@ -241,20 +243,20 @@ static int ath10k_wmi_tlv_parse_peer_stats_info(struct ath10k *ar, u16 tag, u16__le32_to_cpu (stat->last_tx_rate_code), __le32_to_cpu(stat->last_tx_bitrate_kbps)); -rcu_read_lock (); - sta =ieee80211_find_sta_by_ifaddr (ar->hw, stat->peer_macaddr.addr,NULL ); -if (!sta) { -rcu_read_unlock (); -ath10k_warn (ar,"not found station for peer stats\n" ); +guard (spinlock_bh)(&ar->data_lock); + + peer =ath10k_peer_find (ar, vdev_id, stat->peer_macaddr.addr); +if (!peer || !peer->sta) { +ath10k_warn (ar,"not found %s with vdev id %u mac addr %pM for peer stats\n" , + peer ?"sta" :"peer" , vdev_id, stat->peer_macaddr.addr);return -EINVAL ; } - arsta = (struct ath10k_sta *)sta->drv_priv; + arsta = (struct ath10k_sta *)peer->sta->drv_priv; arsta->rx_rate_code =__le32_to_cpu (stat->last_rx_rate_code); arsta->rx_bitrate_kbps =__le32_to_cpu (stat->last_rx_bitrate_kbps); arsta->tx_rate_code =__le32_to_cpu (stat->last_tx_rate_code); arsta->tx_bitrate_kbps =__le32_to_cpu (stat->last_tx_bitrate_kbps); -rcu_read_unlock ();return 0 ; }
@@ -266,6 +268,7 @@ static int ath10k_wmi_tlv_op_pull_peer_stats_info(struct ath10k *ar,const struct wmi_tlv_peer_stats_info_ev *ev;const void *data;u32 num_peer_stats; +u32 vdev_id;int ret; tb =ath10k_wmi_tlv_parse_alloc (ar, skb->data, skb->len,GFP_ATOMIC );
@@ -284,15 +287,16 @@ static int ath10k_wmi_tlv_op_pull_peer_stats_info(struct ath10k *ar, } num_peer_stats =__le32_to_cpu (ev->num_peers); + vdev_id =__le32_to_cpu (ev->vdev_id);ath10k_dbg (ar,ATH10K_DBG_WMI ,"wmi tlv peer stats info update peer vdev id %d peers %i more data %d\n" , -__le32_to_cpu (ev->vdev_id), + vdev_id, num_peer_stats,__le32_to_cpu (ev->more_data)); ret =ath10k_wmi_tlv_iter (ar, data,ath10k_wmi_tlv_len (data), - ath10k_wmi_tlv_parse_peer_stats_info,NULL ); + ath10k_wmi_tlv_parse_peer_stats_info, &vdev_id);if (ret)ath10k_warn (ar,"failed to parse stats info tlv: %d\n" , ret);
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 159/1146 bpf: Fix linked reg delta tracking when src_reg == dst_reg
In reply to Greg Kroah-Hartman7.0-stable review patch. If anyone has any objections, please let me know.
------------------
From: Daniel Borkmann <[email protected]>
[ Upstream commit d7f14173c0d5866c3cae759dee560ad1bed10d2e ]
Consider the case of rX += rX where src_reg and dst_reg are pointers to the same bpf_reg_state in adjust_reg_min_max_vals(). The latter first modifies the dst_reg in-place, and later in the delta tracking, the subsequent is_reg_const(src_reg)/reg_const_value(src_reg) reads the post-{add,sub} value instead of the original source.
This is problematic since it sets an incorrect delta, which sync_linked_regs() then propagates to linked registers, thus creating a verifier-vs-runtime mismatch. Fix it by just skipping this corner case.
--- kernel/bpf/verifier.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
kernel/bpf/verifier.c +2 -1
@@ -16325,7 +16325,8 @@ static int adjust_reg_min_max_vals(struct bpf_verifier_env *env,*/ if (env->bpf_capable && (BPF_OP (insn->code) ==BPF_ADD ||BPF_OP (insn->code) ==BPF_SUB ) && - dst_reg->id &&is_reg_const (src_reg, alu32)) { + dst_reg->id &&is_reg_const (src_reg, alu32) && + !(BPF_SRC (insn->code) ==BPF_X && insn->src_reg == insn->dst_reg)) {u64 val =reg_const_value (src_reg, alu32);s32 off;
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 160/1146 net: dropreason: add SKB_DROP_REASON_RECURSION_LIMIT
In reply to Greg Kroah-Hartman7.0-stable review patch. If anyone has any objections, please let me know.
------------------
From: Eric Dumazet <[email protected]>
[ Upstream commit d15d3de94a4766fb43d7fe7a72ed0479fb268131 ]
ip[6]tunnel_xmit() can drop packets if a too deep recursion level is detected.
Add SKB_DROP_REASON_RECURSION_LIMIT drop reason.
We will use this reason later in __dev_queue_xmit().
Stable-dep-of: 7fb4c1967011 ("net: pull headers in qdisc_pkt_len_segs_init()")
--- include/net/dropreason-core.h | 3 +++ include/net/ip6_tunnel.h | 2 +- net/ipv4/ip_tunnel_core.c | 2 +- 3 files changed, 5 insertions(+), 2 deletions(-)
include/net/dropreason-core.h +3 -0
@@ -130,6 +130,7 @@ FN(DUALPI2_STEP_DROP) \ FN(PSP_INPUT) \ FN(PSP_OUTPUT) \ + FN(RECURSION_LIMIT) \ FNe(MAX)/**
@@ -622,6 +623,8 @@ enum skb_drop_reason {SKB_DROP_REASON_PSP_INPUT ,/** @SKB_DROP_REASON_PSP_OUTPUT: PSP output checks failed */ SKB_DROP_REASON_PSP_OUTPUT , +/** @SKB_DROP_REASON_RECURSION_LIMIT: Dead loop on virtual device. */ + SKB_DROP_REASON_RECURSION_LIMIT,/** * @SKB_DROP_REASON_MAX: the maximum of core drop reasons, which * shouldn't be used as a real 'reason' - only for tracing code gen
include/net/ip6_tunnel.h +1 -1
@@ -162,7 +162,7 @@ static inline void ip6tunnel_xmit(struct sock *sk, struct sk_buff *skb, dev->name);DEV_STATS_INC (dev, tx_errors); } -kfree_skb (skb); +kfree_skb_reason (skb,SKB_DROP_REASON_RECURSION_LIMIT );return ; }
net/ipv4/ip_tunnel_core.c +1 -1
@@ -65,7 +65,7 @@ void iptunnel_xmit(struct sock *sk, struct rtable *rt, struct sk_buff *skb,DEV_STATS_INC (dev, tx_errors); }ip_rt_put (rt); -kfree_skb (skb); +kfree_skb_reason (skb,SKB_DROP_REASON_RECURSION_LIMIT );return ; }
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 161/1146 net: plumb drop reasons to __dev_queue_xmit()
In reply to Greg Kroah-Hartman7.0-stable review patch. If anyone has any objections, please let me know.
------------------
From: Eric Dumazet <[email protected]>
[ Upstream commit 045f977dd4ebdd3ad8e96cf684917adfc5805adb ]
Add drop reasons to __dev_queue_xmit():
- SKB_DROP_REASON_DEV_READY : device is not UP.
- SKB_DROP_REASON_RECURSION_LIMIT : recursion limit on virtual device is hit.
Also add an unlikely() for the SKB_DROP_REASON_DEV_READY case, and reduce indentation level.
Stable-dep-of: 7fb4c1967011 ("net: pull headers in qdisc_pkt_len_segs_init()")
--- net/core/dev.c | 83 ++++++++++++++++++++++++++------------------------ 1 file changed, 43 insertions(+), 40 deletions(-)
net/core/dev.c +43 -40
@@ -4761,9 +4761,10 @@ int __dev_queue_xmit(struct sk_buff *skb, struct net_device *sb_dev) {struct net_device *dev = skb->dev;struct netdev_queue *txq =NULL ; -struct Qdisc *q; -int rc = -ENOMEM ; +enum skb_drop_reason reason; +int cpu, rc = -ENOMEM ;bool again = false; +struct Qdisc *q;skb_reset_mac_header (skb);skb_assert_len (skb);
@@ -4832,59 +4833,61 @@ int __dev_queue_xmit(struct sk_buff *skb, struct net_device *sb_dev)* Check this and shot the lock. It is not prone from deadlocks. *Either shot noqueue qdisc, it is even simpler 8) */ -if (dev->flags &IFF_UP ) { -int cpu =smp_processor_id ();/* ok because BHs are off */ +if (unlikely (!(dev->flags &IFF_UP ))) { + reason =SKB_DROP_REASON_DEV_READY ; + goto drop; + } -if (!netif_tx_owned (txq, cpu)) { -bool is_list = false; + cpu =smp_processor_id ();/* ok because BHs are off */ -if (dev_xmit_recursion ()) - goto recursion_alert; +if (likely (!netif_tx_owned (txq, cpu))) { +bool is_list = false; - skb =validate_xmit_skb (skb, dev, &again); -if (!skb) - goto out; +if (dev_xmit_recursion ()) + goto recursion_alert; -HARD_TX_LOCK (dev, txq, cpu); + skb =validate_xmit_skb (skb, dev, &again); +if (!skb) + goto out; -if (!netif_xmit_stopped (txq)) { - is_list = !!skb->next; +HARD_TX_LOCK (dev, txq, cpu); -dev_xmit_recursion_inc (); - skb =dev_hard_start_xmit (skb, dev, txq, &rc); -dev_xmit_recursion_dec (); +if (!netif_xmit_stopped (txq)) { + is_list = !!skb->next; -/* GSO segments a single SKB into -* a list of frames. TCP expects error -* to mean none of the data was sent. -*/ -if (is_list) - rc =NETDEV_TX_OK ; - } -HARD_TX_UNLOCK (dev, txq); -if (!skb)/* xmit completed */ - goto out; +dev_xmit_recursion_inc (); + skb =dev_hard_start_xmit (skb, dev, txq, &rc); +dev_xmit_recursion_dec (); -net_crit_ratelimited ("Virtual device %s asks to queue packet!\n" , - dev->name); -/* NETDEV_TX_BUSY or queue was stopped */ -if (!is_list) - rc = -ENETDOWN ; - }else { -/* Recursion is detected! It is possible, -* unfortunately +/* GSO segments a single SKB into a list of frames. +* TCP expects error to mean none of the data was sent. */ -recursion_alert: -net_crit_ratelimited ("Dead loop on virtual device %s, fix it urgently!\n" , - dev->name); - rc = -ENETDOWN ; +if (is_list) + rc =NETDEV_TX_OK ; } +HARD_TX_UNLOCK (dev, txq); +if (!skb)/* xmit completed */ + goto out; + +net_crit_ratelimited ("Virtual device %s asks to queue packet!\n" , + dev->name); +/* NETDEV_TX_BUSY or queue was stopped */ +if (!is_list) + rc = -ENETDOWN ; + }else { +/* Recursion is detected! It is possible unfortunately. */ +recursion_alert: +net_crit_ratelimited ("Dead loop on virtual device %s, fix it urgently!\n" , + dev->name); + rc = -ENETDOWN ; } + reason =SKB_DROP_REASON_RECURSION_LIMIT ; +drop:rcu_read_unlock_bh ();dev_core_stats_tx_dropped_inc (dev); -kfree_skb_list (skb); +kfree_skb_list_reason (skb, reason);return rc; out:rcu_read_unlock_bh ();
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 162/1146 net: qdisc_pkt_len_segs_init() cleanup
In reply to Greg Kroah-Hartman7.0-stable review patch. If anyone has any objections, please let me know.
------------------
From: Eric Dumazet <[email protected]>
[ Upstream commit 30e02ec3b4b6bd429a4824f125eb843a291dcccf ]
Reduce indentation level by returning early if the transport header was not set.
Add an unlikely() clause as this is not the common case.
No functional change.
Stable-dep-of: 7fb4c1967011 ("net: pull headers in qdisc_pkt_len_segs_init()")
--- net/core/dev.c | 62 +++++++++++++++++++++++++------------------------- 1 file changed, 31 insertions(+), 31 deletions(-)
net/core/dev.c +31 -31
@@ -4106,6 +4106,7 @@ EXPORT_SYMBOL_GPL(validate_xmit_skb_list);static void qdisc_pkt_len_segs_init (struct sk_buff *skb) {struct skb_shared_info *shinfo =skb_shinfo (skb); +unsigned int hdr_len;u16 gso_segs;qdisc_skb_cb (skb)->pkt_len = skb->len;
@@ -4119,44 +4120,43 @@ static void qdisc_pkt_len_segs_init(struct sk_buff *skb)/* To get more precise estimation of bytes sent on wire, * we add to pkt_len the headers size of all segments */ -if (skb_transport_header_was_set (skb)) { -unsigned int hdr_len; +if (unlikely (!skb_transport_header_was_set (skb))) +return ; -/* mac layer + network layer */ -if (!skb->encapsulation) - hdr_len =skb_transport_offset (skb); -else - hdr_len =skb_inner_transport_offset (skb); +/* mac layer + network layer */ +if (!skb->encapsulation) + hdr_len =skb_transport_offset (skb); +else + hdr_len =skb_inner_transport_offset (skb); -/* + transport layer */ -if (likely (shinfo->gso_type & (SKB_GSO_TCPV4 |SKB_GSO_TCPV6 ))) { -const struct tcphdr *th; -struct tcphdr _tcphdr; +/* + transport layer */ +if (likely (shinfo->gso_type & (SKB_GSO_TCPV4 |SKB_GSO_TCPV6 ))) { +const struct tcphdr *th; +struct tcphdr _tcphdr; - th =skb_header_pointer (skb, hdr_len, -sizeof (_tcphdr), &_tcphdr); -if (likely (th)) - hdr_len +=__tcp_hdrlen (th); - }else if (shinfo->gso_type &SKB_GSO_UDP_L4 ) { -struct udphdr _udphdr; + th =skb_header_pointer (skb, hdr_len, +sizeof (_tcphdr), &_tcphdr); +if (likely (th)) + hdr_len +=__tcp_hdrlen (th); + }else if (shinfo->gso_type &SKB_GSO_UDP_L4 ) { +struct udphdr _udphdr; -if (skb_header_pointer (skb, hdr_len, -sizeof (_udphdr), &_udphdr)) - hdr_len +=sizeof (struct udphdr ); - } +if (skb_header_pointer (skb, hdr_len, +sizeof (_udphdr), &_udphdr)) + hdr_len +=sizeof (struct udphdr ); + } -if (unlikely (shinfo->gso_type &SKB_GSO_DODGY )) { -int payload = skb->len - hdr_len; +if (unlikely (shinfo->gso_type &SKB_GSO_DODGY )) { +int payload = skb->len - hdr_len; -/* Malicious packet. */ -if (payload <=0 ) -return ; - gso_segs =DIV_ROUND_UP (payload, shinfo->gso_size); - shinfo->gso_segs = gso_segs; -qdisc_skb_cb (skb)->pkt_segs = gso_segs; - } -qdisc_skb_cb (skb)->pkt_len += (gso_segs -1 ) * hdr_len; +/* Malicious packet. */ +if (payload <=0 ) +return ; + gso_segs =DIV_ROUND_UP (payload, shinfo->gso_size); + shinfo->gso_segs = gso_segs; +qdisc_skb_cb (skb)->pkt_segs = gso_segs; } +qdisc_skb_cb (skb)->pkt_len += (gso_segs -1 ) * hdr_len; } static int dev_qdisc_enqueue(struct sk_buff *skb, struct Qdisc *q,
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 163/1146 net: pull headers in qdisc_pkt_len_segs_init()
In reply to Greg Kroah-Hartman7.0-stable review patch. If anyone has any objections, please let me know.
------------------
From: Eric Dumazet <[email protected]>
[ Upstream commit 7fb4c19670110f052c04e1ec1d2b953b9f4f57e4 ]
Most ndo_start_xmit() methods expects headers of gso packets to be already in skb->head.
net/core/tso.c users are particularly at risk, because tso_build_hdr() does a memcpy(hdr, skb->data, hdr_len);
qdisc_pkt_len_segs_init() already does a dissection of gso packets.
Use pskb_may_pull() instead of skb_header_pointer() to make sure drivers do not have to reimplement this.
Some malicious packets could be fed, detect them so that we can drop them sooner with a new SKB_DROP_REASON_SKB_BAD_GSO drop_reason.
--- include/net/dropreason-core.h | 3 +++ net/core/dev.c | 51 +++++++++++++++++++++-------------- 2 files changed, 34 insertions(+), 20 deletions(-)
include/net/dropreason-core.h +3 -0
@@ -80,6 +80,7 @@ FN(UNHANDLED_PROTO) \ FN(SKB_CSUM) \ FN(SKB_GSO_SEG) \ + FN(SKB_BAD_GSO) \ FN(SKB_UCOPY_FAULT) \ FN(DEV_HDR) \ FN(DEV_READY) \
@@ -427,6 +428,8 @@ enum skb_drop_reason {SKB_DROP_REASON_SKB_CSUM ,/** @SKB_DROP_REASON_SKB_GSO_SEG: gso segmentation error */ SKB_DROP_REASON_SKB_GSO_SEG , +/** @SKB_DROP_REASON_SKB_BAD_GSO: malicious gso packet. */ + SKB_DROP_REASON_SKB_BAD_GSO,/** * @SKB_DROP_REASON_SKB_UCOPY_FAULT: failed to copy data from user space, * e.g., via zerocopy_sg_from_iter() or skb_orphan_frags_rx()
net/core/dev.c +31 -20
103 lines not on this page · raw message
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 164/1146 arm64: entry: Dont preempt with SError or Debug masked
In reply to Greg Kroah-Hartman7.0-stable review patch. If anyone has any objections, please let me know.
------------------
From: Mark Rutland <[email protected]>
[ Upstream commit 2371bd83b3df9d833191fe58dadb0e69a794a1cd ]
On arm64, involuntary kernel preemption has been subtly broken since the move to the generic irqentry code. When preemption occurs, the new task may run with SError and Debug exceptions masked unexpectedly, leading to a loss of RAS events, breakpoints, watchpoints, and single-step exceptions.
Prior to moving to the generic irqentry code, involuntary preemption of kernel mode would only occur when returning from regular interrupts, in a state where interrupts were masked and all other arm64-specific exceptions (SError, Debug, and pseudo-NMI) were unmasked. This is the only state in which it is valid to switch tasks.
As part of moving to the generic irqentry code, the involuntary preemption logic was moved such that involuntary preemption could occur when returning from any (non-NMI) exception. As most exception handlers mask all arm64-specific exceptions before this point, preemption could occur in a state where arm64-specific exceptions were masked. This is not a valid state to switch tasks, and resulted in the loss of exceptions described above.
As a temporary bodge, avoid the loss of exceptions by avoiding involuntary preemption when SError and/or Debug exceptions are masked. Practically speaking this means that involuntary preemption will only occur when returning from regular interrupts, as was the case before moving to the generic irqentry code.
--- arch/arm64/include/asm/entry-common.h | 21 +++++++++++++-------- 1 file changed, 13 insertions(+), 8 deletions(-)
arch/arm64/include/asm/entry-common.h +13 -8
@@ -29,14 +29,19 @@ static __always_inline void arch_exit_to_user_mode_work(struct pt_regs *regs,static inline bool arch_irqentry_exit_need_resched (void ) { -/* -* DAIF.DA are cleared at the start of IRQ/FIQ handling, and when GIC -* priority masking is used the GIC irqchip driver will clear DAIF.IF -* using gic_arch_enable_irqs() for normal IRQs. If anything is set in -* DAIF we must have handled an NMI, so skip preemption. -*/ -if (system_uses_irq_prio_masking () &&read_sysreg (daif)) -return false; +if (system_uses_irq_prio_masking ()) { +/* +* DAIF.DA are cleared at the start of IRQ/FIQ handling, and when GIC +* priority masking is used the GIC irqchip driver will clear DAIF.IF +* using gic_arch_enable_irqs() for normal IRQs. If anything is set in +* DAIF we must have handled an NMI, so skip preemption. +*/ +if (read_sysreg (daif)) +return false; + }else { +if (read_sysreg (daif) & (PSR_D_BIT |PSR_A_BIT )) +return false; + }/* * Preempting a task from an IRQ means we leave copies of PSTATE
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 165/1146 ACPI: AGDI: fix missing newline in error message
In reply to Greg Kroah-Hartman7.0-stable review patch. If anyone has any objections, please let me know.
------------------
From: Haoyu Lu <[email protected]>
[ Upstream commit b178330b67abb7293b6de28b2a49d49c83962db5 ]
Add the missing trailing newline to the dev_err() message printed when SDEI event registration fails.
This keeps the error output as a properly terminated log line.
--- drivers/acpi/arm64/agdi.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/acpi/arm64/agdi.c +1 -1
@@ -36,7 +36,7 @@ static int agdi_sdei_probe(struct platform_device *pdev, err =sdei_event_register (adata->sdei_event, agdi_sdei_handler, pdev);if (err) { -dev_err (&pdev->dev,"Failed to register for SDEI event %d" , +dev_err (&pdev->dev,"Failed to register for SDEI event %d\n" , adata->sdei_event);return err; }
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 166/1146 arm64: kexec: Remove duplicate allocation for trans_pgd
In reply to Greg Kroah-Hartman7.0-stable review patch. If anyone has any objections, please let me know.
------------------
From: Wang Wensheng <[email protected]>
[ Upstream commit ee020bf6f14094c9ae434bb37e6957a1fdad513c ]
trans_pgd would be allocated in trans_pgd_create_copy(), so remove the duplicate allocation before calling trans_pgd_create_copy().
--- arch/arm64/kernel/machine_kexec.c | 3 --- 1 file changed, 3 deletions(-)
arch/arm64/kernel/machine_kexec.c +0 -3
@@ -129,9 +129,6 @@ int machine_kexec_post_load(struct kimage *kimage) }/* Create a copy of the linear map */ - trans_pgd =kexec_page_alloc (kimage); -if (!trans_pgd) -return -ENOMEM ; rc =trans_pgd_create_copy (&info, &trans_pgd,PAGE_OFFSET ,PAGE_END );if (rc)return rc;
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 167/1146 bpf: Propagate error from visit_tailcall_insn
In reply to Greg Kroah-Hartman7.0-stable review patch. If anyone has any objections, please let me know.
------------------
From: Daniel Borkmann <[email protected]>
[ Upstream commit 6bd96e40f31dde8f8cd79772b4df0f171cf8a915 ]
Commit e40f5a6bf88a ("bpf: correct stack liveness for tail calls") added visit_tailcall_insn() but did not check its return value.
--- kernel/bpf/verifier.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-)
kernel/bpf/verifier.c +5 -2
@@ -18894,8 +18894,11 @@ static int visit_insn(int t, struct bpf_verifier_env *env)mark_subprog_might_sleep (env, t);if (bpf_helper_changes_pkt_data (insn->imm))mark_subprog_changes_pkt_data (env, t); -if (insn->imm == BPF_FUNC_tail_call) -visit_tailcall_insn (env, t); +if (insn->imm == BPF_FUNC_tail_call) { + ret =visit_tailcall_insn (env, t); +if (ret) +return ret; + } }else if (insn->src_reg ==BPF_PSEUDO_KFUNC_CALL ) {struct bpf_kfunc_call_arg_meta meta;
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 168/1146 bpf: Fix ld_{abs,ind} failure path analysis in subprogs
In reply to Greg Kroah-Hartman7.0-stable review patch. If anyone has any objections, please let me know.
------------------
From: Daniel Borkmann <[email protected]>
[ Upstream commit ee861486e377edc55361c08dcbceab3f6b6577bd ]
Usage of ld_{abs,ind} instructions got extended into subprogs some time ago via commit 09b28d76eac4 ("bpf: Add abnormal return checks."). These are only allowed in subprograms when the latter are BTF annotated and have scalar return types.
The code generator in bpf_gen_ld_abs() has an abnormal exit path (r0=0 + exit) from legacy cBPF times. While the enforcement is on scalar return types, the verifier must also simulate the path of abnormal exit if the packet data load via ld_{abs,ind} failed.
This is currently not the case. Fix it by having the verifier simulate both success and failure paths, and extend it in similar ways as we do for tail calls. The success path (r0=unknown, continue to next insn) is pushed onto stack for later validation and the r0=0 and return to the caller is done on the fall-through side.
--- kernel/bpf/verifier.c | 33 +++++++++++++++++++++++++++++++-- 1 file changed, 31 insertions(+), 2 deletions(-)
kernel/bpf/verifier.c +31 -2
@@ -17943,6 +17943,23 @@ static int check_ld_abs(struct bpf_verifier_env *env, struct bpf_insn *insn)mark_reg_unknown (env, regs,BPF_REG_0 );/* ld_abs load up to 32-bit skb data. */ regs[BPF_REG_0 ].subreg_def = env->insn_idx +1 ; +/* +* See bpf_gen_ld_abs() which emits a hidden BPF_EXIT with r0=0 +* which must be explored by the verifier when in a subprog. +*/ +if (env->cur_state->curframe) { +struct bpf_verifier_state *branch; + +mark_reg_scratched (env,BPF_REG_0 ); + branch =push_stack (env, env->insn_idx +1 , env->insn_idx, false); +if (IS_ERR (branch)) +return PTR_ERR (branch); +mark_reg_known_zero (env, regs,BPF_REG_0 ); + err =prepare_func_exit (env, &env->insn_idx); +if (err) +return err; + env->insn_idx--; + }return 0 ; }
@@ -18815,7 +18832,12 @@ static int visit_gotox_insn(int t, struct bpf_verifier_env *env)return keep_exploring ?KEEP_EXPLORING :DONE_EXPLORING ; } -static int visit_tailcall_insn (struct bpf_verifier_env *env,int t) +/* +* Instructions that can abnormally return from a subprog (tail_call +* upon success, ld_{abs,ind} upon load failure) have a hidden exit +* that the verifier must account for. +*/ +static int visit_abnormal_return_insn (struct bpf_verifier_env *env,int t) {static struct bpf_subprog_info *subprog;struct bpf_iarray *jt;
@@ -18850,6 +18872,13 @@ static int visit_insn(int t, struct bpf_verifier_env *env)/* All non-branch instructions have a single fall-through edge. */ if (BPF_CLASS (insn->code) !=BPF_JMP &&BPF_CLASS (insn->code) !=BPF_JMP32 ) { +if (BPF_CLASS (insn->code) ==BPF_LD && + (BPF_MODE (insn->code) ==BPF_ABS || +BPF_MODE (insn->code) ==BPF_IND )) { + ret =visit_abnormal_return_insn (env, t); +if (ret) +return ret; + } insn_sz =bpf_is_ldimm64 (insn) ?2 :1 ;return push_insn (t, t + insn_sz,FALLTHROUGH , env); }
@@ -18895,7 +18924,7 @@ static int visit_insn(int t, struct bpf_verifier_env *env)if (bpf_helper_changes_pkt_data (insn->imm))mark_subprog_changes_pkt_data (env, t);if (insn->imm == BPF_FUNC_tail_call) { - ret =visit_tailcall_insn (env, t); + ret =visit_abnormal_return_insn (env, t);if (ret)return ret; }
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 169/1146 bpf: Remove static qualifier from local subprog pointer
In reply to Greg Kroah-Hartman7.0-stable review patch. If anyone has any objections, please let me know.
------------------
From: Daniel Borkmann <[email protected]>
[ Upstream commit 9dba0ae973e75051b63cbdd5b3532bb24aa63b3f ]
The local subprog pointer in create_jt() and visit_abnormal_return_insn() was declared static.
It is unconditionally assigned via bpf_find_containing_subprog() before every use. Thus, the static qualifier serves no purpose and rather creates confusion. Just remove it.
--- kernel/bpf/verifier.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
kernel/bpf/verifier.c +2 -2
@@ -18764,7 +18764,7 @@ static struct bpf_iarray *jt_from_subprog(struct bpf_verifier_env *env,static struct bpf_iarray *create_jt (int t,struct bpf_verifier_env *env) { -static struct bpf_subprog_info *subprog; +struct bpf_subprog_info *subprog;int subprog_start, subprog_end;struct bpf_iarray *jt;int i;
@@ -18839,7 +18839,7 @@ static int visit_gotox_insn(int t, struct bpf_verifier_env *env)*/ static int visit_abnormal_return_insn (struct bpf_verifier_env *env,int t) { -static struct bpf_subprog_info *subprog; +struct bpf_subprog_info *subprog;struct bpf_iarray *jt;if (env->insn_aux_data[t].jt)
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 170/1146 mptcp: better mptcp-level RTT estimator
In reply to Greg Kroah-Hartman7.0-stable review patch. If anyone has any objections, please let me know.
------------------
From: Paolo Abeni <[email protected]>
[ Upstream commit d2000361e4ddf5047d660a902a3b0ed7520be1e5 ]
The current MPTCP-level RTT estimator has several issues. On high speed links, the MPTCP-level receive buffer auto-tuning happens with a frequency well above the TCP-level's one. That in turn can cause excessive/unneeded receive buffer increase.
On such links, the initial rtt_us value is considerably higher than the actual delay, and the current mptcp_rcv_space_adjust() updates msk->rcvq_space.rtt_us with a period equal to the such field previous value. If the initial rtt_us is 40ms, its first update will happen after 40ms, even if the subflows see actual RTT orders of magnitude lower.
Additionally:
- setting the msk RTT to the maximum among all the subflows RTTs makes DRS constantly overshooting the rcvbuf size when a subflow has considerable higher latency than the other(s).
- during unidirectional bulk transfers with multiple active subflows, the TCP-level RTT estimator occasionally sees considerably higher value than the real link delay, i.e. when the packet scheduler reacts to an incoming ACK on given subflow pushing data on a different subflow.
- currently inactive but still open subflows (i.e. switched to backup mode) are always considered when computing the msk-level RTT.
Address the all the issues above with a more accurate RTT estimation
strategy: the MPTCP-level RTT is set to the minimum of all the subflows actually feeding data into the MPTCP receive buffer, using a small sliding window.
While at it, also use EWMA to compute the msk-level scaling_ratio, to that MPTCP can avoid traversing the subflow list is mptcp_rcv_space_adjust().
Use some care to avoid updating msk and ssk level fields too often.
--- include/trace/events/mptcp.h | 2 +- net/mptcp/protocol.c | 63 ++++++++++++++++++++---------------- net/mptcp/protocol.h | 37 ++++++++++++++++++++- 3 files changed, 72 insertions(+), 30 deletions(-)
include/trace/events/mptcp.h +1 -1
@@ -219,7 +219,7 @@ TRACE_EVENT(mptcp_rcvbuf_grow,__be32 *p32; __entry->time = time; - __entry->rtt_us = msk->rcvq_space.rtt_us >>3 ; + __entry->rtt_us =mptcp_rtt_us_est (msk) >>3 ; __entry->copied = msk->rcvq_space.copied; __entry->inq =mptcp_inq_hint (sk); __entry->space = msk->rcvq_space.space;
net/mptcp/protocol.c +35 -28
110 lines not on this page · raw message
net/mptcp/protocol.h +36 -1
@@ -268,6 +268,13 @@ struct mptcp_data_frag {struct page *page; }; +/* Arbitrary compromise between as low as possible to react timely to subflow +* close event and as big as possible to avoid being fouled by biased large +* samples due to peer sending data on a different subflow WRT to the incoming +* ack. +*/ +#define MPTCP_RTT_SAMPLES 5 +/* MPTCP connection sock */ struct mptcp_sock {/* inet_connection_sock must be the first member */
@@ -340,11 +347,17 @@ struct mptcp_sock {*/ struct mptcp_pm_data pm;struct mptcp_sched_ops *sched; + +/* Most recent rtt_us observed by in use incoming subflows. */ +struct { +u32 samples[MPTCP_RTT_SAMPLES ]; +u32 next_sample; + } rcv_rtt_est; +struct {int space;/* bytes copied in last measurement window */ int copied;/* bytes copied in this measurement window */ u64 time;/* start time of measurement window */ -u64 rtt_us;/* last maximum rtt of subflows */ } rcvq_space;u8 scaling_ratio;bool allow_subflows;
@@ -422,6 +435,27 @@ static inline struct mptcp_data_frag *mptcp_send_head(const struct sock *sk)return msk->first_pending; } +static inline void mptcp_init_rtt_est (struct mptcp_sock *msk) +{ +int i; + +for (i =0 ; i <MPTCP_RTT_SAMPLES ; ++i) + msk->rcv_rtt_est.samples[i] =U32_MAX ; + msk->rcv_rtt_est.next_sample =0 ; + msk->scaling_ratio =TCP_DEFAULT_SCALING_RATIO ; +} + +static inline u32 mptcp_rtt_us_est (const struct mptcp_sock *msk) +{ +u32 rtt_us =READ_ONCE (msk->rcv_rtt_est.samples[0 ]); +int i; + +/* Lockless access of collected samples. */ +for (i =1 ; i <MPTCP_RTT_SAMPLES ; ++i) + rtt_us =min (rtt_us,READ_ONCE (msk->rcv_rtt_est.samples[i])); +return rtt_us; +} +static inline struct mptcp_data_frag *mptcp_send_next (struct sock *sk) {struct mptcp_sock *msk =mptcp_sk (sk);
@@ -523,6 +557,7 @@ struct mptcp_subflow_context {u32 map_data_len;__wsum map_data_csum;u32 map_csum_len; +u32 prev_rtt_seq; u32 request_mptcp : 1, /* send MP_CAPABLE */ request_join : 1, /* send MP_JOIN */ request_bkup : 1,
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 171/1146 bpf: Fix use-after-free in offloaded map/prog info fill
In reply to Greg Kroah-Hartman7.0-stable review patch. If anyone has any objections, please let me know.
------------------
From: Jiayuan Chen <[email protected]>
[ Upstream commit a0c584fc18056709c8e047a82a6045d6c209f4ce ]
When querying info for an offloaded BPF map or program, bpf_map_offload_info_fill_ns() and bpf_prog_offload_info_fill_ns() obtain the network namespace with get_net(dev_net(offmap->netdev)). However, the associated netdev's netns may be racing with teardown during netns destruction. If the netns refcount has already reached 0, get_net() performs a refcount_t increment on 0, triggering:
refcount_t: addition on 0; use-after-free.
Although rtnl_lock and bpf_devs_lock ensure the netdev pointer remains valid, they cannot prevent the netns refcount from reaching zero.
Fix this by using maybe_get_net() instead of get_net(). maybe_get_net() uses refcount_inc_not_zero() and returns NULL if the refcount is already zero, which causes ns_get_path_cb() to fail and the caller to return -ENOENT -- the correct behavior when the netns is being destroyed.
--- kernel/bpf/offload.c | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-)
kernel/bpf/offload.c +4 -6
@@ -435,9 +435,8 @@ static struct ns_common *bpf_prog_offload_info_fill_ns(void *private_data)if (aux->offload) { args->info->ifindex = aux->offload->netdev->ifindex; - net =dev_net (aux->offload->netdev); -get_net (net); - ns = &net->ns; + net =maybe_get_net (dev_net (aux->offload->netdev)); + ns = net ? &net->ns :NULL ; }else { args->info->ifindex =0 ; ns =NULL ;
@@ -647,9 +646,8 @@ static struct ns_common *bpf_map_offload_info_fill_ns(void *private_data)if (args->offmap->netdev) { args->info->ifindex = args->offmap->netdev->ifindex; - net =dev_net (args->offmap->netdev); -get_net (net); - ns = &net->ns; + net =maybe_get_net (dev_net (args->offmap->netdev)); + ns = net ? &net->ns :NULL ; }else { args->info->ifindex =0 ; ns =NULL ;
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 172/1146 macsec: Support VLAN-filtering lower devices
In reply to Greg Kroah-Hartman7.0-stable review patch. If anyone has any objections, please let me know.
------------------
From: Cosmin Ratiu <[email protected]>
[ Upstream commit a363b1c8be879c79a688eaf93ba01b63f8b0e63c ]
VLAN-filtering is done through two netdev features (NETIF_F_HW_VLAN_CTAG_FILTER and NETIF_F_HW_VLAN_STAG_FILTER) and two netdev ops (ndo_vlan_rx_add_vid and ndo_vlan_rx_kill_vid).
Implement these and advertise the features if the lower device supports them. This allows proper VLAN filtering to work on top of MACsec devices, when the lower device is capable of VLAN filtering. As a concrete example, having this chain of interfaces now works:vlan_filtering_capable_dev(1) -> macsec_dev(2) -> macsec_vlan_dev(3)
Before the mentioned commit this used to accidentally work because the MACsec device (and thus the lower device) was put in promiscuous mode and the VLAN filter was not used. But after commit [1] correctly made the macsec driver expose the IFF_UNICAST_FLT flag, promiscuous mode was no longer used and VLAN filters on dev 1 kicked in. Without support in dev 2 for propagating VLAN filters down, the register_vlan_dev -> vlan_vid_add -> __vlan_vid_add -> vlan_add_rx_filter_info call from dev 3 is silently eaten (because vlan_hw_filter_capable returns false and vlan_add_rx_filter_info silently succeeds).
For MACsec, VLAN filters are only relevant for offload, otherwise the VLANs are encrypted and the lower devices don't care about them. So VLAN filters are only passed on to lower devices in offload mode. Flipping between offload modes now needs to offload/unoffload the filters with vlan_{get,drop}_rx_*_filter_info().
To avoid the back-and-forth filter updating during rollback, the setting of macsec->offload is moved after the add/del secy ops. This is safe since none of the code called from those requires macsec->offload.
In case adding the filters fails, the added ones are rolled back and an error is returned to the operation toggling the offload state.
--- drivers/net/macsec.c | 71 +++++++++++++++++++++++++++++++++++++++----- 1 file changed, 63 insertions(+), 8 deletions(-)
drivers/net/macsec.c +63 -8
@@ -2584,7 +2584,9 @@ static void macsec_inherit_tso_max(struct net_device *dev)netif_inherit_tso_max (dev, macsec->real_dev); } -static int macsec_update_offload (struct net_device *dev,enum macsec_offload offload) +static int macsec_update_offload (struct net_device *dev, +enum macsec_offload offload, +struct netlink_ext_ack *extack) {enum macsec_offload prev_offload;const struct macsec_ops *ops;
@@ -2616,14 +2618,35 @@ static int macsec_update_offload(struct net_device *dev, enum macsec_offload offif (!ops)return -EOPNOTSUPP ; - macsec->offload = offload; - ctx.secy = &macsec->secy; ret = offload ==MACSEC_OFFLOAD_OFF ?macsec_offload (ops->mdo_del_secy, &ctx) :macsec_offload (ops->mdo_add_secy, &ctx); -if (ret) { - macsec->offload = prev_offload; +if (ret)return ret; + +/* Remove VLAN filters when disabling offload. */ +if (offload ==MACSEC_OFFLOAD_OFF ) { +vlan_drop_rx_ctag_filter_info (dev); +vlan_drop_rx_stag_filter_info (dev); + } + macsec->offload = offload; +/* Add VLAN filters when enabling offload. */ +if (prev_offload ==MACSEC_OFFLOAD_OFF ) { + ret =vlan_get_rx_ctag_filter_info (dev); +if (ret) { +NL_SET_ERR_MSG_FMT (extack, +"adding ctag VLAN filters failed, err %d" , + ret); + goto rollback_offload; + } + ret =vlan_get_rx_stag_filter_info (dev); +if (ret) { +NL_SET_ERR_MSG_FMT (extack, +"adding stag VLAN filters failed, err %d" , + ret); +vlan_drop_rx_ctag_filter_info (dev); + goto rollback_offload; + } }macsec_set_head_tail_room (dev);
@@ -2633,6 +2656,12 @@ static int macsec_update_offload(struct net_device *dev, enum macsec_offload offnetdev_update_features (dev); +return 0 ; + +rollback_offload: + macsec->offload = prev_offload; +macsec_offload (ops->mdo_del_secy, &ctx); +return ret; }
@@ -2673,7 +2702,7 @@ static int macsec_upd_offload(struct sk_buff *skb, struct genl_info *info) offload =nla_get_u8 (tb_offload[MACSEC_OFFLOAD_ATTR_TYPE ]);if (macsec->offload != offload) - ret =macsec_update_offload (dev, offload); + ret =macsec_update_offload (dev, offload, info->extack); out:rtnl_unlock ();return ret;
@@ -3486,7 +3515,8 @@ static netdev_tx_t macsec_start_xmit(struct sk_buff *skb, }#define MACSEC_FEATURES \ - (NETIF_F_SG | NETIF_F_HIGHDMA | NETIF_F_FRAGLIST) + (NETIF_F_SG | NETIF_F_HIGHDMA | NETIF_F_FRAGLIST | \ + NETIF_F_HW_VLAN_STAG_FILTER | NETIF_F_HW_VLAN_CTAG_FILTER)#define MACSEC_OFFLOAD_FEATURES \ (MACSEC_FEATURES | NETIF_F_GSO_SOFTWARE | NETIF_F_SOFT_FEATURES | \
@@ -3707,6 +3737,29 @@ static int macsec_set_mac_address(struct net_device *dev, void *p)return err; } +static int macsec_vlan_rx_add_vid (struct net_device *dev, +__be16 proto,u16 vid) +{ +struct macsec_dev *macsec =netdev_priv (dev); + +if (!macsec_is_offloaded (macsec)) +return 0 ; + +return vlan_vid_add (macsec->real_dev, proto, vid); +} + +static int macsec_vlan_rx_kill_vid (struct net_device *dev, +__be16 proto,u16 vid) +{ +struct macsec_dev *macsec =netdev_priv (dev); + +if (!macsec_is_offloaded (macsec)) +return 0 ; + +vlan_vid_del (macsec->real_dev, proto, vid); +return 0 ; +} +static int macsec_change_mtu (struct net_device *dev,int new_mtu) {struct macsec_dev *macsec =macsec_priv (dev);
@@ -3748,6 +3801,8 @@ static const struct net_device_ops macsec_netdev_ops = { .ndo_set_rx_mode = macsec_dev_set_rx_mode, .ndo_change_rx_flags = macsec_dev_change_rx_flags, .ndo_set_mac_address = macsec_set_mac_address, + .ndo_vlan_rx_add_vid = macsec_vlan_rx_add_vid, + .ndo_vlan_rx_kill_vid = macsec_vlan_rx_kill_vid, .ndo_start_xmit = macsec_start_xmit, .ndo_get_stats64 = macsec_get_stats64, .ndo_get_iflink = macsec_get_iflink,
@@ -3912,7 +3967,7 @@ static int macsec_changelink(struct net_device *dev, struct nlattr *tb[], offload =nla_get_u8 (data[IFLA_MACSEC_OFFLOAD ]);if (macsec->offload != offload) { macsec_offload_state_change = true; - ret =macsec_update_offload (dev, offload); + ret =macsec_update_offload (dev, offload, extack);if (ret) goto cleanup; }
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 173/1146 net: bcmgenet: fix off-by-one in bcmgenet_put_txcb
In reply to Greg Kroah-Hartman7.0-stable review patch. If anyone has any objections, please let me know.
------------------
From: Justin Chen <[email protected]>
[ Upstream commit 57f3f53d2c9c5a9e133596e2f7bc1c50688a6d38 ]
The write_ptr points to the next open tx_cb. We want to return the tx_cb that gets rewinded, so we must rewind the pointer first then return the tx_cb that it points to. That way the txcb can be correctly cleaned up.
--- drivers/net/ethernet/broadcom/genet/bcmgenet.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-)
drivers/net/ethernet/broadcom/genet/bcmgenet.c +3 -3
@@ -1819,15 +1819,15 @@ static struct enet_cb *bcmgenet_put_txcb(struct bcmgenet_priv *priv, {struct enet_cb *tx_cb_ptr; - tx_cb_ptr = ring->cbs; - tx_cb_ptr += ring->write_ptr - ring->cb_ptr; -/* Rewinding local write pointer */ if (ring->write_ptr == ring->cb_ptr) ring->write_ptr = ring->end_ptr;else ring->write_ptr--; + tx_cb_ptr = ring->cbs; + tx_cb_ptr += ring->write_ptr - ring->cb_ptr; +return tx_cb_ptr; }
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 174/1146 net: bcmgenet: fix leaking free_bds
In reply to Greg Kroah-Hartman7.0-stable review patch. If anyone has any objections, please let me know.
------------------
From: Justin Chen <[email protected]>
[ Upstream commit 3f3168300efb839028328d720ab3962f91d6a0d0 ]
While reclaiming the tx queue we fast forward the write pointer to drop any data in flight. These dropped frames are not added back to the pool of free bds. We also need to tell the netdev that we are dropping said data.
--- drivers/net/ethernet/broadcom/genet/bcmgenet.c | 2 ++ 1 file changed, 2 insertions(+)
drivers/net/ethernet/broadcom/genet/bcmgenet.c +2 -0
@@ -1985,6 +1985,7 @@ static unsigned int bcmgenet_tx_reclaim(struct net_device *dev, drop = (ring->prod_index - ring->c_index) &DMA_C_INDEX_MASK ; released += drop; ring->prod_index = ring->c_index &DMA_C_INDEX_MASK ; + ring->free_bds += drop;while (drop--) { cb_ptr =bcmgenet_put_txcb (priv, ring); skb = cb_ptr->skb;
@@ -1996,6 +1997,7 @@ static unsigned int bcmgenet_tx_reclaim(struct net_device *dev, }if (skb)dev_consume_skb_any (skb); +netdev_tx_reset_queue (netdev_get_tx_queue (dev, ring->index));bcmgenet_tdma_ring_writel (priv, ring->index, ring->prod_index,TDMA_PROD_INDEX ); wr_ptr = ring->write_ptr *WORDS_PER_BD (priv);
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 175/1146 net: bcmgenet: fix racing timeout handler
In reply to Greg Kroah-Hartman7.0-stable review patch. If anyone has any objections, please let me know.
------------------
From: Justin Chen <[email protected]>
[ Upstream commit 5393b2b5bee2ac51a0043dc7f4ac3475f053d08d ]
The bcmgenet_timeout handler tries to take down all tx queues when a single queue times out. This is over zealous and causes many race conditions with queues that are still chugging along. Instead lets only restart the timed out queue.
--- .../net/ethernet/broadcom/genet/bcmgenet.c | 22 ++++++++----------- 1 file changed, 9 insertions(+), 13 deletions(-)
drivers/net/ethernet/broadcom/genet/bcmgenet.c +9 -13
@@ -3477,27 +3477,23 @@ static void bcmgenet_dump_tx_queue(struct bcmgenet_tx_ring *ring)static void bcmgenet_timeout (struct net_device *dev,unsigned int txqueue) {struct bcmgenet_priv *priv =netdev_priv (dev); -u32 int1_enable =0 ; -unsigned int q; +struct bcmgenet_tx_ring *ring = &priv->tx_rings[txqueue]; +struct netdev_queue *txq =netdev_get_tx_queue (dev, txqueue);netif_dbg (priv, tx_err, dev,"bcmgenet_timeout\n" ); -for (q =0 ; q <= priv->hw_params->tx_queues; q++) -bcmgenet_dump_tx_queue (&priv->tx_rings[q]); - -bcmgenet_tx_reclaim_all (dev); +bcmgenet_dump_tx_queue (ring); -for (q =0 ; q <= priv->hw_params->tx_queues; q++) - int1_enable |= (1 << q); +bcmgenet_tx_reclaim (dev, ring, true); -/* Re-enable TX interrupts if disabled */ -bcmgenet_intrl2_1_writel (priv, int1_enable,INTRL2_CPU_MASK_CLEAR ); +/* Re-enable the TX interrupt for this ring */ +bcmgenet_intrl2_1_writel (priv,1 << txqueue,INTRL2_CPU_MASK_CLEAR ); -netif_trans_update (dev); +txq_trans_cond_update (txq); -BCMGENET_STATS64_INC ((&priv->tx_rings[txqueue].stats64), errors); +BCMGENET_STATS64_INC ((&ring->stats64), errors); -netif_tx_wake_all_queues (dev); +netif_tx_wake_queue (txq); }#define MAX_MDF_FILTER 17
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 176/1146 net: airoha: Add dma_rmb() and READ_ONCE() in airoha_qdma_rx_process()
In reply to Greg Kroah-Hartman7.0-stable review patch. If anyone has any objections, please let me know.
------------------
From: Lorenzo Bianconi <[email protected]>
[ Upstream commit 4ae0604a0673e11e2075b178387151fcad5111b5 ]
Add missing dma_rmb() in airoha_qdma_rx_process routine to make sure the DMA read operations are completed when the NIC reports the processing on the current descriptor is done. Moreover, add missing READ_ONCE() in airoha_qdma_rx_process() for DMA descriptor control fields in order to avoid any compiler reordering.
--- drivers/net/ethernet/airoha/airoha_eth.c | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-)
drivers/net/ethernet/airoha/airoha_eth.c +10 -6
@@ -584,7 +584,7 @@ static int airoha_qdma_fill_rx_queue(struct airoha_queue *q)static int airoha_qdma_get_gdm_port (struct airoha_eth *eth,struct airoha_qdma_desc *desc) { -u32 port, sport, msg1 =le32_to_cpu (desc->msg1); +u32 port, sport, msg1 =le32_to_cpu (READ_ONCE (desc->msg1)); sport =FIELD_GET (QDMA_ETH_RXMSG_SPORT_MASK , msg1);switch (sport) {
@@ -612,21 +612,24 @@ static int airoha_qdma_rx_process(struct airoha_queue *q, int budget)while (done < budget) {struct airoha_queue_entry *e = &q->entry[q->tail];struct airoha_qdma_desc *desc = &q->desc[q->tail]; -u32 hash, reason, msg1 =le32_to_cpu (desc->msg1); -struct page *page =virt_to_head_page (e->buf); -u32 desc_ctrl =le32_to_cpu (desc->ctrl); +u32 hash, reason, msg1, desc_ctrl;struct airoha_gdm_port *port;int data_len, len, p; +struct page *page; + desc_ctrl =le32_to_cpu (READ_ONCE (desc->ctrl));if (!(desc_ctrl &QDMA_DESC_DONE_MASK ))break ; +dma_rmb (); + q->tail = (q->tail +1 ) % q->ndesc; q->queued--;dma_sync_single_for_cpu (eth->dev, e->dma_addr,SKB_WITH_OVERHEAD (q->buf_size), dir); + page =virt_to_head_page (e->buf); len =FIELD_GET (QDMA_DESC_LEN_MASK , desc_ctrl); data_len = q->skb ? q->buf_size :SKB_WITH_OVERHEAD (q->buf_size);
@@ -670,8 +673,8 @@ static int airoha_qdma_rx_process(struct airoha_queue *q, int budget)* DMA descriptor. Report DSA tag to the DSA stack * via skb dst info. */ -u32 sptag =FIELD_GET (QDMA_ETH_RXMSG_SPTAG , -le32_to_cpu (desc->msg0)); +u32 msg0 =le32_to_cpu (READ_ONCE (desc->msg0)); +u32 sptag =FIELD_GET (QDMA_ETH_RXMSG_SPTAG , msg0);if (sptag <ARRAY_SIZE (port->dsa_meta) && port->dsa_meta[sptag])
@@ -679,6 +682,7 @@ static int airoha_qdma_rx_process(struct airoha_queue *q, int budget) &port->dsa_meta[sptag]->dst); } + msg1 =le32_to_cpu (READ_ONCE (desc->msg1)); hash =FIELD_GET (AIROHA_RXD4_FOE_ENTRY , msg1);if (hash !=AIROHA_RXD4_FOE_ENTRY ) skb_set_hash(q->skb, jhash_1word(hash, 0),
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 177/1146 eth: fbnic: Use wake instead of start
In reply to Greg Kroah-Hartman7.0-stable review patch. If anyone has any objections, please let me know.
------------------
From: Mohsin Bashir <[email protected]>
[ Upstream commit 12ff2a4aee6c86746623d5aed24389dbf6dffded ]
fbnic_up() calls netif_tx_start_all_queues(), which only clears __QUEUE_STATE_DRV_XOFF. If qdisc backlog has accumulated on any TX queue before the reconfiguration (e.g. ring resize via ethtool -G), start does not call __netif_schedule() to kick the qdisc, so the pending backlog is never drained and the queue stalls.
Switch to netif_tx_wake_all_queues(), which clears DRV_XOFF and also calls __netif_schedule() on every queue, ensuring any backlog that built up before the down/up cycle is promptly dequeued.
--- drivers/net/ethernet/meta/fbnic/fbnic_pci.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/net/ethernet/meta/fbnic/fbnic_pci.c +1 -1
@@ -139,7 +139,7 @@ void fbnic_up(struct fbnic_net *fbn)/* Enable Tx/Rx processing */ fbnic_napi_enable (fbn); -netif_tx_start_all_queues (fbn->netdev); +netif_tx_wake_all_queues (fbn->netdev);fbnic_service_task_start (fbn);
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 178/1146 netfilter: xt_socket: enable defrag after all other checks
In reply to Greg Kroah-Hartman7.0-stable review patch. If anyone has any objections, please let me know.
------------------
From: Florian Westphal <[email protected]>
[ Upstream commit 542be3fa5aff54210a02954c38f07e53ea9bdafd ]
Originally this did not matter because defrag was enabled once per netns and only disabled again on netns dismantle. When this got changed I should have adjusted checkentry to not leave defrag enabled on error.
--- net/netfilter/xt_socket.c | 23 ++++++----------------- 1 file changed, 6 insertions(+), 17 deletions(-)
net/netfilter/xt_socket.c +6 -17
@@ -168,52 +168,41 @@ static int socket_mt_enable_defrag(struct net *net, int family)static int socket_mt_v1_check (const struct xt_mtchk_param *par) {const struct xt_socket_mtinfo1 *info = (struct xt_socket_mtinfo1 *) par->matchinfo; -int err; - - err =socket_mt_enable_defrag (par->net, par->family); -if (err) -return err;if (info->flags & ~XT_SOCKET_FLAGS_V1 ) {pr_info_ratelimited ("unknown flags 0x%x\n" , info->flags & ~XT_SOCKET_FLAGS_V1 );return -EINVAL ; } -return 0 ; + +return socket_mt_enable_defrag (par->net, par->family); }static int socket_mt_v2_check (const struct xt_mtchk_param *par) {const struct xt_socket_mtinfo2 *info = (struct xt_socket_mtinfo2 *) par->matchinfo; -int err; - - err =socket_mt_enable_defrag (par->net, par->family); -if (err) -return err;if (info->flags & ~XT_SOCKET_FLAGS_V2 ) {pr_info_ratelimited ("unknown flags 0x%x\n" , info->flags & ~XT_SOCKET_FLAGS_V2 );return -EINVAL ; } -return 0 ; + +return socket_mt_enable_defrag (par->net, par->family); }static int socket_mt_v3_check (const struct xt_mtchk_param *par) {const struct xt_socket_mtinfo3 *info = (struct xt_socket_mtinfo3 *)par->matchinfo; -int err; - err =socket_mt_enable_defrag (par->net, par->family); -if (err) -return err;if (info->flags & ~XT_SOCKET_FLAGS_V3 ) {pr_info_ratelimited ("unknown flags 0x%x\n" , info->flags & ~XT_SOCKET_FLAGS_V3 );return -EINVAL ; } -return 0 ; + +return socket_mt_enable_defrag (par->net, par->family); }static void socket_mt_destroy (const struct xt_mtdtor_param *par)
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 179/1146 netfilter: nft_fwd_netdev: check ttl/hl before forwarding
In reply to Greg Kroah-Hartman7.0-stable review patch. If anyone has any objections, please let me know.
------------------
From: Florian Westphal <[email protected]>
[ Upstream commit 1dfd95bdf4d18d263aa8fad06bfb9f4d9c992b18 ]
Drop packets if their ttl/hl is too small for forwarding.
--- net/netfilter/nft_fwd_netdev.c | 10 ++++++++++ 1 file changed, 10 insertions(+)
net/netfilter/nft_fwd_netdev.c +10 -0
@@ -116,6 +116,11 @@ static void nft_fwd_neigh_eval(const struct nft_expr *expr, goto out; } iph =ip_hdr (skb); +if (iph->ttl <=1 ) { + verdict =NF_DROP ; + goto out; + } +ip_decrease_ttl (iph); neigh_table =NEIGH_ARP_TABLE ;break ;
@@ -132,6 +137,11 @@ static void nft_fwd_neigh_eval(const struct nft_expr *expr, goto out; } ip6h =ipv6_hdr (skb); +if (ip6h->hop_limit <=1 ) { + verdict =NF_DROP ; + goto out; + } + ip6h->hop_limit--; neigh_table =NEIGH_ND_TABLE ;break ;
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 180/1146 bpf: fix mm lifecycle in open-coded task_vma iterator
In reply to Greg Kroah-Hartman7.0-stable review patch. If anyone has any objections, please let me know.
------------------
From: Puranjay Mohan <[email protected]>
[ Upstream commit d8e27d2d22b6e2df3a0125b8c08e9aace38c954c ]
The open-coded task_vma iterator reads task->mm locklessly and acquires mmap_read_trylock() but never calls mmget(). If the task exits concurrently, the mm_struct can be freed as it is not SLAB_TYPESAFE_BY_RCU, resulting in a use-after-free.
Safely read task->mm with a trylock on alloc_lock and acquire an mm reference. Drop the reference via bpf_iter_mmput_async() in _destroy() and error paths. bpf_iter_mmput_async() is a local wrapper around mmput_async() with a fallback to mmput() on !CONFIG_MMU.
Reject irqs-disabled contexts (including NMI) up front. Operations used by _next() and _destroy() (mmap_read_unlock, bpf_iter_mmput_async) take spinlocks with IRQs disabled (pool->lock, pi_lock). Running from NMI or from a tracepoint that fires with those locks held could deadlock.
A trylock on alloc_lock is used instead of the blocking task_lock() (get_task_mm) to avoid a deadlock when a softirq BPF program iterates a task that already holds its alloc_lock on the same CPU.
--- kernel/bpf/task_iter.c | 54 +++++++++++++++++++++++++++++++++++++++--- 1 file changed, 51 insertions(+), 3 deletions(-)
kernel/bpf/task_iter.c +51 -3
@@ -9,6 +9,7 @@#include <linux/bpf_mem_alloc.h> #include <linux/btf_ids.h> #include <linux/mm_types.h> +#include <linux/sched/mm.h> #include "mmap_unlock_work.h" static const char *const iter_task_type_names[] = {
@@ -794,6 +795,15 @@ const struct bpf_func_proto bpf_find_vma_proto = { .arg5_type = ARG_ANYTHING, }; +static inline void bpf_iter_mmput_async (struct mm_struct *mm) +{ +#ifdef CONFIG_MMU +mmput_async (mm); +#else +mmput (mm); +#endif +} +struct bpf_iter_task_vma_kern_data {struct task_struct *task;struct mm_struct *mm;
@@ -825,6 +835,24 @@ __bpf_kfunc int bpf_iter_task_vma_new(struct bpf_iter_task_vma *it,BUILD_BUG_ON (sizeof (struct bpf_iter_task_vma_kern ) !=sizeof (struct bpf_iter_task_vma ));BUILD_BUG_ON (__alignof__(struct bpf_iter_task_vma_kern ) != __alignof__(struct bpf_iter_task_vma )); +/* bpf_iter_mmput_async() needs mmput_async() which requires CONFIG_MMU */ +if (!IS_ENABLED (CONFIG_MMU )) { + kit->data =NULL ; +return -EOPNOTSUPP ; + } + +/* +* Reject irqs-disabled contexts including NMI. Operations used +* by _next() and _destroy() (mmap_read_unlock, bpf_iter_mmput_async) +* can take spinlocks with IRQs disabled (pi_lock, pool->lock). +* Running from NMI or from a tracepoint that fires with those +* locks held could deadlock. +*/ +if (irqs_disabled ()) { + kit->data =NULL ; +return -EBUSY ; + } +/* is_iter_reg_valid_uninit guarantees that kit hasn't been initialized * before, so non-NULL kit->data doesn't point to previously * bpf_mem_alloc'd bpf_iter_task_vma_kern_data
@@ -834,7 +862,25 @@ __bpf_kfunc int bpf_iter_task_vma_new(struct bpf_iter_task_vma *it,return -ENOMEM ; kit->data->task =get_task_struct (task); +/* +* Safely read task->mm and acquire an mm reference. +* +* Cannot use get_task_mm() because its task_lock() is a +* blocking spin_lock that would deadlock if the target task +* already holds alloc_lock on this CPU (e.g. a softirq BPF +* program iterating a task interrupted while holding its +* alloc_lock). +*/ +if (!spin_trylock (&task->alloc_lock)) { + err = -EBUSY ; + goto err_cleanup_iter; + } kit->data->mm = task->mm; +if (kit->data->mm && !(task->flags &PF_KTHREAD )) +mmget (kit->data->mm); +else + kit->data->mm =NULL ; +spin_unlock (&task->alloc_lock);if (!kit->data->mm) { err = -ENOENT ; goto err_cleanup_iter;
@@ -844,15 +890,16 @@ __bpf_kfunc int bpf_iter_task_vma_new(struct bpf_iter_task_vma *it, irq_work_busy =bpf_mmap_unlock_get_irq_work (&kit->data->work);if (irq_work_busy || !mmap_read_trylock (kit->data->mm)) { err = -EBUSY ; - goto err_cleanup_iter; + goto err_cleanup_mmget; }vma_iter_init (&kit->data->vmi, kit->data->mm, addr);return 0 ; +err_cleanup_mmget: +bpf_iter_mmput_async (kit->data->mm); err_cleanup_iter: -if (kit->data->task) -put_task_struct (kit->data->task); +put_task_struct (kit->data->task);bpf_mem_free (&bpf_global_ma, kit->data);/* NULL kit->data signals failed bpf_iter_task_vma initialization */ kit->data =NULL ;
@@ -875,6 +922,7 @@ __bpf_kfunc void bpf_iter_task_vma_destroy(struct bpf_iter_task_vma *it)if (kit->data) {bpf_mmap_unlock_mm (kit->data->work, kit->data->mm);put_task_struct (kit->data->task); +bpf_iter_mmput_async (kit->data->mm);bpf_mem_free (&bpf_global_ma, kit->data); } }
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 181/1146 bpf: switch task_vma iterator from mmap_lock to per-VMA locks
In reply to Greg Kroah-Hartman7.0-stable review patch. If anyone has any objections, please let me know.
------------------
From: Puranjay Mohan <[email protected]>
[ Upstream commit bee9ef4a40a277bf401be43d39ba7f7f063cf39c ]
The open-coded task_vma iterator holds mmap_lock for the entire duration of iteration, increasing contention on this highly contended lock.
Switch to per-VMA locking. Find the next VMA via an RCU-protected maple tree walk and lock it with lock_vma_under_rcu(). lock_next_vma() is not used because its fallback takes mmap_read_lock(), and the iterator must work in non-sleepable contexts.
lock_vma_under_rcu() is a point lookup (mas_walk) that finds the VMA containing a given address but cannot iterate across gaps. An RCU-protected vma_next() walk (mas_find) first locates the next VMA's vm_start to pass to lock_vma_under_rcu().
Between the RCU walk and the lock, the VMA may be removed, shrunk, or write-locked. On failure, advance past it using vm_end from the RCU walk. Because the VMA slab is SLAB_TYPESAFE_BY_RCU, vm_end may be stale; fall back to PAGE_SIZE advancement when it does not make forward progress. Concurrent VMA insertions at addresses already passed by the iterator are not detected.
CONFIG_PER_VMA_LOCK is required; return -EOPNOTSUPP without it.
Stable-dep-of: 4cbee026db54 ("bpf: return VMA snapshot from task_vma iterator")
--- kernel/bpf/task_iter.c | 91 +++++++++++++++++++++++++++++++++--------- 1 file changed, 73 insertions(+), 18 deletions(-)
kernel/bpf/task_iter.c +73 -18
@@ -9,6 +9,7 @@#include <linux/bpf_mem_alloc.h> #include <linux/btf_ids.h> #include <linux/mm_types.h> +#include <linux/mmap_lock.h> #include <linux/sched/mm.h> #include "mmap_unlock_work.h"
@@ -807,8 +808,8 @@ static inline void bpf_iter_mmput_async(struct mm_struct *mm)struct bpf_iter_task_vma_kern_data {struct task_struct *task;struct mm_struct *mm; -struct mmap_unlock_irq_work *work; -struct vma_iterator vmi; +struct vm_area_struct *locked_vma; +u64 next_addr; };struct bpf_iter_task_vma {
@@ -829,21 +830,19 @@ __bpf_kfunc int bpf_iter_task_vma_new(struct bpf_iter_task_vma *it, struct task_struct *task, u64 addr) {struct bpf_iter_task_vma_kern *kit = (void *)it; -bool irq_work_busy = false;int err;BUILD_BUG_ON (sizeof (struct bpf_iter_task_vma_kern ) !=sizeof (struct bpf_iter_task_vma ));BUILD_BUG_ON (__alignof__(struct bpf_iter_task_vma_kern ) != __alignof__(struct bpf_iter_task_vma )); -/* bpf_iter_mmput_async() needs mmput_async() which requires CONFIG_MMU */ -if (!IS_ENABLED (CONFIG_MMU )) { +if (!IS_ENABLED (CONFIG_PER_VMA_LOCK )) { kit->data =NULL ;return -EOPNOTSUPP ; }/* * Reject irqs-disabled contexts including NMI. Operations used -* by _next() and _destroy() (mmap_read_unlock, bpf_iter_mmput_async) +* by _next() and _destroy() (vma_end_read, bpf_iter_mmput_async) * can take spinlocks with IRQs disabled (pi_lock, pool->lock). * Running from NMI or from a tracepoint that fires with those * locks held could deadlock.
@@ -886,18 +885,10 @@ __bpf_kfunc int bpf_iter_task_vma_new(struct bpf_iter_task_vma *it, goto err_cleanup_iter; } -/* kit->data->work == NULL is valid after bpf_mmap_unlock_get_irq_work */ - irq_work_busy =bpf_mmap_unlock_get_irq_work (&kit->data->work); -if (irq_work_busy || !mmap_read_trylock (kit->data->mm)) { - err = -EBUSY ; - goto err_cleanup_mmget; - } - -vma_iter_init (&kit->data->vmi, kit->data->mm, addr); + kit->data->locked_vma =NULL ; + kit->data->next_addr = addr;return 0 ; -err_cleanup_mmget: -bpf_iter_mmput_async (kit->data->mm); err_cleanup_iter:put_task_struct (kit->data->task);bpf_mem_free (&bpf_global_ma, kit->data);
@@ -906,13 +897,76 @@ __bpf_kfunc int bpf_iter_task_vma_new(struct bpf_iter_task_vma *it,return err; } +/* +* Find and lock the next VMA at or after data->next_addr. +* +* lock_vma_under_rcu() is a point lookup (mas_walk): it finds the VMA +* containing a given address but cannot iterate. An RCU-protected +* maple tree walk with vma_next() (mas_find) is needed first to locate +* the next VMA's vm_start across any gap. +* +* Between the RCU walk and the lock, the VMA may be removed, shrunk, +* or write-locked. On failure, advance past it using vm_end from the +* RCU walk. SLAB_TYPESAFE_BY_RCU can make vm_end stale, so fall back +* to PAGE_SIZE advancement to guarantee forward progress. +*/ +static struct vm_area_struct * +bpf_iter_task_vma_find_next (struct bpf_iter_task_vma_kern_data *data) +{ +struct vm_area_struct *vma; +struct vma_iterator vmi; +unsigned long start, end; + +retry: +rcu_read_lock (); +vma_iter_init (&vmi, data->mm, data->next_addr); + vma =vma_next (&vmi); +if (!vma) { +rcu_read_unlock (); +return NULL ; + } + start = vma->vm_start; + end = vma->vm_end; +rcu_read_unlock (); + + vma =lock_vma_under_rcu (data->mm, start); +if (!vma) { +if (end <= data->next_addr) + data->next_addr +=PAGE_SIZE ; +else + data->next_addr = end; + goto retry; + } + +if (unlikely (vma->vm_end <= data->next_addr)) { + data->next_addr +=PAGE_SIZE ; +vma_end_read (vma); + goto retry; + } + +return vma; +} + __bpf_kfunc struct vm_area_struct *bpf_iter_task_vma_next(struct bpf_iter_task_vma *it) {struct bpf_iter_task_vma_kern *kit = (void *)it; +struct vm_area_struct *vma;if (!kit->data)/* bpf_iter_task_vma_new failed */ return NULL ; -return vma_next (&kit->data->vmi); + +if (kit->data->locked_vma) { +vma_end_read (kit->data->locked_vma); + kit->data->locked_vma =NULL ; + } + + vma =bpf_iter_task_vma_find_next (kit->data); +if (!vma) +return NULL ; + + kit->data->locked_vma = vma; + kit->data->next_addr = vma->vm_end; +return vma; } __bpf_kfunc void bpf_iter_task_vma_destroy(struct bpf_iter_task_vma *it)
@@ -920,7 +974,8 @@ __bpf_kfunc void bpf_iter_task_vma_destroy(struct bpf_iter_task_vma *it)struct bpf_iter_task_vma_kern *kit = (void *)it;if (kit->data) { -bpf_mmap_unlock_mm (kit->data->work, kit->data->mm); +if (kit->data->locked_vma) +vma_end_read (kit->data->locked_vma);put_task_struct (kit->data->task);bpf_iter_mmput_async (kit->data->mm);bpf_mem_free (&bpf_global_ma, kit->data);
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 182/1146 bpf: return VMA snapshot from task_vma iterator
In reply to Greg Kroah-Hartman7.0-stable review patch. If anyone has any objections, please let me know.
------------------
From: Puranjay Mohan <[email protected]>
[ Upstream commit 4cbee026db54cad39c39db4d356100cb133412b3 ]
Holding the per-VMA lock across the BPF program body creates a lock ordering problem when helpers acquire locks that depend on mmap_lock:
vm_lock -> i_rwsem -> mmap_lock -> vm_lock
Snapshot the VMA under the per-VMA lock in _next() via memcpy(), then drop the lock before returning. The BPF program accesses only the snapshot.
The verifier only trusts vm_mm and vm_file pointers (see BTF_TYPE_SAFE_TRUSTED_OR_NULL in verifier.c). vm_file is reference- counted with get_file() under the lock and released via fput() on the next iteration or in _destroy(). vm_mm is already correct because lock_vma_under_rcu() verifies vma->vm_mm == mm. All other pointers are left as-is by memcpy() since the verifier treats them as untrusted.
--- kernel/bpf/task_iter.c | 42 ++++++++++++++++++++++++++++++------------ 1 file changed, 30 insertions(+), 12 deletions(-)
kernel/bpf/task_iter.c +30 -12
@@ -808,7 +808,7 @@ static inline void bpf_iter_mmput_async(struct mm_struct *mm)struct bpf_iter_task_vma_kern_data {struct task_struct *task;struct mm_struct *mm; -struct vm_area_struct *locked_vma; +struct vm_area_struct snapshot;u64 next_addr; };
@@ -842,7 +842,7 @@ __bpf_kfunc int bpf_iter_task_vma_new(struct bpf_iter_task_vma *it,/* * Reject irqs-disabled contexts including NMI. Operations used -* by _next() and _destroy() (vma_end_read, bpf_iter_mmput_async) +* by _next() and _destroy() (vma_end_read, fput, bpf_iter_mmput_async) * can take spinlocks with IRQs disabled (pi_lock, pool->lock). * Running from NMI or from a tracepoint that fires with those * locks held could deadlock.
@@ -885,7 +885,7 @@ __bpf_kfunc int bpf_iter_task_vma_new(struct bpf_iter_task_vma *it, goto err_cleanup_iter; } - kit->data->locked_vma =NULL ; + kit->data->snapshot.vm_file =NULL ; kit->data->next_addr = addr;return 0 ;
@@ -947,26 +947,45 @@ bpf_iter_task_vma_find_next(struct bpf_iter_task_vma_kern_data *data)return vma; } +static void bpf_iter_task_vma_snapshot_reset (struct vm_area_struct *snap) +{ +if (snap->vm_file) { +fput (snap->vm_file); + snap->vm_file =NULL ; + } +} + __bpf_kfunc struct vm_area_struct *bpf_iter_task_vma_next(struct bpf_iter_task_vma *it) {struct bpf_iter_task_vma_kern *kit = (void *)it; -struct vm_area_struct *vma; +struct vm_area_struct *snap, *vma;if (!kit->data)/* bpf_iter_task_vma_new failed */ return NULL ; -if (kit->data->locked_vma) { -vma_end_read (kit->data->locked_vma); - kit->data->locked_vma =NULL ; - } + snap = &kit->data->snapshot; + +bpf_iter_task_vma_snapshot_reset (snap); vma =bpf_iter_task_vma_find_next (kit->data);if (!vma)return NULL ; - kit->data->locked_vma = vma; +memcpy (snap, vma,sizeof (*snap)); + +/* +* The verifier only trusts vm_mm and vm_file (see +* BTF_TYPE_SAFE_TRUSTED_OR_NULL in verifier.c). Take a reference +* on vm_file; vm_mm is already correct because lock_vma_under_rcu() +* verifies vma->vm_mm == mm. All other pointers are untrusted by +* the verifier and left as-is. +*/ +if (snap->vm_file) +get_file (snap->vm_file); + kit->data->next_addr = vma->vm_end; -return vma; +vma_end_read (vma); +return snap; } __bpf_kfunc void bpf_iter_task_vma_destroy(struct bpf_iter_task_vma *it)
@@ -974,8 +993,7 @@ __bpf_kfunc void bpf_iter_task_vma_destroy(struct bpf_iter_task_vma *it)struct bpf_iter_task_vma_kern *kit = (void *)it;if (kit->data) { -if (kit->data->locked_vma) -vma_end_read (kit->data->locked_vma); +bpf_iter_task_vma_snapshot_reset (&kit->data->snapshot);put_task_struct (kit->data->task);bpf_iter_mmput_async (kit->data->mm);bpf_mem_free (&bpf_global_ma, kit->data);
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 183/1146 bpf: Fix RCU stall in bpf_fd_array_map_clear()
In reply to Greg Kroah-Hartman7.0-stable review patch. If anyone has any objections, please let me know.
------------------
From: Sechang Lim <[email protected]>
[ Upstream commit 4406942e65ca128c56c67443832988873c21d2e9 ]
Add a missing cond_resched() in bpf_fd_array_map_clear() loop.
For PROG_ARRAY maps with many entries this loop calls prog_array_map_poke_run() per entry which can be expensive, and without yielding this can cause RCU stalls under load:
rcu: Stack dump where RCU GP kthread last ran:
CPU: 0 UID: 0 PID: 30932 Comm: kworker/0:2 Not tainted 6.14.0-13195-g967e8def1100 #2 PREEMPT(undef) Workqueue: events prog_array_map_clear_deferred RIP: 0010:write_comp_data+0x38/0x90 kernel/kcov.c:246 Call Trace: <TASK> prog_array_map_poke_run+0x77/0x380 kernel/bpf/arraymap.c:1096 __fd_array_map_delete_elem+0x197/0x310 kernel/bpf/arraymap.c:925 bpf_fd_array_map_clear kernel/bpf/arraymap.c:1000 [inline] prog_array_map_clear_deferred+0x119/0x1b0 kernel/bpf/arraymap.c:1141 process_one_work+0x898/0x19d0 kernel/workqueue.c:3238 process_scheduled_works kernel/workqueue.c:3319 [inline] worker_thread+0x770/0x10b0 kernel/workqueue.c:3400 kthread+0x465/0x880 kernel/kthread.c:464 ret_from_fork+0x4d/0x80 arch/x86/kernel/process.c:153 ret_from_fork_asm+0x19/0x30 arch/x86/entry/entry_64.S:245 </TASK>
--- kernel/bpf/arraymap.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-)
kernel/bpf/arraymap.c +3 -1
@@ -1015,8 +1015,10 @@ static void bpf_fd_array_map_clear(struct bpf_map *map, bool need_defer) struct bpf_array *array = container_of(map, struct bpf_array, map);int i; -for (i =0 ; i < array->map.max_entries; i++) +for (i =0 ; i < array->map.max_entries; i++) {__fd_array_map_delete_elem (map, &i, need_defer); +cond_resched (); + } } static void prog_array_map_seq_show_elem(struct bpf_map *map, void *key,
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 184/1146 net: hamradio: 6pack: fix uninit-value in sixpack_receive_buf
In reply to Greg Kroah-Hartman7.0-stable review patch. If anyone has any objections, please let me know.
------------------
From: Mashiro Chen <[email protected]>
[ Upstream commit bf9a38803b2626b01cc769aaf13485d8650f576f ]
sixpack_receive_buf() does not properly skip bytes with TTY error flags. The while loop iterates through the flags buffer but never advances the data pointer (cp), and passes the original count (including error bytes) to sixpack_decode(). This causes sixpack_decode() to process bytes that should have been skipped due to TTY errors. The TTY layer does not guarantee that cp[i] holds a meaningful value when fp[i] is set, so passing those positions to sixpack_decode() results in KMSAN reporting an uninit-value read.
Fix this by processing bytes one at a time, advancing cp on each iteration, and only passing valid (non-error) bytes to sixpack_decode(). This matches the pattern used by slip_receive_buf() and mkiss_receive_buf() for the same purpose.
--- drivers/net/hamradio/6pack.c | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-)
drivers/net/hamradio/6pack.c +4 -5
@@ -391,7 +391,6 @@ static void sixpack_receive_buf(struct tty_struct *tty, const u8 *cp, const u8 *fp, size_t count) {struct sixpack *sp; -size_t count1;if (!count)return ;
@@ -401,16 +400,16 @@ static void sixpack_receive_buf(struct tty_struct *tty, const u8 *cp,return ;/* Read the characters out of the buffer */ - count1 = count; -while (count) { - count--; +while (count--) {if (fp && *fp++) {if (!test_and_set_bit (SIXPF_ERROR , &sp->flags)) sp->dev->stats.rx_errors++; + cp++;continue ; } +sixpack_decode (sp, cp,1 ); + cp++; } -sixpack_decode (sp, cp, count1);tty_unthrottle (tty); }
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 185/1146 net: airoha: Fix FE_PSE_BUF_SET configuration if PPE2 is available
In reply to Greg Kroah-Hartman7.0-stable review patch. If anyone has any objections, please let me know.
------------------
From: Lorenzo Bianconi <[email protected]>
[ Upstream commit 02f72964395911e7a09bb2ea2fe6f79eda4ea2c2 ]
airoha_fe_set routine is used to set specified bits to 1 in the selected register. In the FE_PSE_BUF_SET case this can due to a overestimation of the required buffers for I/O queues since we can miss to set some bits of PSE_ALLRSV_MASK subfield to 0. Fix the issue relying on airoha_fe_rmw routine instead.
--- drivers/net/ethernet/airoha/airoha_eth.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-)
drivers/net/ethernet/airoha/airoha_eth.c +5 -3
@@ -293,16 +293,18 @@ static void airoha_fe_pse_ports_init(struct airoha_eth *eth) [FE_PSE_PORT_GDM4] = 2, [FE_PSE_PORT_CDM5] = 2, }; -u32 all_rsv;int q; - all_rsv =airoha_fe_get_pse_all_rsv (eth);if (airoha_ppe_is_enabled (eth,1 )) { +u32 all_rsv; +/* hw misses PPE2 oq rsv */ + all_rsv =airoha_fe_get_pse_all_rsv (eth); all_rsv +=PSE_RSV_PAGES * pse_port_num_queues[FE_PSE_PORT_PPE2 ]; +airoha_fe_rmw (eth,REG_FE_PSE_BUF_SET ,PSE_ALLRSV_MASK , +FIELD_PREP (PSE_ALLRSV_MASK , all_rsv)); } -airoha_fe_set (eth,REG_FE_PSE_BUF_SET , all_rsv);/* CMD1 */ for (q =0 ; q < pse_port_num_queues[FE_PSE_PORT_CDM1 ]; q++)
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 186/1146 bpf: Enforce regsafe base id consistency for BPF_ADD_CONST scalars
In reply to Greg Kroah-Hartman7.0-stable review patch. If anyone has any objections, please let me know.
------------------
From: Daniel Borkmann <[email protected]>
[ Upstream commit 2f2ec8e7730e21fc9bd49e0de9cdd58213ea24d0 ]
When regsafe() compares two scalar registers that both carry BPF_ADD_CONST, check_scalar_ids() maps their full compound id (aka base | BPF_ADD_CONST flag) as one idmap entry. However, it never verifies that the underlying base ids, that is, with the flag stripped are consistent with existing idmap mappings.
This allows construction of two verifier states where the old state has R3 = R2 + 10 (both sharing base id A) while the current state has R3 = R4 + 10 (base id C, unrelated to R2). The idmap creates two independent entries: A->B (for R2) and A|flag->C|flag (for R3), without catching that A->C conflicts with A->B. State pruning then incorrectly succeeds.
Fix this by additionally verifying base ID mapping consistency whenever BPF_ADD_CONST is set: after mapping the compound ids, also invoke check_ids() on the base IDs (flag bits stripped). This ensures that if A was already mapped to B from comparing the source register, any ADD_CONST derivative must also derive from B, not an unrelated C.
--- kernel/bpf/verifier.c | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-)
kernel/bpf/verifier.c +16 -1
@@ -19674,6 +19674,13 @@ static bool check_ids(u32 old_id, u32 cur_id, struct bpf_idmap *idmap)* and r7.id=0 (both independent), without temp IDs both would map old_id=X * to cur_id=0 and pass. With temp IDs: r6 maps X->temp1, r7 tries to map * X->temp2, but X is already mapped to temp1, so the check fails correctly. +* +* When old_id has BPF_ADD_CONST set, the compound id (base | flag) and the +* base id (flag stripped) must both map consistently. Example: old has +* r2.id=A, r3.id=A|flag (r3 = r2 + delta), cur has r2.id=B, r3.id=C|flag +* (r3 derived from unrelated r4). Without the base check, idmap gets two +* independent entries A->B and A|flag->C|flag, missing that A->C conflicts +* with A->B. The base ID cross-check catches this. */ static bool check_scalar_ids (u32 old_id,u32 cur_id,struct bpf_idmap *idmap) {
@@ -19682,7 +19689,15 @@ static bool check_scalar_ids(u32 old_id, u32 cur_id, struct bpf_idmap *idmap) cur_id = cur_id ? cur_id : ++idmap->tmp_id_gen; -return check_ids (old_id, cur_id, idmap); +if (!check_ids (old_id, cur_id, idmap)) +return false; +if (old_id &BPF_ADD_CONST ) { + old_id &= ~BPF_ADD_CONST ; + cur_id &= ~BPF_ADD_CONST ; +if (!check_ids (old_id, cur_id, idmap)) +return false; + } +return true; } static void clean_func_state(struct bpf_verifier_env *env,
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 187/1146 selftests/bpf: fix __jited_unpriv tag name
In reply to Greg Kroah-Hartman7.0-stable review patch. If anyone has any objections, please let me know.
------------------
From: Eduard Zingerman <[email protected]>
[ Upstream commit cdd54fe98c00549264a92613af6bb0e9a5fd0d1c ]
__jited_unpriv was using "test_jited=" as its tag name, same as the priv variant __jited. Fix by using "test_jited_unpriv=".
--- tools/testing/selftests/bpf/progs/bpf_misc.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
tools/testing/selftests/bpf/progs/bpf_misc.h +1 -1
@@ -140,7 +140,7 @@#define __msg_unpriv (msg) __attribute__((btf_decl_tag("comment:test_expect_msg_unpriv=" XSTR(__COUNTER__) "=" msg)))#define __not_msg_unpriv (msg) __attribute__((btf_decl_tag("comment:test_expect_not_msg_unpriv=" XSTR(__COUNTER__) "=" msg)))#define __xlated_unpriv (msg) __attribute__((btf_decl_tag("comment:test_expect_xlated_unpriv=" XSTR(__COUNTER__) "=" msg))) -#define __jited_unpriv (msg) __attribute__((btf_decl_tag("comment:test_jited=" XSTR(__COUNTER__) "=" msg))) +#define __jited_unpriv (msg) __attribute__((btf_decl_tag("comment:test_jited_unpriv=" XSTR(__COUNTER__) "=" msg)))#define __failure_unpriv __attribute__((btf_decl_tag("comment:test_expect_failure_unpriv")))#define __success_unpriv __attribute__((btf_decl_tag("comment:test_expect_success_unpriv")))#define __log_level (lvl) __attribute__((btf_decl_tag("comment:test_log_level="#lvl)))
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 188/1146 net/sched: cls_fw: fix NULL dereference of "old" filters before change()
In reply to Greg Kroah-Hartman7.0-stable review patch. If anyone has any objections, please let me know.
------------------
From: Davide Caratti <[email protected]>
[ Upstream commit 65782b2db7321d5f97c16718c4c7f6c7205a56be ]
Like pointed out by Sashiko [1], since commit ed76f5edccc9 ("net: sched:
protect filter_chain list with filter_chain_lock mutex") TC filters are added to a shared block and published to datapath before their ->change() function is called. This is a problem for cls_fw: an invalid filter created with the "old" method can still classify some packets before it is destroyed by the validation logic added by Xiang. Therefore, insisting with repeated runs of the following script:
# ip link add dev crash0 type dummy # ip link set dev crash0 up # mausezahn crash0 -c 100000 -P 10 \
Quoted 1 line
-A 4.3.2.1 -B 1.2.3.4 -t udp "dp=1234" -q &
# sleep 1 # tc qdisc add dev crash0 egress_block 1 clsact # tc filter add block 1 protocol ip prio 1 matchall \
Quoted 1 line
action skbedit mark 65536 continue
# tc filter add block 1 protocol ip prio 2 fw # ip link del dev crash0
can still make fw_classify() hit the WARN_ON() in [2]:
WARNING: ./include/net/pkt_cls.h:88 at fw_classify+0x244/0x250 [cls_fw], CPU#18: mausezahn/1399 Modules linked in: cls_fw(E) act_skbedit(E) CPU: 18 UID: 0 PID: 1399 Comm: mausezahn Tainted: G E 7.0.0-rc6-virtme #17 PREEMPT(full) Tainted: [E]=UNSIGNED_MODULE Hardware name: Red Hat KVM, BIOS 1.16.3-2.el9 04/01/2014 RIP: 0010:fw_classify+0x244/0x250 [cls_fw] Code: 5c 49 c7 45 00 00 00 00 00 41 5d 41 5e 41 5f 5d c3 cc cc cc cc 5b b8 ff ff ff ff 41 5c 41 5d 41 5e 41 5f 5d c3 cc cc cc cc 90 <0f> 0b 90 eb a0 0f 1f 80 00 00 00 00 90 90 90 90 90 90 90 90 90 90 RSP: 0018:ffffd1b7026bf8a8 EFLAGS: 00010202 RAX: ffff8c5ac9c60800 RBX: ffff8c5ac99322c0 RCX: 0000000000000004 RDX: 0000000000000001 RSI: ffff8c5b74d7a000 RDI: ffff8c5ac8284f40 RBP: ffffd1b7026bf8d0 R08: 0000000000000000 R09: ffffd1b7026bf9b0 R10: 00000000ffffffff R11: 0000000000000000 R12: 0000000000010000 R13: ffffd1b7026bf930 R14: ffff8c5ac8284f40 R15: 0000000000000000 FS: 00007fca40c37740(0000) GS:ffff8c5b74d7a000(0000) knlGS:0000000000000000 CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 CR2: 00007fca40e822a0 CR3: 0000000005ca0001 CR4: 0000000000172ef0 Call Trace: <TASK> tcf_classify+0x17d/0x5c0 tc_run+0x9d/0x150 __dev_queue_xmit+0x2ab/0x14d0 ip_finish_output2+0x340/0x8f0 ip_output+0xa4/0x250 raw_sendmsg+0x147d/0x14b0 __sys_sendto+0x1cc/0x1f0 __x64_sys_sendto+0x24/0x30 do_syscall_64+0x126/0xf80 entry_SYSCALL_64_after_hwframe+0x77/0x7f RIP: 0033:0x7fca40e822ba Code: d8 64 89 02 48 c7 c0 ff ff ff ff eb b8 0f 1f 00 f3 0f 1e fa 41 89 ca 64 8b 04 25 18 00 00 00 85 c0 75 15 b8 2c 00 00 00 0f 05 <48> 3d 00 f0 ff ff 77 7e c3 0f 1f 44 00 00 41 54 48 83 ec 30 44 89 RSP: 002b:00007ffc248a42c8 EFLAGS: 00000246 ORIG_RAX: 000000000000002c RAX: ffffffffffffffda RBX: 000055ef233289d0 RCX: 00007fca40e822ba RDX: 000000000000001e RSI: 000055ef23328c30 RDI: 0000000000000003 RBP: 000055ef233289d0 R08: 00007ffc248a42d0 R09: 0000000000000010 R10: 0000000000000000 R11: 0000000000000246 R12: 000000000000001e R13: 00000000000186a0 R14: 0000000000000000 R15: 00007fca41043000 </TASK> irq event stamp: 1045778 hardirqs last enabled at (1045784): [<ffffffff864ec042>] __up_console_sem+0x52/0x60 hardirqs last disabled at (1045789): [<ffffffff864ec027>] __up_console_sem+0x37/0x60 softirqs last enabled at (1045426): [<ffffffff874d48c7>] __alloc_skb+0x207/0x260 softirqs last disabled at (1045434): [<ffffffff874fe8f8>] __dev_queue_xmit+0x78/0x14d0
Then, because of the value in the packet's mark, dereference on 'q->handle' with NULL 'q' occurs:
BUG: kernel NULL pointer dereference, address: 0000000000000038 [...] RIP: 0010:fw_classify+0x1fe/0x250 [cls_fw] [...]
Skip "old-style" classification on shared blocks, so that the NULL dereference is fixed and WARN_ON() is not hit anymore in the short lifetime of invalid cls_fw "old-style" filters.
[1] https://sashiko.dev/#/patchset/20260331050217.504278-1-xmei5%40asu.edu
[2] https://elixir.bootlin.com/linux/v7.0-rc6/source/include/net/pkt_cls.h#L86
--- net/sched/cls_fw.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-)
net/sched/cls_fw.c +5 -1
@@ -74,9 +74,13 @@ TC_INDIRECT_SCOPE int fw_classify(struct sk_buff *skb, } } }else { -struct Qdisc *q =tcf_block_q (tp->chain->block); +struct Qdisc *q;/* Old method: classify the packet using its skb mark. */ +if (tcf_block_shared (tp->chain->block)) +return -1 ; + + q =tcf_block_q (tp->chain->block);if (id && (TC_H_MAJ (id) ==0 || !(TC_H_MAJ (id ^ q->handle)))) { res->classid = id;
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 189/1146 net/sched: act_ct: Only release RCU read lock after ct_ft
In reply to Greg Kroah-Hartman7.0-stable review patch. If anyone has any objections, please let me know.
------------------
From: Jamal Hadi Salim <[email protected]>
[ Upstream commit f462dca0c8415bf0058d0ffa476354c4476d0f09 ]
When looking up a flow table in act_ct in tcf_ct_flow_table_get(), rhashtable_lookup_fast() internally opens and closes an RCU read critical section before returning ct_ft.
The tcf_ct_flow_table_cleanup_work() can complete before refcount_inc_not_zero() is invoked on the returned ct_ft resulting in a UAF on the already freed ct_ft object. This vulnerability can lead to privilege escalation.
Analysis from [email protected]:
When initializing act_ct, tcf_ct_init() is called, which internally triggers tcf_ct_flow_table_get().
static int tcf_ct_flow_table_get(struct net *net, struct tcf_ct_params *params)
{
struct zones_ht_key key = { .net = net, .zone = params->zone };
struct tcf_ct_flow_table *ct_ft;
int err = -ENOMEM;
mutex_lock(&zones_mutex);
ct_ft = rhashtable_lookup_fast(&zones_ht, &key, zones_params); // [1]
if (ct_ft && refcount_inc_not_zero(&ct_ft->ref)) // [2]
goto out_unlock;
...
}static __always_inline void *rhashtable_lookup_fast(
struct rhashtable *ht, const void *key, const struct rhashtable_params params)
{
void *obj;
rcu_read_lock();
obj = rhashtable_lookup(ht, key, params);
rcu_read_unlock();
return obj;
}At [1], rhashtable_lookup_fast() looks up and returns the corresponding ct_ft from zones_ht . The lookup is performed within an RCU read critical section through rcu_read_lock() / rcu_read_unlock(), which prevents the object from being freed. However, at the point of function return, rcu_read_unlock() has already been called, and there is nothing preventing ct_ft from being freed before reaching refcount_inc_not_zero(&ct_ft->ref) at [2]. This interval becomes the race window, during which ct_ft can be freed.
Free Process:
tcf_ct_flow_table_put() is executed through the path tcf_ct_cleanup() call_rcu() tcf_ct_params_free_rcu() tcf_ct_params_free() tcf_ct_flow_table_put().
static void tcf_ct_flow_table_put(struct tcf_ct_flow_table *ct_ft)
{
if (refcount_dec_and_test(&ct_ft->ref)) {
rhashtable_remove_fast(&zones_ht, &ct_ft->node, zones_params);
INIT_RCU_WORK(&ct_ft->rwork, tcf_ct_flow_table_cleanup_work); // [3]
queue_rcu_work(act_ct_wq, &ct_ft->rwork);
}
}At [3], tcf_ct_flow_table_cleanup_work() is scheduled as RCU work
static void tcf_ct_flow_table_cleanup_work(struct work_struct *work)
{
struct tcf_ct_flow_table *ct_ft;
struct flow_block *block;
ct_ft = container_of(to_rcu_work(work), struct tcf_ct_flow_table,
rwork);
nf_flow_table_free(&ct_ft->nf_ft);
block = &ct_ft->nf_ft.flow_block;
down_write(&ct_ft->nf_ft.flow_block_lock);
WARN_ON(!list_empty(&block->cb_list));
up_write(&ct_ft->nf_ft.flow_block_lock);
kfree(ct_ft); // [4]
module_put(THIS_MODULE);
}tcf_ct_flow_table_cleanup_work() frees ct_ft at [4]. When this function executes between [1] and [2], UAF occurs.
This race condition has a very short race window, making it generally difficult to trigger. Therefore, to trigger the vulnerability an msleep(100) was inserted after[1]
--- net/sched/act_ct.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-)
net/sched/act_ct.c +6 -2
@@ -328,9 +328,13 @@ static int tcf_ct_flow_table_get(struct net *net, struct tcf_ct_params *params)int err = -ENOMEM ;mutex_lock (&zones_mutex); - ct_ft =rhashtable_lookup_fast (&zones_ht, &key, zones_params); -if (ct_ft &&refcount_inc_not_zero (&ct_ft->ref)) +rcu_read_lock (); + ct_ft =rhashtable_lookup (&zones_ht, &key, zones_params); +if (ct_ft &&refcount_inc_not_zero (&ct_ft->ref)) { +rcu_read_unlock (); goto out_unlock; + } +rcu_read_unlock (); ct_ft =kzalloc_obj (*ct_ft);if (!ct_ft)
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 190/1146 selftests: netfilter: nft_tproxy.sh: adjust to socat changes
In reply to Greg Kroah-Hartman7.0-stable review patch. If anyone has any objections, please let me know.
------------------
From: Florian Westphal <[email protected]>
[ Upstream commit 61119542663cac70898aef532eb57ee41ea9b477 ]
Like e65d8b6f3092 ("selftests: drv-net: adjust to socat changes") we need to add shut-none for this test too.
The extra 0-packet can trigger a second (unexpected) reply from the server.
--- .../selftests/net/netfilter/nft_tproxy_udp.sh | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-)
tools/testing/selftests/net/netfilter/nft_tproxy_udp.sh +7 -7
@@ -190,13 +190,13 @@ table inet filter { } EOF - timeout "$timeout" ip netns exec "$nsrouter" socat -u "$socat_ipproto" udp-listen:12345,fork,ip-transparent,reuseport udp:"$ns1_ip_port",ip-transparent,reuseport,bind="$ns2_ip_port" 2>/dev/null & + timeout "$timeout" ip netns exec "$nsrouter" socat -u "$socat_ipproto" udp-listen:12345,fork,ip-transparent,reuseport,shut-none udp:"$ns1_ip_port",ip-transparent,reuseport,bind="$ns2_ip_port",shut-none 2>/dev/null & local tproxy_pid=$! - timeout "$timeout" ip netns exec "$ns2" socat "$socat_ipproto" udp-listen:8080,fork SYSTEM:"echo PONG_NS2" 2>/dev/null & + timeout "$timeout" ip netns exec "$ns2" socat "$socat_ipproto" udp-listen:8080,fork,shut-none SYSTEM:"echo PONG_NS2" 2>/dev/null & local server2_pid=$! - timeout "$timeout" ip netns exec "$ns3" socat "$socat_ipproto" udp-listen:8080,fork SYSTEM:"echo PONG_NS3" 2>/dev/null & + timeout "$timeout" ip netns exec "$ns3" socat "$socat_ipproto" udp-listen:8080,fork,shut-none SYSTEM:"echo PONG_NS3" 2>/dev/null & local server3_pid=$! busywait "$BUSYWAIT_TIMEOUT" listener_ready "$nsrouter" 12345 "-u"
@@ -205,7 +205,7 @@ EOF local result # request from ns1 to ns2 (forwarded traffic) - result=$(echo I_M_PROXIED | ip netns exec "$ns1" socat -t 2 -T 2 STDIO udp:"$ns2_ip_port",sourceport=18888) + result=$(echo I_M_PROXIED | ip netns exec "$ns1" socat -t 2 -T 2 STDIO udp:"$ns2_ip_port",sourceport=18888,shut-none) if [ "$result" == "$expect_ns1_ns2" ] ;then echo "PASS: tproxy test $testname: ns1 got reply \"$result\" connecting to ns2" else
@@ -214,7 +214,7 @@ EOF fi # request from ns1 to ns3 (forwarded traffic) - result=$(echo I_M_PROXIED | ip netns exec "$ns1" socat -t 2 -T 2 STDIO udp:"$ns3_ip_port") + result=$(echo I_M_PROXIED | ip netns exec "$ns1" socat -t 2 -T 2 STDIO udp:"$ns3_ip_port",shut-none) if [ "$result" = "$expect_ns1_ns3" ] ;then echo "PASS: tproxy test $testname: ns1 got reply \"$result\" connecting to ns3" else
@@ -223,7 +223,7 @@ EOF fi # request from nsrouter to ns2 (localy originated traffic) - result=$(echo I_M_PROXIED | ip netns exec "$nsrouter" socat -t 2 -T 2 STDIO udp:"$ns2_ip_port") + result=$(echo I_M_PROXIED | ip netns exec "$nsrouter" socat -t 2 -T 2 STDIO udp:"$ns2_ip_port",shut-none) if [ "$result" == "$expect_nsrouter_ns2" ] ;then echo "PASS: tproxy test $testname: nsrouter got reply \"$result\" connecting to ns2" else
@@ -232,7 +232,7 @@ EOF fi # request from nsrouter to ns3 (localy originated traffic) - result=$(echo I_M_PROXIED | ip netns exec "$nsrouter" socat -t 2 -T 2 STDIO udp:"$ns3_ip_port") + result=$(echo I_M_PROXIED | ip netns exec "$nsrouter" socat -t 2 -T 2 STDIO udp:"$ns3_ip_port",shut-none) if [ "$result" = "$expect_nsrouter_ns3" ] ;then echo "PASS: tproxy test $testname: nsrouter got reply \"$result\" connecting to ns3" else
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 191/1146 net: mana: Use pci_name() for debugfs directory naming
In reply to Greg Kroah-Hartman7.0-stable review patch. If anyone has any objections, please let me know.
------------------
From: Erni Sri Satya Vennela <[email protected]>
[ Upstream commit c116f07ab9d22bb6f355f3cf9e44c1e6a47fe559 ]
Use pci_name(pdev) for the per-device debugfs directory instead of hardcoded "0" for PFs and pci_slot_name(pdev->slot) for VFs. The previous approach had two issues:
1. pci_slot_name() dereferences pdev->slot, which can be NULL for VFs in environments like generic VFIO passthrough or nested KVM, causing a NULL pointer dereference.
2. Multiple PFs would all use "0", and VFs across different PCI domains or buses could share the same slot name, leading to -EEXIST errors from debugfs_create_dir().
pci_name(pdev) returns the unique BDF address, is always valid, and is unique across the system.
--- drivers/net/ethernet/microsoft/mana/gdma_main.c | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-)
drivers/net/ethernet/microsoft/mana/gdma_main.c +2 -5
@@ -2007,11 +2007,8 @@ static int mana_gd_probe(struct pci_dev *pdev, const struct pci_device_id *ent) gc->dev = &pdev->dev;xa_init (&gc->irq_contexts); -if (gc->is_pf) - gc->mana_pci_debugfs =debugfs_create_dir ("0" , mana_debugfs_root); -else - gc->mana_pci_debugfs =debugfs_create_dir (pci_slot_name (pdev->slot), - mana_debugfs_root); + gc->mana_pci_debugfs =debugfs_create_dir (pci_name (pdev), + mana_debugfs_root); err =mana_gd_setup (pdev);if (err)
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 192/1146 net: mana: Move current_speed debugfs file to mana_init_port()
In reply to Greg Kroah-Hartman7.0-stable review patch. If anyone has any objections, please let me know.
------------------
From: Erni Sri Satya Vennela <[email protected]>
[ Upstream commit 3b7c7fc97aea7b4048001d12f45777201c74a17f ]
Move the current_speed debugfs file creation from mana_probe_port() to mana_init_port(). The file was previously created only during initial probe, but mana_cleanup_port_context() removes the entire vPort debugfs directory during detach/attach cycles. Since mana_init_port() recreates the directory on re-attach, moving current_speed here ensures it survives these cycles.
--- drivers/net/ethernet/microsoft/mana/mana_en.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
drivers/net/ethernet/microsoft/mana/mana_en.c +2 -2
@@ -3124,6 +3124,8 @@ static int mana_init_port(struct net_device *ndev)eth_hw_addr_set (ndev, apc->mac_addr);sprintf (vport,"vport%d" , port_idx); apc->mana_port_debugfs =debugfs_create_dir (vport, gc->mana_pci_debugfs); +debugfs_create_u32 ("current_speed" ,0400 , apc->mana_port_debugfs, + &apc->speed);return 0 ; reset_apc:
@@ -3402,8 +3404,6 @@ static int mana_probe_port(struct mana_context *ac, int port_idx,netif_carrier_on (ndev); -debugfs_create_u32 ("current_speed" ,0400 , apc->mana_port_debugfs, &apc->speed); -return 0 ; free_indir:
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 193/1146 net: airoha: Add missing RX_CPU_IDX() configuration in airoha_qdma_cleanup_rx_queue()
In reply to Greg Kroah-Hartman7.0-stable review patch. If anyone has any objections, please let me know.
------------------
From: Lorenzo Bianconi <[email protected]>
[ Upstream commit 656121b155030086b01cfce9bd31b0c925ee6860 ]
When the descriptor index written in REG_RX_CPU_IDX() is equal to the one stored in REG_RX_DMA_IDX(), the hw will stop since the QDMA RX ring is empty.
Add missing REG_RX_CPU_IDX() configuration in airoha_qdma_cleanup_rx_queue routine during QDMA RX ring cleanup.
--- drivers/net/ethernet/airoha/airoha_eth.c | 5 +++++ 1 file changed, 5 insertions(+)
drivers/net/ethernet/airoha/airoha_eth.c +5 -0
@@ -825,6 +825,11 @@ static void airoha_qdma_cleanup_rx_queue(struct airoha_queue *q) } q->head = q->tail; +/* Set RX_DMA_IDX to RX_CPU_IDX to notify the hw the QDMA RX ring is +* empty. +*/ +airoha_qdma_rmw (qdma,REG_RX_CPU_IDX (qid),RX_RING_CPU_IDX_MASK , +FIELD_PREP (RX_RING_CPU_IDX_MASK , q->head));airoha_qdma_rmw (qdma,REG_RX_DMA_IDX (qid),RX_RING_DMA_IDX_MASK ,FIELD_PREP (RX_RING_DMA_IDX_MASK , q->tail)); }
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 194/1146 net_sched: fix skb memory leak in deferred qdisc drops
In reply to Greg Kroah-Hartman7.0-stable review patch. If anyone has any objections, please let me know.
------------------
From: Fernando Fernandez Mancera <[email protected]>
[ Upstream commit a6bd339dbb3514bce690fdcf252e788dfab4ee76 ]
When the network stack cleans up the deferred list via qdisc_run_end(), it operates on the root qdisc. If the root qdisc do not implement the TCQ_F_DEQUEUE_DROPS flag the packets queue to free are never freed and gets stranded on the child's local to_free list.
Fix this by making qdisc_dequeue_drop() aware of the root qdisc. It fetches the root qdisc and check for the TCQ_F_DEQUEUE_DROPS flag. If the flag is present, the packet is appended directly to the root's to_free list. Otherwise, drop it directly as it was done before the optimization was implemented.
--- include/net/sch_generic.h | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-)
include/net/sch_generic.h +13 -3
@@ -1170,12 +1170,22 @@ static inline void tcf_kfree_skb_list(struct sk_buff *skb)static inline void qdisc_dequeue_drop (struct Qdisc *q,struct sk_buff *skb,enum skb_drop_reason reason) { +struct Qdisc *root; +DEBUG_NET_WARN_ON_ONCE (!(q->flags &TCQ_F_DEQUEUE_DROPS ));DEBUG_NET_WARN_ON_ONCE (q->flags &TCQ_F_NOLOCK ); -tcf_set_drop_reason (skb, reason); - skb->next = q->to_free; - q->to_free = skb; +rcu_read_lock (); + root =qdisc_root_sleeping (q); + +if (root->flags &TCQ_F_DEQUEUE_DROPS ) { +tcf_set_drop_reason (skb, reason); + skb->next = root->to_free; + root->to_free = skb; + }else { +kfree_skb_reason (skb, reason); + } +rcu_read_unlock (); }/* Instead of calling kfree_skb() while root qdisc lock is held,
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 195/1146 bpf: Fix same-register dst/src OOB read and pointer leak in sock_ops
In reply to Greg Kroah-Hartman7.0-stable review patch. If anyone has any objections, please let me know.
------------------
From: Jiayuan Chen <[email protected]>
[ Upstream commit 10f86a2a5c91fc4c4d001960f1c21abe52545ef6 ]
When a BPF sock_ops program accesses ctx fields with dst_reg == src_reg, the SOCK_OPS_GET_SK() and SOCK_OPS_GET_FIELD() macros fail to zero the destination register in the !fullsock / !locked_tcp_sock path.
Both macros borrow a temporary register to check is_fullsock / is_locked_tcp_sock when dst_reg == src_reg, because dst_reg holds the ctx pointer. When the check is false (e.g., TCP_NEW_SYN_RECV state with a request_sock), dst_reg should be zeroed but is not, leaving the stale ctx pointer:
- SOCK_OPS_GET_SK: dst_reg retains the ctx pointer, passes NULL checks as PTR_TO_SOCKET_OR_NULL, and can be used as a bogus socket pointer, leading to stack-out-of-bounds access in helpers like bpf_skc_to_tcp6_sock().
- SOCK_OPS_GET_FIELD: dst_reg retains the ctx pointer which the verifier believes is a SCALAR_VALUE, leaking a kernel pointer.
Fix both macros by:
- Changing JMP_A(1) to JMP_A(2) in the fullsock path to skip the added instruction.
- Adding BPF_MOV64_IMM(si->dst_reg, 0) after the temp register restore in the !fullsock path, placed after the restore because dst_reg == src_reg means we need src_reg intact to read ctx->temp.
--- net/core/filter.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-)
net/core/filter.c +4 -2
@@ -10581,10 +10581,11 @@ static u32 sock_ops_convert_ctx_access(enum bpf_access_type type, si->dst_reg, si->dst_reg, \ offsetof(OBJ, OBJ_FIELD)); \if (si->dst_reg == si->src_reg) { \ - *insn++ =BPF_JMP_A (1 ); \ + *insn++ =BPF_JMP_A (2 ); \ *insn++ =BPF_LDX_MEM (BPF_DW , reg, si->src_reg, \ offsetof(struct bpf_sock_ops_kern , \ temp)); \ + *insn++ =BPF_MOV64_IMM (si->dst_reg,0 ); \ } \ }while (0 )
@@ -10618,10 +10619,11 @@ static u32 sock_ops_convert_ctx_access(enum bpf_access_type type, si->dst_reg, si->src_reg, \ offsetof(struct bpf_sock_ops_kern, sk));\if (si->dst_reg == si->src_reg) { \ - *insn++ =BPF_JMP_A (1 ); \ + *insn++ =BPF_JMP_A (2 ); \ *insn++ =BPF_LDX_MEM (BPF_DW , reg, si->src_reg, \ offsetof(struct bpf_sock_ops_kern , \ temp)); \ + *insn++ =BPF_MOV64_IMM (si->dst_reg,0 ); \ } \ }while (0 )
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 196/1146 bpf: Allow instructions with arena source and non-arena dest registers
In reply to Greg Kroah-Hartman7.0-stable review patch. If anyone has any objections, please let me know.
------------------
From: Emil Tsalapatis <[email protected]>
[ Upstream commit ac61bffe91d4bda08806e12957c6d64756d042db ]
The compiler sometimes stores the result of a PTR_TO_ARENA and SCALAR operation into the scalar register rather than the pointer register. Relax the verifier to allow operations between a source arena register and a destination non-arena register, marking the destination's value as a PTR_TO_ARENA.
--- kernel/bpf/verifier.c | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-)
kernel/bpf/verifier.c +11 -3
@@ -16222,11 +16222,20 @@ static int adjust_reg_min_max_vals(struct bpf_verifier_env *env,int err; dst_reg = ®s[insn->dst_reg]; - src_reg =NULL ; +if (BPF_SRC (insn->code) ==BPF_X ) + src_reg = ®s[insn->src_reg]; +else + src_reg =NULL ; -if (dst_reg->type ==PTR_TO_ARENA ) { +/* Case where at least one operand is an arena. */ +if (dst_reg->type ==PTR_TO_ARENA || (src_reg && src_reg->type ==PTR_TO_ARENA )) {struct bpf_insn_aux_data *aux =cur_aux (env); +if (dst_reg->type !=PTR_TO_ARENA ) + *dst_reg = *src_reg; + + dst_reg->subreg_def = env->insn_idx +1 ; +if (BPF_CLASS (insn->code) ==BPF_ALU64 )/* * 32-bit operations zero upper bits automatically.
@@ -16242,7 +16251,6 @@ static int adjust_reg_min_max_vals(struct bpf_verifier_env *env, ptr_reg = dst_reg;if (BPF_SRC (insn->code) ==BPF_X ) { - src_reg = ®s[insn->src_reg];if (src_reg->type !=SCALAR_VALUE ) {if (dst_reg->type !=SCALAR_VALUE ) {/* Combining two pointers by any ALU op yields
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 197/1146 selftests/bpf: Fix reg_bounds to match new tnum-based refinement
In reply to Greg Kroah-Hartman7.0-stable review patch. If anyone has any objections, please let me know.
------------------
From: Paul Chaignon <[email protected]>
[ Upstream commit 2fefa9c81a25534464911447d51ddb44b04a8e5b ]
Commit efc11a667878 ("bpf: Improve bounds when tnum has a single possible value") improved the bounds refinement to detect when the tnum and u64 range overlap in a single value (and the bounds can thus be set to that value).
Eduard then noticed that it broke the slow-mode reg_bounds selftests because they don't have an equivalent logic and are therefore unable to refine the bounds as much as the verifier. The following test case illustrates this.
ACTUAL TRUE1: scalar(u64=0xffffffff00000000,u32=0,s64=0xffffffff00000000,s32=0)
EXPECTED TRUE1: scalar(u64=[0xfffffffe00000001; 0xffffffff00000000],u32=0,s64=[0xfffffffe00000001; 0xffffffff00000000],s32=0) [...]
#323/1007 reg_bounds_gen_consts_s64_s32/(s64)[0xfffffffe00000001; 0xffffffff00000000] (s32)<op> S64_MIN:FAIL
with the verifier logs:
[...]
19: w0 = w6 ; R0=scalar(smin=0,smax=umax=0xffffffff,
var_off=(0x0; 0xffffffff))
R6=scalar(smin=0xfffffffe00000001,smax=0xffffffff00000000,
umin=0xfffffffe00000001,umax=0xffffffff00000000,
var_off=(0xfffffffe00000000; 0x1ffffffff)) 20: w0 = w7 ; R0=0 R7=0x8000000000000000
21: if w6 == w7 goto pc+3
[...]
from 21 to 25: [...]
25: w0 = w6 ; R0=0 R6=0xffffffff00000000
; ^
; unexpected refined value
26: w0 = w7 ; R0=0 R7=0x8000000000000000
27: exit
When w6 == w7 is true, the verifier can deduce that the R6's tnum is equal to (0xfffffffe00000000; 0x100000000) and then use that information to refine the bounds: the tnum only overlap with the u64 range in 0xffffffff00000000. The reg_bounds selftest doesn't know about tnums and therefore fails to perform the same refinement.
This issue happens when the tnum carries information that cannot be represented in the ranges, as otherwise the selftest could reach the same refined value using just the ranges. The tnum thus needs to represent non-contiguous values (ex., R6's tnum above, after the condition). The only way this can happen in the reg_bounds selftest is at the boundary between the 32 and 64bit ranges. We therefore only need to handle that case.
This patch fixes the selftest refinement logic by checking if the u32 and u64 ranges overlap in a single value. If so, the ranges can be set to that value. We need to handle two cases: either they overlap in umin64...
u64 values
matching u32 range: xxx xxx xxx xxx
|--------------------------------------| u64 range: 0 xxxxx UMAX64
or in umax64:
u64 values
matching u32 range: xxx xxx xxx xxx
|--------------------------------------| u64 range: 0 xxxxx UMAX64
To detect the first case, we decrease umax64 to the maximum value that matches the u32 range. If that happens to be umin64, then umin64 is the only overlap. We proceed similarly for the second case, increasing umin64 to the minimum value that matches the u32 range.
Note this is similar to how the verifier handles the general case using tnum, but we don't need to care about a single-value overlap in the middle of the range. That case is not possible when comparing two ranges.
This patch also adds two test cases reproducing this bug as part of the normal test runs (without SLOW_TESTS=1).
--- .../selftests/bpf/prog_tests/reg_bounds.c | 35 +++++++++++++++++++ 1 file changed, 35 insertions(+)
tools/testing/selftests/bpf/prog_tests/reg_bounds.c +35 -0
@@ -500,6 +500,39 @@ static struct range range_refine(enum num_t x_t, struct range x, enum num_t y_t, (s64)x.a >= S32_MIN && (s64)x.b <= S32_MAX)return range_intersection (x_t, x, y_cast); +if (y_t ==U32 && x_t ==U64 ) { +u64 xmin_swap, xmax_swap, xmin_lower32, xmax_lower32; + + xmin_lower32 = x.a &0xffffffff ; + xmax_lower32 = x.b &0xffffffff ; +if (xmin_lower32 < y.a || xmin_lower32 > y.b) { +/* The 32 lower bits of the umin64 are outside the u32 +* range. Let's update umin64 to match the u32 range. +* We want to *increase* the umin64 to the *minimum* +* value that matches the u32 range. +*/ + xmin_swap =swap_low32 (x.a, y.a); +/* We should always only increase the minimum, so if +* the new value is lower than before, we need to +* increase the 32 upper bits by 1. +*/ +if (xmin_swap < x.a) + xmin_swap +=0x100000000 ; +if (xmin_swap == x.b) +return range (x_t, x.b, x.b); + }else if (xmax_lower32 < y.a || xmax_lower32 > y.b) { +/* Same for the umax64, but we want to *decrease* +* umax64 to the *maximum* value that matches the u32 +* range. +*/ + xmax_swap =swap_low32 (x.b, y.b); +if (xmax_swap > x.b) + xmax_swap -=0x100000000 ; +if (xmax_swap == x.a) +return range (x_t, x.a, x.a); + } + } +/* the case when new range knowledge, *y*, is a 32-bit subregister * range, while previous range knowledge, *x*, is a full register * 64-bit range, needs special treatment to take into account upper 32
@@ -2129,6 +2162,8 @@ static struct subtest_case crafted_cases[] = { {U64, S64, {0x7fffffff00000001ULL, 0xffffffff00000000ULL}, {0, 0}}, {U64, S64, {0, 0xffffffffULL}, {1, 1}}, {U64, S64, {0, 0xffffffffULL}, {0x7fffffff, 0x7fffffff}}, + {U64, S32, {0xfffffffe00000001, 0xffffffff00000000}, {S64_MIN, S64_MIN}}, + {U64, U32, {0xfffffffe00000000, U64_MAX - 1}, {U64_MAX, U64_MAX}}, {U64, U32, {0, 0x100000000}, {0, 0}}, {U64, U32, {0xfffffffe, 0x300000000}, {0x80000000, 0x80000000}},
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 198/1146 net/rds: Optimize rds_ib_laddr_check
In reply to Greg Kroah-Hartman7.0-stable review patch. If anyone has any objections, please let me know.
------------------
From: Håkon Bugge <[email protected]>
[ Upstream commit 236f718ac885965fa886440b9898dfae185c9733 ]
rds_ib_laddr_check() creates a CM_ID and attempts to bind the address in question to it. This in order to qualify the allegedly local address as a usable IB/RoCE address.
In the field, ExaWatcher runs rds-ping to all ports in the fabric from all local ports. This using all active ToS'es. In a full rack system, we have 14 cell servers and eight db servers. Typically, 6 ToS'es are used. This implies 528 rds-ping invocations per ExaWatcher's "RDSinfo" interval.
Adding to this, each rds-ping invocation creates eight sockets and binds the local address to them:
socket(AF_RDS, SOCK_SEQPACKET, 0) = 3
bind(3, {sa_family=AF_INET, sin_port=htons(0),
sin_addr=inet_addr("192.168.36.2")}, 16) = 0
socket(AF_RDS, SOCK_SEQPACKET, 0) = 4
bind(4, {sa_family=AF_INET, sin_port=htons(0),
sin_addr=inet_addr("192.168.36.2")}, 16) = 0
socket(AF_RDS, SOCK_SEQPACKET, 0) = 5
bind(5, {sa_family=AF_INET, sin_port=htons(0),
sin_addr=inet_addr("192.168.36.2")}, 16) = 0
socket(AF_RDS, SOCK_SEQPACKET, 0) = 6
bind(6, {sa_family=AF_INET, sin_port=htons(0),
sin_addr=inet_addr("192.168.36.2")}, 16) = 0
socket(AF_RDS, SOCK_SEQPACKET, 0) = 7
bind(7, {sa_family=AF_INET, sin_port=htons(0),
sin_addr=inet_addr("192.168.36.2")}, 16) = 0
socket(AF_RDS, SOCK_SEQPACKET, 0) = 8
bind(8, {sa_family=AF_INET, sin_port=htons(0),
sin_addr=inet_addr("192.168.36.2")}, 16) = 0
socket(AF_RDS, SOCK_SEQPACKET, 0) = 9
bind(9, {sa_family=AF_INET, sin_port=htons(0),
sin_addr=inet_addr("192.168.36.2")}, 16) = 0
socket(AF_RDS, SOCK_SEQPACKET, 0) = 10
bind(10, {sa_family=AF_INET, sin_port=htons(0),
sin_addr=inet_addr("192.168.36.2")}, 16) = 0So, at every interval ExaWatcher executes rds-ping's, 4224 CM_IDs are allocated, considering this full-rack system. After the a CM_ID has been allocated, rdma_bind_addr() is called, with the port number being zero. This implies that the CMA will attempt to search for an un-used ephemeral port. Simplified, the algorithm is to start at a random position in the available port space, and then if needed, iterate until an un-used port is found.
The book-keeping of used ports uses the idr system, which again uses slab to allocate new struct idr_layer's. The size is 2092 bytes and slab tries to reduce the wasted space. Hence, it chooses an order:3 allocation, for which 15 idr_layer structs will fit and only 1388 bytes are wasted per the 32KiB order:3 chunk.
Although this order:3 allocation seems like a good space/speed trade-off, it does not resonate well with how it used by the CMA. The combination of the randomized starting point in the port space (which has close to zero spatial locality) and the close proximity in time of the 4224 invocations of the rds-ping's, creates a memory hog for order:3 allocations.
These costly allocations may need reclaims and/or compaction. At worst, they may fail and produce a stack trace such as (from uek4):
[<ffffffff811a72d5>] __inc_zone_page_state+0x35/0x40 [<ffffffff811c2e97>] page_add_file_rmap+0x57/0x60 [<ffffffffa37ca1df>] remove_migration_pte+0x3f/0x3c0 [ksplice_6cn872bt_vmlinux_new] [<ffffffff811c3de8>] rmap_walk+0xd8/0x340 [<ffffffff811e8860>] remove_migration_ptes+0x40/0x50 [<ffffffff811ea83c>] migrate_pages+0x3ec/0x890 [<ffffffff811afa0d>] compact_zone+0x32d/0x9a0 [<ffffffff811b00ed>] compact_zone_order+0x6d/0x90 [<ffffffff811b03b2>] try_to_compact_pages+0x102/0x270 [<ffffffff81190e56>] __alloc_pages_direct_compact+0x46/0x100 [<ffffffff8119165b>] __alloc_pages_nodemask+0x74b/0xaa0 [<ffffffff811d8411>] alloc_pages_current+0x91/0x110 [<ffffffff811e3b0b>] new_slab+0x38b/0x480 [<ffffffffa41323c7>] __slab_alloc+0x3b7/0x4a0 [ksplice_s0dk66a8_vmlinux_new] [<ffffffff811e42ab>] kmem_cache_alloc+0x1fb/0x250 [<ffffffff8131fdd6>] idr_layer_alloc+0x36/0x90 [<ffffffff8132029c>] idr_get_empty_slot+0x28c/0x3d0 [<ffffffff813204ad>] idr_alloc+0x4d/0xf0 [<ffffffffa051727d>] cma_alloc_port+0x4d/0xa0 [rdma_cm] [<ffffffffa0517cbe>] rdma_bind_addr+0x2ae/0x5b0 [rdma_cm] [<ffffffffa09d8083>] rds_ib_laddr_check+0x83/0x2c0 [ksplice_6l2xst5i_rds_rdma_new] [<ffffffffa05f892b>] rds_trans_get_preferred+0x5b/0xa0 [rds] [<ffffffffa05f09f2>] rds_bind+0x212/0x280 [rds] [<ffffffff815b4016>] SYSC_bind+0xe6/0x120 [<ffffffff815b4d3e>] SyS_bind+0xe/0x10 [<ffffffff816b031a>] system_call_fastpath+0x18/0xd4
To avoid these excessive calls to rdma_bind_addr(), we optimize rds_ib_laddr_check() by simply checking if the address in question has been used before. The rds_rdma module keeps track of addresses associated with IB devices, and the function rds_ib_get_device() is used to determine if the address already has been qualified as a valid local address. If not found, we call the legacy rds_ib_laddr_check(), now renamed to rds_ib_laddr_check_cm().
Stable-dep-of: ebf71dd4aff4 ("net/rds: Restrict use of RDS/IB to the initial network namespace")
--- net/rds/ib.c | 20 ++++++++++++++++++-- net/rds/ib.h | 1 + net/rds/ib_rdma.c | 2 +- 3 files changed, 20 insertions(+), 3 deletions(-)
net/rds/ib.c +18 -2
@@ -401,8 +401,8 @@ static void rds6_ib_ic_info(struct socket *sock, unsigned int len,* allowed to influence which paths have priority. We could call userspace * asserting this policy "routing". */ -static int rds_ib_laddr_check (struct net *net,const struct in6_addr *addr, -__u32 scope_id) +static int rds_ib_laddr_check_cm (struct net *net,const struct in6_addr *addr, +__u32 scope_id) {int ret;struct rdma_cm_id *cm_id;
@@ -487,6 +487,22 @@ static int rds_ib_laddr_check(struct net *net, const struct in6_addr *addr,return ret; } +static int rds_ib_laddr_check (struct net *net,const struct in6_addr *addr, +__u32 scope_id) +{ +struct rds_ib_device *rds_ibdev =NULL ; + +if (ipv6_addr_v4mapped (addr)) { + rds_ibdev =rds_ib_get_device (addr->s6_addr32[3 ]); +if (rds_ibdev) { +rds_ib_dev_put (rds_ibdev); +return 0 ; + } + } + +return rds_ib_laddr_check_cm (net, addr, scope_id); +} +static void rds_ib_unregister_client (void ) {ib_unregister_client (&rds_ib_client);
net/rds/ib.h +1 -0
@@ -381,6 +381,7 @@ void rds_ib_cm_connect_complete(struct rds_connection *conn,__rds_ib_conn_error (conn,KERN_WARNING "RDS/IB: " fmt) /* ib_rdma.c */ +struct rds_ib_device *rds_ib_get_device (__be32 ipaddr);int rds_ib_update_ipaddr (struct rds_ib_device *rds_ibdev,struct in6_addr *ipaddr);void rds_ib_add_conn (struct rds_ib_device *rds_ibdev,struct rds_connection *conn);
net/rds/ib_rdma.c +1 -1
@@ -43,7 +43,7 @@ struct workqueue_struct *rds_ib_mr_wq;static void rds_ib_odp_mr_worker (struct work_struct *work); -static struct rds_ib_device *rds_ib_get_device (__be32 ipaddr) +struct rds_ib_device *rds_ib_get_device (__be32 ipaddr) {struct rds_ib_device *rds_ibdev;struct rds_ib_ipaddr *i_ipaddr;
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 199/1146 net/rds: Restrict use of RDS/IB to the initial network namespace
In reply to Greg Kroah-Hartman7.0-stable review patch. If anyone has any objections, please let me know.
------------------
From: Greg Jumper <[email protected]>
[ Upstream commit ebf71dd4aff46e8e421d455db3e231ba43d2fa8a ]
Prevent using RDS/IB in network namespaces other than the initial one. The existing RDS/IB code will not work properly in non-initial network namespaces.
--- net/rds/af_rds.c | 10 ++++++++-- net/rds/ib.c | 4 ++++ 2 files changed, 12 insertions(+), 2 deletions(-)
net/rds/af_rds.c +8 -2
@@ -357,7 +357,8 @@ static int rds_cong_monitor(struct rds_sock *rs, sockptr_t optval, int optlen)return ret; } -static int rds_set_transport (struct rds_sock *rs,sockptr_t optval,int optlen) +static int rds_set_transport (struct net *net,struct rds_sock *rs, +sockptr_t optval,int optlen) {int t_type;
@@ -373,6 +374,10 @@ static int rds_set_transport(struct rds_sock *rs, sockptr_t optval, int optlen)if (t_type <0 || t_type >=RDS_TRANS_COUNT )return -EINVAL ; +/* RDS/IB is restricted to the initial network namespace */ +if (t_type !=RDS_TRANS_TCP && !net_eq (net, &init_net)) +return -EPROTOTYPE ; + rs->rs_transport =rds_trans_get (t_type);return rs->rs_transport ?0 : -ENOPROTOOPT ;
@@ -433,6 +438,7 @@ static int rds_setsockopt(struct socket *sock, int level, int optname, sockptr_t optval, unsigned int optlen) {struct rds_sock *rs =rds_sk_to_rs (sock->sk); +struct net *net =sock_net (sock->sk);int ret;if (level !=SOL_RDS ) {
@@ -461,7 +467,7 @@ static int rds_setsockopt(struct socket *sock, int level, int optname,break ;case SO_RDS_TRANSPORT :lock_sock (sock->sk); - ret =rds_set_transport (rs, optval, optlen); + ret =rds_set_transport (net, rs, optval, optlen);release_sock (sock->sk);break ;case SO_TIMESTAMP_OLD :
net/rds/ib.c +4 -0
@@ -492,6 +492,10 @@ static int rds_ib_laddr_check(struct net *net, const struct in6_addr *addr, {struct rds_ib_device *rds_ibdev =NULL ; +/* RDS/IB is restricted to the initial network namespace */ +if (!net_eq (net, &init_net)) +return -EPROTOTYPE ; +if (ipv6_addr_v4mapped (addr)) { rds_ibdev =rds_ib_get_device (addr->s6_addr32[3 ]);if (rds_ibdev) {
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 200/1146 bpf: Fix OOB in pcpu_init_value
In reply to Greg Kroah-Hartman7.0-stable review patch. If anyone has any objections, please let me know.
------------------
From: Lang Xu <[email protected]>
[ Upstream commit 576afddfee8d1108ee299bf10f581593540d1a36 ]
An out-of-bounds read occurs when copying element from a BPF_MAP_TYPE_CGROUP_STORAGE map to another pcpu map with the same value_size that is not rounded up to 8 bytes.
The issue happens when:
1. A CGROUP_STORAGE map is created with value_size not aligned to 8 bytes (e.g., 4 bytes)
2. A pcpu map is created with the same value_size (e.g., 4 bytes)
3. Update element in 2 with data in 1
pcpu_init_value assumes that all sources are rounded up to 8 bytes, and invokes copy_map_value_long to make a data copy, However, the assumption doesn't stand since there are some cases where the source may not be rounded up to 8 bytes, e.g., CGROUP_STORAGE, skb->data. the verifier verifies exactly the size that the source claims, not the size rounded up to 8 bytes by kernel, an OOB happens when the source has only 4 bytes while the copy size(4) is rounded up to 8.
--- kernel/bpf/hashtab.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
kernel/bpf/hashtab.c +1 -1
@@ -1056,7 +1056,7 @@ static void pcpu_init_value(struct bpf_htab *htab, void __percpu *pptr,for_each_possible_cpu (cpu) {if (cpu == current_cpu) -copy_map_value_long (&htab->map,per_cpu_ptr (pptr, cpu), value); +copy_map_value (&htab->map,per_cpu_ptr (pptr, cpu), value);else /* Since elem is preallocated, we cannot touch special fields */ zero_map_value (&htab->map,per_cpu_ptr (pptr, cpu)); }
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 201/1146 ppp: require CAP_NET_ADMIN in target netns for unattached ioctls
In reply to Greg Kroah-Hartman7.0-stable review patch. If anyone has any objections, please let me know.
------------------
From: Taegu Ha <[email protected]>
[ Upstream commit 2bb6379416fd19f44c3423a00bfd8626259f6067 ]
/dev/ppp open is currently authorized against file->f_cred->user_ns, while unattached administrative ioctls operate on current->nsproxy->net_ns.
As a result, a local unprivileged user can create a new user namespace with CLONE_NEWUSER, gain CAP_NET_ADMIN only in that new user namespace, and still issue PPPIOCNEWUNIT, PPPIOCATTACH, or PPPIOCATTCHAN against an inherited network namespace.
Require CAP_NET_ADMIN in the user namespace that owns the target network namespace before handling unattached PPP administrative ioctls.
This preserves normal pppd operation in the network namespace it is actually privileged in, while rejecting the userns-only inherited-netns case.
--- drivers/net/ppp/ppp_generic.c | 3 +++ 1 file changed, 3 insertions(+)
drivers/net/ppp/ppp_generic.c +3 -0
@@ -1057,6 +1057,9 @@ static int ppp_unattached_ioctl(struct net *net, struct ppp_file *pf,struct ppp_net *pn;int __user *p = (int __user *)arg; +if (!ns_capable (net->user_ns,CAP_NET_ADMIN )) +return -EPERM ; +switch (cmd) {case PPPIOCNEWUNIT :/* Create a new ppp unit */
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 202/1146 net: ipa: Fix programming of QTIME_TIMESTAMP_CFG
In reply to Greg Kroah-Hartman7.0-stable review patch. If anyone has any objections, please let me know.
------------------
From: Luca Weiss <[email protected]>
[ Upstream commit de08f9585692813bd41ee654fca0487664c4de30 ]
The 'val' variable gets overwritten multiple times, discarding previous values. Looking at the git log shows these should be combined with |= instead.
--- drivers/net/ipa/ipa_main.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-)
drivers/net/ipa/ipa_main.c +3 -3
@@ -361,7 +361,7 @@ static void ipa_qtime_config(struct ipa *ipa) {const struct reg *reg;u32 offset; -u32 val; +u32 val =0 ;/* Timer clock divider must be disabled when we change the rate */ reg =ipa_reg (ipa,TIMERS_XO_CLK_DIV_CFG );
@@ -374,8 +374,8 @@ static void ipa_qtime_config(struct ipa *ipa) val |=reg_bit (reg,DPL_TIMESTAMP_SEL ); }/* Configure tag and NAT Qtime timestamp resolution as well */ - val =reg_encode (reg,TAG_TIMESTAMP_LSB ,TAG_TIMESTAMP_SHIFT ); - val =reg_encode (reg,NAT_TIMESTAMP_LSB ,NAT_TIMESTAMP_SHIFT ); + val |=reg_encode (reg,TAG_TIMESTAMP_LSB ,TAG_TIMESTAMP_SHIFT ); + val |=reg_encode (reg,NAT_TIMESTAMP_LSB ,NAT_TIMESTAMP_SHIFT );iowrite32 (val, ipa->reg_virt +reg_offset (reg));
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 203/1146 net: ipa: Fix decoding EV_PER_EE for IPA v5.0+
In reply to Greg Kroah-Hartman7.0-stable review patch. If anyone has any objections, please let me know.
------------------
From: Luca Weiss <[email protected]>
[ Upstream commit 1335b903cf2e8aeaca87fd665683384c731ec941 ]
Initially 'reg' and 'val' are assigned from HW_PARAM_2.
But since IPA v5.0+ takes EV_PER_EE from HW_PARAM_4 (instead of NUM_EV_PER_EE from HW_PARAM_2), we not only need to re-assign 'reg' but also read the register value of that register into 'val' so that reg_decode() works on the correct value.
--- drivers/net/ipa/gsi.c | 1 + 1 file changed, 1 insertion(+)
drivers/net/ipa/gsi.c +1 -0
@@ -2044,6 +2044,7 @@ static int gsi_ring_setup(struct gsi *gsi) count =reg_decode (reg,NUM_EV_PER_EE , val); }else { reg =gsi_reg (gsi,HW_PARAM_4 ); + val =ioread32 (gsi->virt +reg_offset (reg)); count =reg_decode (reg,EV_PER_EE , val); }if (!count) {
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 204/1146 dt-bindings: net: dsa: nxp,sja1105: make spi-cpol optional for sja1110
In reply to Greg Kroah-Hartman7.0-stable review patch. If anyone has any objections, please let me know.
------------------
From: Josua Mayer <[email protected]>
[ Upstream commit 600f01dc4bd0c736b3ffea9f7976136d8bf1b136 ]
Currently, the binding requires 'spi-cpha' for SJA1105 and 'spi-cpol' for SJA1110.
However, the SJA1110 supports both SPI modes 0 and 2. Mode 2 (cpha=0, cpol=1) is used by the NXP LX2160 Bluebox 3.
On the SolidRun i.MX8DXL HummingBoard Telematics, mode 0 is stable, while forcing mode 2 introduces CRC errors especially during bursts.
Drop the requirement on spi-cpol for SJA1110.
--- Documentation/devicetree/bindings/net/dsa/nxp,sja1105.yaml | 2 -- 1 file changed, 2 deletions(-)
Documentation/devicetree/bindings/net/dsa/nxp,sja1105.yaml +0 -2
@@ -143,8 +143,6 @@ allOf: else: properties: spi-cpha: false - required: - - spi-cpol unevaluatedProperties: false
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 205/1146 net: phy: fix a return path in get_phy_c45_ids()
In reply to Greg Kroah-Hartman7.0-stable review patch. If anyone has any objections, please let me know.
------------------
From: Charles Perry <[email protected]>
[ Upstream commit 6f533abe7bbad2eef1e42c639b6bb9dad2b02362 ]
The return value of phy_c45_probe_present() is stored in "ret", not "phy_reg", fix this. "phy_reg" always has a positive value if we reach this return path (since it would have returned earlier otherwise), which means that the original goal of the patch of not considering -ENODEV fatal wasn't achieved.
--- drivers/net/phy/phy_device.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
drivers/net/phy/phy_device.c +2 -2
@@ -927,8 +927,8 @@ static int get_phy_c45_ids(struct mii_bus *bus, int addr,/* returning -ENODEV doesn't stop bus * scanning */ -return (phy_reg == -EIO || - phy_reg == -ENODEV ) ? -ENODEV : -EIO ; +return (ret == -EIO || + ret == -ENODEV ) ? -ENODEV : -EIO ;if (!ret)continue ;
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 206/1146 net/mlx5e: Fix features not applied during netdev registration
In reply to Greg Kroah-Hartman7.0-stable review patch. If anyone has any objections, please let me know.
------------------
From: Gal Pressman <[email protected]>
[ Upstream commit 9994ad4df82d64e57135c0f0906897685f5a9e87 ]
mlx5e_fix_features() returns early when the netdevice is not present. This is correct during profile transitions where priv is cleared, but it also incorrectly blocks feature fixups during register_netdev(), when the device is also not yet present.
It is not trivial to distinguish between both cases as we cannot use priv to carry state, and in both cases reg_state == NETREG_REGISTERED.
Force a netdev features update after register_netdev() completes, where the device is present and fix_features() can actually work.
This is not a pretty solution, as it results in an additional features update call (register_netdevice() already calls __netdev_update_features() internally), but it is the simplest, cleanest, and most robust way I found to fix this issue after multiple attempts.
This fixes an issue on systems where CQE compression is enabled by default, RXHASH remains enabled after registration despite the two features being mutually exclusive.
--- drivers/net/ethernet/mellanox/mlx5/core/en_main.c | 8 ++++++++ 1 file changed, 8 insertions(+)
drivers/net/ethernet/mellanox/mlx5/core/en_main.c +8 -0
@@ -6756,6 +6756,14 @@ static int _mlx5e_probe(struct auxiliary_device *adev) goto err_resume; } +/* mlx5e_fix_features() returns early when the device is not present +* to avoid dereferencing cleared priv during profile changes. +* This also causes it to be a no-op during register_netdev(), where +* the device is not yet present. +* Trigger an additional features update that will actually work. +*/ +mlx5e_update_features (netdev); +mlx5e_dcbnl_init_app (priv);mlx5_core_uplink_netdev_set (mdev, netdev);mlx5e_params_print_info (mdev, &priv->channels.params);
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 207/1146 net/mlx5e: IPsec, fix ASO poll timeout with read_poll_timeout_atomic()
In reply to Greg Kroah-Hartman7.0-stable review patch. If anyone has any objections, please let me know.
------------------
From: Gal Pressman <[email protected]>
[ Upstream commit edccdd1eb94712da97a6ce71123ec27890add754 ]
The do-while poll loop uses jiffies for its timeout:
expires = jiffies + msecs_to_jiffies(10);
jiffies is sampled at an arbitrary point within the current tick, so the first partial tick contributes anywhere from a full tick down to nearly zero real time. For small msecs_to_jiffies() results this is significant, the effective poll window can be much shorter than the requested 10ms, and in the worst case the loop exits after a single iteration (e.g., when HZ=100), well before the device has delivered the CQE.
Replace the loop with read_poll_timeout_atomic(), which counts elapsed time via udelay() accounting rather than jiffies, guaranteeing the full poll window regardless of HZ.
Additionally, read_poll_timeout_atomic() executes the poll operation one more time after the timeout has expired, giving the CQE a final chance to be detected. The old do-while loop could exit without a final poll if the timeout expired during the udelay() between iterations.
--- .../mellanox/mlx5/core/en_accel/ipsec_offload.c | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-)
drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec_offload.c +4 -8
@@ -1,6 +1,8 @@// SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB /* Copyright (c) 2017, Mellanox Technologies inc. All rights reserved. */ +#include <linux/iopoll.h> +#include "mlx5_core.h" #include "en.h" #include "ipsec.h"
@@ -592,7 +594,6 @@ int mlx5e_ipsec_aso_query(struct mlx5e_ipsec_sa_entry *sa_entry,struct mlx5_wqe_aso_ctrl_seg *ctrl;struct mlx5e_hw_objs *res;struct mlx5_aso_wqe *wqe; -unsigned long expires;u8 ds_cnt;int ret;
@@ -614,13 +615,8 @@ int mlx5e_ipsec_aso_query(struct mlx5e_ipsec_sa_entry *sa_entry,mlx5e_ipsec_aso_copy (ctrl, data);mlx5_aso_post_wqe (aso->aso, false, &wqe->ctrl); - expires = jiffies +msecs_to_jiffies (10 ); -do { - ret =mlx5_aso_poll_cq (aso->aso, false); -if (ret) -/* We are in atomic context */ -udelay (10 ); - }while (ret &&time_is_after_jiffies (expires)); +read_poll_timeout_atomic (mlx5_aso_poll_cq, ret, !ret,10 , +10 *USEC_PER_MSEC , false, aso->aso, false);if (!ret)memcpy (sa_entry->ctx, aso->ctx,MLX5_ST_SZ_BYTES (ipsec_aso));spin_unlock_bh (&aso->lock);
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 208/1146 net: ethernet: mtk_eth_soc: initialize PPE per-tag-layer MTU registers
In reply to Greg Kroah-Hartman7.0-stable review patch. If anyone has any objections, please let me know.
------------------
From: Daniel Golle <[email protected]>
[ Upstream commit 2dddb34dd0d07b01fa770eca89480a4da4f13153 ]
The PPE enforces output frame size limits via per-tag-layer VLAN_MTU registers that the driver never initializes. The hardware defaults do not account for PPPoE overhead, causing the PPE to punt encapsulated frames back to the CPU instead of forwarding them.
Initialize the registers at PPE start and on MTU changes using the maximum GMAC MTU. This is a conservative approximation -- the actual per-PPE requirement depends on egress path, but using the global maximum ensures the limits are never too small.
--- drivers/net/ethernet/mediatek/mtk_eth_soc.c | 22 ++++++++++++++- drivers/net/ethernet/mediatek/mtk_ppe.c | 30 +++++++++++++++++++++ drivers/net/ethernet/mediatek/mtk_ppe.h | 1 + 3 files changed, 52 insertions(+), 1 deletion(-)
drivers/net/ethernet/mediatek/mtk_eth_soc.c +21 -1
@@ -3566,12 +3566,23 @@ static int mtk_device_event(struct notifier_block *n, unsigned long event, voidreturn NOTIFY_DONE ; } +static int mtk_max_gmac_mtu (struct mtk_eth *eth) +{ +int i, max_mtu =ETH_DATA_LEN ; + +for (i =0 ; i <ARRAY_SIZE (eth->netdev); i++) +if (eth->netdev[i] && eth->netdev[i]->mtu > max_mtu) + max_mtu = eth->netdev[i]->mtu; + +return max_mtu; +} +static int mtk_open (struct net_device *dev) {struct mtk_mac *mac =netdev_priv (dev);struct mtk_eth *eth = mac->hw;struct mtk_mac *target_mac; -int i, err, ppe_num; +int i, err, ppe_num, mtu; ppe_num = eth->soc->ppe_num;
@@ -3618,6 +3629,10 @@ static int mtk_open(struct net_device *dev)mtk_gdm_config (eth, target_mac->id, gdm_config); } + mtu =mtk_max_gmac_mtu (eth); +for (i =0 ; i <ARRAY_SIZE (eth->ppe); i++) +mtk_ppe_update_mtu (eth->ppe[i], mtu); +napi_enable (ð->tx_napi);napi_enable (ð->rx_napi);mtk_tx_irq_enable (eth,MTK_TX_DONE_INT );
@@ -4311,6 +4326,7 @@ static int mtk_change_mtu(struct net_device *dev, int new_mtu)int length = new_mtu +MTK_RX_ETH_HLEN ;struct mtk_mac *mac =netdev_priv (dev);struct mtk_eth *eth = mac->hw; +int max_mtu, i;if (rcu_access_pointer (eth->prog) && length >MTK_PP_MAX_BUF_SIZE ) {
@@ -4321,6 +4337,10 @@ static int mtk_change_mtu(struct net_device *dev, int new_mtu)mtk_set_mcr_max_rx (mac, length);WRITE_ONCE (dev->mtu, new_mtu); + max_mtu =mtk_max_gmac_mtu (eth); +for (i =0 ; i <ARRAY_SIZE (eth->ppe); i++) +mtk_ppe_update_mtu (eth->ppe[i], max_mtu); +return 0 ; }
drivers/net/ethernet/mediatek/mtk_ppe.c +30 -0
@@ -973,6 +973,36 @@ static void mtk_ppe_init_foe_table(struct mtk_ppe *ppe) } } +void mtk_ppe_update_mtu (struct mtk_ppe *ppe,int mtu) +{ +int base; +u32 val; + +if (!ppe) +return ; + +/* The PPE checks output frame size against per-tag-layer MTU limits, +* treating PPPoE and DSA tags just like 802.1Q VLAN tags. The Linux +* device MTU already accounts for PPPoE (PPPOE_SES_HLEN) and DSA tag +* overhead, but 802.1Q VLAN tags are handled transparently without +* being reflected by the lower device MTU being increased by 4. +* Use the maximum MTU across all GMAC interfaces so that PPE output +* frame limits are sufficiently high regardless of which port a flow +* egresses through. +*/ + base =ETH_HLEN + mtu; + + val =FIELD_PREP (MTK_PPE_VLAN_MTU0_NONE , base) | +FIELD_PREP (MTK_PPE_VLAN_MTU0_1TAG , base +VLAN_HLEN ); +ppe_w32 (ppe,MTK_PPE_VLAN_MTU0 , val); + + val =FIELD_PREP (MTK_PPE_VLAN_MTU1_2TAG , + base +2 *VLAN_HLEN ) | +FIELD_PREP (MTK_PPE_VLAN_MTU1_3TAG , + base +3 *VLAN_HLEN ); +ppe_w32 (ppe,MTK_PPE_VLAN_MTU1 , val); +} +void mtk_ppe_start (struct mtk_ppe *ppe) {u32 val;
drivers/net/ethernet/mediatek/mtk_ppe.h +1 -0
@@ -346,6 +346,7 @@ struct mtk_ppe {struct mtk_ppe *mtk_ppe_init (struct mtk_eth *eth,void __iomem *base,int index);void mtk_ppe_deinit (struct mtk_eth *eth); +void mtk_ppe_update_mtu (struct mtk_ppe *ppe,int mtu);void mtk_ppe_start (struct mtk_ppe *ppe);int mtk_ppe_stop (struct mtk_ppe *ppe);int mtk_ppe_prepare_reset (struct mtk_ppe *ppe);
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 209/1146 net: fix skb_ext_total_length() BUILD_BUG_ON with CONFIG_GCOV_PROFILE_ALL
In reply to Greg Kroah-Hartman7.0-stable review patch. If anyone has any objections, please let me know.
------------------
From: Konstantin Khorenko <[email protected]>
[ Upstream commit c0b4382c86e3d92f79b71c9ed55654db520d7b36 ]
When CONFIG_GCOV_PROFILE_ALL=y is enabled, the kernel fails to build:
In file included from <command-line>:
In function 'skb_extensions_init',
inlined from 'skb_init' at net/core/skbuff.c:5214:2:
././include/linux/compiler_types.h:706:45: error: call to
'__compiletime_assert_1490' declared with attribute error:
BUILD_BUG_ON failed: skb_ext_total_length() > 255
CONFIG_GCOV_PROFILE_ALL adds -fprofile-arcs -ftest-coverage -fno-tree-loop-im to CFLAGS globally. GCC inserts branch profiling counters into the skb_ext_total_length() loop and, combined with -fno-tree-loop-im (which disables loop invariant motion), cannot constant-fold the result.BUILD_BUG_ON requires a compile-time constant and fails.
The issue manifests in kernels with 5+ SKB extension types enabled (e.g., after addition of SKB_EXT_CAN, SKB_EXT_PSP). With 4 extensions GCC can still unroll and fold the loop despite GCOV instrumentation; with 5+ it gives up.
Mark skb_ext_total_length() with __no_profile to prevent GCOV from inserting counters into this function. Without counters the loop is "clean" and GCC can constant-fold it even with -fno-tree-loop-im active. This allows BUILD_BUG_ON to work correctly while keeping GCOV profiling for the rest of the kernel.
This also removes the CONFIG_KCOV_INSTRUMENT_ALL preprocessor guard introduced by d6e5794b06c0. That guard was added as a precaution because KCOV instrumentation was also suspected of inhibiting constant folding. However, KCOV uses -fsanitize-coverage=trace-pc, which inserts lightweight trace callbacks that do not interfere with GCC's constant folding or loop optimization passes. Only GCOV's -fprofile-arcs combined with -fno-tree-loop-im actually prevents the compiler from evaluating the loop at compile time. The guard is therefore unnecessary and can be safely removed.
--- net/core/skbuff.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-)
net/core/skbuff.c +1 -3
@@ -5142,7 +5142,7 @@ static const u8 skb_ext_type_len[] = {#endif }; -static __always_inline unsigned int skb_ext_total_length(void) +static __always_inline __no_profile unsigned int skb_ext_total_length(void) { unsigned int l = SKB_EXT_CHUNKSIZEOF(struct skb_ext);int i;
@@ -5156,9 +5156,7 @@ static __always_inline unsigned int skb_ext_total_length(void)static void skb_extensions_init (void ) {BUILD_BUG_ON (SKB_EXT_NUM >8 ); -#if !IS_ENABLED (CONFIG_KCOV_INSTRUMENT_ALL )BUILD_BUG_ON (skb_ext_total_length () >255 ); -#endif skbuff_ext_cache = kmem_cache_create("skbuff_ext_cache", SKB_EXT_ALIGN_VALUE * skb_ext_total_length(),
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 210/1146 bpf: reject short IPv4/IPv6 inputs in bpf_prog_test_run_skb
In reply to Greg Kroah-Hartman7.0-stable review patch. If anyone has any objections, please let me know.
------------------
From: Sun Jian <[email protected]>
[ Upstream commit 12bec2bd4b76d81c5d3996bd14ec1b7f4d983747 ]
bpf_prog_test_run_skb() calls eth_type_trans() first and then uses skb->protocol to initialize sk family and address fields for the test run.
For IPv4 and IPv6 packets, it may access ip_hdr(skb) or ipv6_hdr(skb) even when the provided test input only contains an Ethernet header.
Reject the input earlier if the Ethernet frame carries IPv4/IPv6 EtherType but the L3 header is too short.
Fold the IPv4/IPv6 header length checks into the existing protocol switch and return -EINVAL before accessing the network headers.
--- net/bpf/test_run.c | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-)
net/bpf/test_run.c +12 -8
@@ -1120,19 +1120,23 @@ int bpf_prog_test_run_skb(struct bpf_prog *prog, const union bpf_attr *kattr,switch (skb->protocol) {case htons (ETH_P_IP ): - sk->sk_family =AF_INET ; -if (sizeof (struct iphdr ) <=skb_headlen (skb)) { - sk->sk_rcv_saddr =ip_hdr (skb)->saddr; - sk->sk_daddr =ip_hdr (skb)->daddr; +if (skb_headlen (skb) <sizeof (struct iphdr )) { + ret = -EINVAL ; + goto out; } + sk->sk_family =AF_INET ; + sk->sk_rcv_saddr =ip_hdr (skb)->saddr; + sk->sk_daddr =ip_hdr (skb)->daddr;break ;#if IS_ENABLED (CONFIG_IPV6 )case htons (ETH_P_IPV6 ): - sk->sk_family =AF_INET6 ; -if (sizeof (struct ipv6hdr ) <=skb_headlen (skb)) { - sk->sk_v6_rcv_saddr =ipv6_hdr (skb)->saddr; - sk->sk_v6_daddr =ipv6_hdr (skb)->daddr; +if (skb_headlen (skb) <sizeof (struct ipv6hdr )) { + ret = -EINVAL ; + goto out; } + sk->sk_family =AF_INET6 ; + sk->sk_v6_rcv_saddr =ipv6_hdr (skb)->saddr; + sk->sk_v6_daddr =ipv6_hdr (skb)->daddr;break ;#endif default :
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 211/1146 Bluetooth: L2CAP: Fix printing wrong information if SDU length exceeds MTU
In reply to Greg Kroah-Hartman7.0-stable review patch. If anyone has any objections, please let me know.
------------------
From: Luiz Augusto von Dentz <[email protected]>
[ Upstream commit 15bf35a660eb82a49f8397fc3d3acada8dae13db ]
The code was printing skb->len and sdu_len in the places where it should be sdu_len and chan->imtu respectively to match the if conditions.
--- net/bluetooth/l2cap_core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
net/bluetooth/l2cap_core.c +1 -1
@@ -6733,7 +6733,7 @@ static int l2cap_ecred_data_rcv(struct l2cap_chan *chan, struct sk_buff *skb)if (sdu_len > chan->imtu) {BT_ERR ("Too big LE L2CAP SDU length: len %u > %u" , - skb->len, sdu_len); + sdu_len, chan->imtu);l2cap_send_disconn_req (chan,ECONNRESET ); err = -EMSGSIZE ; goto failed;
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 212/1146 Bluetooth: hci_ldisc: Clear HCI_UART_PROTO_INIT on error
In reply to Greg Kroah-Hartman7.0-stable review patch. If anyone has any objections, please let me know.
------------------
From: Jonathan Rissanen <[email protected]>
[ Upstream commit 68d39ea5e0adc9ecaea1ce8abd842ec972eb8718 ]
When hci_register_dev() fails in hci_uart_register_dev() HCI_UART_PROTO_INIT is not cleared before calling hu->proto->close(hu) and setting hu->hdev to NULL. This means incoming UART data will reach the protocol-specific recv handler in hci_uart_tty_receive() after resources are freed.
Clear HCI_UART_PROTO_INIT with a write lock before calling hu->proto->close() and setting hu->hdev to NULL. The write lock ensures all active readers have completed and no new reader can enter the protocol recv path before resources are freed.
This allows the protocol-specific recv functions to remove the "HCI_UART_REGISTERED" guard without risking a null pointer dereference if hci_register_dev() fails.
--- drivers/bluetooth/hci_ldisc.c | 3 +++ 1 file changed, 3 insertions(+)
drivers/bluetooth/hci_ldisc.c +3 -0
@@ -692,6 +692,9 @@ static int hci_uart_register_dev(struct hci_uart *hu)if (hci_register_dev (hdev) <0 ) {BT_ERR ("Can't register HCI device" ); +percpu_down_write (&hu->proto_lock); +clear_bit (HCI_UART_PROTO_INIT , &hu->flags); +percpu_up_write (&hu->proto_lock); hu->proto->close (hu); hu->hdev =NULL ;hci_free_dev (hdev);
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 213/1146 Bluetooth: fix locking in hci_conn_request_evt() with HCI_PROTO_DEFER
In reply to Greg Kroah-Hartman7.0-stable review patch. If anyone has any objections, please let me know.
------------------
From: Pauli Virtanen <[email protected]>
[ Upstream commit 5c7209a341ff2ac338b2b0375c34a307b37c9ac2 ]
When protocol sets HCI_PROTO_DEFER, hci_conn_request_evt() calls hci_connect_cfm(conn) without hdev->lock. Generally hci_connect_cfm() assumes it is held, and if conn is deleted concurrently -> UAF.
Only SCO and ISO set HCI_PROTO_DEFER and only for defer setup listen, and HCI_EV_CONN_REQUEST is not generated for ISO. In the non-deferred listening socket code paths, hci_connect_cfm(conn) is called with hdev->lock held.
Fix by holding the lock.
--- net/bluetooth/hci_event.c | 3 --- 1 file changed, 3 deletions(-)
net/bluetooth/hci_event.c +0 -3
@@ -3340,8 +3340,6 @@ static void hci_conn_request_evt(struct hci_dev *hdev, void *data,memcpy (conn->dev_class, ev->dev_class,3 ); -hci_dev_unlock (hdev); -if (ev->link_type ==ACL_LINK || (!(flags &HCI_PROTO_DEFER ) && !lmp_esco_capable (hdev))) {struct hci_cp_accept_conn_req cp;
@@ -3375,7 +3373,6 @@ static void hci_conn_request_evt(struct hci_dev *hdev, void *data,hci_connect_cfm (conn,0 ); } -return ; unlock:hci_dev_unlock (hdev); }
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 214/1146 Bluetooth: l2cap: Add missing chan lock in l2cap_ecred_reconf_rsp
In reply to Greg Kroah-Hartman7.0-stable review patch. If anyone has any objections, please let me know.
------------------
From: Dudu Lu <[email protected]>
[ Upstream commit 42776497cdbc9a665b384a6dcb85f0d4bd927eab ]
l2cap_ecred_reconf_rsp() calls l2cap_chan_del() without holding l2cap_chan_lock(). Every other l2cap_chan_del() caller in the file acquires the lock first. A remote BLE device can send a crafted L2CAP ECRED reconfiguration response to corrupt the channel list while another thread is iterating it.
Add l2cap_chan_hold() and l2cap_chan_lock() before l2cap_chan_del(), and l2cap_chan_unlock() and l2cap_chan_put() after, matching the pattern used in l2cap_ecred_conn_rsp() and l2cap_conn_del().
--- net/bluetooth/l2cap_core.c | 6 ++++++ 1 file changed, 6 insertions(+)
net/bluetooth/l2cap_core.c +6 -0
@@ -5473,7 +5473,13 @@ static inline int l2cap_ecred_reconf_rsp(struct l2cap_conn *conn,if (chan->ident != cmd->ident)continue ; +l2cap_chan_hold (chan); +l2cap_chan_lock (chan); +l2cap_chan_del (chan,ECONNRESET ); + +l2cap_chan_unlock (chan); +l2cap_chan_put (chan); }return 0 ;
Signature · 1 line
2.53.0