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

Pull networking fixes from David Miller:

 1) Fix memory leak in vti6, from Torsten Hilbrich.

 2) Fix double free in xfrm_policy_timer, from YueHaibing.

 3) NL80211_ATTR_CHANNEL_WIDTH attribute is put with wrong type, from
    Johannes Berg.

 4) Wrong allocation failure check in qlcnic driver, from Xu Wang.

 5) Get ks8851-ml IO operations right, for real this time, from Marek
    Vasut.

* git://git.kernel.org/pub/scm/linux/kernel/git/netdev/net: (22 commits)
  r8169: fix PHY driver check on platforms w/o module softdeps
  net: ks8851-ml: Fix IO operations, again
  mlxsw: spectrum_mr: Fix list iteration in error path
  qlcnic: Fix bad kzalloc null test
  mac80211: set IEEE80211_TX_CTRL_PORT_CTRL_PROTO for nl80211 TX
  mac80211: mark station unauthorized before key removal
  mac80211: Check port authorization in the ieee80211_tx_dequeue() case
  cfg80211: Do not warn on same channel at the end of CSA
  mac80211: drop data frames without key on encrypted links
  ieee80211: fix HE SPR size calculation
  nl80211: fix NL80211_ATTR_CHANNEL_WIDTH attribute type
  xfrm: policy: Fix doulbe free in xfrm_policy_timer
  bpf: Explicitly memset some bpf info structures declared on the stack
  bpf: Explicitly memset the bpf_attr structure
  bpf: Sanitize the bpf_struct_ops tcp-cc name
  vti6: Fix memory leak of skb if input policy check fails
  esp: remove the skb from the chain when it's enqueued in cryptd_wq
  ipv6: xfrm6_tunnel.c: Use built-in RCU list checking
  xfrm: add the missing verify_sec_ctx_len check in xfrm_add_acquire
  xfrm: fix uctx len check in verify_sec_ctx_len
  ...
This commit is contained in:
Linus Torvalds 2020-03-28 18:55:15 -07:00
commit e595dd9451
23 changed files with 220 additions and 79 deletions

View File

