Skip to content

Commit fb60bcc

Browse files
committed
Merge git://git.kernel.org/pub/scm/linux/kernel/git/pablo/nf
Pablo Neira Ayuso says: ==================== Netfilter/IPVS fixes for net The following patchset contains Netfilter/IPVS fixes for your net tree, they are: 1) Fix packet drops due to incorrect ECN handling in IPVS, from Vadim Fedorenko. 2) Fix splat with mark restoration in xt_socket with non-full-sock, patch from Subash Abhinov Kasiviswanathan. 3) ipset bogusly bails out when adding IPv4 range containing more than 2^31 addresses, from Jozsef Kadlecsik. 4) Incorrect pernet unregistration order in ipset, from Florian Westphal. 5) Races between dump and swap in ipset results in BUG_ON splats, from Ross Lagerwall. 6) Fix chain renames in nf_tables, from JingPiao Chen. 7) Fix race in pernet codepath with ebtables table registration, from Artem Savkov. 8) Memory leak in error path in set name allocation in nf_tables, patch from Arvind Yadav. 9) Don't dump chain counters if they are not available, this fixes a crash when listing the ruleset. 10) Fix out of bound memory read in strlcpy() in x_tables compat code, from Eric Dumazet. 11) Make sure we only process TCP packets in SYNPROXY hooks, patch from Lin Zhang. 12) Cannot load rules incrementally anymore after xt_bpf with pinned objects, added in revision 1. From Shmulik Ladkani. ==================== Signed-off-by: David S. Miller <davem@davemloft.net>
2 parents 5766cd6 + 98589a0 commit fb60bcc

26 files changed

+107
-64
lines changed

include/linux/bpf.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -368,6 +368,11 @@ static inline void __bpf_prog_uncharge(struct user_struct *user, u32 pages)
368368
{
369369
}
370370

