forked from Minki/linux
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:
commit
e595dd9451
@ -637,12 +637,12 @@ static int mlxsw_sp_mr_vif_resolve(struct mlxsw_sp_mr_table *mr_table,
|
||||
return 0;
|
||||
|
||||
err_erif_unresolve:
|
||||
list_for_each_entry_from_reverse(erve, &mr_vif->route_evif_list,
|
||||
vif_node)
|
||||
list_for_each_entry_continue_reverse(erve, &mr_vif->route_evif_list,
|
||||
vif_node)
|
||||
mlxsw_sp_mr_route_evif_unresolve(mr_table, erve);
|
||||
err_irif_unresolve:
|
||||
list_for_each_entry_from_reverse(irve, &mr_vif->route_ivif_list,
|
||||
vif_node)
|
||||
list_for_each_entry_continue_reverse(irve, &mr_vif->route_ivif_list,
|
||||
vif_node)
|
||||
mlxsw_sp_mr_route_ivif_unresolve(mr_table, irve);
|
||||
mr_vif->rif = NULL;
|
||||
return err;
|
||||
|
@ -156,6 +156,50 @@ static int msg_enable;
|
||||
* 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 : The chip information
|
||||
@ -166,7 +210,7 @@ static int msg_enable;
|
||||
|
||||
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);
|
||||
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)
|
||||
{
|
||||
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(value, ks->hw_addr);
|
||||
}
|
||||
@ -197,7 +241,7 @@ static inline void ks_inblk(struct ks_net *ks, u16 *wptr, u32 len)
|
||||
{
|
||||
len >>= 1;
|
||||
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;
|
||||
while (len--)
|
||||
iowrite16(cpu_to_be16(*wptr++), ks->hw_addr);
|
||||
iowrite16(*wptr++, ks->hw_addr);
|
||||
}
|
||||
|
||||
static void ks_disable_int(struct ks_net *ks)
|
||||
@ -1218,6 +1262,10 @@ static int ks8851_probe(struct platform_device *pdev)
|
||||
goto err_free;
|
||||
}
|
||||
|
||||
err = ks_check_endian(ks);
|
||||
if (err)
|
||||
goto err_free;
|
||||
|
||||
netdev->irq = platform_get_irq(pdev, 0);
|
||||
|
||||
if ((int)netdev->irq < 0) {
|
||||
|
@ -1720,7 +1720,7 @@ static int qlcnic_83xx_get_reset_instruction_template(struct qlcnic_adapter *p_d
|
||||
|
||||
ahw->reset.seq_error = 0;
|
||||
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;
|
||||
|
||||
p_buff = p_dev->ahw->reset.buff;
|
||||
|
@ -5285,6 +5285,13 @@ static int r8169_mdio_register(struct rtl8169_private *tp)
|
||||
if (!tp->phydev) {
|
||||
mdiobus_unregister(new_bus);
|
||||
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() */
|
||||
@ -5446,15 +5453,6 @@ static int rtl_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
|
||||
int chipset, region;
|
||||
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));
|
||||
if (!dev)
|
||||
return -ENOMEM;
|
||||
|
@ -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,
|
||||
bool lock_src);
|
||||
int bpf_obj_name_cpy(char *dst, const char *src, unsigned int size);
|
||||
|
||||
struct bpf_offload_dev;
|
||||
struct bpf_offloaded_map;
|
||||
|
@ -2102,14 +2102,14 @@ ieee80211_he_spr_size(const u8 *he_spr_ie)
|
||||
{
|
||||
struct ieee80211_he_spr *he_spr = (void *)he_spr_ie;
|
||||
u8 spr_len = sizeof(struct ieee80211_he_spr);
|
||||
u32 he_spr_params;
|
||||
u8 he_spr_params;
|
||||
|
||||
/* Make sure the input is not NULL */
|
||||
if (!he_spr_ie)
|
||||
return 0;
|
||||
|
||||
/* 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)
|
||||
spr_len++;
|
||||
if (he_spr_params & IEEE80211_HE_SPR_SRG_INFORMATION_PRESENT)
|
||||
|
@ -4564,7 +4564,7 @@ int btf_get_info_by_fd(const struct btf *btf,
|
||||
union bpf_attr __user *uattr)
|
||||
{
|
||||
struct bpf_btf_info __user *uinfo;
|
||||
struct bpf_btf_info info = {};
|
||||
struct bpf_btf_info info;
|
||||
u32 info_copy, btf_copy;
|
||||
void __user *ubtf;
|
||||
u32 uinfo_len;
|
||||
@ -4573,6 +4573,7 @@ int btf_get_info_by_fd(const struct btf *btf,
|
||||
uinfo_len = attr->info.info_len;
|
||||
|
||||
info_copy = min_t(u32, uinfo_len, sizeof(info));
|
||||
memset(&info, 0, sizeof(info));
|
||||
if (copy_from_user(&info, uinfo, info_copy))
|
||||
return -EFAULT;
|
||||
|
||||
|
@ -696,14 +696,15 @@ int bpf_get_file_flag(int flags)
|
||||
offsetof(union bpf_attr, CMD##_LAST_FIELD) - \
|
||||
sizeof(attr->CMD##_LAST_FIELD)) != NULL
|
||||
|
||||
/* dst and src must have at least BPF_OBJ_NAME_LEN number of bytes.
|
||||
* Return 0 on success and < 0 on error.
|
||||
/* dst and src must have at least "size" number of bytes.
|
||||
* 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. */
|
||||
while (src < end && *src) {
|
||||
if (!isalnum(*src) &&
|
||||
@ -712,11 +713,11 @@ static int bpf_obj_name_cpy(char *dst, const char *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)
|
||||
return -EINVAL;
|
||||
|
||||
return 0;
|
||||
return src - orig_src;
|
||||
}
|
||||
|
||||
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))
|
||||
return PTR_ERR(map);
|
||||
|
||||
err = bpf_obj_name_cpy(map->name, attr->map_name);
|
||||
if (err)
|
||||
err = bpf_obj_name_cpy(map->name, attr->map_name,
|
||||
sizeof(attr->map_name));
|
||||
if (err < 0)
|
||||
goto free_map;
|
||||
|
||||
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;
|
||||
|
||||
prog->aux->load_time = ktime_get_boottime_ns();
|
||||
err = bpf_obj_name_cpy(prog->aux->name, attr->prog_name);
|
||||
if (err)
|
||||
err = bpf_obj_name_cpy(prog->aux->name, attr->prog_name,
|
||||
sizeof(attr->prog_name));
|
||||
if (err < 0)
|
||||
goto free_prog;
|
||||
|
||||
/* run eBPF verifier */
|
||||
@ -2792,7 +2795,7 @@ static int bpf_prog_get_info_by_fd(struct bpf_prog *prog,
|
||||
union bpf_attr __user *uattr)
|
||||
{
|
||||
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;
|
||||
struct bpf_prog_stats stats;
|
||||
char __user *uinsns;
|
||||
@ -2804,6 +2807,7 @@ static int bpf_prog_get_info_by_fd(struct bpf_prog *prog,
|
||||
return err;
|
||||
info_len = min_t(u32, sizeof(info), info_len);
|
||||
|
||||
memset(&info, 0, sizeof(info));
|
||||
if (copy_from_user(&info, uinfo, info_len))
|
||||
return -EFAULT;
|
||||
|
||||
@ -3067,7 +3071,7 @@ static int bpf_map_get_info_by_fd(struct bpf_map *map,
|
||||
union bpf_attr __user *uattr)
|
||||
{
|
||||
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;
|
||||
int err;
|
||||
|
||||
@ -3076,6 +3080,7 @@ static int bpf_map_get_info_by_fd(struct bpf_map *map,
|
||||
return err;
|
||||
info_len = min_t(u32, sizeof(info), info_len);
|
||||
|
||||
memset(&info, 0, sizeof(info));
|
||||
info.type = map->map_type;
|
||||
info.id = map->id;
|
||||
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)
|
||||
{
|
||||
union bpf_attr attr = {};
|
||||
union bpf_attr attr;
|
||||
int err;
|
||||
|
||||
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));
|
||||
|
||||
/* 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)
|
||||
return -EFAULT;
|
||||
|
||||
|
@ -303,6 +303,7 @@ config SYN_COOKIES
|
||||
|
||||
config NET_IPVTI
|
||||
tristate "Virtual (secure) IP: tunneling"
|
||||
depends on IPV6 || IPV6=n
|
||||
select INET_TUNNEL
|
||||
select NET_IP_TUNNEL
|
||||
select XFRM
|
||||
|
@ -184,7 +184,6 @@ static int bpf_tcp_ca_init_member(const struct btf_type *t,
|
||||
{
|
||||
const struct tcp_congestion_ops *utcp_ca;
|
||||
struct tcp_congestion_ops *tcp_ca;
|
||||
size_t tcp_ca_name_len;
|
||||
int prog_fd;
|
||||
u32 moff;
|
||||
|
||||
@ -199,13 +198,11 @@ static int bpf_tcp_ca_init_member(const struct btf_type *t,
|
||||
tcp_ca->flags = utcp_ca->flags;
|
||||
return 1;
|
||||
case offsetof(struct tcp_congestion_ops, name):
|
||||
tcp_ca_name_len = strnlen(utcp_ca->name, sizeof(utcp_ca->name));
|
||||
if (!tcp_ca_name_len ||
|
||||
tcp_ca_name_len == sizeof(utcp_ca->name))
|
||||
if (bpf_obj_name_cpy(tcp_ca->name, utcp_ca->name,
|
||||
sizeof(tcp_ca->name)) <= 0)
|
||||
return -EINVAL;
|
||||
if (tcp_ca_find(utcp_ca->name))
|
||||
return -EEXIST;
|
||||
memcpy(tcp_ca->name, utcp_ca->name, sizeof(tcp_ca->name));
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
@ -187,17 +187,39 @@ static netdev_tx_t vti_xmit(struct sk_buff *skb, struct net_device *dev,
|
||||
int mtu;
|
||||
|
||||
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_flags |= FLOWI_FLAG_ANYSRC;
|
||||
rt = __ip_route_output_key(dev_net(dev), &fl->u.ip4);
|
||||
if (IS_ERR(rt)) {
|
||||
fl->u.ip4.flowi4_oif = dev->ifindex;
|
||||
fl->u.ip4.flowi4_flags |= FLOWI_FLAG_ANYSRC;
|
||||
rt = __ip_route_output_key(dev_net(dev), &fl->u.ip4);
|
||||
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++;
|
||||
goto tx_error_icmp;
|
||||
}
|
||||
dst = &rt->dst;
|
||||
skb_dst_set(skb, dst);
|
||||
}
|
||||
|
||||
dst_hold(dst);
|
||||
|
@ -311,7 +311,7 @@ static int vti6_rcv(struct sk_buff *skb)
|
||||
|
||||
if (!xfrm6_policy_check(NULL, XFRM_POLICY_IN, skb)) {
|
||||
rcu_read_unlock();
|
||||
return 0;
|
||||
goto discard;
|
||||
}
|
||||
|
||||
ipv6h = ipv6_hdr(skb);
|
||||
@ -450,15 +450,33 @@ vti6_xmit(struct sk_buff *skb, struct net_device *dev, struct flowi *fl)
|
||||
int mtu;
|
||||
|
||||
if (!dst) {
|
||||
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;
|
||||
switch (skb->protocol) {
|
||||
case htons(ETH_P_IP): {
|
||||
struct rtable *rt;
|
||||
|
||||
fl->u.ip4.flowi4_oif = dev->ifindex;
|
||||
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;
|
||||
}
|
||||
skb_dst_set(skb, dst);
|
||||
}
|
||||
|
||||
dst_hold(dst);
|
||||
|
@ -78,7 +78,7 @@ static struct xfrm6_tunnel_spi *__xfrm6_tunnel_spi_lookup(struct net *net, const
|
||||
|
||||
hlist_for_each_entry_rcu(x6spi,
|
||||
&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))
|
||||
return x6spi;
|
||||
}
|
||||
|
@ -5,7 +5,7 @@
|
||||
* Copyright 2007 Johannes Berg <johannes@sipsolutions.net>
|
||||
* Copyright 2013-2014 Intel Mobile Communications GmbH
|
||||
* Copyright(c) 2016 Intel Deutschland GmbH
|
||||
* Copyright (C) 2018 - 2019 Intel Corporation
|
||||
* Copyright (C) 2018 - 2020 Intel Corporation
|
||||
*/
|
||||
|
||||
#include <linux/debugfs.h>
|
||||
@ -78,6 +78,7 @@ static const char * const sta_flag_names[] = {
|
||||
FLAG(MPSP_OWNER),
|
||||
FLAG(MPSP_RECIPIENT),
|
||||
FLAG(PS_DELIVER),
|
||||
FLAG(USES_ENCRYPTION),
|
||||
#undef FLAG
|
||||
};
|
||||
|
||||
|
@ -6,7 +6,7 @@
|
||||
* Copyright 2007-2008 Johannes Berg <johannes@sipsolutions.net>
|
||||
* Copyright 2013-2014 Intel Mobile Communications GmbH
|
||||
* Copyright 2015-2017 Intel Deutschland GmbH
|
||||
* Copyright 2018-2019 Intel Corporation
|
||||
* Copyright 2018-2020 Intel Corporation
|
||||
*/
|
||||
|
||||
#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);
|
||||
}
|
||||
|
||||
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 ieee80211_local *local = key->local;
|
||||
|
||||
assert_key_lock(local);
|
||||
|
||||
set_sta_flag(sta, WLAN_STA_USES_ENCRYPTION);
|
||||
|
||||
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);
|
||||
ieee80211_check_fast_xmit(sta);
|
||||
|
||||
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,
|
||||
struct ieee80211_key *new)
|
||||
{
|
||||
@ -441,11 +448,8 @@ static int ieee80211_key_replace(struct ieee80211_sub_if_data *sdata,
|
||||
if (pairwise) {
|
||||
rcu_assign_pointer(sta->ptk[idx], new);
|
||||
if (new &&
|
||||
!(new->conf.flags & IEEE80211_KEY_FLAG_NO_AUTO_TX)) {
|
||||
sta->ptk_idx = idx;
|
||||
clear_sta_flag(sta, WLAN_STA_BLOCK_BA);
|
||||
ieee80211_check_fast_xmit(sta);
|
||||
}
|
||||
!(new->conf.flags & IEEE80211_KEY_FLAG_NO_AUTO_TX))
|
||||
_ieee80211_set_tx_key(new, true);
|
||||
} else {
|
||||
rcu_assign_pointer(sta->gtk[idx], new);
|
||||
}
|
||||
|
@ -4,7 +4,7 @@
|
||||
* Copyright 2006-2007 Jiri Benc <jbenc@suse.cz>
|
||||
* Copyright 2013-2014 Intel Mobile Communications GmbH
|
||||
* Copyright (C) 2015 - 2017 Intel Deutschland GmbH
|
||||
* Copyright (C) 2018-2019 Intel Corporation
|
||||
* Copyright (C) 2018-2020 Intel Corporation
|
||||
*/
|
||||
|
||||
#include <linux/module.h>
|
||||
@ -1049,6 +1049,11 @@ static void __sta_info_destroy_part2(struct sta_info *sta)
|
||||
might_sleep();
|
||||
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 */
|
||||
ieee80211_free_sta_keys(local, sta);
|
||||
|
||||
|
@ -98,6 +98,7 @@ enum ieee80211_sta_info_flags {
|
||||
WLAN_STA_MPSP_OWNER,
|
||||
WLAN_STA_MPSP_RECIPIENT,
|
||||
WLAN_STA_PS_DELIVER,
|
||||
WLAN_STA_USES_ENCRYPTION,
|
||||
|
||||
NUM_WLAN_STA_FLAGS,
|
||||
};
|
||||
|
@ -5,7 +5,7 @@
|
||||
* Copyright 2006-2007 Jiri Benc <jbenc@suse.cz>
|
||||
* Copyright 2007 Johannes Berg <johannes@sipsolutions.net>
|
||||
* Copyright 2013-2014 Intel Mobile Communications GmbH
|
||||
* Copyright (C) 2018 Intel Corporation
|
||||
* Copyright (C) 2018, 2020 Intel Corporation
|
||||
*
|
||||
* 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_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;
|
||||
else if (tx->sta &&
|
||||
(key = rcu_dereference(tx->sta->ptk[tx->sta->ptk_idx])))
|
||||
return TX_CONTINUE;
|
||||
}
|
||||
|
||||
if (tx->sta &&
|
||||
(key = rcu_dereference(tx->sta->ptk[tx->sta->ptk_idx])))
|
||||
tx->key = key;
|
||||
else if (ieee80211_is_group_privacy_action(tx->skb) &&
|
||||
(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 &&
|
||||
tx->key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE)
|
||||
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;
|
||||
@ -3598,8 +3604,25 @@ begin:
|
||||
tx.skb = skb;
|
||||
tx.sdata = vif_to_sdata(info->control.vif);
|
||||
|
||||
if (txq->sta)
|
||||
if (txq->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
|
||||
@ -5126,6 +5149,7 @@ int ieee80211_tx_control_port(struct wiphy *wiphy, struct net_device *dev,
|
||||
struct ieee80211_local *local = sdata->local;
|
||||
struct sk_buff *skb;
|
||||
struct ethhdr *ehdr;
|
||||
u32 ctrl_flags = 0;
|
||||
u32 flags;
|
||||
|
||||
/* 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))
|
||||
return -EINVAL;
|
||||
|
||||
if (proto == sdata->control_port_protocol)
|
||||
ctrl_flags |= IEEE80211_TX_CTRL_PORT_CTRL_PROTO;
|
||||
|
||||
if (unencrypted)
|
||||
flags = IEEE80211_TX_INTFL_DONT_ENCRYPT;
|
||||
else
|
||||
@ -5160,7 +5187,7 @@ int ieee80211_tx_control_port(struct wiphy *wiphy, struct net_device *dev,
|
||||
skb_reset_mac_header(skb);
|
||||
|
||||
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();
|
||||
|
||||
return 0;
|
||||
|
@ -16416,7 +16416,7 @@ void cfg80211_sta_opmode_change_notify(struct net_device *dev, const u8 *mac,
|
||||
goto nla_put_failure;
|
||||
|
||||
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;
|
||||
|
||||
if ((sta_opmode->changed & STA_OPMODE_N_SS_CHANGED) &&
|
||||
|
@ -2022,7 +2022,11 @@ void cfg80211_update_assoc_bss_entry(struct wireless_dev *wdev,
|
||||
|
||||
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;
|
||||
|
||||
/* use transmitting bss */
|
||||
|
@ -78,8 +78,8 @@ struct sk_buff *validate_xmit_xfrm(struct sk_buff *skb, netdev_features_t featur
|
||||
int err;
|
||||
unsigned long flags;
|
||||
struct xfrm_state *x;
|
||||
struct sk_buff *skb2, *nskb;
|
||||
struct softnet_data *sd;
|
||||
struct sk_buff *skb2, *nskb, *pskb = NULL;
|
||||
netdev_features_t esp_features = features;
|
||||
struct xfrm_offload *xo = xfrm_offload(skb);
|
||||
struct sec_path *sp;
|
||||
@ -168,14 +168,14 @@ struct sk_buff *validate_xmit_xfrm(struct sk_buff *skb, netdev_features_t featur
|
||||
} else {
|
||||
if (skb == skb2)
|
||||
skb = nskb;
|
||||
|
||||
if (!skb)
|
||||
return NULL;
|
||||
else
|
||||
pskb->next = nskb;
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
skb_push(skb2, skb2->data - skb_mac_header(skb2));
|
||||
pskb = skb2;
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
case NETDEV_DOWN:
|
||||
case NETDEV_UNREGISTER:
|
||||
return xfrm_dev_down(dev);
|
||||
}
|
||||
return NOTIFY_DONE;
|
||||
|
@ -434,7 +434,9 @@ EXPORT_SYMBOL(xfrm_policy_destroy);
|
||||
|
||||
static void xfrm_policy_kill(struct xfrm_policy *policy)
|
||||
{
|
||||
write_lock_bh(&policy->lock);
|
||||
policy->walk.dead = 1;
|
||||
write_unlock_bh(&policy->lock);
|
||||
|
||||
atomic_inc(&policy->genid);
|
||||
|
||||
|
@ -110,7 +110,8 @@ static inline int verify_sec_ctx_len(struct nlattr **attrs)
|
||||
return 0;
|
||||
|
||||
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 0;
|
||||
@ -2273,6 +2274,9 @@ static int xfrm_add_acquire(struct sk_buff *skb, struct nlmsghdr *nlh,
|
||||
xfrm_mark_get(attrs, &mark);
|
||||
|
||||
err = verify_newpolicy_info(&ua->policy);
|
||||
if (err)
|
||||
goto free_state;
|
||||
err = verify_sec_ctx_len(attrs);
|
||||
if (err)
|
||||
goto free_state;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user