@ -637,12 +637,12 @@ static int mlxsw_sp_mr_vif_resolve(struct mlxsw_sp_mr_table *mr_table,
return 0; return 0;
err_erif_unresolve: err_erif_unresolve:
list_for_each_entry_from_reverse(erve, &mr_vif->route_evif_list, list_for_each_entry_continue_reverse(erve, &mr_vif->route_evif_list,
vif_node) vif_node)
mlxsw_sp_mr_route_evif_unresolve(mr_table, erve); mlxsw_sp_mr_route_evif_unresolve(mr_table, erve);
err_irif_unresolve: err_irif_unresolve:
list_for_each_entry_from_reverse(irve, &mr_vif->route_ivif_list, list_for_each_entry_continue_reverse(irve, &mr_vif->route_ivif_list,
vif_node) vif_node)
mlxsw_sp_mr_route_ivif_unresolve(mr_table, irve); mlxsw_sp_mr_route_ivif_unresolve(mr_table, irve);
mr_vif->rif = NULL; mr_vif->rif = NULL;
return err; return err;

View File

@ -156,6 +156,50 @@ static int msg_enable;
* chip is busy transferring packet data (RX/TX FIFO accesses). * chip is busy transferring packet data (RX/TX FIFO accesses).
*/ */
/**
* ks_check_endian - Check whether endianness of the bus is correct
* @ks : The chip information
*
* The KS8851-16MLL EESK pin allows selecting the endianness of the 16bit
* bus. To maintain optimum performance, the bus endianness should be set
* such that it matches the endianness of the CPU.
*/
static int ks_check_endian(struct ks_net *ks)
{
u16 cider;
/*
* Read CIDER register first, however read it the "wrong" way around.
* If the endian strap on the KS8851-16MLL in incorrect and the chip
* is operating in different endianness than the CPU, then the meaning
* of BE[3:0] byte-enable bits is also swapped such that:
* BE[3,2,1,0] becomes BE[1,0,3,2]
*
* Luckily for us, the byte-enable bits are the top four MSbits of
* the address register and the CIDER register is at offset 0xc0.
* Hence, by reading address 0xc0c0, which is not impacted by endian
* swapping, we assert either BE[3:2] or BE[1:0] while reading the
* CIDER register.
*
* If the bus configuration is correct, reading 0xc0c0 asserts
* BE[3:2] and this read returns 0x0000, because to read register
* with bottom two LSbits of address set to 0, BE[1:0] must be
* asserted.
*
* If the bus configuration is NOT correct, reading 0xc0c0 asserts
* BE[1:0] and this read returns non-zero 0x8872 value.
*/
iowrite16(BE3 | BE2 | KS_CIDER, ks->hw_addr_cmd);
cider = ioread16(ks->hw_addr);
if (!cider)
return 0;
netdev_err(ks->netdev, "incorrect EESK endian strap setting\n");
return -EINVAL;
}
/** /**
* ks_rdreg16 - read 16 bit register from device * ks_rdreg16 - read 16 bit register from device
* @ks : The chip information * @ks : The chip information
@ -166,7 +210,7 @@ static int msg_enable;
static u16 ks_rdreg16(struct ks_net *ks, int offset) static u16 ks_rdreg16(struct ks_net *ks, int offset)
{ {
ks->cmd_reg_cache = (u16)offset | ((BE3 | BE2) >> (offset & 0x02)); ks->cmd_reg_cache = (u16)offset | ((BE1 | BE0) << (offset & 0x02));
iowrite16(ks->cmd_reg_cache, ks->hw_addr_cmd); iowrite16(ks->cmd_reg_cache, ks->hw_addr_cmd);
return ioread16(ks->hw_addr); return ioread16(ks->hw_addr);
} }
@ -181,7 +225,7 @@ static u16 ks_rdreg16(struct ks_net *ks, int offset)
static void ks_wrreg16(struct ks_net *ks, int offset, u16 value) static void ks_wrreg16(struct ks_net *ks, int offset, u16 value)
{ {
ks->cmd_reg_cache = (u16)offset | ((BE3 | BE2) >> (offset & 0x02)); ks->cmd_reg_cache = (u16)offset | ((BE1 | BE0) << (offset & 0x02));
iowrite16(ks->cmd_reg_cache, ks->hw_addr_cmd); iowrite16(ks->cmd_reg_cache, ks->hw_addr_cmd);
iowrite16(value, ks->hw_addr); iowrite16(value, ks->hw_addr);
} }
@ -197,7 +241,7 @@ static inline void ks_inblk(struct ks_net *ks, u16 *wptr, u32 len)
{ {
len >>= 1; len >>= 1;
while (len--) while (len--)
*wptr++ = be16_to_cpu(ioread16(ks->hw_addr)); *wptr++ = (u16)ioread16(ks->hw_addr);
} }
/** /**
@ -211,7 +255,7 @@ static inline void ks_outblk(struct ks_net *ks, u16 *wptr, u32 len)
{ {
len >>= 1; len >>= 1;
while (len--) while (len--)
iowrite16(cpu_to_be16(*wptr++), ks->hw_addr); iowrite16(*wptr++, ks->hw_addr);
} }
static void ks_disable_int(struct ks_net *ks) static void ks_disable_int(struct ks_net *ks)
@ -1218,6 +1262,10 @@ static int ks8851_probe(struct platform_device *pdev)
goto err_free; goto err_free;
} }
err = ks_check_endian(ks);
if (err)
goto err_free;
netdev->irq = platform_get_irq(pdev, 0); netdev->irq = platform_get_irq(pdev, 0);
if ((int)netdev->irq < 0) { if ((int)netdev->irq < 0) {

View File

@ -1720,7 +1720,7 @@ static int qlcnic_83xx_get_reset_instruction_template(struct qlcnic_adapter *p_d
ahw->reset.seq_error = 0; ahw->reset.seq_error = 0;
ahw->reset.buff = kzalloc(QLC_83XX_RESTART_TEMPLATE_SIZE, GFP_KERNEL); ahw->reset.buff = kzalloc(QLC_83XX_RESTART_TEMPLATE_SIZE, GFP_KERNEL);
if (p_dev->ahw->reset.buff == NULL) if (ahw->reset.buff == NULL)
return -ENOMEM; return -ENOMEM;
p_buff = p_dev->ahw->reset.buff; p_buff = p_dev->ahw->reset.buff;

View File

@ -5285,6 +5285,13 @@ static int r8169_mdio_register(struct rtl8169_private *tp)
if (!tp->phydev) { if (!tp->phydev) {
mdiobus_unregister(new_bus); mdiobus_unregister(new_bus);
return -ENODEV; return -ENODEV;
} else if (!tp->phydev->drv) {
/* Most chip versions fail with the genphy driver.
* Therefore ensure that the dedicated PHY driver is loaded.
*/
dev_err(&pdev->dev, "realtek.ko not loaded, maybe it needs to be added to initramfs?\n");
mdiobus_unregister(new_bus);
return -EUNATCH;
} }
/* PHY will be woken up in rtl_open() */ /* PHY will be woken up in rtl_open() */
@ -5446,15 +5453,6 @@ static int rtl_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
int chipset, region; int chipset, region;
int jumbo_max, rc; int jumbo_max, rc;
/* Some tools for creating an initramfs don't consider softdeps, then
* r8169.ko may be in initramfs, but realtek.ko not. Then the generic
* PHY driver is used that doesn't work with most chip versions.
*/
if (!driver_find("RTL8201CP Ethernet", &mdio_bus_type)) {
dev_err(&pdev->dev, "realtek.ko not loaded, maybe it needs to be added to initramfs?\n");
return -ENOENT;
}
dev = devm_alloc_etherdev(&pdev->dev, sizeof (*tp)); dev = devm_alloc_etherdev(&pdev->dev, sizeof (*tp));
if (!dev) if (!dev)
return -ENOMEM; return -ENOMEM;

View File

@ -160,6 +160,7 @@ static inline void copy_map_value(struct bpf_map *map, void *dst, void *src)
} }
void copy_map_value_locked(struct bpf_map *map, void *dst, void *src, void copy_map_value_locked(struct bpf_map *map, void *dst, void *src,
bool lock_src); bool lock_src);
int bpf_obj_name_cpy(char *dst, const char *src, unsigned int size);
struct bpf_offload_dev; struct bpf_offload_dev;
struct bpf_offloaded_map; struct bpf_offloaded_map;

