Commit 291abfea authored by Linus Torvalds's avatar Linus Torvalds
Browse files

Merge git://git.kernel.org/pub/scm/linux/kernel/git/netdev/net

Pull networking fixes from David Miller:

 1) Unbalanced locking in mwifiex_process_country_ie, from Brian Norris.

 2) Fix thermal zone registration in iwlwifi, from Andrei
    Otcheretianski.

 3) Fix double free_irq in sgi ioc3 eth, from Thomas Bogendoerfer.

 4) Use after free in mptcp, from Florian Westphal.

 5) Use after free in wireguard's root_remove_peer_lists, from Eric
    Dumazet.

 6) Properly access packets heads in bonding alb code, from Eric
    Dumazet.

 7) Fix data race in skb_queue_len(), from Qian Cai.

 8) Fix regression in r8169 on some chips, from Heiner Kallweit.

 9) Fix XDP program ref counting in hv_netvsc, from Haiyang Zhang.

10) Certain kinds of set link netlink operations can cause a NULL deref
    in the ipv6 addrconf code. Fix from Eric Dumazet.

11) Don't cancel uninitialized work queue in drop monitor, from Ido
    Schimmel.

* git://git.kernel.org/pub/scm/linux/kernel/git/netdev/net: (84 commits)
  net: thunderx: use proper interface type for RGMII
  mt76: mt7615: fix max_nss in mt7615_eeprom_parse_hw_cap
  bpf: Improve bucket_log calculation logic
  selftests/bpf: Test freeing sockmap/sockhash with a socket in it
  bpf, sockhash: Synchronize_rcu before free'ing map
  bpf, sockmap: Don't sleep while holding RCU lock on tear-down
  bpftool: Don't crash on missing xlated program instructions
  bpf, sockmap: Check update requirements after locking
  drop_monitor: Do not cancel uninitialized work item
  mlxsw: spectrum_dpipe: Add missing error path
  mlxsw: core: Add validation of hardware device types for MGPIR register
  mlxsw: spectrum_router: Clear offload indication from IPv6 nexthops on abort
  selftests: mlxsw: Add test cases for local table route replacement
  mlxsw: spectrum_router: Prevent incorrect replacement of local table routes
  net: dsa: microchip: enable module autoprobe
  ipv6/addrconf: fix potential NULL deref in inet6_set_link_af()
  dpaa_eth: support all modes with rate adapting PHYs
  net: stmmac: update pci platform data to use phy_interface
  net: stmmac: xgmac: fix missing IFF_MULTICAST checki in dwxgmac2_set_filter
  net: stmmac: fix missing IFF_MULTICAST check in dwmac4_set_filter
  ...
