diff options
26 files changed, 107 insertions, 64 deletions
diff --git a/include/linux/bpf.h b/include/linux/bpf.h index 8390859e79e7..f1af7d63d678 100644 --- a/include/linux/bpf.h +++ b/include/linux/bpf.h | |||
@@ -368,6 +368,11 @@ static inline void __bpf_prog_uncharge(struct user_struct *user, u32 pages) | |||
368 | { | 368 | { |
369 | } | 369 | } |
370 | 370 | ||
371 | static inline int bpf_obj_get_user(const char __user *pathname) | ||
372 | { | ||
373 | return -EOPNOTSUPP; | ||
374 | } | ||
375 | |||
371 | static inline struct net_device *__dev_map_lookup_elem(struct bpf_map *map, | 376 | static inline struct net_device *__dev_map_lookup_elem(struct bpf_map *map, |
372 | u32 key) | 377 | u32 key) |
373 | { | 378 | { |
diff --git a/include/linux/netfilter_bridge/ebtables.h b/include/linux/netfilter_bridge/ebtables.h index 2c2a5514b0df..528b24c78308 100644 --- a/include/linux/netfilter_bridge/ebtables.h +++ b/include/linux/netfilter_bridge/ebtables.h | |||
@@ -108,9 +108,10 @@ struct ebt_table { | |||
108 | 108 | ||
109 | #define EBT_ALIGN(s) (((s) + (__alignof__(struct _xt_align)-1)) & \ | 109 | #define EBT_ALIGN(s) (((s) + (__alignof__(struct _xt_align)-1)) & \ |
110 | ~(__alignof__(struct _xt_align)-1)) | 110 | ~(__alignof__(struct _xt_align)-1)) |
111 | extern struct ebt_table *ebt_register_table(struct net *net, | 111 | extern int ebt_register_table(struct net *net, |
112 | const struct ebt_table *table, | 112 | const struct ebt_table *table, |
113 | const struct nf_hook_ops *); | 113 | const struct nf_hook_ops *ops, |
114 | struct ebt_table **res); | ||
114 | extern void ebt_unregister_table(struct net *net, struct ebt_table *table, | 115 | extern void ebt_unregister_table(struct net *net, struct ebt_table *table, |
115 | const struct nf_hook_ops *); | 116 | const struct nf_hook_ops *); |
116 | extern unsigned int ebt_do_table(struct sk_buff *skb, | 117 | extern unsigned int ebt_do_table(struct sk_buff *skb, |
diff --git a/include/uapi/linux/netfilter/xt_bpf.h b/include/uapi/linux/netfilter/xt_bpf.h index b97725af2ac0..da161b56c79e 100644 --- a/include/uapi/linux/netfilter/xt_bpf.h +++ b/include/uapi/linux/netfilter/xt_bpf.h | |||
@@ -23,6 +23,7 @@ enum xt_bpf_modes { | |||
23 | XT_BPF_MODE_FD_PINNED, | 23 | XT_BPF_MODE_FD_PINNED, |
24 | XT_BPF_MODE_FD_ELF, | 24 | XT_BPF_MODE_FD_ELF, |
25 | }; | 25 | }; |
26 | #define XT_BPF_MODE_PATH_PINNED XT_BPF_MODE_FD_PINNED | ||
26 | 27 | ||
27 | struct xt_bpf_info_v1 { | 28 | struct xt_bpf_info_v1 { |
28 | __u16 mode; | 29 | __u16 mode; |
diff --git a/kernel/bpf/inode.c b/kernel/bpf/inode.c index e833ed914358..be1dde967208 100644 --- a/kernel/bpf/inode.c +++ b/kernel/bpf/inode.c | |||
@@ -363,6 +363,7 @@ out: | |||
363 | putname(pname); | 363 | putname(pname); |
364 | return ret; | 364 | return ret; |
365 | } | 365 | } |
366 | EXPORT_SYMBOL_GPL(bpf_obj_get_user); | ||
366 | 367 | ||
367 | static void bpf_evict_inode(struct inode *inode) | 368 | static void bpf_evict_inode(struct inode *inode) |
368 | { | 369 | { |
diff --git a/net/bridge/netfilter/ebtable_broute.c b/net/bridge/netfilter/ebtable_broute.c index 2585b100ebbb..276b60262981 100644 --- a/net/bridge/netfilter/ebtable_broute.c +++ b/net/bridge/netfilter/ebtable_broute.c | |||
@@ -65,8 +65,8 @@ static int ebt_broute(struct sk_buff *skb) | |||
65 | 65 | ||
66 | static int __net_init broute_net_init(struct net *net) | 66 | static int __net_init broute_net_init(struct net *net) |
67 | { | 67 | { |
68 | net->xt.broute_table = ebt_register_table(net, &broute_table, NULL); | 68 | return ebt_register_table(net, &broute_table, NULL, |
69 | return PTR_ERR_OR_ZERO(net->xt.broute_table); | 69 | &net->xt.broute_table); |
70 | } | 70 | } |
71 | 71 | ||
72 | static void __net_exit broute_net_exit(struct net *net) | 72 | static void __net_exit broute_net_exit(struct net *net) |
diff --git a/net/bridge/netfilter/ebtable_filter.c b/net/bridge/netfilter/ebtable_filter.c index 45a00dbdbcad..c41da5fac84f 100644 --- a/net/bridge/netfilter/ebtable_filter.c +++ b/net/bridge/netfilter/ebtable_filter.c | |||
@@ -93,8 +93,8 @@ static const struct nf_hook_ops ebt_ops_filter[] = { | |||
93 | 93 | ||
94 | static int __net_init frame_filter_net_init(struct net *net) | 94 | static int __net_init frame_filter_net_init(struct net *net) |
95 | { | 95 | { |
96 | net->xt.frame_filter = ebt_register_table(net, &frame_filter, ebt_ops_filter); | 96 | return ebt_register_table(net, &frame_filter, ebt_ops_filter, |
97 | return PTR_ERR_OR_ZERO(net->xt.frame_filter); | 97 | &net->xt.frame_filter); |
98 | } | 98 | } |
99 | 99 | ||
100 | static void __net_exit frame_filter_net_exit(struct net *net) | 100 | static void __net_exit frame_filter_net_exit(struct net *net) |
diff --git a/net/bridge/netfilter/ebtable_nat.c b/net/bridge/netfilter/ebtable_nat.c index 57cd5bb154e7..08df7406ecb3 100644 --- a/net/bridge/netfilter/ebtable_nat.c +++ b/net/bridge/netfilter/ebtable_nat.c | |||
@@ -93,8 +93,8 @@ static const struct nf_hook_ops ebt_ops_nat[] = { | |||
93 | 93 | ||
94 | static int __net_init frame_nat_net_init(struct net *net) | 94 | static int __net_init frame_nat_net_init(struct net *net) |
95 | { | 95 | { |
96 | net->xt.frame_nat = ebt_register_table(net, &frame_nat, ebt_ops_nat); | 96 | return ebt_register_table(net, &frame_nat, ebt_ops_nat, |
97 | return PTR_ERR_OR_ZERO(net->xt.frame_nat); | 97 | &net->xt.frame_nat); |
98 | } | 98 | } |
99 | 99 | ||
100 | static void __net_exit frame_nat_net_exit(struct net *net) | 100 | static void __net_exit frame_nat_net_exit(struct net *net) |
diff --git a/net/bridge/netfilter/ebtables.c b/net/bridge/netfilter/ebtables.c index 83951f978445..3b3dcf719e07 100644 --- a/net/bridge/netfilter/ebtables.c +++ b/net/bridge/netfilter/ebtables.c | |||
@@ -1169,9 +1169,8 @@ static void __ebt_unregister_table(struct net *net, struct ebt_table *table) | |||
1169 | kfree(table); | 1169 | kfree(table); |
1170 | } | 1170 | } |
1171 | 1171 | ||
1172 | struct ebt_table * | 1172 | int ebt_register_table(struct net *net, const struct ebt_table *input_table, |
1173 | ebt_register_table(struct net *net, const struct ebt_table *input_table, | 1173 | const struct nf_hook_ops *ops, struct ebt_table **res) |
1174 | const struct nf_hook_ops *ops) | ||
1175 | { | 1174 | { |
1176 | struct ebt_table_info *newinfo; | 1175 | struct ebt_table_info *newinfo; |
1177 | struct ebt_table *t, *table; | 1176 | struct ebt_table *t, *table; |
@@ -1183,7 +1182,7 @@ ebt_register_table(struct net *net, const struct ebt_table *input_table, | |||
1183 | repl->entries == NULL || repl->entries_size == 0 || | 1182 | repl->entries == NULL || repl->entries_size == 0 || |
1184 | repl->counters != NULL || input_table->private != NULL) { | 1183 | repl->counters != NULL || input_table->private != NULL) { |
1185 | BUGPRINT("Bad table data for ebt_register_table!!!\n"); | 1184 | BUGPRINT("Bad table data for ebt_register_table!!!\n"); |
1186 | return ERR_PTR(-EINVAL); | 1185 | return -EINVAL; |
1187 | } | 1186 | } |
1188 | 1187 | ||
1189 | /* Don't add one table to multiple lists. */ | 1188 | /* Don't add one table to multiple lists. */ |
@@ -1252,16 +1251,18 @@ ebt_register_table(struct net *net, const struct ebt_table *input_table, | |||
1252 | list_add(&table->list, &net->xt.tables[NFPROTO_BRIDGE]); | 1251 | list_add(&table->list, &net->xt.tables[NFPROTO_BRIDGE]); |
1253 | mutex_unlock(&ebt_mutex); | 1252 | mutex_unlock(&ebt_mutex); |
1254 | 1253 | ||
1254 | WRITE_ONCE(*res, table); | ||
1255 | |||
1255 | if (!ops) | 1256 | if (!ops) |
1256 | return table; | 1257 | return 0; |
1257 | 1258 | ||
1258 | ret = nf_register_net_hooks(net, ops, hweight32(table->valid_hooks)); | 1259 | ret = nf_register_net_hooks(net, ops, hweight32(table->valid_hooks)); |
1259 | if (ret) { | 1260 | if (ret) { |
1260 | __ebt_unregister_table(net, table); | 1261 | __ebt_unregister_table(net, table); |
1261 | return ERR_PTR(ret); | 1262 | *res = NULL; |
1262 | } | 1263 | } |
1263 | 1264 | ||
1264 | return table; | 1265 | return ret; |
1265 | free_unlock: | 1266 | free_unlock: |
1266 | mutex_unlock(&ebt_mutex); | 1267 | mutex_unlock(&ebt_mutex); |
1267 | free_chainstack: | 1268 | free_chainstack: |
@@ -1276,7 +1277,7 @@ free_newinfo: | |||
1276 | free_table: | 1277 | free_table: |
1277 | kfree(table); | 1278 | kfree(table); |
1278 | out: | 1279 | out: |
1279 | return ERR_PTR(ret); | 1280 | return ret; |
1280 | } | 1281 | } |
1281 | 1282 | ||
1282 | void ebt_unregister_table(struct net *net, struct ebt_table *table, | 1283 | void ebt_unregister_table(struct net *net, struct ebt_table *table, |
diff --git a/net/ipv4/netfilter/ipt_SYNPROXY.c b/net/ipv4/netfilter/ipt_SYNPROXY.c index 811689e523c3..f75fc6b53115 100644 --- a/net/ipv4/netfilter/ipt_SYNPROXY.c +++ b/net/ipv4/netfilter/ipt_SYNPROXY.c | |||
@@ -330,7 +330,8 @@ static unsigned int ipv4_synproxy_hook(void *priv, | |||
330 | if (synproxy == NULL) | 330 | if (synproxy == NULL) |
331 | return NF_ACCEPT; | 331 | return NF_ACCEPT; |
332 | 332 | ||
333 | if (nf_is_loopback_packet(skb)) | 333 | if (nf_is_loopback_packet(skb) || |
334 | ip_hdr(skb)->protocol != IPPROTO_TCP) | ||
334 | return NF_ACCEPT; | 335 | return NF_ACCEPT; |
335 | 336 | ||
336 | thoff = ip_hdrlen(skb); | 337 | thoff = ip_hdrlen(skb); |
diff --git a/net/ipv6/netfilter/ip6t_SYNPROXY.c b/net/ipv6/netfilter/ip6t_SYNPROXY.c index a5cd43d75393..437af8c95277 100644 --- a/net/ipv6/netfilter/ip6t_SYNPROXY.c +++ b/net/ipv6/netfilter/ip6t_SYNPROXY.c | |||
@@ -353,7 +353,7 @@ static unsigned int ipv6_synproxy_hook(void *priv, | |||
353 | nexthdr = ipv6_hdr(skb)->nexthdr; | 353 | nexthdr = ipv6_hdr(skb)->nexthdr; |
354 | thoff = ipv6_skip_exthdr(skb, sizeof(struct ipv6hdr), &nexthdr, | 354 | thoff = ipv6_skip_exthdr(skb, sizeof(struct ipv6hdr), &nexthdr, |
355 | &frag_off); | 355 | &frag_off); |
356 | if (thoff < 0) | 356 | if (thoff < 0 || nexthdr != IPPROTO_TCP) |
357 | return NF_ACCEPT; | 357 | return NF_ACCEPT; |
358 | 358 | ||
359 | th = skb_header_pointer(skb, thoff, sizeof(_th), &_th); | 359 | th = skb_header_pointer(skb, thoff, sizeof(_th), &_th); |
diff --git a/net/netfilter/ipset/ip_set_core.c b/net/netfilter/ipset/ip_set_core.c index e495b5e484b1..cf84f7b37cd9 100644 --- a/net/netfilter/ipset/ip_set_core.c +++ b/net/netfilter/ipset/ip_set_core.c | |||
@@ -1191,14 +1191,17 @@ static int ip_set_swap(struct net *net, struct sock *ctnl, struct sk_buff *skb, | |||
1191 | from->family == to->family)) | 1191 | from->family == to->family)) |
1192 | return -IPSET_ERR_TYPE_MISMATCH; | 1192 | return -IPSET_ERR_TYPE_MISMATCH; |
1193 | 1193 | ||
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); | ||
1195 | return -EBUSY; | 1198 | return -EBUSY; |
1199 | } | ||
1196 | 1200 | ||
1197 | strncpy(from_name, from->name, IPSET_MAXNAMELEN); | 1201 | strncpy(from_name, from->name, IPSET_MAXNAMELEN); |
1198 | strncpy(from->name, to->name, IPSET_MAXNAMELEN); | 1202 | strncpy(from->name, to->name, IPSET_MAXNAMELEN); |
1199 | strncpy(to->name, from_name, IPSET_MAXNAMELEN); | 1203 | strncpy(to->name, from_name, IPSET_MAXNAMELEN); |
1200 | 1204 | ||
1201 | write_lock_bh(&ip_set_ref_lock); | ||
1202 | swap(from->ref, to->ref); | 1205 | swap(from->ref, to->ref); |
1203 | ip_set(inst, from_id) = to; | 1206 | ip_set(inst, from_id) = to; |
1204 | ip_set(inst, to_id) = from; | 1207 | ip_set(inst, to_id) = from; |
@@ -2072,25 +2075,28 @@ static struct pernet_operations ip_set_net_ops = { | |||
2072 | static int __init | 2075 | static int __init |
2073 | ip_set_init(void) | 2076 | ip_set_init(void) |
2074 | { | 2077 | { |
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 | } | ||
2076 | 2084 | ||
2085 | ret = nfnetlink_subsys_register(&ip_set_netlink_subsys); | ||
2077 | if (ret != 0) { | 2086 | if (ret != 0) { |
2078 | pr_err("ip_set: cannot register with nfnetlink.\n"); | 2087 | pr_err("ip_set: cannot register with nfnetlink.\n"); |
2088 | unregister_pernet_subsys(&ip_set_net_ops); | ||
2079 | return ret; | 2089 | return ret; |
2080 | } | 2090 | } |
2091 | |||
2081 | ret = nf_register_sockopt(&so_set); | 2092 | ret = nf_register_sockopt(&so_set); |
2082 | if (ret != 0) { | 2093 | if (ret != 0) { |
2083 | pr_err("SO_SET registry failed: %d\n", ret); | 2094 | pr_err("SO_SET registry failed: %d\n", ret); |
2084 | nfnetlink_subsys_unregister(&ip_set_netlink_subsys); | 2095 | nfnetlink_subsys_unregister(&ip_set_netlink_subsys); |
2096 | unregister_pernet_subsys(&ip_set_net_ops); | ||
2085 | return ret; | 2097 | return ret; |
2086 | } | 2098 | } |
2087 | ret = register_pernet_subsys(&ip_set_net_ops); | 2099 | |
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 | } | ||
2094 | pr_info("ip_set: protocol %u\n", IPSET_PROTOCOL); | 2100 | pr_info("ip_set: protocol %u\n", IPSET_PROTOCOL); |
2095 | return 0; | 2101 | return 0; |
2096 | } | 2102 | } |
@@ -2098,9 +2104,10 @@ ip_set_init(void) | |||
2098 | static void __exit | 2104 | static void __exit |
2099 | ip_set_fini(void) | 2105 | ip_set_fini(void) |
2100 | { | 2106 | { |
2101 | unregister_pernet_subsys(&ip_set_net_ops); | ||
2102 | nf_unregister_sockopt(&so_set); | 2107 | nf_unregister_sockopt(&so_set); |
2103 | nfnetlink_subsys_unregister(&ip_set_netlink_subsys); | 2108 | nfnetlink_subsys_unregister(&ip_set_netlink_subsys); |
2109 | |||
2110 | unregister_pernet_subsys(&ip_set_net_ops); | ||
2104 | pr_debug("these are the famous last words\n"); | 2111 | pr_debug("these are the famous last words\n"); |
2105 | } | 2112 | } |
2106 | 2113 | ||
diff --git a/net/netfilter/ipset/ip_set_hash_ip.c b/net/netfilter/ipset/ip_set_hash_ip.c index 20bfbd315f61..613eb212cb48 100644 --- a/net/netfilter/ipset/ip_set_hash_ip.c +++ b/net/netfilter/ipset/ip_set_hash_ip.c | |||
@@ -123,13 +123,12 @@ hash_ip4_uadt(struct ip_set *set, struct nlattr *tb[], | |||
123 | return ret; | 123 | return ret; |
124 | 124 | ||
125 | ip &= ip_set_hostmask(h->netmask); | 125 | ip &= ip_set_hostmask(h->netmask); |
126 | e.ip = htonl(ip); | ||
127 | if (e.ip == 0) | ||
128 | return -IPSET_ERR_HASH_ELEM; | ||
126 | 129 | ||
127 | if (adt == IPSET_TEST) { | 130 | if (adt == IPSET_TEST) |
128 | e.ip = htonl(ip); | ||
129 | if (e.ip == 0) | ||
130 | return -IPSET_ERR_HASH_ELEM; | ||
131 | return adtfn(set, &e, &ext, &ext, flags); | 131 | return adtfn(set, &e, &ext, &ext, flags); |
132 | } | ||
133 | 132 | ||
134 | ip_to = ip; | 133 | ip_to = ip; |
135 | if (tb[IPSET_ATTR_IP_TO]) { | 134 | if (tb[IPSET_ATTR_IP_TO]) { |
@@ -148,17 +147,20 @@ hash_ip4_uadt(struct ip_set *set, struct nlattr *tb[], | |||
148 | 147 | ||
149 | hosts = h->netmask == 32 ? 1 : 2 << (32 - h->netmask - 1); | 148 | hosts = h->netmask == 32 ? 1 : 2 << (32 - h->netmask - 1); |
150 | 149 | ||
151 | if (retried) | 150 | if (retried) { |
152 | ip = ntohl(h->next.ip); | 151 | ip = ntohl(h->next.ip); |
153 | for (; !before(ip_to, ip); ip += hosts) { | ||
154 | e.ip = htonl(ip); | 152 | e.ip = htonl(ip); |
155 | if (e.ip == 0) | 153 | } |
156 | return -IPSET_ERR_HASH_ELEM; | 154 | for (; ip <= ip_to;) { |
157 | ret = adtfn(set, &e, &ext, &ext, flags); | 155 | ret = adtfn(set, &e, &ext, &ext, flags); |
158 | |||
159 | if (ret && !ip_set_eexist(ret, flags)) | 156 | if (ret && !ip_set_eexist(ret, flags)) |
160 | return ret; | 157 | return ret; |
161 | 158 | ||
159 | ip += hosts; | ||
160 | e.ip = htonl(ip); | ||
161 | if (e.ip == 0) | ||
162 | return 0; | ||
163 | |||
162 | ret = 0; | 164 | ret = 0; |
163 | } | 165 | } |
164 | return ret; | 166 | return ret; |
diff --git a/net/netfilter/ipset/ip_set_hash_ipmark.c b/net/netfilter/ipset/ip_set_hash_ipmark.c index b64cf14e8352..f3ba8348cf9d 100644 --- a/net/netfilter/ipset/ip_set_hash_ipmark.c +++ b/net/netfilter/ipset/ip_set_hash_ipmark.c | |||
@@ -149,7 +149,7 @@ hash_ipmark4_uadt(struct ip_set *set, struct nlattr *tb[], | |||
149 | 149 | ||
150 | if (retried) | 150 | if (retried) |
151 | ip = ntohl(h->next.ip); | 151 | ip = ntohl(h->next.ip); |
152 | for (; !before(ip_to, ip); ip++) { | 152 | for (; ip <= ip_to; ip++) { |
153 | e.ip = htonl(ip); | 153 | e.ip = htonl(ip); |
154 | ret = adtfn(set, &e, &ext, &ext, flags); | 154 | ret = adtfn(set, &e, &ext, &ext, flags); |
155 | 155 | ||
diff --git a/net/netfilter/ipset/ip_set_hash_ipport.c b/net/netfilter/ipset/ip_set_hash_ipport.c index f438740e6c6a..ddb8039ec1d2 100644 --- a/net/netfilter/ipset/ip_set_hash_ipport.c +++ b/net/netfilter/ipset/ip_set_hash_ipport.c | |||
@@ -178,7 +178,7 @@ hash_ipport4_uadt(struct ip_set *set, struct nlattr *tb[], | |||
178 | 178 | ||
179 | if (retried) | 179 | if (retried) |
180 | ip = ntohl(h->next.ip); | 180 | ip = ntohl(h->next.ip); |
181 | for (; !before(ip_to, ip); ip++) { | 181 | for (; ip <= ip_to; ip++) { |
182 | p = retried && ip == ntohl(h->next.ip) ? ntohs(h->next.port) | 182 | p = retried && ip == ntohl(h->next.ip) ? ntohs(h->next.port) |
183 | : port; | 183 | : port; |
184 | for (; p <= port_to; p++) { | 184 | for (; p <= port_to; p++) { |
diff --git a/net/netfilter/ipset/ip_set_hash_ipportip.c b/net/netfilter/ipset/ip_set_hash_ipportip.c index 6215fb898c50..a7f4d7a85420 100644 --- a/net/netfilter/ipset/ip_set_hash_ipportip.c +++ b/net/netfilter/ipset/ip_set_hash_ipportip.c | |||
@@ -185,7 +185,7 @@ hash_ipportip4_uadt(struct ip_set *set, struct nlattr *tb[], | |||
185 | 185 | ||
186 | if (retried) | 186 | if (retried) |
187 | ip = ntohl(h->next.ip); | 187 | ip = ntohl(h->next.ip); |
188 | for (; !before(ip_to, ip); ip++) { | 188 | for (; ip <= ip_to; ip++) { |
189 | p = retried && ip == ntohl(h->next.ip) ? ntohs(h->next.port) | 189 | p = retried && ip == ntohl(h->next.ip) ? ntohs(h->next.port) |
190 | : port; | 190 | : port; |
191 | for (; p <= port_to; p++) { | 191 | for (; p <= port_to; p++) { |
diff --git a/net/netfilter/ipset/ip_set_hash_ipportnet.c b/net/netfilter/ipset/ip_set_hash_ipportnet.c index 5ab1b99a53c2..a2f19b9906e9 100644 --- a/net/netfilter/ipset/ip_set_hash_ipportnet.c +++ b/net/netfilter/ipset/ip_set_hash_ipportnet.c | |||
@@ -271,7 +271,7 @@ hash_ipportnet4_uadt(struct ip_set *set, struct nlattr *tb[], | |||
271 | 271 | ||
272 | if (retried) | 272 | if (retried) |
273 | ip = ntohl(h->next.ip); | 273 | ip = ntohl(h->next.ip); |
274 | for (; !before(ip_to, ip); ip++) { | 274 | for (; ip <= ip_to; ip++) { |
275 | e.ip = htonl(ip); | 275 | e.ip = htonl(ip); |
276 | p = retried && ip == ntohl(h->next.ip) ? ntohs(h->next.port) | 276 | p = retried && ip == ntohl(h->next.ip) ? ntohs(h->next.port) |
277 | : port; | 277 | : port; |
@@ -281,7 +281,7 @@ hash_ipportnet4_uadt(struct ip_set *set, struct nlattr *tb[], | |||
281 | ip == ntohl(h->next.ip) && | 281 | ip == ntohl(h->next.ip) && |
282 | p == ntohs(h->next.port) | 282 | p == ntohs(h->next.port) |
283 | ? ntohl(h->next.ip2) : ip2_from; | 283 | ? ntohl(h->next.ip2) : ip2_from; |
284 | while (!after(ip2, ip2_to)) { | 284 | while (ip2 <= ip2_to) { |
285 | e.ip2 = htonl(ip2); | 285 | e.ip2 = htonl(ip2); |
286 | ip2_last = ip_set_range_to_cidr(ip2, ip2_to, | 286 | ip2_last = ip_set_range_to_cidr(ip2, ip2_to, |
287 | &cidr); | 287 | &cidr); |
diff --git a/net/netfilter/ipset/ip_set_hash_net.c b/net/netfilter/ipset/ip_set_hash_net.c index 5d9e895452e7..1c67a1761e45 100644 --- a/net/netfilter/ipset/ip_set_hash_net.c +++ b/net/netfilter/ipset/ip_set_hash_net.c | |||
@@ -193,7 +193,7 @@ hash_net4_uadt(struct ip_set *set, struct nlattr *tb[], | |||
193 | } | 193 | } |
194 | if (retried) | 194 | if (retried) |
195 | ip = ntohl(h->next.ip); | 195 | ip = ntohl(h->next.ip); |
196 | while (!after(ip, ip_to)) { | 196 | while (ip <= ip_to) { |
197 | e.ip = htonl(ip); | 197 | e.ip = htonl(ip); |
198 | last = ip_set_range_to_cidr(ip, ip_to, &e.cidr); | 198 | last = ip_set_range_to_cidr(ip, ip_to, &e.cidr); |
199 | ret = adtfn(set, &e, &ext, &ext, flags); | 199 | ret = adtfn(set, &e, &ext, &ext, flags); |
diff --git a/net/netfilter/ipset/ip_set_hash_netiface.c b/net/netfilter/ipset/ip_set_hash_netiface.c index 44cf11939c91..d417074f1c1a 100644 --- a/net/netfilter/ipset/ip_set_hash_netiface.c +++ b/net/netfilter/ipset/ip_set_hash_netiface.c | |||
@@ -255,7 +255,7 @@ hash_netiface4_uadt(struct ip_set *set, struct nlattr *tb[], | |||
255 | 255 | ||
256 | if (retried) | 256 | if (retried) |
257 | ip = ntohl(h->next.ip); | 257 | ip = ntohl(h->next.ip); |
258 | while (!after(ip, ip_to)) { | 258 | while (ip <= ip_to) { |
259 | e.ip = htonl(ip); | 259 | e.ip = htonl(ip); |
260 | last = ip_set_range_to_cidr(ip, ip_to, &e.cidr); | 260 | last = ip_set_range_to_cidr(ip, ip_to, &e.cidr); |
261 | ret = adtfn(set, &e, &ext, &ext, flags); | 261 | ret = adtfn(set, &e, &ext, &ext, flags); |
diff --git a/net/netfilter/ipset/ip_set_hash_netnet.c b/net/netfilter/ipset/ip_set_hash_netnet.c index db614e13b193..7f9ae2e9645b 100644 --- a/net/netfilter/ipset/ip_set_hash_netnet.c +++ b/net/netfilter/ipset/ip_set_hash_netnet.c | |||
@@ -250,13 +250,13 @@ hash_netnet4_uadt(struct ip_set *set, struct nlattr *tb[], | |||
250 | if (retried) | 250 | if (retried) |
251 | ip = ntohl(h->next.ip[0]); | 251 | ip = ntohl(h->next.ip[0]); |
252 | 252 | ||
253 | while (!after(ip, ip_to)) { | 253 | while (ip <= ip_to) { |
254 | e.ip[0] = htonl(ip); | 254 | e.ip[0] = htonl(ip); |
255 | last = ip_set_range_to_cidr(ip, ip_to, &e.cidr[0]); | 255 | last = ip_set_range_to_cidr(ip, ip_to, &e.cidr[0]); |
256 | ip2 = (retried && | 256 | ip2 = (retried && |
257 | ip == ntohl(h->next.ip[0])) ? ntohl(h->next.ip[1]) | 257 | ip == ntohl(h->next.ip[0])) ? ntohl(h->next.ip[1]) |
258 | : ip2_from; | 258 | : ip2_from; |
259 | while (!after(ip2, ip2_to)) { | 259 | while (ip2 <= ip2_to) { |
260 | e.ip[1] = htonl(ip2); | 260 | e.ip[1] = htonl(ip2); |
261 | last2 = ip_set_range_to_cidr(ip2, ip2_to, &e.cidr[1]); | 261 | last2 = ip_set_range_to_cidr(ip2, ip2_to, &e.cidr[1]); |
262 | ret = adtfn(set, &e, &ext, &ext, flags); | 262 | ret = adtfn(set, &e, &ext, &ext, flags); |
diff --git a/net/netfilter/ipset/ip_set_hash_netport.c b/net/netfilter/ipset/ip_set_hash_netport.c index 54b64b6cd0cd..e6ef382febe4 100644 --- a/net/netfilter/ipset/ip_set_hash_netport.c +++ b/net/netfilter/ipset/ip_set_hash_netport.c | |||
@@ -241,7 +241,7 @@ hash_netport4_uadt(struct ip_set *set, struct nlattr *tb[], | |||
241 | 241 | ||
242 | if (retried) | 242 | if (retried) |
243 | ip = ntohl(h->next.ip); | 243 | ip = ntohl(h->next.ip); |
244 | while (!after(ip, ip_to)) { | 244 | while (ip <= ip_to) { |
245 | e.ip = htonl(ip); | 245 | e.ip = htonl(ip); |
246 | last = ip_set_range_to_cidr(ip, ip_to, &cidr); | 246 | last = ip_set_range_to_cidr(ip, ip_to, &cidr); |
247 | e.cidr = cidr - 1; | 247 | e.cidr = cidr - 1; |
diff --git a/net/netfilter/ipset/ip_set_hash_netportnet.c b/net/netfilter/ipset/ip_set_hash_netportnet.c index aff846960ac4..8602f2595a1a 100644 --- a/net/netfilter/ipset/ip_set_hash_netportnet.c +++ b/net/netfilter/ipset/ip_set_hash_netportnet.c | |||
@@ -291,7 +291,7 @@ hash_netportnet4_uadt(struct ip_set *set, struct nlattr *tb[], | |||
291 | if (retried) | 291 | if (retried) |
292 | ip = ntohl(h->next.ip[0]); | 292 | ip = ntohl(h->next.ip[0]); |
293 | 293 | ||
294 | while (!after(ip, ip_to)) { | 294 | while (ip <= ip_to) { |
295 | e.ip[0] = htonl(ip); | 295 | e.ip[0] = htonl(ip); |
296 | ip_last = ip_set_range_to_cidr(ip, ip_to, &e.cidr[0]); | 296 | ip_last = ip_set_range_to_cidr(ip, ip_to, &e.cidr[0]); |
297 | p = retried && ip == ntohl(h->next.ip[0]) ? ntohs(h->next.port) | 297 | 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[], | |||
301 | ip2 = (retried && ip == ntohl(h->next.ip[0]) && | 301 | ip2 = (retried && ip == ntohl(h->next.ip[0]) && |
302 | p == ntohs(h->next.port)) ? ntohl(h->next.ip[1]) | 302 | p == ntohs(h->next.port)) ? ntohl(h->next.ip[1]) |
303 | : ip2_from; | 303 | : ip2_from; |
304 | while (!after(ip2, ip2_to)) { | 304 | while (ip2 <= ip2_to) { |
305 | e.ip[1] = htonl(ip2); | 305 | e.ip[1] = htonl(ip2); |
306 | ip2_last = ip_set_range_to_cidr(ip2, ip2_to, | 306 | ip2_last = ip_set_range_to_cidr(ip2, ip2_to, |
307 | &e.cidr[1]); | 307 | &e.cidr[1]); |
diff --git a/net/netfilter/ipvs/ip_vs_xmit.c b/net/netfilter/ipvs/ip_vs_xmit.c index 90d396814798..4527921b1c3a 100644 --- a/net/netfilter/ipvs/ip_vs_xmit.c +++ b/net/netfilter/ipvs/ip_vs_xmit.c | |||
@@ -921,6 +921,7 @@ ip_vs_prepare_tunneled_skb(struct sk_buff *skb, int skb_af, | |||
921 | { | 921 | { |
922 | struct sk_buff *new_skb = NULL; | 922 | struct sk_buff *new_skb = NULL; |
923 | struct iphdr *old_iph = NULL; | 923 | struct iphdr *old_iph = NULL; |
924 | __u8 old_dsfield; | ||
924 | #ifdef CONFIG_IP_VS_IPV6 | 925 | #ifdef CONFIG_IP_VS_IPV6 |
925 | struct ipv6hdr *old_ipv6h = NULL; | 926 | struct ipv6hdr *old_ipv6h = NULL; |
926 | #endif | 927 | #endif |
@@ -945,7 +946,7 @@ ip_vs_prepare_tunneled_skb(struct sk_buff *skb, int skb_af, | |||
945 | *payload_len = | 946 | *payload_len = |
946 | ntohs(old_ipv6h->payload_len) + | 947 | ntohs(old_ipv6h->payload_len) + |
947 | sizeof(*old_ipv6h); | 948 | sizeof(*old_ipv6h); |
948 | *dsfield = ipv6_get_dsfield(old_ipv6h); | 949 | old_dsfield = ipv6_get_dsfield(old_ipv6h); |
949 | *ttl = old_ipv6h->hop_limit; | 950 | *ttl = old_ipv6h->hop_limit; |
950 | if (df) | 951 | if (df) |
951 | *df = 0; | 952 | *df = 0; |
@@ -960,12 +961,15 @@ ip_vs_prepare_tunneled_skb(struct sk_buff *skb, int skb_af, | |||
960 | 961 | ||
961 | /* fix old IP header checksum */ | 962 | /* fix old IP header checksum */ |
962 | ip_send_check(old_iph); | 963 | ip_send_check(old_iph); |
963 | *dsfield = ipv4_get_dsfield(old_iph); | 964 | old_dsfield = ipv4_get_dsfield(old_iph); |
964 | *ttl = old_iph->ttl; | 965 | *ttl = old_iph->ttl; |
965 | if (payload_len) | 966 | if (payload_len) |
966 | *payload_len = ntohs(old_iph->tot_len); | 967 | *payload_len = ntohs(old_iph->tot_len); |
967 | } | 968 | } |
968 | 969 | ||
970 | /* Implement full-functionality option for ECN encapsulation */ | ||
971 | *dsfield = INET_ECN_encapsulate(old_dsfield, old_dsfield); | ||
972 | |||
969 | return skb; | 973 | return skb; |
970 | error: | 974 | error: |
971 | kfree_skb(skb); | 975 | kfree_skb(skb); |
diff --git a/net/netfilter/nf_tables_api.c b/net/netfilter/nf_tables_api.c index 929927171426..64e1ee091225 100644 --- a/net/netfilter/nf_tables_api.c +++ b/net/netfilter/nf_tables_api.c | |||
@@ -1048,7 +1048,7 @@ static int nf_tables_fill_chain_info(struct sk_buff *skb, struct net *net, | |||
1048 | if (nla_put_string(skb, NFTA_CHAIN_TYPE, basechain->type->name)) | 1048 | if (nla_put_string(skb, NFTA_CHAIN_TYPE, basechain->type->name)) |
1049 | goto nla_put_failure; | 1049 | goto nla_put_failure; |
1050 | 1050 | ||
1051 | if (nft_dump_stats(skb, nft_base_chain(chain)->stats)) | 1051 | if (basechain->stats && nft_dump_stats(skb, basechain->stats)) |
1052 | goto nla_put_failure; | 1052 | goto nla_put_failure; |
1053 | } | 1053 | } |
1054 | 1054 | ||
@@ -1487,8 +1487,8 @@ static int nf_tables_updchain(struct nft_ctx *ctx, u8 genmask, u8 policy, | |||
1487 | 1487 | ||
1488 | chain2 = nf_tables_chain_lookup(table, nla[NFTA_CHAIN_NAME], | 1488 | chain2 = nf_tables_chain_lookup(table, nla[NFTA_CHAIN_NAME], |
1489 | genmask); | 1489 | genmask); |
1490 | if (IS_ERR(chain2)) | 1490 | if (!IS_ERR(chain2)) |
1491 | return PTR_ERR(chain2); | 1491 | return -EEXIST; |
1492 | } | 1492 | } |
1493 | 1493 | ||
1494 | if (nla[NFTA_CHAIN_COUNTERS]) { | 1494 | if (nla[NFTA_CHAIN_COUNTERS]) { |
@@ -2741,8 +2741,10 @@ cont: | |||
2741 | list_for_each_entry(i, &ctx->table->sets, list) { | 2741 | list_for_each_entry(i, &ctx->table->sets, list) { |
2742 | if (!nft_is_active_next(ctx->net, i)) | 2742 | if (!nft_is_active_next(ctx->net, i)) |
2743 | continue; | 2743 | continue; |
2744 | if (!strcmp(set->name, i->name)) | 2744 | if (!strcmp(set->name, i->name)) { |
2745 | kfree(set->name); | ||
2745 | return -ENFILE; | 2746 | return -ENFILE; |
2747 | } | ||
2746 | } | 2748 | } |
2747 | return 0; | 2749 | return 0; |
2748 | } | 2750 | } |
diff --git a/net/netfilter/x_tables.c b/net/netfilter/x_tables.c index c83a3b5e1c6c..d8571f414208 100644 --- a/net/netfilter/x_tables.c +++ b/net/netfilter/x_tables.c | |||
@@ -892,7 +892,7 @@ void *xt_copy_counters_from_user(const void __user *user, unsigned int len, | |||
892 | if (copy_from_user(&compat_tmp, user, sizeof(compat_tmp)) != 0) | 892 | if (copy_from_user(&compat_tmp, user, sizeof(compat_tmp)) != 0) |
893 | return ERR_PTR(-EFAULT); | 893 | return ERR_PTR(-EFAULT); |
894 | 894 | ||
895 | strlcpy(info->name, compat_tmp.name, sizeof(info->name)); | 895 | memcpy(info->name, compat_tmp.name, sizeof(info->name) - 1); |
896 | info->num_counters = compat_tmp.num_counters; | 896 | info->num_counters = compat_tmp.num_counters; |
897 | user += sizeof(compat_tmp); | 897 | user += sizeof(compat_tmp); |
898 | } else | 898 | } else |
@@ -905,9 +905,9 @@ void *xt_copy_counters_from_user(const void __user *user, unsigned int len, | |||
905 | if (copy_from_user(info, user, sizeof(*info)) != 0) | 905 | if (copy_from_user(info, user, sizeof(*info)) != 0) |
906 | return ERR_PTR(-EFAULT); | 906 | return ERR_PTR(-EFAULT); |
907 | 907 | ||
908 | info->name[sizeof(info->name) - 1] = '\0'; | ||
909 | user += sizeof(*info); | 908 | user += sizeof(*info); |
910 | } | 909 | } |
910 | info->name[sizeof(info->name) - 1] = '\0'; | ||
911 | 911 | ||
912 | size = sizeof(struct xt_counters); | 912 | size = sizeof(struct xt_counters); |
913 | size *= info->num_counters; | 913 | size *= info->num_counters; |
diff --git a/net/netfilter/xt_bpf.c b/net/netfilter/xt_bpf.c index 38986a95216c..29123934887b 100644 --- a/net/netfilter/xt_bpf.c +++ b/net/netfilter/xt_bpf.c | |||
@@ -8,6 +8,7 @@ | |||
8 | */ | 8 | */ |
9 | 9 | ||
10 | #include <linux/module.h> | 10 | #include <linux/module.h> |
11 | #include <linux/syscalls.h> | ||
11 | #include <linux/skbuff.h> | 12 | #include <linux/skbuff.h> |
12 | #include <linux/filter.h> | 13 | #include <linux/filter.h> |
13 | #include <linux/bpf.h> | 14 | #include <linux/bpf.h> |
@@ -49,6 +50,22 @@ static int __bpf_mt_check_fd(int fd, struct bpf_prog **ret) | |||
49 | return 0; | 50 | return 0; |
50 | } | 51 | } |
51 | 52 | ||
53 | static int __bpf_mt_check_path(const char *path, struct bpf_prog **ret) | ||
54 | { | ||
55 | mm_segment_t oldfs = get_fs(); | ||
56 | int retval, fd; | ||
57 | |||
58 | set_fs(KERNEL_DS); | ||
59 | fd = bpf_obj_get_user(path); | ||
60 | set_fs(oldfs); | ||
61 | if (fd < 0) | ||
62 | return fd; | ||
63 | |||
64 | retval = __bpf_mt_check_fd(fd, ret); | ||
65 | sys_close(fd); | ||
66 | return retval; | ||
67 | } | ||
68 | |||
52 | static int bpf_mt_check(const struct xt_mtchk_param *par) | 69 | static int bpf_mt_check(const struct xt_mtchk_param *par) |
53 | { | 70 | { |
54 | struct xt_bpf_info *info = par->matchinfo; | 71 | struct xt_bpf_info *info = par->matchinfo; |
@@ -66,9 +83,10 @@ static int bpf_mt_check_v1(const struct xt_mtchk_param *par) | |||
66 | return __bpf_mt_check_bytecode(info->bpf_program, | 83 | return __bpf_mt_check_bytecode(info->bpf_program, |
67 | info->bpf_program_num_elem, | 84 | info->bpf_program_num_elem, |
68 | &info->filter); | 85 | &info->filter); |
69 | else if (info->mode == XT_BPF_MODE_FD_PINNED || | 86 | else if (info->mode == XT_BPF_MODE_FD_ELF) |
70 | info->mode == XT_BPF_MODE_FD_ELF) | ||
71 | return __bpf_mt_check_fd(info->fd, &info->filter); | 87 | return __bpf_mt_check_fd(info->fd, &info->filter); |
88 | else if (info->mode == XT_BPF_MODE_PATH_PINNED) | ||
89 | return __bpf_mt_check_path(info->path, &info->filter); | ||
72 | else | 90 | else |
73 | return -EINVAL; | 91 | return -EINVAL; |
74 | } | 92 | } |
diff --git a/net/netfilter/xt_socket.c b/net/netfilter/xt_socket.c index e75ef39669c5..575d2153e3b8 100644 --- a/net/netfilter/xt_socket.c +++ b/net/netfilter/xt_socket.c | |||
@@ -76,7 +76,7 @@ socket_match(const struct sk_buff *skb, struct xt_action_param *par, | |||
76 | transparent = nf_sk_is_transparent(sk); | 76 | transparent = nf_sk_is_transparent(sk); |
77 | 77 | ||
78 | if (info->flags & XT_SOCKET_RESTORESKMARK && !wildcard && | 78 | if (info->flags & XT_SOCKET_RESTORESKMARK && !wildcard && |
79 | transparent) | 79 | transparent && sk_fullsock(sk)) |
80 | pskb->mark = sk->sk_mark; | 80 | pskb->mark = sk->sk_mark; |
81 | 81 | ||
82 | if (sk != skb->sk) | 82 | if (sk != skb->sk) |
@@ -133,7 +133,7 @@ socket_mt6_v1_v2_v3(const struct sk_buff *skb, struct xt_action_param *par) | |||
133 | transparent = nf_sk_is_transparent(sk); | 133 | transparent = nf_sk_is_transparent(sk); |
134 | 134 | ||
135 | if (info->flags & XT_SOCKET_RESTORESKMARK && !wildcard && | 135 | if (info->flags & XT_SOCKET_RESTORESKMARK && !wildcard && |
136 | transparent) | 136 | transparent && sk_fullsock(sk)) |
137 | pskb->mark = sk->sk_mark; | 137 | pskb->mark = sk->sk_mark; |
138 | 138 | ||
139 | if (sk != skb->sk) | 139 | if (sk != skb->sk) |