View File

@ -2102,14 +2102,14 @@ ieee80211_he_spr_size(const u8 *he_spr_ie)
{ {
struct ieee80211_he_spr *he_spr = (void *)he_spr_ie; struct ieee80211_he_spr *he_spr = (void *)he_spr_ie;
u8 spr_len = sizeof(struct ieee80211_he_spr); u8 spr_len = sizeof(struct ieee80211_he_spr);
u32 he_spr_params; u8 he_spr_params;
/* Make sure the input is not NULL */ /* Make sure the input is not NULL */
if (!he_spr_ie) if (!he_spr_ie)
return 0; return 0;
/* Calc required length */ /* Calc required length */
he_spr_params = le32_to_cpu(he_spr->he_sr_control); he_spr_params = he_spr->he_sr_control;
if (he_spr_params & IEEE80211_HE_SPR_NON_SRG_OFFSET_PRESENT) if (he_spr_params & IEEE80211_HE_SPR_NON_SRG_OFFSET_PRESENT)
spr_len++; spr_len++;
if (he_spr_params & IEEE80211_HE_SPR_SRG_INFORMATION_PRESENT) if (he_spr_params & IEEE80211_HE_SPR_SRG_INFORMATION_PRESENT)

View File

@ -4564,7 +4564,7 @@ int btf_get_info_by_fd(const struct btf *btf,
union bpf_attr __user *uattr) union bpf_attr __user *uattr)
{ {
struct bpf_btf_info __user *uinfo; struct bpf_btf_info __user *uinfo;
struct bpf_btf_info info = {}; struct bpf_btf_info info;
u32 info_copy, btf_copy; u32 info_copy, btf_copy;
void __user *ubtf; void __user *ubtf;
u32 uinfo_len; u32 uinfo_len;
@ -4573,6 +4573,7 @@ int btf_get_info_by_fd(const struct btf *btf,
uinfo_len = attr->info.info_len; uinfo_len = attr->info.info_len;
info_copy = min_t(u32, uinfo_len, sizeof(info)); info_copy = min_t(u32, uinfo_len, sizeof(info));
memset(&info, 0, sizeof(info));
if (copy_from_user(&info, uinfo, info_copy)) if (copy_from_user(&info, uinfo, info_copy))
return -EFAULT; return -EFAULT;

View File

@ -696,14 +696,15 @@ int bpf_get_file_flag(int flags)
offsetof(union bpf_attr, CMD##_LAST_FIELD) - \ offsetof(union bpf_attr, CMD##_LAST_FIELD) - \
sizeof(attr->CMD##_LAST_FIELD)) != NULL sizeof(attr->CMD##_LAST_FIELD)) != NULL
/* dst and src must have at least BPF_OBJ_NAME_LEN number of bytes. /* dst and src must have at least "size" number of bytes.
* Return 0 on success and < 0 on error. * Return strlen on success and < 0 on error.
*/ */
static int bpf_obj_name_cpy(char *dst, const char *src) int bpf_obj_name_cpy(char *dst, const char *src, unsigned int size)
{ {
const char *end = src + BPF_OBJ_NAME_LEN; const char *end = src + size;
const char *orig_src = src;
memset(dst, 0, BPF_OBJ_NAME_LEN); memset(dst, 0, size);
/* Copy all isalnum(), '_' and '.' chars. */ /* Copy all isalnum(), '_' and '.' chars. */
while (src < end && *src) { while (src < end && *src) {
if (!isalnum(*src) && if (!isalnum(*src) &&
@ -712,11 +713,11 @@ static int bpf_obj_name_cpy(char *dst, const char *src)
*dst++ = *src++; *dst++ = *src++;
} }
/* No '\0' found in BPF_OBJ_NAME_LEN number of bytes */ /* No '\0' found in "size" number of bytes */
if (src == end) if (src == end)
return -EINVAL; return -EINVAL;
return 0; return src - orig_src;
} }
int map_check_no_btf(const struct bpf_map *map, int map_check_no_btf(const struct bpf_map *map,
@ -810,8 +811,9 @@ static int map_create(union bpf_attr *attr)
if (IS_ERR(map)) if (IS_ERR(map))
return PTR_ERR(map); return PTR_ERR(map);
err = bpf_obj_name_cpy(map->name, attr->map_name); err = bpf_obj_name_cpy(map->name, attr->map_name,
if (err) sizeof(attr->map_name));
if (err < 0)
goto free_map; goto free_map;
atomic64_set(&map->refcnt, 1); atomic64_set(&map->refcnt, 1);
@ -2098,8 +2100,9 @@ static int bpf_prog_load(union bpf_attr *attr, union bpf_attr __user *uattr)
goto free_prog; goto free_prog;
prog->aux->load_time = ktime_get_boottime_ns(); prog->aux->load_time = ktime_get_boottime_ns();
err = bpf_obj_name_cpy(prog->aux->name, attr->prog_name); err = bpf_obj_name_cpy(prog->aux->name, attr->prog_name,
if (err) sizeof(attr->prog_name));
if (err < 0)
goto free_prog; goto free_prog;
/* run eBPF verifier */ /* run eBPF verifier */
@ -2792,7 +2795,7 @@ static int bpf_prog_get_info_by_fd(struct bpf_prog *prog,
union bpf_attr __user *uattr) union bpf_attr __user *uattr)
{ {
struct bpf_prog_info __user *uinfo = u64_to_user_ptr(attr->info.info); struct bpf_prog_info __user *uinfo = u64_to_user_ptr(attr->info.info);
struct bpf_prog_info info = {}; struct bpf_prog_info info;
u32 info_len = attr->info.info_len; u32 info_len = attr->info.info_len;
struct bpf_prog_stats stats; struct bpf_prog_stats stats;
char __user *uinsns; char __user *uinsns;
@ -2804,6 +2807,7 @@ static int bpf_prog_get_info_by_fd(struct bpf_prog *prog,
return err; return err;
info_len = min_t(u32, sizeof(info), info_len); info_len = min_t(u32, sizeof(info), info_len);
memset(&info, 0, sizeof(info));
if (copy_from_user(&info, uinfo, info_len)) if (copy_from_user(&info, uinfo, info_len))
return -EFAULT; return -EFAULT;
@ -3067,7 +3071,7 @@ static int bpf_map_get_info_by_fd(struct bpf_map *map,
union bpf_attr __user *uattr) union bpf_attr __user *uattr)
{ {
struct bpf_map_info __user *uinfo = u64_to_user_ptr(attr->info.info); struct bpf_map_info __user *uinfo = u64_to_user_ptr(attr->info.info);
struct bpf_map_info info = {}; struct bpf_map_info info;
u32 info_len = attr->info.info_len; u32 info_len = attr->info.info_len;
int err; int err;
@ -3076,6 +3080,7 @@ static int bpf_map_get_info_by_fd(struct bpf_map *map,
return err; return err;
info_len = min_t(u32, sizeof(info), info_len); info_len = min_t(u32, sizeof(info), info_len);
memset(&info, 0, sizeof(info));
info.type = map->map_type; info.type = map->map_type;
info.id = map->id; info.id = map->id;
info.key_size = map->key_size; info.key_size = map->key_size;
@ -3359,7 +3364,7 @@ err_put:
SYSCALL_DEFINE3(bpf, int, cmd, union bpf_attr __user *, uattr, unsigned int, size) SYSCALL_DEFINE3(bpf, int, cmd, union bpf_attr __user *, uattr, unsigned int, size)
{ {
union bpf_attr attr = {}; union bpf_attr attr;
int err; int err;
if (sysctl_unprivileged_bpf_disabled && !capable(CAP_SYS_ADMIN)) if (sysctl_unprivileged_bpf_disabled && !capable(CAP_SYS_ADMIN))
@ -3371,6 +3376,7 @@ SYSCALL_DEFINE3(bpf, int, cmd, union bpf_attr __user *, uattr, unsigned int, siz
size = min_t(u32, size, sizeof(attr)); size = min_t(u32, size, sizeof(attr));
/* copy attributes from user space, may be less than sizeof(bpf_attr) */ /* copy attributes from user space, may be less than sizeof(bpf_attr) */
memset(&attr, 0, sizeof(attr));
if (copy_from_user(&attr, uattr, size) != 0) if (copy_from_user(&attr, uattr, size) != 0)
return -EFAULT; return -EFAULT;

View File

@ -303,6 +303,7 @@ config SYN_COOKIES
config NET_IPVTI config NET_IPVTI
tristate "Virtual (secure) IP: tunneling" tristate "Virtual (secure) IP: tunneling"
depends on IPV6 || IPV6=n
select INET_TUNNEL select INET_TUNNEL
select NET_IP_TUNNEL select NET_IP_TUNNEL
select XFRM select XFRM

View File

@ -184,7 +184,6 @@ static int bpf_tcp_ca_init_member(const struct btf_type *t,
{ {
const struct tcp_congestion_ops *utcp_ca; const struct tcp_congestion_ops *utcp_ca;
struct tcp_congestion_ops *tcp_ca; struct tcp_congestion_ops *tcp_ca;
size_t tcp_ca_name_len;
int prog_fd; int prog_fd;
u32 moff; u32 moff;
@ -199,13 +198,11 @@ static int bpf_tcp_ca_init_member(const struct btf_type *t,
tcp_ca->flags = utcp_ca->flags; tcp_ca->flags = utcp_ca->flags;
return 1; return 1;
case offsetof(struct tcp_congestion_ops, name): case offsetof(struct tcp_congestion_ops, name):
tcp_ca_name_len = strnlen(utcp_ca->name, sizeof(utcp_ca->name)); if (bpf_obj_name_cpy(tcp_ca->name, utcp_ca->name,
if (!tcp_ca_name_len || sizeof(tcp_ca->name)) <= 0)
tcp_ca_name_len == sizeof(utcp_ca->name))
return -EINVAL; return -EINVAL;
if (tcp_ca_find(utcp_ca->name)) if (tcp_ca_find(utcp_ca->name))
return -EEXIST; return -EEXIST;
memcpy(tcp_ca->name, utcp_ca->name, sizeof(tcp_ca->name));
return 1; return 1;
} }

View File

@ -187,17 +187,39 @@ static netdev_tx_t vti_xmit(struct sk_buff *skb, struct net_device *dev,
int mtu; int mtu;
if (!dst) { if (!dst) {
struct rtable *rt; switch (skb->protocol) {
case htons(ETH_P_IP): {
struct rtable *rt;
fl->u.ip4.flowi4_oif = dev->ifindex; fl->u.ip4.flowi4_oif = dev->ifindex;
fl->u.ip4.flowi4_flags |= FLOWI_FLAG_ANYSRC; fl->u.ip4.flowi4_flags |= FLOWI_FLAG_ANYSRC;
rt = __ip_route_output_key(dev_net(dev), &fl->u.ip4); rt = __ip_route_output_key(dev_net(dev), &fl->u.ip4);
if (IS_ERR(rt)) { if (IS_ERR(rt)) {
dev->stats.tx_carrier_errors++;
goto tx_error_icmp;
}
dst = &rt->dst;
skb_dst_set(skb, dst);
break;
}
#if IS_ENABLED(CONFIG_IPV6)
case htons(ETH_P_IPV6):
fl->u.ip6.flowi6_oif = dev->ifindex;
fl->u.ip6.flowi6_flags |= FLOWI_FLAG_ANYSRC;
dst = ip6_route_output(dev_net(dev), NULL, &fl->u.ip6);
if (dst->error) {
dst_release(dst);
dst = NULL;
dev->stats.tx_carrier_errors++;
goto tx_error_icmp;
}
skb_dst_set(skb, dst);
break;
#endif
default:
dev->stats.tx_carrier_errors++; dev->stats.tx_carrier_errors++;
goto tx_error_icmp; goto tx_error_icmp;
} }
dst = &rt->dst;
skb_dst_set(skb, dst);
} }
dst_hold(dst); dst_hold(dst);

View File

@ -311,7 +311,7 @@ static int vti6_rcv(struct sk_buff *skb)
if (!xfrm6_policy_check(NULL, XFRM_POLICY_IN, skb)) { if (!xfrm6_policy_check(NULL, XFRM_POLICY_IN, skb)) {
rcu_read_unlock(); rcu_read_unlock();
return 0; goto discard;
} }
ipv6h = ipv6_hdr(skb); ipv6h = ipv6_hdr(skb);
@ -450,15 +450,33 @@ vti6_xmit(struct sk_buff *skb, struct net_device *dev, struct flowi *fl)
int mtu; int mtu;
if (!dst) { if (!dst) {
fl->u.ip6.flowi6_oif = dev->ifindex; switch (skb->protocol) {
fl->u.ip6.flowi6_flags |= FLOWI_FLAG_ANYSRC; case htons(ETH_P_IP): {
dst = ip6_route_output(dev_net(dev), NULL, &fl->u.ip6); struct rtable *rt;
if (dst->error) {
dst_release(dst); fl->u.ip4.flowi4_oif = dev->ifindex;
dst = NULL; fl->u.ip4.flowi4_flags |= FLOWI_FLAG_ANYSRC;
rt = __ip_route_output_key(dev_net(dev), &fl->u.ip4);
if (IS_ERR(rt))
goto tx_err_link_failure;
dst = &rt->dst;
skb_dst_set(skb, dst);
break;
}
case htons(ETH_P_IPV6):
fl->u.ip6.flowi6_oif = dev->ifindex;
fl->u.ip6.flowi6_flags |= FLOWI_FLAG_ANYSRC;
dst = ip6_route_output(dev_net(dev), NULL, &fl->u.ip6);
if (dst->error) {
dst_release(dst);
dst = NULL;
goto tx_err_link_failure;
}
skb_dst_set(skb, dst);
break;
default:
goto tx_err_link_failure; goto tx_err_link_failure;
} }
skb_dst_set(skb, dst);
} }
dst_hold(dst); dst_hold(dst);

View File

@ -78,7 +78,7 @@ static struct xfrm6_tunnel_spi *__xfrm6_tunnel_spi_lookup(struct net *net, const
hlist_for_each_entry_rcu(x6spi, hlist_for_each_entry_rcu(x6spi,
&xfrm6_tn->spi_byaddr[xfrm6_tunnel_spi_hash_byaddr(saddr)], &xfrm6_tn->spi_byaddr[xfrm6_tunnel_spi_hash_byaddr(saddr)],
list_byaddr) { list_byaddr, lockdep_is_held(&xfrm6_tunnel_spi_lock)) {
if (xfrm6_addr_equal(&x6spi->addr, saddr)) if (xfrm6_addr_equal(&x6spi->addr, saddr))
return x6spi; return x6spi;
} }

View File

@ -5,7 +5,7 @@
* Copyright 2007 Johannes Berg <johannes@sipsolutions.net> * Copyright 2007 Johannes Berg <johannes@sipsolutions.net>
* Copyright 2013-2014 Intel Mobile Communications GmbH * Copyright 2013-2014 Intel Mobile Communications GmbH
* Copyright(c) 2016 Intel Deutschland GmbH * Copyright(c) 2016 Intel Deutschland GmbH
* Copyright (C) 2018 - 2019 Intel Corporation * Copyright (C) 2018 - 2020 Intel Corporation
*/ */
#include <linux/debugfs.h> #include <linux/debugfs.h>
@ -78,6 +78,7 @@ static const char * const sta_flag_names[] = {
FLAG(MPSP_OWNER), FLAG(MPSP_OWNER),
FLAG(MPSP_RECIPIENT), FLAG(MPSP_RECIPIENT),
FLAG(PS_DELIVER), FLAG(PS_DELIVER),
FLAG(USES_ENCRYPTION),
#undef FLAG #undef FLAG
}; };

View File

@ -6,7 +6,7 @@
* Copyright 2007-2008 Johannes Berg <johannes@sipsolutions.net> * Copyright 2007-2008 Johannes Berg <johannes@sipsolutions.net>
* Copyright 2013-2014 Intel Mobile Communications GmbH * Copyright 2013-2014 Intel Mobile Communications GmbH
* Copyright 2015-2017 Intel Deutschland GmbH * Copyright 2015-2017 Intel Deutschland GmbH
* Copyright 2018-2019 Intel Corporation * Copyright 2018-2020 Intel Corporation
*/ */
#include <linux/if_ether.h> #include <linux/if_ether.h>
@ -262,22 +262,29 @@ static void ieee80211_key_disable_hw_accel(struct ieee80211_key *key)
sta ? sta->sta.addr : bcast_addr, ret); sta ? sta->sta.addr : bcast_addr, ret);
} }
int ieee80211_set_tx_key(struct ieee80211_key *key) static int _ieee80211_set_tx_key(struct ieee80211_key *key, bool force)
{ {
struct sta_info *sta = key->sta; struct sta_info *sta = key->sta;
struct ieee80211_local *local = key->local; struct ieee80211_local *local = key->local;
assert_key_lock(local); assert_key_lock(local);
set_sta_flag(sta, WLAN_STA_USES_ENCRYPTION);
sta->ptk_idx = key->conf.keyidx; sta->ptk_idx = key->conf.keyidx;
if (!ieee80211_hw_check(&local->hw, AMPDU_KEYBORDER_SUPPORT)) if (force || !ieee80211_hw_check(&local->hw, AMPDU_KEYBORDER_SUPPORT))
clear_sta_flag(sta, WLAN_STA_BLOCK_BA); clear_sta_flag(sta, WLAN_STA_BLOCK_BA);
ieee80211_check_fast_xmit(sta); ieee80211_check_fast_xmit(sta);
return 0; return 0;
} }
int ieee80211_set_tx_key(struct ieee80211_key *key)
{
return _ieee80211_set_tx_key(key, false);
}
static void ieee80211_pairwise_rekey(struct ieee80211_key *old, static void ieee80211_pairwise_rekey(struct ieee80211_key *old,
struct ieee80211_key *new) struct ieee80211_key *new)
{ {
@ -441,11 +448,8 @@ static int ieee80211_key_replace(struct ieee80211_sub_if_data *sdata,
if (pairwise) { if (pairwise) {
rcu_assign_pointer(sta->ptk[idx], new); rcu_assign_pointer(sta->ptk[idx], new);
if (new && if (new &&
!(new->conf.flags & IEEE80211_KEY_FLAG_NO_AUTO_TX)) { !(new->conf.flags & IEEE80211_KEY_FLAG_NO_AUTO_TX))
sta->ptk_idx = idx; _ieee80211_set_tx_key(new, true);
clear_sta_flag(sta, WLAN_STA_BLOCK_BA);
ieee80211_check_fast_xmit(sta);
}
} else { } else {
rcu_assign_pointer(sta->gtk[idx], new); rcu_assign_pointer(sta->gtk[idx], new);
} }

View File

@ -4,7 +4,7 @@
* Copyright 2006-2007 Jiri Benc <jbenc@suse.cz> * Copyright 2006-2007 Jiri Benc <jbenc@suse.cz>
* Copyright 2013-2014 Intel Mobile Communications GmbH * Copyright 2013-2014 Intel Mobile Communications GmbH
* Copyright (C) 2015 - 2017 Intel Deutschland GmbH * Copyright (C) 2015 - 2017 Intel Deutschland GmbH
* Copyright (C) 2018-2019 Intel Corporation * Copyright (C) 2018-2020 Intel Corporation
*/ */
#include <linux/module.h> #include <linux/module.h>
@ -1049,6 +1049,11 @@ static void __sta_info_destroy_part2(struct sta_info *sta)
might_sleep(); might_sleep();
lockdep_assert_held(&local->sta_mtx); lockdep_assert_held(&local->sta_mtx);
while (sta->sta_state == IEEE80211_STA_AUTHORIZED) {
ret = sta_info_move_state(sta, IEEE80211_STA_ASSOC);
WARN_ON_ONCE(ret);
}
/* now keys can no longer be reached */ /* now keys can no longer be reached */
ieee80211_free_sta_keys(local, sta); ieee80211_free_sta_keys(local, sta);

View File

@ -98,6 +98,7 @@ enum ieee80211_sta_info_flags {
WLAN_STA_MPSP_OWNER, WLAN_STA_MPSP_OWNER,
WLAN_STA_MPSP_RECIPIENT, WLAN_STA_MPSP_RECIPIENT,
WLAN_STA_PS_DELIVER, WLAN_STA_PS_DELIVER,
WLAN_STA_USES_ENCRYPTION,
NUM_WLAN_STA_FLAGS, NUM_WLAN_STA_FLAGS,
}; };

View File

@ -5,7 +5,7 @@
* Copyright 2006-2007 Jiri Benc <jbenc@suse.cz> * Copyright 2006-2007 Jiri Benc <jbenc@suse.cz>
* Copyright 2007 Johannes Berg <johannes@sipsolutions.net> * Copyright 2007 Johannes Berg <johannes@sipsolutions.net>
* Copyright 2013-2014 Intel Mobile Communications GmbH * Copyright 2013-2014 Intel Mobile Communications GmbH
* Copyright (C) 2018 Intel Corporation * Copyright (C) 2018, 2020 Intel Corporation
* *
* Transmit and frame generation functions. * Transmit and frame generation functions.
*/ */
@ -590,10 +590,13 @@ ieee80211_tx_h_select_key(struct ieee80211_tx_data *tx)
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(tx->skb); struct ieee80211_tx_info *info = IEEE80211_SKB_CB(tx->skb);
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)tx->skb->data; struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)tx->skb->data;
if (unlikely(info->flags & IEEE80211_TX_INTFL_DONT_ENCRYPT)) if (unlikely(info->flags & IEEE80211_TX_INTFL_DONT_ENCRYPT)) {
tx->key = NULL; tx->key = NULL;
else if (tx->sta && return TX_CONTINUE;
(key = rcu_dereference(tx->sta->ptk[tx->sta->ptk_idx]))) }
if (tx->sta &&
(key = rcu_dereference(tx->sta->ptk[tx->sta->ptk_idx])))
tx->key = key; tx->key = key;
else if (ieee80211_is_group_privacy_action(tx->skb) && else if (ieee80211_is_group_privacy_action(tx->skb) &&
(key = rcu_dereference(tx->sdata->default_multicast_key))) (key = rcu_dereference(tx->sdata->default_multicast_key)))
@ -654,6 +657,9 @@ ieee80211_tx_h_select_key(struct ieee80211_tx_data *tx)
if (!skip_hw && tx->key && if (!skip_hw && tx->key &&
tx->key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE) tx->key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE)
info->control.hw_key = &tx->key->conf; info->control.hw_key = &tx->key->conf;
} else if (!ieee80211_is_mgmt(hdr->frame_control) && tx->sta &&
test_sta_flag(tx->sta, WLAN_STA_USES_ENCRYPTION)) {
return TX_DROP;
} }
return TX_CONTINUE; return TX_CONTINUE;
@ -3598,8 +3604,25 @@ begin:
tx.skb = skb; tx.skb = skb;
tx.sdata = vif_to_sdata(info->control.vif); tx.sdata = vif_to_sdata(info->control.vif);
if (txq->sta) if (txq->sta) {
tx.sta = container_of(txq->sta, struct sta_info, sta); tx.sta = container_of(txq->sta, struct sta_info, sta);
/*
* Drop unicast frames to unauthorised stations unless they are
* EAPOL frames from the local station.
*/
if (unlikely(!ieee80211_vif_is_mesh(&tx.sdata->vif) &&
tx.sdata->vif.type != NL80211_IFTYPE_OCB &&
!is_multicast_ether_addr(hdr->addr1) &&
!test_sta_flag(tx.sta, WLAN_STA_AUTHORIZED) &&
(!(info->control.flags &
IEEE80211_TX_CTRL_PORT_CTRL_PROTO) ||
!ether_addr_equal(tx.sdata->vif.addr,
hdr->addr2)))) {
I802_DEBUG_INC(local->tx_handlers_drop_unauth_port);
ieee80211_free_txskb(&local->hw, skb);
goto begin;
}
}
/* /*
* The key can be removed while the packet was queued, so need to call * The key can be removed while the packet was queued, so need to call
@ -5126,6 +5149,7 @@ int ieee80211_tx_control_port(struct wiphy *wiphy, struct net_device *dev,
struct ieee80211_local *local = sdata->local; struct ieee80211_local *local = sdata->local;
struct sk_buff *skb; struct sk_buff *skb;
struct ethhdr *ehdr; struct ethhdr *ehdr;
u32 ctrl_flags = 0;
u32 flags; u32 flags;
/* Only accept CONTROL_PORT_PROTOCOL configured in CONNECT/ASSOCIATE /* Only accept CONTROL_PORT_PROTOCOL configured in CONNECT/ASSOCIATE
@ -5135,6 +5159,9 @@ int ieee80211_tx_control_port(struct wiphy *wiphy, struct net_device *dev,
proto != cpu_to_be16(ETH_P_PREAUTH)) proto != cpu_to_be16(ETH_P_PREAUTH))
return -EINVAL; return -EINVAL;
if (proto == sdata->control_port_protocol)
ctrl_flags |= IEEE80211_TX_CTRL_PORT_CTRL_PROTO;
if (unencrypted) if (unencrypted)
flags = IEEE80211_TX_INTFL_DONT_ENCRYPT; flags = IEEE80211_TX_INTFL_DONT_ENCRYPT;
else else
@ -5160,7 +5187,7 @@ int ieee80211_tx_control_port(struct wiphy *wiphy, struct net_device *dev,
skb_reset_mac_header(skb); skb_reset_mac_header(skb);
local_bh_disable(); local_bh_disable();
__ieee80211_subif_start_xmit(skb, skb->dev, flags, 0); __ieee80211_subif_start_xmit(skb, skb->dev, flags, ctrl_flags);
local_bh_enable(); local_bh_enable();
return 0; return 0;

View File

@ -16416,7 +16416,7 @@ void cfg80211_sta_opmode_change_notify(struct net_device *dev, const u8 *mac,
goto nla_put_failure; goto nla_put_failure;
if ((sta_opmode->changed & STA_OPMODE_MAX_BW_CHANGED) && if ((sta_opmode->changed & STA_OPMODE_MAX_BW_CHANGED) &&
nla_put_u8(msg, NL80211_ATTR_CHANNEL_WIDTH, sta_opmode->bw)) nla_put_u32(msg, NL80211_ATTR_CHANNEL_WIDTH, sta_opmode->bw))
goto nla_put_failure; goto nla_put_failure;
if ((sta_opmode->changed & STA_OPMODE_N_SS_CHANGED) && if ((sta_opmode->changed & STA_OPMODE_N_SS_CHANGED) &&

View File

@ -2022,7 +2022,11 @@ void cfg80211_update_assoc_bss_entry(struct wireless_dev *wdev,
spin_lock_bh(&rdev->bss_lock); spin_lock_bh(&rdev->bss_lock);
if (WARN_ON(cbss->pub.channel == chan)) /*
* Some APs use CSA also for bandwidth changes, i.e., without actually
* changing the control channel, so no need to update in such a case.
*/
if (cbss->pub.channel == chan)
goto done; goto done;
/* use transmitting bss */ /* use transmitting bss */

View File

@ -78,8 +78,8 @@ struct sk_buff *validate_xmit_xfrm(struct sk_buff *skb, netdev_features_t featur
int err; int err;
unsigned long flags; unsigned long flags;
struct xfrm_state *x; struct xfrm_state *x;
struct sk_buff *skb2, *nskb;
struct softnet_data *sd; struct softnet_data *sd;
struct sk_buff *skb2, *nskb, *pskb = NULL;
netdev_features_t esp_features = features; netdev_features_t esp_features = features;
struct xfrm_offload *xo = xfrm_offload(skb); struct xfrm_offload *xo = xfrm_offload(skb);
struct sec_path *sp; struct sec_path *sp;
@ -168,14 +168,14 @@ struct sk_buff *validate_xmit_xfrm(struct sk_buff *skb, netdev_features_t featur
} else { } else {
if (skb == skb2) if (skb == skb2)
skb = nskb; skb = nskb;
else
if (!skb) pskb->next = nskb;
return NULL;
continue; continue;
} }
skb_push(skb2, skb2->data - skb_mac_header(skb2)); skb_push(skb2, skb2->data - skb_mac_header(skb2));
pskb = skb2;
} }
return skb; return skb;
@ -383,6 +383,7 @@ static int xfrm_dev_event(struct notifier_block *this, unsigned long event, void
return xfrm_dev_feat_change(dev); return xfrm_dev_feat_change(dev);
case NETDEV_DOWN: case NETDEV_DOWN:
case NETDEV_UNREGISTER:
return xfrm_dev_down(dev); return xfrm_dev_down(dev);
} }
return NOTIFY_DONE; return NOTIFY_DONE;

View File

@ -434,7 +434,9 @@ EXPORT_SYMBOL(xfrm_policy_destroy);
static void xfrm_policy_kill(struct xfrm_policy *policy) static void xfrm_policy_kill(struct xfrm_policy *policy)
{ {
write_lock_bh(&policy->lock);
policy->walk.dead = 1; policy->walk.dead = 1;
write_unlock_bh(&policy->lock);
atomic_inc(&policy->genid); atomic_inc(&policy->genid);

View File

@ -110,7 +110,8 @@ static inline int verify_sec_ctx_len(struct nlattr **attrs)
return 0; return 0;
uctx = nla_data(rt); uctx = nla_data(rt);
if (uctx->len != (sizeof(struct xfrm_user_sec_ctx) + uctx->ctx_len)) if (uctx->len > nla_len(rt) ||
uctx->len != (sizeof(struct xfrm_user_sec_ctx) + uctx->ctx_len))
return -EINVAL; return -EINVAL;
return 0; return 0;
@ -2273,6 +2274,9 @@ static int xfrm_add_acquire(struct sk_buff *skb, struct nlmsghdr *nlh,
xfrm_mark_get(attrs, &mark); xfrm_mark_get(attrs, &mark);
err = verify_newpolicy_info(&ua->policy); err = verify_newpolicy_info(&ua->policy);
if (err)
goto free_state;
err = verify_sec_ctx_len(attrs);
if (err) if (err)
goto free_state; goto free_state;