371+
static inline int bpf_obj_get_user(const char __user *pathname)
372+
{
373+
return -EOPNOTSUPP;
374+
}
375+
371376
static inline struct net_device *__dev_map_lookup_elem(struct bpf_map *map,
372377
u32 key)
373378
{

include/linux/netfilter_bridge/ebtables.h

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -108,9 +108,10 @@ struct ebt_table {
108108

109109
#define EBT_ALIGN(s) (((s) + (__alignof__(struct _xt_align)-1)) & \
110110
~(__alignof__(struct _xt_align)-1))
111-
extern struct ebt_table *ebt_register_table(struct net *net,
112-
const struct ebt_table *table,
113-
const struct nf_hook_ops *);
111+
extern int ebt_register_table(struct net *net,
112+
const struct ebt_table *table,
113+
const struct nf_hook_ops *ops,
114+
struct ebt_table **res);
114115
extern void ebt_unregister_table(struct net *net, struct ebt_table *table,
115116
const struct nf_hook_ops *);
116117
extern unsigned int ebt_do_table(struct sk_buff *skb,

include/uapi/linux/netfilter/xt_bpf.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ enum xt_bpf_modes {
2323
XT_BPF_MODE_FD_PINNED,
2424
XT_BPF_MODE_FD_ELF,
2525
};
26+
#define XT_BPF_MODE_PATH_PINNED XT_BPF_MODE_FD_PINNED
2627

2728
struct xt_bpf_info_v1 {
2829
__u16 mode;

kernel/bpf/inode.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -363,6 +363,7 @@ int bpf_obj_get_user(const char __user *pathname)
363363
putname(pname);
364364
return ret;
365365
}
366+
EXPORT_SYMBOL_GPL(bpf_obj_get_user);
366367

367368
static void bpf_evict_inode(struct inode *inode)
368369
{

net/bridge/netfilter/ebtable_broute.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -65,8 +65,8 @@ static int ebt_broute(struct sk_buff *skb)
6565

6666
static int __net_init broute_net_init(struct net *net)
6767
{
68-
net->xt.broute_table = ebt_register_table(net, &broute_table, NULL);
69-
return PTR_ERR_OR_ZERO(net->xt.broute_table);
68+
return ebt_register_table(net, &broute_table, NULL,
69+
&net->xt.broute_table);
7070
}
7171

7272
static void __net_exit broute_net_exit(struct net *net)

net/bridge/netfilter/ebtable_filter.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -93,8 +93,8 @@ static const struct nf_hook_ops ebt_ops_filter[] = {
9393

9494
static int __net_init frame_filter_net_init(struct net *net)
9595
{
96-
net->xt.frame_filter = ebt_register_table(net, &frame_filter, ebt_ops_filter);
97-
return PTR_ERR_OR_ZERO(net->xt.frame_filter);
96+
return ebt_register_table(net, &frame_filter, ebt_ops_filter,
97+
&net->xt.frame_filter);
9898
}
9999

100100
static void __net_exit frame_filter_net_exit(struct net *net)

net/bridge/netfilter/ebtable_nat.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -93,8 +93,8 @@ static const struct nf_hook_ops ebt_ops_nat[] = {
9393

9494
static int __net_init frame_nat_net_init(struct net *net)
9595
{
96-
net->xt.frame_nat = ebt_register_table(net, &frame_nat, ebt_ops_nat);
97-
return PTR_ERR_OR_ZERO(net->xt.frame_nat);
96+
return ebt_register_table(net, &frame_nat, ebt_ops_nat,
97+
&net->xt.frame_nat);
9898
}
9999

100100
static void __net_exit frame_nat_net_exit(struct net *net)

net/bridge/netfilter/ebtables.c

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1169,9 +1169,8 @@ static void __ebt_unregister_table(struct net *net, struct ebt_table *table)
11691169
kfree(table);
11701170
}
11711171

1172-
struct ebt_table *
1173-
ebt_register_table(struct net *net, const struct ebt_table *input_table,
1174-
const struct nf_hook_ops *ops)
1172+
int ebt_register_table(struct net *net, const struct ebt_table *input_table,
1173+
const struct nf_hook_ops *ops, struct ebt_table **res)
11751174
{
11761175
struct ebt_table_info *newinfo;
11771176
struct ebt_table *t, *table;
@@ -1183,7 +1182,7 @@ ebt_register_table(struct net *net, const struct ebt_table *input_table,
11831182
repl->entries == NULL || repl->entries_size == 0 ||
11841183
repl->counters != NULL || input_table->private != NULL) {
11851184
BUGPRINT("Bad table data for ebt_register_table!!!\n");
1186-
return ERR_PTR(-EINVAL);
1185+
return -EINVAL;
11871186
}
11881187

11891188
/* Don't add one table to multiple lists. */
@@ -1252,16 +1251,18 @@ ebt_register_table(struct net *net, const struct ebt_table *input_table,
12521251
list_add(&table->list, &net->xt.tables[NFPROTO_BRIDGE]);
12531252
mutex_unlock(&ebt_mutex);
12541253

1254+
WRITE_ONCE(*res, table);
1255+
12551256
if (!ops)
1256-
return table;
1257+
return 0;
12571258

12581259
ret = nf_register_net_hooks(net, ops, hweight32(table->valid_hooks));
12591260
if (ret) {
12601261
__ebt_unregister_table(net, table);
1261-
return ERR_PTR(ret);
1262+
*res = NULL;
12621263
}
12631264

1264-
return table;
1265+
return ret;
12651266
free_unlock:
12661267
mutex_unlock(&ebt_mutex);
12671268
free_chainstack:
@@ -1276,7 +1277,7 @@ ebt_register_table(struct net *net, const struct ebt_table *input_table,
12761277
free_table:
12771278
kfree(table);
12781279
out:
1279-
return ERR_PTR(ret);
1280+
return ret;
12801281
}
12811282

12821283
void ebt_unregister_table(struct net *net, struct ebt_table *table,

net/ipv4/netfilter/ipt_SYNPROXY.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -330,7 +330,8 @@ static unsigned int ipv4_synproxy_hook(void *priv,
330330
if (synproxy == NULL)
331331
return NF_ACCEPT;
332332

333-
if (nf_is_loopback_packet(skb))
333+
if (nf_is_loopback_packet(skb) ||
334+
ip_hdr(skb)->protocol != IPPROTO_TCP)
334335
return NF_ACCEPT;
335336

336337
thoff = ip_hdrlen(skb);

net/ipv6/netfilter/ip6t_SYNPROXY.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -353,7 +353,7 @@ static unsigned int ipv6_synproxy_hook(void *priv,
353353
nexthdr = ipv6_hdr(skb)->nexthdr;
354354
thoff = ipv6_skip_exthdr(skb, sizeof(struct ipv6hdr), &nexthdr,
355355
&frag_off);
356-
if (thoff < 0)
356+
if (thoff < 0 || nexthdr != IPPROTO_TCP)
357357
return NF_ACCEPT;
358358

359359
th = skb_header_pointer(skb, thoff, sizeof(_th), &_th);

net/netfilter/ipset/ip_set_core.c

Lines changed: 18 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1191,14 +1191,17 @@ static int ip_set_swap(struct net *net, struct sock *ctnl, struct sk_buff *skb,
11911191
from->family == to->family))
11921192
return -IPSET_ERR_TYPE_MISMATCH;
11931193

1194-
if (from->ref_netlink || to->ref_netlink)
1194+
write_lock_bh(&ip_set_ref_lock);
1195+
1196+
if (from->ref_netlink || to->ref_netlink) {
1197+
write_unlock_bh(&ip_set_ref_lock);
11951198
return -EBUSY;
1199+
}
11961200

11971201
strncpy(from_name, from->name, IPSET_MAXNAMELEN);
11981202
strncpy(from->name, to->name, IPSET_MAXNAMELEN);
11991203
strncpy(to->name, from_name, IPSET_MAXNAMELEN);
12001204

1201-
write_lock_bh(&ip_set_ref_lock);
12021205
swap(from->ref, to->ref);
12031206
ip_set(inst, from_id) = to;
12041207
ip_set(inst, to_id) = from;
@@ -2072,35 +2075,39 @@ static struct pernet_operations ip_set_net_ops = {
20722075
static int __init
20732076
ip_set_init(void)
20742077
{
2075-
int ret = nfnetlink_subsys_register(&ip_set_netlink_subsys);
2078+
int ret = register_pernet_subsys(&ip_set_net_ops);
2079+
2080+
if (ret) {
2081+
pr_err("ip_set: cannot register pernet_subsys.\n");
2082+
return ret;
2083+
}
20762084

2085+
ret = nfnetlink_subsys_register(&ip_set_netlink_subsys);
20772086
if (ret != 0) {
20782087
pr_err("ip_set: cannot register with nfnetlink.\n");
2088+
unregister_pernet_subsys(&ip_set_net_ops);
20792089
return ret;
20802090
}
2091+
20812092
ret = nf_register_sockopt(&so_set);
20822093
if (ret != 0) {
20832094
pr_err("SO_SET registry failed: %d\n", ret);
20842095
nfnetlink_subsys_unregister(&ip_set_netlink_subsys);
2096+
unregister_pernet_subsys(&ip_set_net_ops);
20852097
return ret;
20862098
}
2087-
ret = register_pernet_subsys(&ip_set_net_ops);
2088-
if (ret) {
2089-
pr_err("ip_set: cannot register pernet_subsys.\n");
2090-
nf_unregister_sockopt(&so_set);
2091-
nfnetlink_subsys_unregister(&ip_set_netlink_subsys);
2092-
return ret;
2093-
}
2099+
20942100
pr_info("ip_set: protocol %u\n", IPSET_PROTOCOL);
20952101
return 0;
20962102
}
20972103

20982104
static void __exit
20992105
ip_set_fini(void)
21002106
{
2101-
unregister_pernet_subsys(&ip_set_net_ops);
21022107
nf_unregister_sockopt(&so_set);
21032108
nfnetlink_subsys_unregister(&ip_set_netlink_subsys);
2109+
2110+
unregister_pernet_subsys(&ip_set_net_ops);
21042111
pr_debug("these are the famous last words\n");
21052112
}
21062113

net/netfilter/ipset/ip_set_hash_ip.c

Lines changed: 12 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -123,13 +123,12 @@ hash_ip4_uadt(struct ip_set *set, struct nlattr *tb[],
123123
return ret;
124124

125125
ip &= ip_set_hostmask(h->netmask);
126+
e.ip = htonl(ip);
127+
if (e.ip == 0)
128+
return -IPSET_ERR_HASH_ELEM;
126129

127-
if (adt == IPSET_TEST) {
128-
e.ip = htonl(ip);
129-
if (e.ip == 0)
130-
return -IPSET_ERR_HASH_ELEM;
130+
if (adt == IPSET_TEST)
131131
return adtfn(set, &e, &ext, &ext, flags);
132-
}
133132

134133
ip_to = ip;
135134
if (tb[IPSET_ATTR_IP_TO]) {
@@ -148,17 +147,20 @@ hash_ip4_uadt(struct ip_set *set, struct nlattr *tb[],
148147

149148
hosts = h->netmask == 32 ? 1 : 2 << (32 - h->netmask - 1);
150149

151-
if (retried)
150+
if (retried) {
152151
ip = ntohl(h->next.ip);
153-
for (; !before(ip_to, ip); ip += hosts) {
154152
e.ip = htonl(ip);
155-
if (e.ip == 0)
156-
return -IPSET_ERR_HASH_ELEM;
153+
}
154+
for (; ip <= ip_to;) {
157155
ret = adtfn(set, &e, &ext, &ext, flags);
158-
159156
if (ret && !ip_set_eexist(ret, flags))
160157
return ret;
161158

159+
ip += hosts;
160+
e.ip = htonl(ip);
161+
if (e.ip == 0)
162+
return 0;
163+
162164
ret = 0;
163165
}
164166
return ret;

net/netfilter/ipset/ip_set_hash_ipmark.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -149,7 +149,7 @@ hash_ipmark4_uadt(struct ip_set *set, struct nlattr *tb[],
149149

150150
if (retried)
151151
ip = ntohl(h->next.ip);
152-
for (; !before(ip_to, ip); ip++) {
152+
for (; ip <= ip_to; ip++) {
153153
e.ip = htonl(ip);
154154
ret = adtfn(set, &e, &ext, &ext, flags);
155155

net/netfilter/ipset/ip_set_hash_ipport.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -178,7 +178,7 @@ hash_ipport4_uadt(struct ip_set *set, struct nlattr *tb[],
178178

179179
if (retried)
180180
ip = ntohl(h->next.ip);
181-
for (; !before(ip_to, ip); ip++) {
181+
for (; ip <= ip_to; ip++) {
182182
p = retried && ip == ntohl(h->next.ip) ? ntohs(h->next.port)
183183
: port;
184184
for (; p <= port_to; p++) {

net/netfilter/ipset/ip_set_hash_ipportip.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -185,7 +185,7 @@ hash_ipportip4_uadt(struct ip_set *set, struct nlattr *tb[],
185185

186186
if (retried)
187187
ip = ntohl(h->next.ip);
188-
for (; !before(ip_to, ip); ip++) {
188+
for (; ip <= ip_to; ip++) {
189189
p = retried && ip == ntohl(h->next.ip) ? ntohs(h->next.port)
190190
: port;
191191
for (; p <= port_to; p++) {

net/netfilter/ipset/ip_set_hash_ipportnet.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -271,7 +271,7 @@ hash_ipportnet4_uadt(struct ip_set *set, struct nlattr *tb[],
271271

272272
if (retried)
273273
ip = ntohl(h->next.ip);
274-
for (; !before(ip_to, ip); ip++) {
274+
for (; ip <= ip_to; ip++) {
275275
e.ip = htonl(ip);
276276
p = retried && ip == ntohl(h->next.ip) ? ntohs(h->next.port)
277277
: port;
@@ -281,7 +281,7 @@ hash_ipportnet4_uadt(struct ip_set *set, struct nlattr *tb[],
281281
ip == ntohl(h->next.ip) &&
282282
p == ntohs(h->next.port)
283283
? ntohl(h->next.ip2) : ip2_from;
284-
while (!after(ip2, ip2_to)) {
284+
while (ip2 <= ip2_to) {
285285
e.ip2 = htonl(ip2);
286286
ip2_last = ip_set_range_to_cidr(ip2, ip2_to,
287287
&cidr);

net/netfilter/ipset/ip_set_hash_net.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -193,7 +193,7 @@ hash_net4_uadt(struct ip_set *set, struct nlattr *tb[],
193193
}
194194
if (retried)
195195
ip = ntohl(h->next.ip);
196-
while (!after(ip, ip_to)) {
196+
while (ip <= ip_to) {
197197
e.ip = htonl(ip);
198198
last = ip_set_range_to_cidr(ip, ip_to, &e.cidr);
199199
ret = adtfn(set, &e, &ext, &ext, flags);

net/netfilter/ipset/ip_set_hash_netiface.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -255,7 +255,7 @@ hash_netiface4_uadt(struct ip_set *set, struct nlattr *tb[],
255255

256256
if (retried)
257257
ip = ntohl(h->next.ip);
258-
while (!after(ip, ip_to)) {
258+
while (ip <= ip_to) {
259259
e.ip = htonl(ip);
260260
last = ip_set_range_to_cidr(ip, ip_to, &e.cidr);
261261
ret = adtfn(set, &e, &ext, &ext, flags);

net/netfilter/ipset/ip_set_hash_netnet.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -250,13 +250,13 @@ hash_netnet4_uadt(struct ip_set *set, struct nlattr *tb[],
250250
if (retried)
251251
ip = ntohl(h->next.ip[0]);
252252

253-
while (!after(ip, ip_to)) {
253+
while (ip <= ip_to) {
254254
e.ip[0] = htonl(ip);
255255
last = ip_set_range_to_cidr(ip, ip_to, &e.cidr[0]);
256256
ip2 = (retried &&
257257
ip == ntohl(h->next.ip[0])) ? ntohl(h->next.ip[1])
258258
: ip2_from;
259-
while (!after(ip2, ip2_to)) {
259+
while (ip2 <= ip2_to) {
260260
e.ip[1] = htonl(ip2);
261261
last2 = ip_set_range_to_cidr(ip2, ip2_to, &e.cidr[1]);
262262
ret = adtfn(set, &e, &ext, &ext, flags);

net/netfilter/ipset/ip_set_hash_netport.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -241,7 +241,7 @@ hash_netport4_uadt(struct ip_set *set, struct nlattr *tb[],
241241

242242
if (retried)
243243
ip = ntohl(h->next.ip);
244-
while (!after(ip, ip_to)) {
244+
while (ip <= ip_to) {
245245
e.ip = htonl(ip);
246246
last = ip_set_range_to_cidr(ip, ip_to, &cidr);
247247
e.cidr = cidr - 1;

net/netfilter/ipset/ip_set_hash_netportnet.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -291,7 +291,7 @@ hash_netportnet4_uadt(struct ip_set *set, struct nlattr *tb[],
291291
if (retried)
292292
ip = ntohl(h->next.ip[0]);
293293

294-
while (!after(ip, ip_to)) {
294+
while (ip <= ip_to) {
295295
e.ip[0] = htonl(ip);
296296
ip_last = ip_set_range_to_cidr(ip, ip_to, &e.cidr[0]);
297297
p = retried && ip == ntohl(h->next.ip[0]) ? ntohs(h->next.port)
@@ -301,7 +301,7 @@ hash_netportnet4_uadt(struct ip_set *set, struct nlattr *tb[],
301301
ip2 = (retried && ip == ntohl(h->next.ip[0]) &&
302302
p == ntohs(h->next.port)) ? ntohl(h->next.ip[1])
303303
: ip2_from;
304-
while (!after(ip2, ip2_to)) {
304+
while (ip2 <= ip2_to) {
305305
e.ip[1] = htonl(ip2);
306306
ip2_last = ip_set_range_to_cidr(ip2, ip2_to,
307307
&e.cidr[1]);

net/netfilter/ipvs/ip_vs_xmit.c

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -921,6 +921,7 @@ ip_vs_prepare_tunneled_skb(struct sk_buff *skb, int skb_af,
921921
{
922922
struct sk_buff *new_skb = NULL;
923923
struct iphdr *old_iph = NULL;
924+
__u8 old_dsfield;
924925
#ifdef CONFIG_IP_VS_IPV6
925926
struct ipv6hdr *old_ipv6h = NULL;
926927
#endif
@@ -945,7 +946,7 @@ ip_vs_prepare_tunneled_skb(struct sk_buff *skb, int skb_af,
945946
*payload_len =
946947
ntohs(old_ipv6h->payload_len) +
947948
sizeof(*old_ipv6h);
948-
*dsfield = ipv6_get_dsfield(old_ipv6h);
949+
old_dsfield = ipv6_get_dsfield(old_ipv6h);
949950
*ttl = old_ipv6h->hop_limit;
950951
if (df)
951952
*df = 0;
@@ -960,12 +961,15 @@ ip_vs_prepare_tunneled_skb(struct sk_buff *skb, int skb_af,
960961

961962
/* fix old IP header checksum */
962963
ip_send_check(old_iph);
963-
*dsfield = ipv4_get_dsfield(old_iph);
964+
old_dsfield = ipv4_get_dsfield(old_iph);
964965
*ttl = old_iph->ttl;
965966
if (payload_len)
966967
*payload_len = ntohs(old_iph->tot_len);
967968
}
968969

970+
/* Implement full-functionality option for ECN encapsulation */
971+
*dsfield = INET_ECN_encapsulate(old_dsfield, old_dsfield);
972+
969973
return skb;
970974
error:
971975
kfree_skb(skb);

0 commit comments

Comments
 (0)