diff options
Diffstat (limited to 'net')
32 files changed, 418 insertions, 172 deletions
diff --git a/net/8021q/vlan.c b/net/8021q/vlan.c index 73a65789271b..8ccee3d01822 100644 --- a/net/8021q/vlan.c +++ b/net/8021q/vlan.c | |||
@@ -693,7 +693,7 @@ static struct sk_buff **vlan_gro_receive(struct sk_buff **head, | |||
693 | out_unlock: | 693 | out_unlock: |
694 | rcu_read_unlock(); | 694 | rcu_read_unlock(); |
695 | out: | 695 | out: |
696 | NAPI_GRO_CB(skb)->flush |= flush; | 696 | skb_gro_flush_final(skb, pp, flush); |
697 | 697 | ||
698 | return pp; | 698 | return pp; |
699 | } | 699 | } |
diff --git a/net/9p/client.c b/net/9p/client.c index 18c5271910dc..5c1343195292 100644 --- a/net/9p/client.c +++ b/net/9p/client.c | |||
@@ -225,7 +225,8 @@ static int parse_opts(char *opts, struct p9_client *clnt) | |||
225 | } | 225 | } |
226 | 226 | ||
227 | free_and_return: | 227 | free_and_return: |
228 | v9fs_put_trans(clnt->trans_mod); | 228 | if (ret) |
229 | v9fs_put_trans(clnt->trans_mod); | ||
229 | kfree(tmp_options); | 230 | kfree(tmp_options); |
230 | return ret; | 231 | return ret; |
231 | } | 232 | } |
diff --git a/net/Makefile b/net/Makefile index 13ec0d5415c7..bdaf53925acd 100644 --- a/net/Makefile +++ b/net/Makefile | |||
@@ -20,11 +20,7 @@ obj-$(CONFIG_TLS) += tls/ | |||
20 | obj-$(CONFIG_XFRM) += xfrm/ | 20 | obj-$(CONFIG_XFRM) += xfrm/ |
21 | obj-$(CONFIG_UNIX) += unix/ | 21 | obj-$(CONFIG_UNIX) += unix/ |
22 | obj-$(CONFIG_NET) += ipv6/ | 22 | obj-$(CONFIG_NET) += ipv6/ |
23 | ifneq ($(CC_CAN_LINK),y) | ||
24 | $(warning CC cannot link executables. Skipping bpfilter.) | ||
25 | else | ||
26 | obj-$(CONFIG_BPFILTER) += bpfilter/ | 23 | obj-$(CONFIG_BPFILTER) += bpfilter/ |
27 | endif | ||
28 | obj-$(CONFIG_PACKET) += packet/ | 24 | obj-$(CONFIG_PACKET) += packet/ |
29 | obj-$(CONFIG_NET_KEY) += key/ | 25 | obj-$(CONFIG_NET_KEY) += key/ |
30 | obj-$(CONFIG_BRIDGE) += bridge/ | 26 | obj-$(CONFIG_BRIDGE) += bridge/ |
diff --git a/net/bpfilter/Kconfig b/net/bpfilter/Kconfig index a948b072c28f..76deb6615883 100644 --- a/net/bpfilter/Kconfig +++ b/net/bpfilter/Kconfig | |||
@@ -1,6 +1,5 @@ | |||
1 | menuconfig BPFILTER | 1 | menuconfig BPFILTER |
2 | bool "BPF based packet filtering framework (BPFILTER)" | 2 | bool "BPF based packet filtering framework (BPFILTER)" |
3 | default n | ||
4 | depends on NET && BPF && INET | 3 | depends on NET && BPF && INET |
5 | help | 4 | help |
6 | This builds experimental bpfilter framework that is aiming to | 5 | This builds experimental bpfilter framework that is aiming to |
@@ -9,6 +8,7 @@ menuconfig BPFILTER | |||
9 | if BPFILTER | 8 | if BPFILTER |
10 | config BPFILTER_UMH | 9 | config BPFILTER_UMH |
11 | tristate "bpfilter kernel module with user mode helper" | 10 | tristate "bpfilter kernel module with user mode helper" |
11 | depends on $(success,$(srctree)/scripts/cc-can-link.sh $(CC)) | ||
12 | default m | 12 | default m |
13 | help | 13 | help |
14 | This builds bpfilter kernel module with embedded user mode helper | 14 | This builds bpfilter kernel module with embedded user mode helper |
diff --git a/net/bpfilter/Makefile b/net/bpfilter/Makefile index 051dc18b8ccb..39c6980b5d99 100644 --- a/net/bpfilter/Makefile +++ b/net/bpfilter/Makefile | |||
@@ -15,20 +15,7 @@ ifeq ($(CONFIG_BPFILTER_UMH), y) | |||
15 | HOSTLDFLAGS += -static | 15 | HOSTLDFLAGS += -static |
16 | endif | 16 | endif |
17 | 17 | ||
18 | # a bit of elf magic to convert bpfilter_umh binary into a binary blob | 18 | $(obj)/bpfilter_umh_blob.o: $(obj)/bpfilter_umh |
19 | # inside bpfilter_umh.o elf file referenced by | ||
20 | # _binary_net_bpfilter_bpfilter_umh_start symbol | ||
21 | # which bpfilter_kern.c passes further into umh blob loader at run-time | ||
22 | quiet_cmd_copy_umh = GEN $@ | ||
23 | cmd_copy_umh = echo ':' > $(obj)/.bpfilter_umh.o.cmd; \ | ||
24 | $(OBJCOPY) -I binary \ | ||
25 | `LC_ALL=C $(OBJDUMP) -f net/bpfilter/bpfilter_umh \ | ||
26 | |awk -F' |,' '/file format/{print "-O",$$NF} \ | ||
27 | /^architecture:/{print "-B",$$2}'` \ | ||
28 | --rename-section .data=.init.rodata $< $@ | ||
29 | |||
30 | $(obj)/bpfilter_umh.o: $(obj)/bpfilter_umh | ||
31 | $(call cmd,copy_umh) | ||
32 | 19 | ||
33 | obj-$(CONFIG_BPFILTER_UMH) += bpfilter.o | 20 | obj-$(CONFIG_BPFILTER_UMH) += bpfilter.o |
34 | bpfilter-objs += bpfilter_kern.o bpfilter_umh.o | 21 | bpfilter-objs += bpfilter_kern.o bpfilter_umh_blob.o |
diff --git a/net/bpfilter/bpfilter_kern.c b/net/bpfilter/bpfilter_kern.c index 09522573f611..f0fc182d3db7 100644 --- a/net/bpfilter/bpfilter_kern.c +++ b/net/bpfilter/bpfilter_kern.c | |||
@@ -10,11 +10,8 @@ | |||
10 | #include <linux/file.h> | 10 | #include <linux/file.h> |
11 | #include "msgfmt.h" | 11 | #include "msgfmt.h" |
12 | 12 | ||
13 | #define UMH_start _binary_net_bpfilter_bpfilter_umh_start | 13 | extern char bpfilter_umh_start; |
14 | #define UMH_end _binary_net_bpfilter_bpfilter_umh_end | 14 | extern char bpfilter_umh_end; |
15 | |||
16 | extern char UMH_start; | ||
17 | extern char UMH_end; | ||
18 | 15 | ||
19 | static struct umh_info info; | 16 | static struct umh_info info; |
20 | /* since ip_getsockopt() can run in parallel, serialize access to umh */ | 17 | /* since ip_getsockopt() can run in parallel, serialize access to umh */ |
@@ -93,7 +90,9 @@ static int __init load_umh(void) | |||
93 | int err; | 90 | int err; |
94 | 91 | ||
95 | /* fork usermode process */ | 92 | /* fork usermode process */ |
96 | err = fork_usermode_blob(&UMH_start, &UMH_end - &UMH_start, &info); | 93 | err = fork_usermode_blob(&bpfilter_umh_start, |
94 | &bpfilter_umh_end - &bpfilter_umh_start, | ||
95 | &info); | ||
97 | if (err) | 96 | if (err) |
98 | return err; | 97 | return err; |
99 | pr_info("Loaded bpfilter_umh pid %d\n", info.pid); | 98 | pr_info("Loaded bpfilter_umh pid %d\n", info.pid); |
diff --git a/net/bpfilter/bpfilter_umh_blob.S b/net/bpfilter/bpfilter_umh_blob.S new file mode 100644 index 000000000000..40311d10d2f2 --- /dev/null +++ b/net/bpfilter/bpfilter_umh_blob.S | |||
@@ -0,0 +1,7 @@ | |||
1 | /* SPDX-License-Identifier: GPL-2.0 */ | ||
2 | .section .init.rodata, "a" | ||
3 | .global bpfilter_umh_start | ||
4 | bpfilter_umh_start: | ||
5 | .incbin "net/bpfilter/bpfilter_umh" | ||
6 | .global bpfilter_umh_end | ||
7 | bpfilter_umh_end: | ||
diff --git a/net/core/dev_ioctl.c b/net/core/dev_ioctl.c index a04e1e88bf3a..50537ff961a7 100644 --- a/net/core/dev_ioctl.c +++ b/net/core/dev_ioctl.c | |||
@@ -285,16 +285,9 @@ static int dev_ifsioc(struct net *net, struct ifreq *ifr, unsigned int cmd) | |||
285 | if (ifr->ifr_qlen < 0) | 285 | if (ifr->ifr_qlen < 0) |
286 | return -EINVAL; | 286 | return -EINVAL; |
287 | if (dev->tx_queue_len ^ ifr->ifr_qlen) { | 287 | if (dev->tx_queue_len ^ ifr->ifr_qlen) { |
288 | unsigned int orig_len = dev->tx_queue_len; | 288 | err = dev_change_tx_queue_len(dev, ifr->ifr_qlen); |
289 | 289 | if (err) | |
290 | dev->tx_queue_len = ifr->ifr_qlen; | ||
291 | err = call_netdevice_notifiers( | ||
292 | NETDEV_CHANGE_TX_QUEUE_LEN, dev); | ||
293 | err = notifier_to_errno(err); | ||
294 | if (err) { | ||
295 | dev->tx_queue_len = orig_len; | ||
296 | return err; | 290 | return err; |
297 | } | ||
298 | } | 291 | } |
299 | return 0; | 292 | return 0; |
300 | 293 | ||
diff --git a/net/core/fib_rules.c b/net/core/fib_rules.c index 126ffc5bc630..f64aa13811ea 100644 --- a/net/core/fib_rules.c +++ b/net/core/fib_rules.c | |||
@@ -416,6 +416,14 @@ static struct fib_rule *rule_find(struct fib_rules_ops *ops, | |||
416 | if (rule->mark && r->mark != rule->mark) | 416 | if (rule->mark && r->mark != rule->mark) |
417 | continue; | 417 | continue; |
418 | 418 | ||
419 | if (rule->suppress_ifgroup != -1 && | ||
420 | r->suppress_ifgroup != rule->suppress_ifgroup) | ||
421 | continue; | ||
422 | |||
423 | if (rule->suppress_prefixlen != -1 && | ||
424 | r->suppress_prefixlen != rule->suppress_prefixlen) | ||
425 | continue; | ||
426 | |||
419 | if (rule->mark_mask && r->mark_mask != rule->mark_mask) | 427 | if (rule->mark_mask && r->mark_mask != rule->mark_mask) |
420 | continue; | 428 | continue; |
421 | 429 | ||
@@ -436,6 +444,9 @@ static struct fib_rule *rule_find(struct fib_rules_ops *ops, | |||
436 | if (rule->ip_proto && r->ip_proto != rule->ip_proto) | 444 | if (rule->ip_proto && r->ip_proto != rule->ip_proto) |
437 | continue; | 445 | continue; |
438 | 446 | ||
447 | if (rule->proto && r->proto != rule->proto) | ||
448 | continue; | ||
449 | |||
439 | if (fib_rule_port_range_set(&rule->sport_range) && | 450 | if (fib_rule_port_range_set(&rule->sport_range) && |
440 | !fib_rule_port_range_compare(&r->sport_range, | 451 | !fib_rule_port_range_compare(&r->sport_range, |
441 | &rule->sport_range)) | 452 | &rule->sport_range)) |
@@ -645,6 +656,73 @@ errout: | |||
645 | return err; | 656 | return err; |
646 | } | 657 | } |
647 | 658 | ||
659 | static int rule_exists(struct fib_rules_ops *ops, struct fib_rule_hdr *frh, | ||
660 | struct nlattr **tb, struct fib_rule *rule) | ||
661 | { | ||
662 | struct fib_rule *r; | ||
663 | |||
664 | list_for_each_entry(r, &ops->rules_list, list) { | ||
665 | if (r->action != rule->action) | ||
666 | continue; | ||
667 | |||
668 | if (r->table != rule->table) | ||
669 | continue; | ||
670 | |||
671 | if (r->pref != rule->pref) | ||
672 | continue; | ||
673 | |||
674 | if (memcmp(r->iifname, rule->iifname, IFNAMSIZ)) | ||
675 | continue; | ||
676 | |||
677 | if (memcmp(r->oifname, rule->oifname, IFNAMSIZ)) | ||
678 | continue; | ||
679 | |||
680 | if (r->mark != rule->mark) | ||
681 | continue; | ||
682 | |||
683 | if (r->suppress_ifgroup != rule->suppress_ifgroup) | ||
684 | continue; | ||
685 | |||
686 | if (r->suppress_prefixlen != rule->suppress_prefixlen) | ||
687 | continue; | ||
688 | |||
689 | if (r->mark_mask != rule->mark_mask) | ||
690 | continue; | ||
691 | |||
692 | if (r->tun_id != rule->tun_id) | ||
693 | continue; | ||
694 | |||
695 | if (r->fr_net != rule->fr_net) | ||
696 | continue; | ||
697 | |||
698 | if (r->l3mdev != rule->l3mdev) | ||
699 | continue; | ||
700 | |||
701 | if (!uid_eq(r->uid_range.start, rule->uid_range.start) || | ||
702 | !uid_eq(r->uid_range.end, rule->uid_range.end)) | ||
703 | continue; | ||
704 | |||
705 | if (r->ip_proto != rule->ip_proto) | ||
706 | continue; | ||
707 | |||
708 | if (r->proto != rule->proto) | ||
709 | continue; | ||
710 | |||
711 | if (!fib_rule_port_range_compare(&r->sport_range, | ||
712 | &rule->sport_range)) | ||
713 | continue; | ||
714 | |||
715 | if (!fib_rule_port_range_compare(&r->dport_range, | ||
716 | &rule->dport_range)) | ||
717 | continue; | ||
718 | |||
719 | if (!ops->compare(r, frh, tb)) | ||
720 | continue; | ||
721 | return 1; | ||
722 | } | ||
723 | return 0; | ||
724 | } | ||
725 | |||
648 | int fib_nl_newrule(struct sk_buff *skb, struct nlmsghdr *nlh, | 726 | int fib_nl_newrule(struct sk_buff *skb, struct nlmsghdr *nlh, |
649 | struct netlink_ext_ack *extack) | 727 | struct netlink_ext_ack *extack) |
650 | { | 728 | { |
@@ -679,7 +757,7 @@ int fib_nl_newrule(struct sk_buff *skb, struct nlmsghdr *nlh, | |||
679 | goto errout; | 757 | goto errout; |
680 | 758 | ||
681 | if ((nlh->nlmsg_flags & NLM_F_EXCL) && | 759 | if ((nlh->nlmsg_flags & NLM_F_EXCL) && |
682 | rule_find(ops, frh, tb, rule, user_priority)) { | 760 | rule_exists(ops, frh, tb, rule)) { |
683 | err = -EEXIST; | 761 | err = -EEXIST; |
684 | goto errout_free; | 762 | goto errout_free; |
685 | } | 763 | } |
diff --git a/net/core/filter.c b/net/core/filter.c index e7f12e9f598c..0ca6907d7efe 100644 --- a/net/core/filter.c +++ b/net/core/filter.c | |||
@@ -4073,8 +4073,9 @@ static int bpf_fib_set_fwd_params(struct bpf_fib_lookup *params, | |||
4073 | memcpy(params->smac, dev->dev_addr, ETH_ALEN); | 4073 | memcpy(params->smac, dev->dev_addr, ETH_ALEN); |
4074 | params->h_vlan_TCI = 0; | 4074 | params->h_vlan_TCI = 0; |
4075 | params->h_vlan_proto = 0; | 4075 | params->h_vlan_proto = 0; |
4076 | params->ifindex = dev->ifindex; | ||
4076 | 4077 | ||
4077 | return dev->ifindex; | 4078 | return 0; |
4078 | } | 4079 | } |
4079 | #endif | 4080 | #endif |
4080 | 4081 | ||
@@ -4098,7 +4099,7 @@ static int bpf_ipv4_fib_lookup(struct net *net, struct bpf_fib_lookup *params, | |||
4098 | /* verify forwarding is enabled on this interface */ | 4099 | /* verify forwarding is enabled on this interface */ |
4099 | in_dev = __in_dev_get_rcu(dev); | 4100 | in_dev = __in_dev_get_rcu(dev); |
4100 | if (unlikely(!in_dev || !IN_DEV_FORWARD(in_dev))) | 4101 | if (unlikely(!in_dev || !IN_DEV_FORWARD(in_dev))) |
4101 | return 0; | 4102 | return BPF_FIB_LKUP_RET_FWD_DISABLED; |
4102 | 4103 | ||
4103 | if (flags & BPF_FIB_LOOKUP_OUTPUT) { | 4104 | if (flags & BPF_FIB_LOOKUP_OUTPUT) { |
4104 | fl4.flowi4_iif = 1; | 4105 | fl4.flowi4_iif = 1; |
@@ -4123,7 +4124,7 @@ static int bpf_ipv4_fib_lookup(struct net *net, struct bpf_fib_lookup *params, | |||
4123 | 4124 | ||
4124 | tb = fib_get_table(net, tbid); | 4125 | tb = fib_get_table(net, tbid); |
4125 | if (unlikely(!tb)) | 4126 | if (unlikely(!tb)) |
4126 | return 0; | 4127 | return BPF_FIB_LKUP_RET_NOT_FWDED; |
4127 | 4128 | ||
4128 | err = fib_table_lookup(tb, &fl4, &res, FIB_LOOKUP_NOREF); | 4129 | err = fib_table_lookup(tb, &fl4, &res, FIB_LOOKUP_NOREF); |
4129 | } else { | 4130 | } else { |
@@ -4135,8 +4136,20 @@ static int bpf_ipv4_fib_lookup(struct net *net, struct bpf_fib_lookup *params, | |||
4135 | err = fib_lookup(net, &fl4, &res, FIB_LOOKUP_NOREF); | 4136 | err = fib_lookup(net, &fl4, &res, FIB_LOOKUP_NOREF); |
4136 | } | 4137 | } |
4137 | 4138 | ||
4138 | if (err || res.type != RTN_UNICAST) | 4139 | if (err) { |
4139 | return 0; | 4140 | /* map fib lookup errors to RTN_ type */ |
4141 | if (err == -EINVAL) | ||
4142 | return BPF_FIB_LKUP_RET_BLACKHOLE; | ||
4143 | if (err == -EHOSTUNREACH) | ||
4144 | return BPF_FIB_LKUP_RET_UNREACHABLE; | ||
4145 | if (err == -EACCES) | ||
4146 | return BPF_FIB_LKUP_RET_PROHIBIT; | ||
4147 | |||
4148 | return BPF_FIB_LKUP_RET_NOT_FWDED; | ||
4149 | } | ||
4150 | |||
4151 | if (res.type != RTN_UNICAST) | ||
4152 | return BPF_FIB_LKUP_RET_NOT_FWDED; | ||
4140 | 4153 | ||
4141 | if (res.fi->fib_nhs > 1) | 4154 | if (res.fi->fib_nhs > 1) |
4142 | fib_select_path(net, &res, &fl4, NULL); | 4155 | fib_select_path(net, &res, &fl4, NULL); |
@@ -4144,19 +4157,16 @@ static int bpf_ipv4_fib_lookup(struct net *net, struct bpf_fib_lookup *params, | |||
4144 | if (check_mtu) { | 4157 | if (check_mtu) { |
4145 | mtu = ip_mtu_from_fib_result(&res, params->ipv4_dst); | 4158 | mtu = ip_mtu_from_fib_result(&res, params->ipv4_dst); |
4146 | if (params->tot_len > mtu) | 4159 | if (params->tot_len > mtu) |
4147 | return 0; | 4160 | return BPF_FIB_LKUP_RET_FRAG_NEEDED; |
4148 | } | 4161 | } |
4149 | 4162 | ||
4150 | nh = &res.fi->fib_nh[res.nh_sel]; | 4163 | nh = &res.fi->fib_nh[res.nh_sel]; |
4151 | 4164 | ||
4152 | /* do not handle lwt encaps right now */ | 4165 | /* do not handle lwt encaps right now */ |
4153 | if (nh->nh_lwtstate) | 4166 | if (nh->nh_lwtstate) |
4154 | return 0; | 4167 | return BPF_FIB_LKUP_RET_UNSUPP_LWT; |
4155 | 4168 | ||
4156 | dev = nh->nh_dev; | 4169 | dev = nh->nh_dev; |
4157 | if (unlikely(!dev)) | ||
4158 | return 0; | ||
4159 | |||
4160 | if (nh->nh_gw) | 4170 | if (nh->nh_gw) |
4161 | params->ipv4_dst = nh->nh_gw; | 4171 | params->ipv4_dst = nh->nh_gw; |
4162 | 4172 | ||
@@ -4166,10 +4176,10 @@ static int bpf_ipv4_fib_lookup(struct net *net, struct bpf_fib_lookup *params, | |||
4166 | * rcu_read_lock_bh is not needed here | 4176 | * rcu_read_lock_bh is not needed here |
4167 | */ | 4177 | */ |
4168 | neigh = __ipv4_neigh_lookup_noref(dev, (__force u32)params->ipv4_dst); | 4178 | neigh = __ipv4_neigh_lookup_noref(dev, (__force u32)params->ipv4_dst); |
4169 | if (neigh) | 4179 | if (!neigh) |
4170 | return bpf_fib_set_fwd_params(params, neigh, dev); | 4180 | return BPF_FIB_LKUP_RET_NO_NEIGH; |
4171 | 4181 | ||
4172 | return 0; | 4182 | return bpf_fib_set_fwd_params(params, neigh, dev); |
4173 | } | 4183 | } |
4174 | #endif | 4184 | #endif |
4175 | 4185 | ||
@@ -4190,7 +4200,7 @@ static int bpf_ipv6_fib_lookup(struct net *net, struct bpf_fib_lookup *params, | |||
4190 | 4200 | ||
4191 | /* link local addresses are never forwarded */ | 4201 | /* link local addresses are never forwarded */ |
4192 | if (rt6_need_strict(dst) || rt6_need_strict(src)) | 4202 | if (rt6_need_strict(dst) || rt6_need_strict(src)) |
4193 | return 0; | 4203 | return BPF_FIB_LKUP_RET_NOT_FWDED; |
4194 | 4204 | ||
4195 | dev = dev_get_by_index_rcu(net, params->ifindex); | 4205 | dev = dev_get_by_index_rcu(net, params->ifindex); |
4196 | if (unlikely(!dev)) | 4206 | if (unlikely(!dev)) |
@@ -4198,7 +4208,7 @@ static int bpf_ipv6_fib_lookup(struct net *net, struct bpf_fib_lookup *params, | |||
4198 | 4208 | ||
4199 | idev = __in6_dev_get_safely(dev); | 4209 | idev = __in6_dev_get_safely(dev); |
4200 | if (unlikely(!idev || !net->ipv6.devconf_all->forwarding)) | 4210 | if (unlikely(!idev || !net->ipv6.devconf_all->forwarding)) |
4201 | return 0; | 4211 | return BPF_FIB_LKUP_RET_FWD_DISABLED; |
4202 | 4212 | ||
4203 | if (flags & BPF_FIB_LOOKUP_OUTPUT) { | 4213 | if (flags & BPF_FIB_LOOKUP_OUTPUT) { |
4204 | fl6.flowi6_iif = 1; | 4214 | fl6.flowi6_iif = 1; |
@@ -4225,7 +4235,7 @@ static int bpf_ipv6_fib_lookup(struct net *net, struct bpf_fib_lookup *params, | |||
4225 | 4235 | ||
4226 | tb = ipv6_stub->fib6_get_table(net, tbid); | 4236 | tb = ipv6_stub->fib6_get_table(net, tbid); |
4227 | if (unlikely(!tb)) | 4237 | if (unlikely(!tb)) |
4228 | return 0; | 4238 | return BPF_FIB_LKUP_RET_NOT_FWDED; |
4229 | 4239 | ||
4230 | f6i = ipv6_stub->fib6_table_lookup(net, tb, oif, &fl6, strict); | 4240 | f6i = ipv6_stub->fib6_table_lookup(net, tb, oif, &fl6, strict); |
4231 | } else { | 4241 | } else { |
@@ -4238,11 +4248,23 @@ static int bpf_ipv6_fib_lookup(struct net *net, struct bpf_fib_lookup *params, | |||
4238 | } | 4248 | } |
4239 | 4249 | ||
4240 | if (unlikely(IS_ERR_OR_NULL(f6i) || f6i == net->ipv6.fib6_null_entry)) | 4250 | if (unlikely(IS_ERR_OR_NULL(f6i) || f6i == net->ipv6.fib6_null_entry)) |
4241 | return 0; | 4251 | return BPF_FIB_LKUP_RET_NOT_FWDED; |
4252 | |||
4253 | if (unlikely(f6i->fib6_flags & RTF_REJECT)) { | ||
4254 | switch (f6i->fib6_type) { | ||
4255 | case RTN_BLACKHOLE: | ||
4256 | return BPF_FIB_LKUP_RET_BLACKHOLE; | ||
4257 | case RTN_UNREACHABLE: | ||
4258 | return BPF_FIB_LKUP_RET_UNREACHABLE; | ||
4259 | case RTN_PROHIBIT: | ||
4260 | return BPF_FIB_LKUP_RET_PROHIBIT; | ||
4261 | default: | ||
4262 | return BPF_FIB_LKUP_RET_NOT_FWDED; | ||
4263 | } | ||
4264 | } | ||
4242 | 4265 | ||
4243 | if (unlikely(f6i->fib6_flags & RTF_REJECT || | 4266 | if (f6i->fib6_type != RTN_UNICAST) |
4244 | f6i->fib6_type != RTN_UNICAST)) | 4267 | return BPF_FIB_LKUP_RET_NOT_FWDED; |
4245 | return 0; | ||
4246 | 4268 | ||
4247 | if (f6i->fib6_nsiblings && fl6.flowi6_oif == 0) | 4269 | if (f6i->fib6_nsiblings && fl6.flowi6_oif == 0) |
4248 | f6i = ipv6_stub->fib6_multipath_select(net, f6i, &fl6, | 4270 | f6i = ipv6_stub->fib6_multipath_select(net, f6i, &fl6, |
@@ -4252,11 +4274,11 @@ static int bpf_ipv6_fib_lookup(struct net *net, struct bpf_fib_lookup *params, | |||
4252 | if (check_mtu) { | 4274 | if (check_mtu) { |
4253 | mtu = ipv6_stub->ip6_mtu_from_fib6(f6i, dst, src); | 4275 | mtu = ipv6_stub->ip6_mtu_from_fib6(f6i, dst, src); |
4254 | if (params->tot_len > mtu) | 4276 | if (params->tot_len > mtu) |
4255 | return 0; | 4277 | return BPF_FIB_LKUP_RET_FRAG_NEEDED; |
4256 | } | 4278 | } |
4257 | 4279 | ||
4258 | if (f6i->fib6_nh.nh_lwtstate) | 4280 | if (f6i->fib6_nh.nh_lwtstate) |
4259 | return 0; | 4281 | return BPF_FIB_LKUP_RET_UNSUPP_LWT; |
4260 | 4282 | ||
4261 | if (f6i->fib6_flags & RTF_GATEWAY) | 4283 | if (f6i->fib6_flags & RTF_GATEWAY) |
4262 | *dst = f6i->fib6_nh.nh_gw; | 4284 | *dst = f6i->fib6_nh.nh_gw; |
@@ -4270,10 +4292,10 @@ static int bpf_ipv6_fib_lookup(struct net *net, struct bpf_fib_lookup *params, | |||
4270 | */ | 4292 | */ |
4271 | neigh = ___neigh_lookup_noref(ipv6_stub->nd_tbl, neigh_key_eq128, | 4293 | neigh = ___neigh_lookup_noref(ipv6_stub->nd_tbl, neigh_key_eq128, |
4272 | ndisc_hashfn, dst, dev); | 4294 | ndisc_hashfn, dst, dev); |
4273 | if (neigh) | 4295 | if (!neigh) |
4274 | return bpf_fib_set_fwd_params(params, neigh, dev); | 4296 | return BPF_FIB_LKUP_RET_NO_NEIGH; |
4275 | 4297 | ||
4276 | return 0; | 4298 | return bpf_fib_set_fwd_params(params, neigh, dev); |
4277 | } | 4299 | } |
4278 | #endif | 4300 | #endif |
4279 | 4301 | ||
@@ -4315,7 +4337,7 @@ BPF_CALL_4(bpf_skb_fib_lookup, struct sk_buff *, skb, | |||
4315 | struct bpf_fib_lookup *, params, int, plen, u32, flags) | 4337 | struct bpf_fib_lookup *, params, int, plen, u32, flags) |
4316 | { | 4338 | { |
4317 | struct net *net = dev_net(skb->dev); | 4339 | struct net *net = dev_net(skb->dev); |
4318 | int index = -EAFNOSUPPORT; | 4340 | int rc = -EAFNOSUPPORT; |
4319 | 4341 | ||
4320 | if (plen < sizeof(*params)) | 4342 | if (plen < sizeof(*params)) |
4321 | return -EINVAL; | 4343 | return -EINVAL; |
@@ -4326,25 +4348,25 @@ BPF_CALL_4(bpf_skb_fib_lookup, struct sk_buff *, skb, | |||
4326 | switch (params->family) { | 4348 | switch (params->family) { |
4327 | #if IS_ENABLED(CONFIG_INET) | 4349 | #if IS_ENABLED(CONFIG_INET) |
4328 | case AF_INET: | 4350 | case AF_INET: |
4329 | index = bpf_ipv4_fib_lookup(net, params, flags, false); | 4351 | rc = bpf_ipv4_fib_lookup(net, params, flags, false); |
4330 | break; | 4352 | break; |
4331 | #endif | 4353 | #endif |
4332 | #if IS_ENABLED(CONFIG_IPV6) | 4354 | #if IS_ENABLED(CONFIG_IPV6) |
4333 | case AF_INET6: | 4355 | case AF_INET6: |
4334 | index = bpf_ipv6_fib_lookup(net, params, flags, false); | 4356 | rc = bpf_ipv6_fib_lookup(net, params, flags, false); |
4335 | break; | 4357 | break; |
4336 | #endif | 4358 | #endif |
4337 | } | 4359 | } |
4338 | 4360 | ||
4339 | if (index > 0) { | 4361 | if (!rc) { |
4340 | struct net_device *dev; | 4362 | struct net_device *dev; |
4341 | 4363 | ||
4342 | dev = dev_get_by_index_rcu(net, index); | 4364 | dev = dev_get_by_index_rcu(net, params->ifindex); |
4343 | if (!is_skb_forwardable(dev, skb)) | 4365 | if (!is_skb_forwardable(dev, skb)) |
4344 | index = 0; | 4366 | rc = BPF_FIB_LKUP_RET_FRAG_NEEDED; |
4345 | } | 4367 | } |
4346 | 4368 | ||
4347 | return index; | 4369 | return rc; |
4348 | } | 4370 | } |
4349 | 4371 | ||
4350 | static const struct bpf_func_proto bpf_skb_fib_lookup_proto = { | 4372 | static const struct bpf_func_proto bpf_skb_fib_lookup_proto = { |
diff --git a/net/core/skbuff.c b/net/core/skbuff.c index c642304f178c..eba8dae22c25 100644 --- a/net/core/skbuff.c +++ b/net/core/skbuff.c | |||
@@ -5276,8 +5276,7 @@ struct sk_buff *alloc_skb_with_frags(unsigned long header_len, | |||
5276 | if (npages >= 1 << order) { | 5276 | if (npages >= 1 << order) { |
5277 | page = alloc_pages((gfp_mask & ~__GFP_DIRECT_RECLAIM) | | 5277 | page = alloc_pages((gfp_mask & ~__GFP_DIRECT_RECLAIM) | |
5278 | __GFP_COMP | | 5278 | __GFP_COMP | |
5279 | __GFP_NOWARN | | 5279 | __GFP_NOWARN, |
5280 | __GFP_NORETRY, | ||
5281 | order); | 5280 | order); |
5282 | if (page) | 5281 | if (page) |
5283 | goto fill_page; | 5282 | goto fill_page; |
diff --git a/net/core/sock.c b/net/core/sock.c index bcc41829a16d..9e8f65585b81 100644 --- a/net/core/sock.c +++ b/net/core/sock.c | |||
@@ -3243,7 +3243,8 @@ static int req_prot_init(const struct proto *prot) | |||
3243 | 3243 | ||
3244 | rsk_prot->slab = kmem_cache_create(rsk_prot->slab_name, | 3244 | rsk_prot->slab = kmem_cache_create(rsk_prot->slab_name, |
3245 | rsk_prot->obj_size, 0, | 3245 | rsk_prot->obj_size, 0, |
3246 | prot->slab_flags, NULL); | 3246 | SLAB_ACCOUNT | prot->slab_flags, |
3247 | NULL); | ||
3247 | 3248 | ||
3248 | if (!rsk_prot->slab) { | 3249 | if (!rsk_prot->slab) { |
3249 | pr_crit("%s: Can't create request sock SLAB cache!\n", | 3250 | pr_crit("%s: Can't create request sock SLAB cache!\n", |
@@ -3258,7 +3259,8 @@ int proto_register(struct proto *prot, int alloc_slab) | |||
3258 | if (alloc_slab) { | 3259 | if (alloc_slab) { |
3259 | prot->slab = kmem_cache_create_usercopy(prot->name, | 3260 | prot->slab = kmem_cache_create_usercopy(prot->name, |
3260 | prot->obj_size, 0, | 3261 | prot->obj_size, 0, |
3261 | SLAB_HWCACHE_ALIGN | prot->slab_flags, | 3262 | SLAB_HWCACHE_ALIGN | SLAB_ACCOUNT | |
3263 | prot->slab_flags, | ||
3262 | prot->useroffset, prot->usersize, | 3264 | prot->useroffset, prot->usersize, |
3263 | NULL); | 3265 | NULL); |
3264 | 3266 | ||
@@ -3281,6 +3283,7 @@ int proto_register(struct proto *prot, int alloc_slab) | |||
3281 | kmem_cache_create(prot->twsk_prot->twsk_slab_name, | 3283 | kmem_cache_create(prot->twsk_prot->twsk_slab_name, |
3282 | prot->twsk_prot->twsk_obj_size, | 3284 | prot->twsk_prot->twsk_obj_size, |
3283 | 0, | 3285 | 0, |
3286 | SLAB_ACCOUNT | | ||
3284 | prot->slab_flags, | 3287 | prot->slab_flags, |
3285 | NULL); | 3288 | NULL); |
3286 | if (prot->twsk_prot->twsk_slab == NULL) | 3289 | if (prot->twsk_prot->twsk_slab == NULL) |
diff --git a/net/ipv4/fou.c b/net/ipv4/fou.c index 1540db65241a..c9ec1603666b 100644 --- a/net/ipv4/fou.c +++ b/net/ipv4/fou.c | |||
@@ -448,9 +448,7 @@ next_proto: | |||
448 | out_unlock: | 448 | out_unlock: |
449 | rcu_read_unlock(); | 449 | rcu_read_unlock(); |
450 | out: | 450 | out: |
451 | NAPI_GRO_CB(skb)->flush |= flush; | 451 | skb_gro_flush_final_remcsum(skb, pp, flush, &grc); |
452 | skb_gro_remcsum_cleanup(skb, &grc); | ||
453 | skb->remcsum_offload = 0; | ||
454 | 452 | ||
455 | return pp; | 453 | return pp; |
456 | } | 454 | } |
diff --git a/net/ipv4/gre_offload.c b/net/ipv4/gre_offload.c index 1859c473b21a..6a7d980105f6 100644 --- a/net/ipv4/gre_offload.c +++ b/net/ipv4/gre_offload.c | |||
@@ -223,7 +223,7 @@ static struct sk_buff **gre_gro_receive(struct sk_buff **head, | |||
223 | out_unlock: | 223 | out_unlock: |
224 | rcu_read_unlock(); | 224 | rcu_read_unlock(); |
225 | out: | 225 | out: |
226 | NAPI_GRO_CB(skb)->flush |= flush; | 226 | skb_gro_flush_final(skb, pp, flush); |
227 | 227 | ||
228 | return pp; | 228 | return pp; |
229 | } | 229 | } |
diff --git a/net/ipv4/sysctl_net_ipv4.c b/net/ipv4/sysctl_net_ipv4.c index d06247ba08b2..af0a857d8352 100644 --- a/net/ipv4/sysctl_net_ipv4.c +++ b/net/ipv4/sysctl_net_ipv4.c | |||
@@ -265,8 +265,9 @@ static int proc_tcp_fastopen_key(struct ctl_table *table, int write, | |||
265 | ipv4.sysctl_tcp_fastopen); | 265 | ipv4.sysctl_tcp_fastopen); |
266 | struct ctl_table tbl = { .maxlen = (TCP_FASTOPEN_KEY_LENGTH * 2 + 10) }; | 266 | struct ctl_table tbl = { .maxlen = (TCP_FASTOPEN_KEY_LENGTH * 2 + 10) }; |
267 | struct tcp_fastopen_context *ctxt; | 267 | struct tcp_fastopen_context *ctxt; |
268 | int ret; | ||
269 | u32 user_key[4]; /* 16 bytes, matching TCP_FASTOPEN_KEY_LENGTH */ | 268 | u32 user_key[4]; /* 16 bytes, matching TCP_FASTOPEN_KEY_LENGTH */ |
269 | __le32 key[4]; | ||
270 | int ret, i; | ||
270 | 271 | ||
271 | tbl.data = kmalloc(tbl.maxlen, GFP_KERNEL); | 272 | tbl.data = kmalloc(tbl.maxlen, GFP_KERNEL); |
272 | if (!tbl.data) | 273 | if (!tbl.data) |
@@ -275,11 +276,14 @@ static int proc_tcp_fastopen_key(struct ctl_table *table, int write, | |||
275 | rcu_read_lock(); | 276 | rcu_read_lock(); |
276 | ctxt = rcu_dereference(net->ipv4.tcp_fastopen_ctx); | 277 | ctxt = rcu_dereference(net->ipv4.tcp_fastopen_ctx); |
277 | if (ctxt) | 278 | if (ctxt) |
278 | memcpy(user_key, ctxt->key, TCP_FASTOPEN_KEY_LENGTH); | 279 | memcpy(key, ctxt->key, TCP_FASTOPEN_KEY_LENGTH); |
279 | else | 280 | else |
280 | memset(user_key, 0, sizeof(user_key)); | 281 | memset(key, 0, sizeof(key)); |
281 | rcu_read_unlock(); | 282 | rcu_read_unlock(); |
282 | 283 | ||
284 | for (i = 0; i < ARRAY_SIZE(key); i++) | ||
285 | user_key[i] = le32_to_cpu(key[i]); | ||
286 | |||
283 | snprintf(tbl.data, tbl.maxlen, "%08x-%08x-%08x-%08x", | 287 | snprintf(tbl.data, tbl.maxlen, "%08x-%08x-%08x-%08x", |
284 | user_key[0], user_key[1], user_key[2], user_key[3]); | 288 | user_key[0], user_key[1], user_key[2], user_key[3]); |
285 | ret = proc_dostring(&tbl, write, buffer, lenp, ppos); | 289 | ret = proc_dostring(&tbl, write, buffer, lenp, ppos); |
@@ -290,13 +294,17 @@ static int proc_tcp_fastopen_key(struct ctl_table *table, int write, | |||
290 | ret = -EINVAL; | 294 | ret = -EINVAL; |
291 | goto bad_key; | 295 | goto bad_key; |
292 | } | 296 | } |
293 | tcp_fastopen_reset_cipher(net, NULL, user_key, | 297 | |
298 | for (i = 0; i < ARRAY_SIZE(user_key); i++) | ||
299 | key[i] = cpu_to_le32(user_key[i]); | ||
300 | |||
301 | tcp_fastopen_reset_cipher(net, NULL, key, | ||
294 | TCP_FASTOPEN_KEY_LENGTH); | 302 | TCP_FASTOPEN_KEY_LENGTH); |
295 | } | 303 | } |
296 | 304 | ||
297 | bad_key: | 305 | bad_key: |
298 | pr_debug("proc FO key set 0x%x-%x-%x-%x <- 0x%s: %u\n", | 306 | pr_debug("proc FO key set 0x%x-%x-%x-%x <- 0x%s: %u\n", |
299 | user_key[0], user_key[1], user_key[2], user_key[3], | 307 | user_key[0], user_key[1], user_key[2], user_key[3], |
300 | (char *)tbl.data, ret); | 308 | (char *)tbl.data, ret); |
301 | kfree(tbl.data); | 309 | kfree(tbl.data); |
302 | return ret; | 310 | return ret; |
diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c index 355d3dffd021..8e5522c6833a 100644 --- a/net/ipv4/tcp_input.c +++ b/net/ipv4/tcp_input.c | |||
@@ -265,7 +265,7 @@ static void __tcp_ecn_check_ce(struct sock *sk, const struct sk_buff *skb) | |||
265 | * it is probably a retransmit. | 265 | * it is probably a retransmit. |
266 | */ | 266 | */ |
267 | if (tp->ecn_flags & TCP_ECN_SEEN) | 267 | if (tp->ecn_flags & TCP_ECN_SEEN) |
268 | tcp_enter_quickack_mode(sk, 1); | 268 | tcp_enter_quickack_mode(sk, 2); |
269 | break; | 269 | break; |
270 | case INET_ECN_CE: | 270 | case INET_ECN_CE: |
271 | if (tcp_ca_needs_ecn(sk)) | 271 | if (tcp_ca_needs_ecn(sk)) |
@@ -273,7 +273,7 @@ static void __tcp_ecn_check_ce(struct sock *sk, const struct sk_buff *skb) | |||
273 | 273 | ||
274 | if (!(tp->ecn_flags & TCP_ECN_DEMAND_CWR)) { | 274 | if (!(tp->ecn_flags & TCP_ECN_DEMAND_CWR)) { |
275 | /* Better not delay acks, sender can have a very low cwnd */ | 275 | /* Better not delay acks, sender can have a very low cwnd */ |
276 | tcp_enter_quickack_mode(sk, 1); | 276 | tcp_enter_quickack_mode(sk, 2); |
277 | tp->ecn_flags |= TCP_ECN_DEMAND_CWR; | 277 | tp->ecn_flags |= TCP_ECN_DEMAND_CWR; |
278 | } | 278 | } |
279 | tp->ecn_flags |= TCP_ECN_SEEN; | 279 | tp->ecn_flags |= TCP_ECN_SEEN; |
@@ -3181,6 +3181,15 @@ static int tcp_clean_rtx_queue(struct sock *sk, u32 prior_fack, | |||
3181 | 3181 | ||
3182 | if (tcp_is_reno(tp)) { | 3182 | if (tcp_is_reno(tp)) { |
3183 | tcp_remove_reno_sacks(sk, pkts_acked); | 3183 | tcp_remove_reno_sacks(sk, pkts_acked); |
3184 | |||
3185 | /* If any of the cumulatively ACKed segments was | ||
3186 | * retransmitted, non-SACK case cannot confirm that | ||
3187 | * progress was due to original transmission due to | ||
3188 | * lack of TCPCB_SACKED_ACKED bits even if some of | ||
3189 | * the packets may have been never retransmitted. | ||
3190 | */ | ||
3191 | if (flag & FLAG_RETRANS_DATA_ACKED) | ||
3192 | flag &= ~FLAG_ORIG_SACK_ACKED; | ||
3184 | } else { | 3193 | } else { |
3185 | int delta; | 3194 | int delta; |
3186 | 3195 | ||
diff --git a/net/ipv4/udp_offload.c b/net/ipv4/udp_offload.c index 92dc9e5a7ff3..69c54540d5b4 100644 --- a/net/ipv4/udp_offload.c +++ b/net/ipv4/udp_offload.c | |||
@@ -394,7 +394,7 @@ unflush: | |||
394 | out_unlock: | 394 | out_unlock: |
395 | rcu_read_unlock(); | 395 | rcu_read_unlock(); |
396 | out: | 396 | out: |
397 | NAPI_GRO_CB(skb)->flush |= flush; | 397 | skb_gro_flush_final(skb, pp, flush); |
398 | return pp; | 398 | return pp; |
399 | } | 399 | } |
400 | EXPORT_SYMBOL(udp_gro_receive); | 400 | EXPORT_SYMBOL(udp_gro_receive); |
diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c index c134286d6a41..91580c62bb86 100644 --- a/net/ipv6/addrconf.c +++ b/net/ipv6/addrconf.c | |||
@@ -4528,6 +4528,7 @@ static int modify_prefix_route(struct inet6_ifaddr *ifp, | |||
4528 | unsigned long expires, u32 flags) | 4528 | unsigned long expires, u32 flags) |
4529 | { | 4529 | { |
4530 | struct fib6_info *f6i; | 4530 | struct fib6_info *f6i; |
4531 | u32 prio; | ||
4531 | 4532 | ||
4532 | f6i = addrconf_get_prefix_route(&ifp->addr, | 4533 | f6i = addrconf_get_prefix_route(&ifp->addr, |
4533 | ifp->prefix_len, | 4534 | ifp->prefix_len, |
@@ -4536,13 +4537,15 @@ static int modify_prefix_route(struct inet6_ifaddr *ifp, | |||
4536 | if (!f6i) | 4537 | if (!f6i) |
4537 | return -ENOENT; | 4538 | return -ENOENT; |
4538 | 4539 | ||
4539 | if (f6i->fib6_metric != ifp->rt_priority) { | 4540 | prio = ifp->rt_priority ? : IP6_RT_PRIO_ADDRCONF; |
4541 | if (f6i->fib6_metric != prio) { | ||
4542 | /* delete old one */ | ||
4543 | ip6_del_rt(dev_net(ifp->idev->dev), f6i); | ||
4544 | |||
4540 | /* add new one */ | 4545 | /* add new one */ |
4541 | addrconf_prefix_route(&ifp->addr, ifp->prefix_len, | 4546 | addrconf_prefix_route(&ifp->addr, ifp->prefix_len, |
4542 | ifp->rt_priority, ifp->idev->dev, | 4547 | ifp->rt_priority, ifp->idev->dev, |
4543 | expires, flags, GFP_KERNEL); | 4548 | expires, flags, GFP_KERNEL); |
4544 | /* delete old one */ | ||
4545 | ip6_del_rt(dev_net(ifp->idev->dev), f6i); | ||
4546 | } else { | 4549 | } else { |
4547 | if (!expires) | 4550 | if (!expires) |
4548 | fib6_clean_expires(f6i); | 4551 | fib6_clean_expires(f6i); |
diff --git a/net/ipv6/netfilter/nf_conntrack_reasm.c b/net/ipv6/netfilter/nf_conntrack_reasm.c index 5e0332014c17..a452d99c9f52 100644 --- a/net/ipv6/netfilter/nf_conntrack_reasm.c +++ b/net/ipv6/netfilter/nf_conntrack_reasm.c | |||
@@ -107,7 +107,7 @@ static int nf_ct_frag6_sysctl_register(struct net *net) | |||
107 | if (hdr == NULL) | 107 | if (hdr == NULL) |
108 | goto err_reg; | 108 | goto err_reg; |
109 | 109 | ||
110 | net->nf_frag.sysctl.frags_hdr = hdr; | 110 | net->nf_frag_frags_hdr = hdr; |
111 | return 0; | 111 | return 0; |
112 | 112 | ||
113 | err_reg: | 113 | err_reg: |
@@ -121,8 +121,8 @@ static void __net_exit nf_ct_frags6_sysctl_unregister(struct net *net) | |||
121 | { | 121 | { |
122 | struct ctl_table *table; | 122 | struct ctl_table *table; |
123 | 123 | ||
124 | table = net->nf_frag.sysctl.frags_hdr->ctl_table_arg; | 124 | table = net->nf_frag_frags_hdr->ctl_table_arg; |
125 | unregister_net_sysctl_table(net->nf_frag.sysctl.frags_hdr); | 125 | unregister_net_sysctl_table(net->nf_frag_frags_hdr); |
126 | if (!net_eq(net, &init_net)) | 126 | if (!net_eq(net, &init_net)) |
127 | kfree(table); | 127 | kfree(table); |
128 | } | 128 | } |
diff --git a/net/ipv6/seg6_hmac.c b/net/ipv6/seg6_hmac.c index 33fb35cbfac1..558fe8cc6d43 100644 --- a/net/ipv6/seg6_hmac.c +++ b/net/ipv6/seg6_hmac.c | |||
@@ -373,7 +373,7 @@ static int seg6_hmac_init_algo(void) | |||
373 | return -ENOMEM; | 373 | return -ENOMEM; |
374 | 374 | ||
375 | for_each_possible_cpu(cpu) { | 375 | for_each_possible_cpu(cpu) { |
376 | tfm = crypto_alloc_shash(algo->name, 0, GFP_KERNEL); | 376 | tfm = crypto_alloc_shash(algo->name, 0, 0); |
377 | if (IS_ERR(tfm)) | 377 | if (IS_ERR(tfm)) |
378 | return PTR_ERR(tfm); | 378 | return PTR_ERR(tfm); |
379 | p_tfm = per_cpu_ptr(algo->tfms, cpu); | 379 | p_tfm = per_cpu_ptr(algo->tfms, cpu); |
diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c index 44b5dfe8727d..fa1f1e63a264 100644 --- a/net/mac80211/tx.c +++ b/net/mac80211/tx.c | |||
@@ -4845,7 +4845,9 @@ int ieee80211_tx_control_port(struct wiphy *wiphy, struct net_device *dev, | |||
4845 | skb_reset_network_header(skb); | 4845 | skb_reset_network_header(skb); |
4846 | skb_reset_mac_header(skb); | 4846 | skb_reset_mac_header(skb); |
4847 | 4847 | ||
4848 | local_bh_disable(); | ||
4848 | __ieee80211_subif_start_xmit(skb, skb->dev, flags); | 4849 | __ieee80211_subif_start_xmit(skb, skb->dev, flags); |
4850 | local_bh_enable(); | ||
4849 | 4851 | ||
4850 | return 0; | 4852 | return 0; |
4851 | } | 4853 | } |
diff --git a/net/netfilter/nf_conncount.c b/net/netfilter/nf_conncount.c index d8383609fe28..510039862aa9 100644 --- a/net/netfilter/nf_conncount.c +++ b/net/netfilter/nf_conncount.c | |||
@@ -47,6 +47,8 @@ struct nf_conncount_tuple { | |||
47 | struct hlist_node node; | 47 | struct hlist_node node; |
48 | struct nf_conntrack_tuple tuple; | 48 | struct nf_conntrack_tuple tuple; |
49 | struct nf_conntrack_zone zone; | 49 | struct nf_conntrack_zone zone; |
50 | int cpu; | ||
51 | u32 jiffies32; | ||
50 | }; | 52 | }; |
51 | 53 | ||
52 | struct nf_conncount_rb { | 54 | struct nf_conncount_rb { |
@@ -91,11 +93,42 @@ bool nf_conncount_add(struct hlist_head *head, | |||
91 | return false; | 93 | return false; |
92 | conn->tuple = *tuple; | 94 | conn->tuple = *tuple; |
93 | conn->zone = *zone; | 95 | conn->zone = *zone; |
96 | conn->cpu = raw_smp_processor_id(); | ||
97 | conn->jiffies32 = (u32)jiffies; | ||
94 | hlist_add_head(&conn->node, head); | 98 | hlist_add_head(&conn->node, head); |
95 | return true; | 99 | return true; |
96 | } | 100 | } |
97 | EXPORT_SYMBOL_GPL(nf_conncount_add); | 101 | EXPORT_SYMBOL_GPL(nf_conncount_add); |
98 | 102 | ||
103 | static const struct nf_conntrack_tuple_hash * | ||
104 | find_or_evict(struct net *net, struct nf_conncount_tuple *conn) | ||
105 | { | ||
106 | const struct nf_conntrack_tuple_hash *found; | ||
107 | unsigned long a, b; | ||
108 | int cpu = raw_smp_processor_id(); | ||
109 | __s32 age; | ||
110 | |||
111 | found = nf_conntrack_find_get(net, &conn->zone, &conn->tuple); | ||
112 | if (found) | ||
113 | return found; | ||
114 | b = conn->jiffies32; | ||
115 | a = (u32)jiffies; | ||
116 | |||
117 | /* conn might have been added just before by another cpu and | ||
118 | * might still be unconfirmed. In this case, nf_conntrack_find() | ||
119 | * returns no result. Thus only evict if this cpu added the | ||
120 | * stale entry or if the entry is older than two jiffies. | ||
121 | */ | ||
122 | age = a - b; | ||
123 | if (conn->cpu == cpu || age >= 2) { | ||
124 | hlist_del(&conn->node); | ||
125 | kmem_cache_free(conncount_conn_cachep, conn); | ||
126 | return ERR_PTR(-ENOENT); | ||
127 | } | ||
128 | |||
129 | return ERR_PTR(-EAGAIN); | ||
130 | } | ||
131 | |||
99 | unsigned int nf_conncount_lookup(struct net *net, struct hlist_head *head, | 132 | unsigned int nf_conncount_lookup(struct net *net, struct hlist_head *head, |
100 | const struct nf_conntrack_tuple *tuple, | 133 | const struct nf_conntrack_tuple *tuple, |
101 | const struct nf_conntrack_zone *zone, | 134 | const struct nf_conntrack_zone *zone, |
@@ -103,18 +136,27 @@ unsigned int nf_conncount_lookup(struct net *net, struct hlist_head *head, | |||
103 | { | 136 | { |
104 | const struct nf_conntrack_tuple_hash *found; | 137 | const struct nf_conntrack_tuple_hash *found; |
105 | struct nf_conncount_tuple *conn; | 138 | struct nf_conncount_tuple *conn; |
106 | struct hlist_node *n; | ||
107 | struct nf_conn *found_ct; | 139 | struct nf_conn *found_ct; |
140 | struct hlist_node *n; | ||
108 | unsigned int length = 0; | 141 | unsigned int length = 0; |
109 | 142 | ||
110 | *addit = tuple ? true : false; | 143 | *addit = tuple ? true : false; |
111 | 144 | ||
112 | /* check the saved connections */ | 145 | /* check the saved connections */ |
113 | hlist_for_each_entry_safe(conn, n, head, node) { | 146 | hlist_for_each_entry_safe(conn, n, head, node) { |
114 | found = nf_conntrack_find_get(net, &conn->zone, &conn->tuple); | 147 | found = find_or_evict(net, conn); |
115 | if (found == NULL) { | 148 | if (IS_ERR(found)) { |
116 | hlist_del(&conn->node); | 149 | /* Not found, but might be about to be confirmed */ |
117 | kmem_cache_free(conncount_conn_cachep, conn); | 150 | if (PTR_ERR(found) == -EAGAIN) { |
151 | length++; | ||
152 | if (!tuple) | ||
153 | continue; | ||
154 | |||
155 | if (nf_ct_tuple_equal(&conn->tuple, tuple) && | ||
156 | nf_ct_zone_id(&conn->zone, conn->zone.dir) == | ||
157 | nf_ct_zone_id(zone, zone->dir)) | ||
158 | *addit = false; | ||
159 | } | ||
118 | continue; | 160 | continue; |
119 | } | 161 | } |
120 | 162 | ||
diff --git a/net/netfilter/nf_conntrack_helper.c b/net/netfilter/nf_conntrack_helper.c index 551a1eddf0fa..a75b11c39312 100644 --- a/net/netfilter/nf_conntrack_helper.c +++ b/net/netfilter/nf_conntrack_helper.c | |||
@@ -465,6 +465,11 @@ void nf_conntrack_helper_unregister(struct nf_conntrack_helper *me) | |||
465 | 465 | ||
466 | nf_ct_expect_iterate_destroy(expect_iter_me, NULL); | 466 | nf_ct_expect_iterate_destroy(expect_iter_me, NULL); |
467 | nf_ct_iterate_destroy(unhelp, me); | 467 | nf_ct_iterate_destroy(unhelp, me); |
468 | |||
469 | /* Maybe someone has gotten the helper already when unhelp above. | ||
470 | * So need to wait it. | ||
471 | */ | ||
472 | synchronize_rcu(); | ||
468 | } | 473 | } |
469 | EXPORT_SYMBOL_GPL(nf_conntrack_helper_unregister); | 474 | EXPORT_SYMBOL_GPL(nf_conntrack_helper_unregister); |
470 | 475 | ||
diff --git a/net/netfilter/nf_log.c b/net/netfilter/nf_log.c index 426457047578..a61d6df6e5f6 100644 --- a/net/netfilter/nf_log.c +++ b/net/netfilter/nf_log.c | |||
@@ -424,6 +424,10 @@ static int nf_log_proc_dostring(struct ctl_table *table, int write, | |||
424 | if (write) { | 424 | if (write) { |
425 | struct ctl_table tmp = *table; | 425 | struct ctl_table tmp = *table; |
426 | 426 | ||
427 | /* proc_dostring() can append to existing strings, so we need to | ||
428 | * initialize it as an empty string. | ||
429 | */ | ||
430 | buf[0] = '\0'; | ||
427 | tmp.data = buf; | 431 | tmp.data = buf; |
428 | r = proc_dostring(&tmp, write, buffer, lenp, ppos); | 432 | r = proc_dostring(&tmp, write, buffer, lenp, ppos); |
429 | if (r) | 433 | if (r) |
@@ -442,14 +446,17 @@ static int nf_log_proc_dostring(struct ctl_table *table, int write, | |||
442 | rcu_assign_pointer(net->nf.nf_loggers[tindex], logger); | 446 | rcu_assign_pointer(net->nf.nf_loggers[tindex], logger); |
443 | mutex_unlock(&nf_log_mutex); | 447 | mutex_unlock(&nf_log_mutex); |
444 | } else { | 448 | } else { |
449 | struct ctl_table tmp = *table; | ||
450 | |||
451 | tmp.data = buf; | ||
445 | mutex_lock(&nf_log_mutex); | 452 | mutex_lock(&nf_log_mutex); |
446 | logger = nft_log_dereference(net->nf.nf_loggers[tindex]); | 453 | logger = nft_log_dereference(net->nf.nf_loggers[tindex]); |
447 | if (!logger) | 454 | if (!logger) |
448 | table->data = "NONE"; | 455 | strlcpy(buf, "NONE", sizeof(buf)); |
449 | else | 456 | else |
450 | table->data = logger->name; | 457 | strlcpy(buf, logger->name, sizeof(buf)); |
451 | r = proc_dostring(table, write, buffer, lenp, ppos); | ||
452 | mutex_unlock(&nf_log_mutex); | 458 | mutex_unlock(&nf_log_mutex); |
459 | r = proc_dostring(&tmp, write, buffer, lenp, ppos); | ||
453 | } | 460 | } |
454 | 461 | ||
455 | return r; | 462 | return r; |
diff --git a/net/netfilter/nfnetlink_queue.c b/net/netfilter/nfnetlink_queue.c index 4ccd2988f9db..ea4ba551abb2 100644 --- a/net/netfilter/nfnetlink_queue.c +++ b/net/netfilter/nfnetlink_queue.c | |||
@@ -1243,6 +1243,9 @@ static int nfqnl_recv_unsupp(struct net *net, struct sock *ctnl, | |||
1243 | static const struct nla_policy nfqa_cfg_policy[NFQA_CFG_MAX+1] = { | 1243 | static const struct nla_policy nfqa_cfg_policy[NFQA_CFG_MAX+1] = { |
1244 | [NFQA_CFG_CMD] = { .len = sizeof(struct nfqnl_msg_config_cmd) }, | 1244 | [NFQA_CFG_CMD] = { .len = sizeof(struct nfqnl_msg_config_cmd) }, |
1245 | [NFQA_CFG_PARAMS] = { .len = sizeof(struct nfqnl_msg_config_params) }, | 1245 | [NFQA_CFG_PARAMS] = { .len = sizeof(struct nfqnl_msg_config_params) }, |
1246 | [NFQA_CFG_QUEUE_MAXLEN] = { .type = NLA_U32 }, | ||
1247 | [NFQA_CFG_MASK] = { .type = NLA_U32 }, | ||
1248 | [NFQA_CFG_FLAGS] = { .type = NLA_U32 }, | ||
1246 | }; | 1249 | }; |
1247 | 1250 | ||
1248 | static const struct nf_queue_handler nfqh = { | 1251 | static const struct nf_queue_handler nfqh = { |
diff --git a/net/rds/connection.c b/net/rds/connection.c index abef75da89a7..cfb05953b0e5 100644 --- a/net/rds/connection.c +++ b/net/rds/connection.c | |||
@@ -659,11 +659,19 @@ static void rds_conn_info(struct socket *sock, unsigned int len, | |||
659 | 659 | ||
660 | int rds_conn_init(void) | 660 | int rds_conn_init(void) |
661 | { | 661 | { |
662 | int ret; | ||
663 | |||
664 | ret = rds_loop_net_init(); /* register pernet callback */ | ||
665 | if (ret) | ||
666 | return ret; | ||
667 | |||
662 | rds_conn_slab = kmem_cache_create("rds_connection", | 668 | rds_conn_slab = kmem_cache_create("rds_connection", |
663 | sizeof(struct rds_connection), | 669 | sizeof(struct rds_connection), |
664 | 0, 0, NULL); | 670 | 0, 0, NULL); |
665 | if (!rds_conn_slab) | 671 | if (!rds_conn_slab) { |
672 | rds_loop_net_exit(); | ||
666 | return -ENOMEM; | 673 | return -ENOMEM; |
674 | } | ||
667 | 675 | ||
668 | rds_info_register_func(RDS_INFO_CONNECTIONS, rds_conn_info); | 676 | rds_info_register_func(RDS_INFO_CONNECTIONS, rds_conn_info); |
669 | rds_info_register_func(RDS_INFO_SEND_MESSAGES, | 677 | rds_info_register_func(RDS_INFO_SEND_MESSAGES, |
@@ -676,6 +684,7 @@ int rds_conn_init(void) | |||
676 | 684 | ||
677 | void rds_conn_exit(void) | 685 | void rds_conn_exit(void) |
678 | { | 686 | { |
687 | rds_loop_net_exit(); /* unregister pernet callback */ | ||
679 | rds_loop_exit(); | 688 | rds_loop_exit(); |
680 | 689 | ||
681 | WARN_ON(!hlist_empty(rds_conn_hash)); | 690 | WARN_ON(!hlist_empty(rds_conn_hash)); |
diff --git a/net/rds/loop.c b/net/rds/loop.c index dac6218a460e..feea1f96ee2a 100644 --- a/net/rds/loop.c +++ b/net/rds/loop.c | |||
@@ -33,6 +33,8 @@ | |||
33 | #include <linux/kernel.h> | 33 | #include <linux/kernel.h> |
34 | #include <linux/slab.h> | 34 | #include <linux/slab.h> |
35 | #include <linux/in.h> | 35 | #include <linux/in.h> |
36 | #include <net/net_namespace.h> | ||
37 | #include <net/netns/generic.h> | ||
36 | 38 | ||
37 | #include "rds_single_path.h" | 39 | #include "rds_single_path.h" |
38 | #include "rds.h" | 40 | #include "rds.h" |
@@ -40,6 +42,17 @@ | |||
40 | 42 | ||
41 | static DEFINE_SPINLOCK(loop_conns_lock); | 43 | static DEFINE_SPINLOCK(loop_conns_lock); |
42 | static LIST_HEAD(loop_conns); | 44 | static LIST_HEAD(loop_conns); |
45 | static atomic_t rds_loop_unloading = ATOMIC_INIT(0); | ||
46 | |||
47 | static void rds_loop_set_unloading(void) | ||
48 | { | ||
49 | atomic_set(&rds_loop_unloading, 1); | ||
50 | } | ||
51 | |||
52 | static bool rds_loop_is_unloading(struct rds_connection *conn) | ||
53 | { | ||
54 | return atomic_read(&rds_loop_unloading) != 0; | ||
55 | } | ||
43 | 56 | ||
44 | /* | 57 | /* |
45 | * This 'loopback' transport is a special case for flows that originate | 58 | * This 'loopback' transport is a special case for flows that originate |
@@ -165,6 +178,8 @@ void rds_loop_exit(void) | |||
165 | struct rds_loop_connection *lc, *_lc; | 178 | struct rds_loop_connection *lc, *_lc; |
166 | LIST_HEAD(tmp_list); | 179 | LIST_HEAD(tmp_list); |
167 | 180 | ||
181 | rds_loop_set_unloading(); | ||
182 | synchronize_rcu(); | ||
168 | /* avoid calling conn_destroy with irqs off */ | 183 | /* avoid calling conn_destroy with irqs off */ |
169 | spin_lock_irq(&loop_conns_lock); | 184 | spin_lock_irq(&loop_conns_lock); |
170 | list_splice(&loop_conns, &tmp_list); | 185 | list_splice(&loop_conns, &tmp_list); |
@@ -177,6 +192,46 @@ void rds_loop_exit(void) | |||
177 | } | 192 | } |
178 | } | 193 | } |
179 | 194 | ||
195 | static void rds_loop_kill_conns(struct net *net) | ||
196 | { | ||
197 | struct rds_loop_connection *lc, *_lc; | ||
198 | LIST_HEAD(tmp_list); | ||
199 | |||
200 | spin_lock_irq(&loop_conns_lock); | ||
201 | list_for_each_entry_safe(lc, _lc, &loop_conns, loop_node) { | ||
202 | struct net *c_net = read_pnet(&lc->conn->c_net); | ||
203 | |||
204 | if (net != c_net) | ||
205 | continue; | ||
206 | list_move_tail(&lc->loop_node, &tmp_list); | ||
207 | } | ||
208 | spin_unlock_irq(&loop_conns_lock); | ||
209 | |||
210 | list_for_each_entry_safe(lc, _lc, &tmp_list, loop_node) { | ||
211 | WARN_ON(lc->conn->c_passive); | ||
212 | rds_conn_destroy(lc->conn); | ||
213 | } | ||
214 | } | ||
215 | |||
216 | static void __net_exit rds_loop_exit_net(struct net *net) | ||
217 | { | ||
218 | rds_loop_kill_conns(net); | ||
219 | } | ||
220 | |||
221 | static struct pernet_operations rds_loop_net_ops = { | ||
222 | .exit = rds_loop_exit_net, | ||
223 | }; | ||
224 | |||
225 | int rds_loop_net_init(void) | ||
226 | { | ||
227 | return register_pernet_device(&rds_loop_net_ops); | ||
228 | } | ||
229 | |||
230 | void rds_loop_net_exit(void) | ||
231 | { | ||
232 | unregister_pernet_device(&rds_loop_net_ops); | ||
233 | } | ||
234 | |||
180 | /* | 235 | /* |
181 | * This is missing .xmit_* because loop doesn't go through generic | 236 | * This is missing .xmit_* because loop doesn't go through generic |
182 | * rds_send_xmit() and doesn't call rds_recv_incoming(). .listen_stop and | 237 | * rds_send_xmit() and doesn't call rds_recv_incoming(). .listen_stop and |
@@ -194,4 +249,5 @@ struct rds_transport rds_loop_transport = { | |||
194 | .inc_free = rds_loop_inc_free, | 249 | .inc_free = rds_loop_inc_free, |
195 | .t_name = "loopback", | 250 | .t_name = "loopback", |
196 | .t_type = RDS_TRANS_LOOP, | 251 | .t_type = RDS_TRANS_LOOP, |
252 | .t_unloading = rds_loop_is_unloading, | ||
197 | }; | 253 | }; |
diff --git a/net/rds/loop.h b/net/rds/loop.h index 469fa4b2da4f..bbc8cdd030df 100644 --- a/net/rds/loop.h +++ b/net/rds/loop.h | |||
@@ -5,6 +5,8 @@ | |||
5 | /* loop.c */ | 5 | /* loop.c */ |
6 | extern struct rds_transport rds_loop_transport; | 6 | extern struct rds_transport rds_loop_transport; |
7 | 7 | ||
8 | int rds_loop_net_init(void); | ||
9 | void rds_loop_net_exit(void); | ||
8 | void rds_loop_exit(void); | 10 | void rds_loop_exit(void); |
9 | 11 | ||
10 | #endif | 12 | #endif |
diff --git a/net/smc/af_smc.c b/net/smc/af_smc.c index 973b4471b532..3c1405df936c 100644 --- a/net/smc/af_smc.c +++ b/net/smc/af_smc.c | |||
@@ -45,6 +45,7 @@ static DEFINE_MUTEX(smc_create_lgr_pending); /* serialize link group | |||
45 | */ | 45 | */ |
46 | 46 | ||
47 | static void smc_tcp_listen_work(struct work_struct *); | 47 | static void smc_tcp_listen_work(struct work_struct *); |
48 | static void smc_connect_work(struct work_struct *); | ||
48 | 49 | ||
49 | static void smc_set_keepalive(struct sock *sk, int val) | 50 | static void smc_set_keepalive(struct sock *sk, int val) |
50 | { | 51 | { |
@@ -122,6 +123,12 @@ static int smc_release(struct socket *sock) | |||
122 | goto out; | 123 | goto out; |
123 | 124 | ||
124 | smc = smc_sk(sk); | 125 | smc = smc_sk(sk); |
126 | |||
127 | /* cleanup for a dangling non-blocking connect */ | ||
128 | flush_work(&smc->connect_work); | ||
129 | kfree(smc->connect_info); | ||
130 | smc->connect_info = NULL; | ||
131 | |||
125 | if (sk->sk_state == SMC_LISTEN) | 132 | if (sk->sk_state == SMC_LISTEN) |
126 | /* smc_close_non_accepted() is called and acquires | 133 | /* smc_close_non_accepted() is called and acquires |
127 | * sock lock for child sockets again | 134 | * sock lock for child sockets again |
@@ -186,6 +193,7 @@ static struct sock *smc_sock_alloc(struct net *net, struct socket *sock, | |||
186 | sk->sk_protocol = protocol; | 193 | sk->sk_protocol = protocol; |
187 | smc = smc_sk(sk); | 194 | smc = smc_sk(sk); |
188 | INIT_WORK(&smc->tcp_listen_work, smc_tcp_listen_work); | 195 | INIT_WORK(&smc->tcp_listen_work, smc_tcp_listen_work); |
196 | INIT_WORK(&smc->connect_work, smc_connect_work); | ||
189 | INIT_DELAYED_WORK(&smc->conn.tx_work, smc_tx_work); | 197 | INIT_DELAYED_WORK(&smc->conn.tx_work, smc_tx_work); |
190 | INIT_LIST_HEAD(&smc->accept_q); | 198 | INIT_LIST_HEAD(&smc->accept_q); |
191 | spin_lock_init(&smc->accept_q_lock); | 199 | spin_lock_init(&smc->accept_q_lock); |
@@ -576,6 +584,35 @@ static int __smc_connect(struct smc_sock *smc) | |||
576 | return 0; | 584 | return 0; |
577 | } | 585 | } |
578 | 586 | ||
587 | static void smc_connect_work(struct work_struct *work) | ||
588 | { | ||
589 | struct smc_sock *smc = container_of(work, struct smc_sock, | ||
590 | connect_work); | ||
591 | int rc; | ||
592 | |||
593 | lock_sock(&smc->sk); | ||
594 | rc = kernel_connect(smc->clcsock, &smc->connect_info->addr, | ||
595 | smc->connect_info->alen, smc->connect_info->flags); | ||
596 | if (smc->clcsock->sk->sk_err) { | ||
597 | smc->sk.sk_err = smc->clcsock->sk->sk_err; | ||
598 | goto out; | ||
599 | } | ||
600 | if (rc < 0) { | ||
601 | smc->sk.sk_err = -rc; | ||
602 | goto out; | ||
603 | } | ||
604 | |||
605 | rc = __smc_connect(smc); | ||
606 | if (rc < 0) | ||
607 | smc->sk.sk_err = -rc; | ||
608 | |||
609 | out: | ||
610 | smc->sk.sk_state_change(&smc->sk); | ||
611 | kfree(smc->connect_info); | ||
612 | smc->connect_info = NULL; | ||
613 | release_sock(&smc->sk); | ||
614 | } | ||
615 | |||
579 | static int smc_connect(struct socket *sock, struct sockaddr *addr, | 616 | static int smc_connect(struct socket *sock, struct sockaddr *addr, |
580 | int alen, int flags) | 617 | int alen, int flags) |
581 | { | 618 | { |
@@ -605,15 +642,32 @@ static int smc_connect(struct socket *sock, struct sockaddr *addr, | |||
605 | 642 | ||
606 | smc_copy_sock_settings_to_clc(smc); | 643 | smc_copy_sock_settings_to_clc(smc); |
607 | tcp_sk(smc->clcsock->sk)->syn_smc = 1; | 644 | tcp_sk(smc->clcsock->sk)->syn_smc = 1; |
608 | rc = kernel_connect(smc->clcsock, addr, alen, flags); | 645 | if (flags & O_NONBLOCK) { |
609 | if (rc) | 646 | if (smc->connect_info) { |
610 | goto out; | 647 | rc = -EALREADY; |
648 | goto out; | ||
649 | } | ||
650 | smc->connect_info = kzalloc(alen + 2 * sizeof(int), GFP_KERNEL); | ||
651 | if (!smc->connect_info) { | ||
652 | rc = -ENOMEM; | ||
653 | goto out; | ||
654 | } | ||
655 | smc->connect_info->alen = alen; | ||
656 | smc->connect_info->flags = flags ^ O_NONBLOCK; | ||
657 | memcpy(&smc->connect_info->addr, addr, alen); | ||
658 | schedule_work(&smc->connect_work); | ||
659 | rc = -EINPROGRESS; | ||
660 | } else { | ||
661 | rc = kernel_connect(smc->clcsock, addr, alen, flags); | ||
662 | if (rc) | ||
663 | goto out; | ||
611 | 664 | ||
612 | rc = __smc_connect(smc); | 665 | rc = __smc_connect(smc); |
613 | if (rc < 0) | 666 | if (rc < 0) |
614 | goto out; | 667 | goto out; |
615 | else | 668 | else |
616 | rc = 0; /* success cases including fallback */ | 669 | rc = 0; /* success cases including fallback */ |
670 | } | ||
617 | 671 | ||
618 | out: | 672 | out: |
619 | release_sock(sk); | 673 | release_sock(sk); |
@@ -1279,40 +1333,20 @@ static __poll_t smc_poll(struct file *file, struct socket *sock, | |||
1279 | struct sock *sk = sock->sk; | 1333 | struct sock *sk = sock->sk; |
1280 | __poll_t mask = 0; | 1334 | __poll_t mask = 0; |
1281 | struct smc_sock *smc; | 1335 | struct smc_sock *smc; |
1282 | int rc; | ||
1283 | 1336 | ||
1284 | if (!sk) | 1337 | if (!sk) |
1285 | return EPOLLNVAL; | 1338 | return EPOLLNVAL; |
1286 | 1339 | ||
1287 | smc = smc_sk(sock->sk); | 1340 | smc = smc_sk(sock->sk); |
1288 | sock_hold(sk); | ||
1289 | lock_sock(sk); | ||
1290 | if ((sk->sk_state == SMC_INIT) || smc->use_fallback) { | 1341 | if ((sk->sk_state == SMC_INIT) || smc->use_fallback) { |
1291 | /* delegate to CLC child sock */ | 1342 | /* delegate to CLC child sock */ |
1292 | release_sock(sk); | ||
1293 | mask = smc->clcsock->ops->poll(file, smc->clcsock, wait); | 1343 | mask = smc->clcsock->ops->poll(file, smc->clcsock, wait); |
1294 | lock_sock(sk); | ||
1295 | sk->sk_err = smc->clcsock->sk->sk_err; | 1344 | sk->sk_err = smc->clcsock->sk->sk_err; |
1296 | if (sk->sk_err) { | 1345 | if (sk->sk_err) |
1297 | mask |= EPOLLERR; | 1346 | mask |= EPOLLERR; |
1298 | } else { | ||
1299 | /* if non-blocking connect finished ... */ | ||
1300 | if (sk->sk_state == SMC_INIT && | ||
1301 | mask & EPOLLOUT && | ||
1302 | smc->clcsock->sk->sk_state != TCP_CLOSE) { | ||
1303 | rc = __smc_connect(smc); | ||
1304 | if (rc < 0) | ||
1305 | mask |= EPOLLERR; | ||
1306 | /* success cases including fallback */ | ||
1307 | mask |= EPOLLOUT | EPOLLWRNORM; | ||
1308 | } | ||
1309 | } | ||
1310 | } else { | 1347 | } else { |
1311 | if (sk->sk_state != SMC_CLOSED) { | 1348 | if (sk->sk_state != SMC_CLOSED) |
1312 | release_sock(sk); | ||
1313 | sock_poll_wait(file, sk_sleep(sk), wait); | 1349 | sock_poll_wait(file, sk_sleep(sk), wait); |
1314 | lock_sock(sk); | ||
1315 | } | ||
1316 | if (sk->sk_err) | 1350 | if (sk->sk_err) |
1317 | mask |= EPOLLERR; | 1351 | mask |= EPOLLERR; |
1318 | if ((sk->sk_shutdown == SHUTDOWN_MASK) || | 1352 | if ((sk->sk_shutdown == SHUTDOWN_MASK) || |
@@ -1338,10 +1372,7 @@ static __poll_t smc_poll(struct file *file, struct socket *sock, | |||
1338 | } | 1372 | } |
1339 | if (smc->conn.urg_state == SMC_URG_VALID) | 1373 | if (smc->conn.urg_state == SMC_URG_VALID) |
1340 | mask |= EPOLLPRI; | 1374 | mask |= EPOLLPRI; |
1341 | |||
1342 | } | 1375 | } |
1343 | release_sock(sk); | ||
1344 | sock_put(sk); | ||
1345 | 1376 | ||
1346 | return mask; | 1377 | return mask; |
1347 | } | 1378 | } |
diff --git a/net/smc/smc.h b/net/smc/smc.h index 51ae1f10d81a..d7ca26570482 100644 --- a/net/smc/smc.h +++ b/net/smc/smc.h | |||
@@ -187,11 +187,19 @@ struct smc_connection { | |||
187 | struct work_struct close_work; /* peer sent some closing */ | 187 | struct work_struct close_work; /* peer sent some closing */ |
188 | }; | 188 | }; |
189 | 189 | ||
190 | struct smc_connect_info { | ||
191 | int flags; | ||
192 | int alen; | ||
193 | struct sockaddr addr; | ||
194 | }; | ||
195 | |||
190 | struct smc_sock { /* smc sock container */ | 196 | struct smc_sock { /* smc sock container */ |
191 | struct sock sk; | 197 | struct sock sk; |
192 | struct socket *clcsock; /* internal tcp socket */ | 198 | struct socket *clcsock; /* internal tcp socket */ |
193 | struct smc_connection conn; /* smc connection */ | 199 | struct smc_connection conn; /* smc connection */ |
194 | struct smc_sock *listen_smc; /* listen parent */ | 200 | struct smc_sock *listen_smc; /* listen parent */ |
201 | struct smc_connect_info *connect_info; /* connect address & flags */ | ||
202 | struct work_struct connect_work; /* handle non-blocking connect*/ | ||
195 | struct work_struct tcp_listen_work;/* handle tcp socket accepts */ | 203 | struct work_struct tcp_listen_work;/* handle tcp socket accepts */ |
196 | struct work_struct smc_listen_work;/* prepare new accept socket */ | 204 | struct work_struct smc_listen_work;/* prepare new accept socket */ |
197 | struct list_head accept_q; /* sockets to be accepted */ | 205 | struct list_head accept_q; /* sockets to be accepted */ |
diff --git a/net/strparser/strparser.c b/net/strparser/strparser.c index 373836615c57..625acb27efcc 100644 --- a/net/strparser/strparser.c +++ b/net/strparser/strparser.c | |||
@@ -35,7 +35,6 @@ struct _strp_msg { | |||
35 | */ | 35 | */ |
36 | struct strp_msg strp; | 36 | struct strp_msg strp; |
37 | int accum_len; | 37 | int accum_len; |
38 | int early_eaten; | ||
39 | }; | 38 | }; |
40 | 39 | ||
41 | static inline struct _strp_msg *_strp_msg(struct sk_buff *skb) | 40 | static inline struct _strp_msg *_strp_msg(struct sk_buff *skb) |
@@ -115,20 +114,6 @@ static int __strp_recv(read_descriptor_t *desc, struct sk_buff *orig_skb, | |||
115 | head = strp->skb_head; | 114 | head = strp->skb_head; |
116 | if (head) { | 115 | if (head) { |
117 | /* Message already in progress */ | 116 | /* Message already in progress */ |
118 | |||
119 | stm = _strp_msg(head); | ||
120 | if (unlikely(stm->early_eaten)) { | ||
121 | /* Already some number of bytes on the receive sock | ||
122 | * data saved in skb_head, just indicate they | ||
123 | * are consumed. | ||
124 | */ | ||
125 | eaten = orig_len <= stm->early_eaten ? | ||
126 | orig_len : stm->early_eaten; | ||
127 | stm->early_eaten -= eaten; | ||
128 | |||
129 | return eaten; | ||
130 | } | ||
131 | |||
132 | if (unlikely(orig_offset)) { | 117 | if (unlikely(orig_offset)) { |
133 | /* Getting data with a non-zero offset when a message is | 118 | /* Getting data with a non-zero offset when a message is |
134 | * in progress is not expected. If it does happen, we | 119 | * in progress is not expected. If it does happen, we |
@@ -297,9 +282,9 @@ static int __strp_recv(read_descriptor_t *desc, struct sk_buff *orig_skb, | |||
297 | } | 282 | } |
298 | 283 | ||
299 | stm->accum_len += cand_len; | 284 | stm->accum_len += cand_len; |
285 | eaten += cand_len; | ||
300 | strp->need_bytes = stm->strp.full_len - | 286 | strp->need_bytes = stm->strp.full_len - |
301 | stm->accum_len; | 287 | stm->accum_len; |
302 | stm->early_eaten = cand_len; | ||
303 | STRP_STATS_ADD(strp->stats.bytes, cand_len); | 288 | STRP_STATS_ADD(strp->stats.bytes, cand_len); |
304 | desc->count = 0; /* Stop reading socket */ | 289 | desc->count = 0; /* Stop reading socket */ |
305 | break; | 290 | break; |
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c index c7bbe5f0aae8..4eece06be1e7 100644 --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c | |||
@@ -6231,7 +6231,7 @@ do { \ | |||
6231 | nl80211_check_s32); | 6231 | nl80211_check_s32); |
6232 | /* | 6232 | /* |
6233 | * Check HT operation mode based on | 6233 | * Check HT operation mode based on |
6234 | * IEEE 802.11 2012 8.4.2.59 HT Operation element. | 6234 | * IEEE 802.11-2016 9.4.2.57 HT Operation element. |
6235 | */ | 6235 | */ |
6236 | if (tb[NL80211_MESHCONF_HT_OPMODE]) { | 6236 | if (tb[NL80211_MESHCONF_HT_OPMODE]) { |
6237 | ht_opmode = nla_get_u16(tb[NL80211_MESHCONF_HT_OPMODE]); | 6237 | ht_opmode = nla_get_u16(tb[NL80211_MESHCONF_HT_OPMODE]); |
@@ -6241,22 +6241,9 @@ do { \ | |||
6241 | IEEE80211_HT_OP_MODE_NON_HT_STA_PRSNT)) | 6241 | IEEE80211_HT_OP_MODE_NON_HT_STA_PRSNT)) |
6242 | return -EINVAL; | 6242 | return -EINVAL; |
6243 | 6243 | ||
6244 | if ((ht_opmode & IEEE80211_HT_OP_MODE_NON_GF_STA_PRSNT) && | 6244 | /* NON_HT_STA bit is reserved, but some programs set it */ |
6245 | (ht_opmode & IEEE80211_HT_OP_MODE_NON_HT_STA_PRSNT)) | 6245 | ht_opmode &= ~IEEE80211_HT_OP_MODE_NON_HT_STA_PRSNT; |
6246 | return -EINVAL; | ||
6247 | 6246 | ||
6248 | switch (ht_opmode & IEEE80211_HT_OP_MODE_PROTECTION) { | ||
6249 | case IEEE80211_HT_OP_MODE_PROTECTION_NONE: | ||
6250 | case IEEE80211_HT_OP_MODE_PROTECTION_20MHZ: | ||
6251 | if (ht_opmode & IEEE80211_HT_OP_MODE_NON_HT_STA_PRSNT) | ||
6252 | return -EINVAL; | ||
6253 | break; | ||
6254 | case IEEE80211_HT_OP_MODE_PROTECTION_NONMEMBER: | ||
6255 | case IEEE80211_HT_OP_MODE_PROTECTION_NONHT_MIXED: | ||
6256 | if (!(ht_opmode & IEEE80211_HT_OP_MODE_NON_HT_STA_PRSNT)) | ||
6257 | return -EINVAL; | ||
6258 | break; | ||
6259 | } | ||
6260 | cfg->ht_opmode = ht_opmode; | 6247 | cfg->ht_opmode = ht_opmode; |
6261 | mask |= (1 << (NL80211_MESHCONF_HT_OPMODE - 1)); | 6248 | mask |= (1 << (NL80211_MESHCONF_HT_OPMODE - 1)); |
6262 | } | 6249 | } |
@@ -10962,9 +10949,12 @@ static int nl80211_set_wowlan(struct sk_buff *skb, struct genl_info *info) | |||
10962 | rem) { | 10949 | rem) { |
10963 | u8 *mask_pat; | 10950 | u8 *mask_pat; |
10964 | 10951 | ||
10965 | nla_parse_nested(pat_tb, MAX_NL80211_PKTPAT, pat, | 10952 | err = nla_parse_nested(pat_tb, MAX_NL80211_PKTPAT, pat, |
10966 | nl80211_packet_pattern_policy, | 10953 | nl80211_packet_pattern_policy, |
10967 | info->extack); | 10954 | info->extack); |
10955 | if (err) | ||
10956 | goto error; | ||
10957 | |||
10968 | err = -EINVAL; | 10958 | err = -EINVAL; |
10969 | if (!pat_tb[NL80211_PKTPAT_MASK] || | 10959 | if (!pat_tb[NL80211_PKTPAT_MASK] || |
10970 | !pat_tb[NL80211_PKTPAT_PATTERN]) | 10960 | !pat_tb[NL80211_PKTPAT_PATTERN]) |
@@ -11213,8 +11203,11 @@ static int nl80211_parse_coalesce_rule(struct cfg80211_registered_device *rdev, | |||
11213 | rem) { | 11203 | rem) { |
11214 | u8 *mask_pat; | 11204 | u8 *mask_pat; |
11215 | 11205 | ||
11216 | nla_parse_nested(pat_tb, MAX_NL80211_PKTPAT, pat, | 11206 | err = nla_parse_nested(pat_tb, MAX_NL80211_PKTPAT, pat, |
11217 | nl80211_packet_pattern_policy, NULL); | 11207 | nl80211_packet_pattern_policy, NULL); |
11208 | if (err) | ||
11209 | return err; | ||
11210 | |||
11218 | if (!pat_tb[NL80211_PKTPAT_MASK] || | 11211 | if (!pat_tb[NL80211_PKTPAT_MASK] || |
11219 | !pat_tb[NL80211_PKTPAT_PATTERN]) | 11212 | !pat_tb[NL80211_PKTPAT_PATTERN]) |
11220 | return -EINVAL; | 11213 | return -EINVAL; |