parents d4f309ca 29ca3b31
......@@ -205,9 +205,15 @@ void iwl_mvm_mac_mgd_protect_tdls_discover(struct ieee80211_hw *hw,
struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
u32 duration = 2 * vif->bss_conf.dtim_period * vif->bss_conf.beacon_int;
mutex_lock(&mvm->mutex);
/* Protect the session to hear the TDLS setup response on the channel */
iwl_mvm_protect_session(mvm, vif, duration, duration, 100, true);
mutex_lock(&mvm->mutex);
if (fw_has_capa(&mvm->fw->ucode_capa,
IWL_UCODE_TLV_CAPA_SESSION_PROT_CMD))
iwl_mvm_schedule_session_protection(mvm, vif, duration,
duration, true);
else
iwl_mvm_protect_session(mvm, vif, duration,
duration, 100, true);
mutex_unlock(&mvm->mutex);
}
......
......@@ -1056,13 +1056,42 @@ int iwl_mvm_schedule_csa_period(struct iwl_mvm *mvm,
return iwl_mvm_time_event_send_add(mvm, vif, te_data, &time_cmd);
}
static bool iwl_mvm_session_prot_notif(struct iwl_notif_wait_data *notif_wait,
struct iwl_rx_packet *pkt, void *data)
{
struct iwl_mvm *mvm =
container_of(notif_wait, struct iwl_mvm, notif_wait);
struct iwl_mvm_session_prot_notif *resp;
int resp_len = iwl_rx_packet_payload_len(pkt);
if (WARN_ON(pkt->hdr.cmd != SESSION_PROTECTION_NOTIF ||
pkt->hdr.group_id != MAC_CONF_GROUP))
return true;
if (WARN_ON_ONCE(resp_len != sizeof(*resp))) {
IWL_ERR(mvm, "Invalid SESSION_PROTECTION_NOTIF response\n");
return true;
}
resp = (void *)pkt->data;
if (!resp->status)
IWL_ERR(mvm,
"TIME_EVENT_NOTIFICATION received but not executed\n");
return true;
}
void iwl_mvm_schedule_session_protection(struct iwl_mvm *mvm,
struct ieee80211_vif *vif,
u32 duration, u32 min_duration)
u32 duration, u32 min_duration,
bool wait_for_notif)
{
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
struct iwl_mvm_time_event_data *te_data = &mvmvif->time_event_data;
const u16 notif[] = { iwl_cmd_id(SESSION_PROTECTION_NOTIF,
MAC_CONF_GROUP, 0) };
struct iwl_notification_wait wait_notif;
struct iwl_mvm_session_prot_cmd cmd = {
.id_and_color =
cpu_to_le32(FW_CMD_ID_AND_COLOR(mvmvif->id,
......@@ -1071,7 +1100,6 @@ void iwl_mvm_schedule_session_protection(struct iwl_mvm *mvm,
.conf_id = cpu_to_le32(SESSION_PROTECT_CONF_ASSOC),
.duration_tu = cpu_to_le32(MSEC_TO_TU(duration)),
};
int ret;
lockdep_assert_held(&mvm->mutex);
......@@ -1092,14 +1120,35 @@ void iwl_mvm_schedule_session_protection(struct iwl_mvm *mvm,
IWL_DEBUG_TE(mvm, "Add new session protection, duration %d TU\n",
le32_to_cpu(cmd.duration_tu));
ret = iwl_mvm_send_cmd_pdu(mvm, iwl_cmd_id(SESSION_PROTECTION_CMD,
MAC_CONF_GROUP, 0),
0, sizeof(cmd), &cmd);
if (ret) {
if (!wait_for_notif) {
if (iwl_mvm_send_cmd_pdu(mvm,
iwl_cmd_id(SESSION_PROTECTION_CMD,
MAC_CONF_GROUP, 0),
0, sizeof(cmd), &cmd)) {
IWL_ERR(mvm,
"Couldn't send the SESSION_PROTECTION_CMD\n");
spin_lock_bh(&mvm->time_event_lock);
iwl_mvm_te_clear_data(mvm, te_data);
spin_unlock_bh(&mvm->time_event_lock);
}
return;
}
iwl_init_notification_wait(&mvm->notif_wait, &wait_notif,
notif, ARRAY_SIZE(notif),
iwl_mvm_session_prot_notif, NULL);
if (iwl_mvm_send_cmd_pdu(mvm,
iwl_cmd_id(SESSION_PROTECTION_CMD,
MAC_CONF_GROUP, 0),
0, sizeof(cmd), &cmd)) {
IWL_ERR(mvm,
"Couldn't send the SESSION_PROTECTION_CMD: %d\n", ret);
spin_lock_bh(&mvm->time_event_lock);
iwl_mvm_te_clear_data(mvm, te_data);
spin_unlock_bh(&mvm->time_event_lock);
"Couldn't send the SESSION_PROTECTION_CMD\n");
iwl_remove_notification(&mvm->notif_wait, &wait_notif);
} else if (iwl_wait_notification(&mvm->notif_wait, &wait_notif,
TU_TO_JIFFIES(100))) {
IWL_ERR(mvm,
"Failed to protect session until session protection\n");
}
}
......@@ -250,10 +250,12 @@ iwl_mvm_te_scheduled(struct iwl_mvm_time_event_data *te_data)
* @mvm: the mvm component
* @vif: the virtual interface for which the protection issued
* @duration: the duration of the protection
* @wait_for_notif: if true, will block until the start of the protection
*/
void iwl_mvm_schedule_session_protection(struct iwl_mvm *mvm,
struct ieee80211_vif *vif,
u32 duration, u32 min_duration);
u32 duration, u32 min_duration,
bool wait_for_notif);
/**
* iwl_mvm_rx_session_protect_notif - handles %SESSION_PROTECTION_NOTIF
......
......@@ -8,7 +8,7 @@
* Copyright(c) 2013 - 2014, 2019 Intel Corporation. All rights reserved.
* Copyright(c) 2013 - 2014 Intel Mobile Communications GmbH
* Copyright(c) 2015 - 2016 Intel Deutschland GmbH
* Copyright(c) 2019 Intel Corporation
* Copyright(c) 2019 - 2020 Intel Corporation
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of version 2 of the GNU General Public License as
......@@ -31,7 +31,7 @@
* Copyright(c) 2012 - 2014, 2019 Intel Corporation. All rights reserved.
* Copyright(c) 2013 - 2014 Intel Mobile Communications GmbH
* Copyright(c) 2015 - 2016 Intel Deutschland GmbH
* Copyright(c) 2019 Intel Corporation
* Copyright(c) 2019 - 2020 Intel Corporation
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
......@@ -234,7 +234,7 @@ static int iwl_mvm_get_temp_cmd(struct iwl_mvm *mvm)
.flags = cpu_to_le32(DTS_TRIGGER_CMD_FLAGS_TEMP),
};
struct iwl_ext_dts_measurement_cmd extcmd = {
.control_mode = cpu_to_le32(DTS_AUTOMATIC),
.control_mode = cpu_to_le32(DTS_DIRECT_WITHOUT_MEASURE),
};
u32 cmdid;
......@@ -734,7 +734,8 @@ static struct thermal_zone_device_ops tzone_ops = {
static void iwl_mvm_thermal_zone_register(struct iwl_mvm *mvm)
{
int i;
char name[] = "iwlwifi";
char name[16];
static atomic_t counter = ATOMIC_INIT(0);
if (!iwl_mvm_is_tt_in_fw(mvm)) {
mvm->tz_device.tzone = NULL;
......@@ -744,6 +745,7 @@ static void iwl_mvm_thermal_zone_register(struct iwl_mvm *mvm)
BUILD_BUG_ON(ARRAY_SIZE(name) >= THERMAL_NAME_LENGTH);
sprintf(name, "iwlwifi_%u", atomic_inc_return(&counter) & 0xFF);
mvm->tz_device.tzone = thermal_zone_device_register(name,
IWL_MAX_DTS_TRIPS,
IWL_WRITABLE_TRIPS_MSK,
......
......@@ -1785,6 +1785,8 @@ static int lbs_ibss_join_existing(struct lbs_private *priv,
rates_max = rates_eid[1];
if (rates_max > MAX_RATES) {
lbs_deb_join("invalid rates");
rcu_read_unlock();
ret = -EINVAL;
goto out;
}
rates = cmd.bss.rates;
......
......@@ -2884,6 +2884,13 @@ mwifiex_cmd_append_vsie_tlv(struct mwifiex_private *priv,
vs_param_set->header.len =
cpu_to_le16((((u16) priv->vs_ie[id].ie[1])
& 0x00FF) + 2);
if (le16_to_cpu(vs_param_set->header.len) >
MWIFIEX_MAX_VSIE_LEN) {
mwifiex_dbg(priv->adapter, ERROR,
"Invalid param length!\n");
break;
}
memcpy(vs_param_set->ie, priv->vs_ie[id].ie,
le16_to_cpu(vs_param_set->header.len));
*buffer += le16_to_cpu(vs_param_set->header.len) +
......
......@@ -232,6 +232,7 @@ static int mwifiex_process_country_ie(struct mwifiex_private *priv,
if (country_ie_len >
(IEEE80211_COUNTRY_STRING_LEN + MWIFIEX_MAX_TRIPLET_802_11D)) {
rcu_read_unlock();
mwifiex_dbg(priv->adapter, ERROR,
"11D: country_ie_len overflow!, deauth AP\n");
return -EINVAL;
......
......@@ -970,6 +970,10 @@ int mwifiex_ret_wmm_get_status(struct mwifiex_private *priv,
"WMM Parameter Set Count: %d\n",
wmm_param_ie->qos_info_bitmap & mask);
if (wmm_param_ie->vend_hdr.len + 2 >
sizeof(struct ieee_types_wmm_parameter))
break;
memcpy((u8 *) &priv->curr_bss_params.bss_descriptor.
wmm_ie, wmm_param_ie,
wmm_param_ie->vend_hdr.len + 2);
......
......@@ -92,8 +92,9 @@ static int mt7615_check_eeprom(struct mt76_dev *dev)
static void mt7615_eeprom_parse_hw_cap(struct mt7615_dev *dev)
{
u8 val, *eeprom = dev->mt76.eeprom.data;
u8 *eeprom = dev->mt76.eeprom.data;
u8 tx_mask, rx_mask, max_nss;
u32 val;
val = FIELD_GET(MT_EE_NIC_WIFI_CONF_BAND_SEL,
eeprom[MT_EE_WIFI_CONF]);
......
......@@ -281,27 +281,26 @@ static void rtw_wow_rx_dma_start(struct rtw_dev *rtwdev)
rtw_write32_clr(rtwdev, REG_RXPKT_NUM, BIT_RW_RELEASE);
}
static bool rtw_wow_check_fw_status(struct rtw_dev *rtwdev, bool wow_enable)
static int rtw_wow_check_fw_status(struct rtw_dev *rtwdev, bool wow_enable)
{
bool ret;
/* wait 100ms for wow firmware to finish work */
msleep(100);
if (wow_enable) {
if (!rtw_read8(rtwdev, REG_WOWLAN_WAKE_REASON))
ret = 0;
if (rtw_read8(rtwdev, REG_WOWLAN_WAKE_REASON))
goto wow_fail;
} else {
if (rtw_read32_mask(rtwdev, REG_FE1IMR, BIT_FS_RXDONE) == 0 &&
rtw_read32_mask(rtwdev, REG_RXPKT_NUM, BIT_RW_RELEASE) == 0)
ret = 0;
if (rtw_read32_mask(rtwdev, REG_FE1IMR, BIT_FS_RXDONE) ||
rtw_read32_mask(rtwdev, REG_RXPKT_NUM, BIT_RW_RELEASE))
goto wow_fail;
}
if (ret)
rtw_err(rtwdev, "failed to check wow status %s\n",
wow_enable ? "enabled" : "disabled");
return 0;
return ret;
wow_fail:
rtw_err(rtwdev, "failed to check wow status %s\n",
wow_enable ? "enabled" : "disabled");
return -EBUSY;
}
static void rtw_wow_fw_security_type_iter(struct ieee80211_hw *hw,
......
......@@ -728,7 +728,7 @@ struct bpf_struct_ops {
#if defined(CONFIG_BPF_JIT) && defined(CONFIG_BPF_SYSCALL)
#define BPF_MODULE_OWNER ((void *)((0xeB9FUL << 2) + POISON_POINTER_DELTA))
const struct bpf_struct_ops *bpf_struct_ops_find(u32 type_id);
void bpf_struct_ops_init(struct btf *btf);
void bpf_struct_ops_init(struct btf *btf, struct bpf_verifier_log *log);
bool bpf_struct_ops_get(const void *kdata);
void bpf_struct_ops_put(const void *kdata);
int bpf_struct_ops_map_sys_lookup_elem(struct bpf_map *map, void *key,
......@@ -752,7 +752,10 @@ static inline const struct bpf_struct_ops *bpf_struct_ops_find(u32 type_id)
{
return NULL;
}
static inline void bpf_struct_ops_init(struct btf *btf) { }
static inline void bpf_struct_ops_init(struct btf *btf,
struct bpf_verifier_log *log)
{
}
static inline bool bpf_try_module_get(const void *data, struct module *owner)
{
return try_module_get(owner);
......
......@@ -1448,14 +1448,15 @@ struct mlx5_ifc_cmd_hca_cap_bits {
u8 reserved_at_440[0x20];
u8 tls[0x1];
u8 reserved_at_461[0x2];
u8 reserved_at_460[0x3];
u8 log_max_uctx[0x5];
u8 reserved_at_468[0x3];
u8 log_max_umem[0x5];
u8 max_num_eqs[0x10];
u8 reserved_at_480[0x3];
u8 reserved_at_480[0x1];
u8 tls_tx[0x1];
u8 reserved_at_482[0x1];
u8 log_max_l2_table[0x5];
u8 reserved_at_488[0x8];
u8 log_uar_page_sz[0x10];
......
......@@ -19,7 +19,7 @@
#ifndef __B53_H
#define __B53_H
#include <linux/kernel.h>
#include <linux/types.h>
#include <linux/platform_data/dsa.h>
struct b53_platform_data {
......
......@@ -19,7 +19,7 @@
#ifndef __MICROCHIP_KSZ_H
#define __MICROCHIP_KSZ_H
#include <linux/kernel.h>
#include <linux/types.h>
struct ksz_platform_data {
u32 chip_id;
......
......@@ -1821,6 +1821,18 @@ static inline __u32 skb_queue_len(const struct sk_buff_head *list_)
return list_->qlen;
}
/**
* skb_queue_len_lockless - get queue length
* @list_: list to measure
*
* Return the length of an &sk_buff queue.
* This variant can be used in lockless contexts.
*/
static inline __u32 skb_queue_len_lockless(const struct sk_buff_head *list_)
{
return READ_ONCE(list_->qlen);
}
/**
* __skb_queue_head_init - initialize non-spinlock portions of sk_buff_head
* @list: queue to initialize
......@@ -2026,7 +2038,7 @@ static inline void __skb_unlink(struct sk_buff *skb, struct sk_buff_head *list)
{
struct sk_buff *next, *prev;
list->qlen--;
WRITE_ONCE(list->qlen, list->qlen - 1);
next = skb->next;
prev = skb->prev;
skb->next = skb->prev = NULL;
......
......@@ -47,11 +47,6 @@ struct ipxhdr {
/* From af_ipx.c */
extern int sysctl_ipx_pprop_broadcasting;
static __inline__ struct ipxhdr *ipx_hdr(struct sk_buff *skb)
{
return (struct ipxhdr *)skb_transport_header(skb);
}
struct ipx_interface {
/* IPX address */
__be32 if_netnum;
......
......@@ -96,12 +96,11 @@ const struct bpf_prog_ops bpf_struct_ops_prog_ops = {
static const struct btf_type *module_type;
void bpf_struct_ops_init(struct btf *btf)
void bpf_struct_ops_init(struct btf *btf, struct bpf_verifier_log *log)
{
s32 type_id, value_id, module_id;
const struct btf_member *member;
struct bpf_struct_ops *st_ops;
struct bpf_verifier_log log = {};
const struct btf_type *t;
char value_name[128];
const char *mname;
......@@ -172,7 +171,7 @@ void bpf_struct_ops_init(struct btf *btf)
member->type,
NULL);
if (func_proto &&
btf_distill_func_proto(&log, btf,
btf_distill_func_proto(log, btf,
func_proto, mname,
&st_ops->func_models[j])) {
pr_warn("Error in parsing func ptr %s in struct %s\n",
......
......@@ -3643,7 +3643,7 @@ struct btf *btf_parse_vmlinux(void)
goto errout;
}
bpf_struct_ops_init(btf);
bpf_struct_ops_init(btf, log);
btf_verifier_env_free(env);
refcount_set(&btf->refcnt, 1);
......@@ -3931,6 +3931,7 @@ again:
if (btf_type_is_ptr(mtype)) {
const struct btf_type *stype;
u32 id;
if (msize != size || off != moff) {
bpf_log(log,
......@@ -3939,12 +3940,9 @@ again:
return -EACCES;
}
stype = btf_type_by_id(btf_vmlinux, mtype->type);
/* skip modifiers */
while (btf_type_is_modifier(stype))
stype = btf_type_by_id(btf_vmlinux, stype->type);
stype = btf_type_skip_modifiers(btf_vmlinux, mtype->type, &id);
if (btf_type_is_struct(stype)) {
*next_btf_id = mtype->type;
*next_btf_id = id;
return PTR_TO_BTF_ID;
}
}
......
......@@ -643,9 +643,10 @@ static struct bpf_map *bpf_sk_storage_map_alloc(union bpf_attr *attr)
return ERR_PTR(-ENOMEM);
bpf_map_init_from_attr(&smap->map, attr);
nbuckets = roundup_pow_of_two(num_possible_cpus());
/* Use at least 2 buckets, select_bucket() is undefined behavior with 1 bucket */
smap->bucket_log = max_t(u32, 1, ilog2(roundup_pow_of_two(num_possible_cpus())));
nbuckets = 1U << smap->bucket_log;
nbuckets = max_t(u32, 2, nbuckets);
smap->bucket_log = ilog2(nbuckets);
cost = sizeof(*smap->buckets) * nbuckets + sizeof(*smap);
ret = bpf_map_charge_init(&smap->map.memory, cost);
......
......@@ -3986,6 +3986,12 @@ static int devlink_nl_cmd_region_read_dumpit(struct sk_buff *skb,
goto out_unlock;
}
/* return 0 if there is no further data to read */
if (start_offset >= region->size) {
err = 0;
goto out_unlock;
}
hdr = genlmsg_put(skb, NETLINK_CB(cb->skb).portid, cb->nlh->nlmsg_seq,
&devlink_nl_family, NLM_F_ACK | NLM_F_MULTI,
DEVLINK_CMD_REGION_READ);
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment