aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/uapi/linux/netfilter/nf_conntrack_common.h4
-rw-r--r--include/uapi/linux/netfilter/nfnetlink_queue.h2
-rw-r--r--net/netfilter/ipset/ip_set_hash_gen.h2
-rw-r--r--net/netfilter/ipset/ip_set_list_set.c9
-rw-r--r--net/netfilter/nf_conntrack_helper.c39
-rw-r--r--net/netfilter/nf_conntrack_netlink.c43
-rw-r--r--net/netfilter/nfnetlink.c2
-rw-r--r--net/netfilter/xt_hashlimit.c25
8 files changed, 86 insertions, 40 deletions
diff --git a/include/uapi/linux/netfilter/nf_conntrack_common.h b/include/uapi/linux/netfilter/nf_conntrack_common.h
index 6d074d14ee27..6a8e33dd4ecb 100644
--- a/include/uapi/linux/netfilter/nf_conntrack_common.h
+++ b/include/uapi/linux/netfilter/nf_conntrack_common.h
@@ -82,6 +82,10 @@ enum ip_conntrack_status {
82 IPS_DYING_BIT = 9, 82 IPS_DYING_BIT = 9,
83 IPS_DYING = (1 << IPS_DYING_BIT), 83 IPS_DYING = (1 << IPS_DYING_BIT),
84 84
85 /* Bits that cannot be altered from userland. */
86 IPS_UNCHANGEABLE_MASK = (IPS_NAT_DONE_MASK | IPS_NAT_MASK |
87 IPS_EXPECTED | IPS_CONFIRMED | IPS_DYING),
88
85 /* Connection has fixed timeout. */ 89 /* Connection has fixed timeout. */
86 IPS_FIXED_TIMEOUT_BIT = 10, 90 IPS_FIXED_TIMEOUT_BIT = 10,
87 IPS_FIXED_TIMEOUT = (1 << IPS_FIXED_TIMEOUT_BIT), 91 IPS_FIXED_TIMEOUT = (1 << IPS_FIXED_TIMEOUT_BIT),
diff --git a/include/uapi/linux/netfilter/nfnetlink_queue.h b/include/uapi/linux/netfilter/nfnetlink_queue.h
index ae30841ff94e..d42f0396fe30 100644
--- a/include/uapi/linux/netfilter/nfnetlink_queue.h
+++ b/include/uapi/linux/netfilter/nfnetlink_queue.h
@@ -36,7 +36,7 @@ enum nfqnl_vlan_attr {
36 NFQA_VLAN_TCI, /* __be16 skb htons(vlan_tci) */ 36 NFQA_VLAN_TCI, /* __be16 skb htons(vlan_tci) */
37 __NFQA_VLAN_MAX, 37 __NFQA_VLAN_MAX,
38}; 38};
39#define NFQA_VLAN_MAX (__NFQA_VLAN_MAX + 1) 39#define NFQA_VLAN_MAX (__NFQA_VLAN_MAX - 1)
40 40
41enum nfqnl_attr_type { 41enum nfqnl_attr_type {
42 NFQA_UNSPEC, 42 NFQA_UNSPEC,
diff --git a/net/netfilter/ipset/ip_set_hash_gen.h b/net/netfilter/ipset/ip_set_hash_gen.h
index 1b05d4a7d5a1..f236c0bc7b3f 100644
--- a/net/netfilter/ipset/ip_set_hash_gen.h
+++ b/net/netfilter/ipset/ip_set_hash_gen.h
@@ -897,7 +897,7 @@ mtype_del(struct ip_set *set, void *value, const struct ip_set_ext *ext,
897 continue; 897 continue;
898 data = ahash_data(n, j, dsize); 898 data = ahash_data(n, j, dsize);
899 memcpy(tmp->value + k * dsize, data, dsize); 899 memcpy(tmp->value + k * dsize, data, dsize);
900 set_bit(j, tmp->used); 900 set_bit(k, tmp->used);
901 k++; 901 k++;
902 } 902 }
903 tmp->pos = k; 903 tmp->pos = k;
diff --git a/net/netfilter/ipset/ip_set_list_set.c b/net/netfilter/ipset/ip_set_list_set.c
index 51077c53d76b..178d4eba013b 100644
--- a/net/netfilter/ipset/ip_set_list_set.c
+++ b/net/netfilter/ipset/ip_set_list_set.c
@@ -260,11 +260,14 @@ list_set_uadd(struct ip_set *set, void *value, const struct ip_set_ext *ext,
260 else 260 else
261 prev = e; 261 prev = e;
262 } 262 }
263
264 /* If before/after is used on an empty set */
265 if ((d->before > 0 && !next) ||
266 (d->before < 0 && !prev))
267 return -IPSET_ERR_REF_EXIST;
268
263 /* Re-add already existing element */ 269 /* Re-add already existing element */
264 if (n) { 270 if (n) {
265 if ((d->before > 0 && !next) ||
266 (d->before < 0 && !prev))
267 return -IPSET_ERR_REF_EXIST;
268 if (!flag_exist) 271 if (!flag_exist)
269 return -IPSET_ERR_EXIST; 272 return -IPSET_ERR_EXIST;
270 /* Update extensions */ 273 /* Update extensions */
diff --git a/net/netfilter/nf_conntrack_helper.c b/net/netfilter/nf_conntrack_helper.c
index 7341adf7059d..6dc44d9b4190 100644
--- a/net/netfilter/nf_conntrack_helper.c
+++ b/net/netfilter/nf_conntrack_helper.c
@@ -188,6 +188,26 @@ nf_ct_helper_ext_add(struct nf_conn *ct,
188} 188}
189EXPORT_SYMBOL_GPL(nf_ct_helper_ext_add); 189EXPORT_SYMBOL_GPL(nf_ct_helper_ext_add);
190 190
191static struct nf_conntrack_helper *
192nf_ct_lookup_helper(struct nf_conn *ct, struct net *net)
193{
194 if (!net->ct.sysctl_auto_assign_helper) {
195 if (net->ct.auto_assign_helper_warned)
196 return NULL;
197 if (!__nf_ct_helper_find(&ct->tuplehash[IP_CT_DIR_REPLY].tuple))
198 return NULL;
199 pr_info("nf_conntrack: default automatic helper assignment "
200 "has been turned off for security reasons and CT-based "
201 " firewall rule not found. Use the iptables CT target "
202 "to attach helpers instead.\n");
203 net->ct.auto_assign_helper_warned = 1;
204 return NULL;
205 }
206
207 return __nf_ct_helper_find(&ct->tuplehash[IP_CT_DIR_REPLY].tuple);
208}
209
210
191int __nf_ct_try_assign_helper(struct nf_conn *ct, struct nf_conn *tmpl, 211int __nf_ct_try_assign_helper(struct nf_conn *ct, struct nf_conn *tmpl,
192 gfp_t flags) 212 gfp_t flags)
193{ 213{
@@ -213,21 +233,14 @@ int __nf_ct_try_assign_helper(struct nf_conn *ct, struct nf_conn *tmpl,
213 } 233 }
214 234
215 help = nfct_help(ct); 235 help = nfct_help(ct);
216 if (net->ct.sysctl_auto_assign_helper && helper == NULL) {
217 helper = __nf_ct_helper_find(&ct->tuplehash[IP_CT_DIR_REPLY].tuple);
218 if (unlikely(!net->ct.auto_assign_helper_warned && helper)) {
219 pr_info("nf_conntrack: automatic helper "
220 "assignment is deprecated and it will "
221 "be removed soon. Use the iptables CT target "
222 "to attach helpers instead.\n");
223 net->ct.auto_assign_helper_warned = true;
224 }
225 }
226 236
227 if (helper == NULL) { 237 if (helper == NULL) {
228 if (help) 238 helper = nf_ct_lookup_helper(ct, net);
229 RCU_INIT_POINTER(help->helper, NULL); 239 if (helper == NULL) {
230 return 0; 240 if (help)
241 RCU_INIT_POINTER(help->helper, NULL);
242 return 0;
243 }
231 } 244 }
232 245
233 if (help == NULL) { 246 if (help == NULL) {
diff --git a/net/netfilter/nf_conntrack_netlink.c b/net/netfilter/nf_conntrack_netlink.c
index 27540455dc62..6806b5e73567 100644
--- a/net/netfilter/nf_conntrack_netlink.c
+++ b/net/netfilter/nf_conntrack_netlink.c
@@ -1478,14 +1478,23 @@ static int ctnetlink_change_helper(struct nf_conn *ct,
1478 struct nlattr *helpinfo = NULL; 1478 struct nlattr *helpinfo = NULL;
1479 int err; 1479 int err;
1480 1480
1481 /* don't change helper of sibling connections */
1482 if (ct->master)
1483 return -EBUSY;
1484
1485 err = ctnetlink_parse_help(cda[CTA_HELP], &helpname, &helpinfo); 1481 err = ctnetlink_parse_help(cda[CTA_HELP], &helpname, &helpinfo);
1486 if (err < 0) 1482 if (err < 0)
1487 return err; 1483 return err;
1488 1484
1485 /* don't change helper of sibling connections */
1486 if (ct->master) {
1487 /* If we try to change the helper to the same thing twice,
1488 * treat the second attempt as a no-op instead of returning
1489 * an error.
1490 */
1491 if (help && help->helper &&
1492 !strcmp(help->helper->name, helpname))
1493 return 0;
1494 else
1495 return -EBUSY;
1496 }
1497
1489 if (!strcmp(helpname, "")) { 1498 if (!strcmp(helpname, "")) {
1490 if (help && help->helper) { 1499 if (help && help->helper) {
1491 /* we had a helper before ... */ 1500 /* we had a helper before ... */
@@ -2270,6 +2279,30 @@ nla_put_failure:
2270} 2279}
2271 2280
2272static int 2281static int
2282ctnetlink_update_status(struct nf_conn *ct, const struct nlattr * const cda[])
2283{
2284 unsigned int status = ntohl(nla_get_be32(cda[CTA_STATUS]));
2285 unsigned long d = ct->status ^ status;
2286
2287 if (d & IPS_SEEN_REPLY && !(status & IPS_SEEN_REPLY))
2288 /* SEEN_REPLY bit can only be set */
2289 return -EBUSY;
2290
2291 if (d & IPS_ASSURED && !(status & IPS_ASSURED))
2292 /* ASSURED bit can only be set */
2293 return -EBUSY;
2294
2295 /* This check is less strict than ctnetlink_change_status()
2296 * because callers often flip IPS_EXPECTED bits when sending
2297 * an NFQA_CT attribute to the kernel. So ignore the
2298 * unchangeable bits but do not error out.
2299 */
2300 ct->status = (status & ~IPS_UNCHANGEABLE_MASK) |
2301 (ct->status & IPS_UNCHANGEABLE_MASK);
2302 return 0;
2303}
2304
2305static int
2273ctnetlink_glue_parse_ct(const struct nlattr *cda[], struct nf_conn *ct) 2306ctnetlink_glue_parse_ct(const struct nlattr *cda[], struct nf_conn *ct)
2274{ 2307{
2275 int err; 2308 int err;
@@ -2280,7 +2313,7 @@ ctnetlink_glue_parse_ct(const struct nlattr *cda[], struct nf_conn *ct)
2280 return err; 2313 return err;
2281 } 2314 }
2282 if (cda[CTA_STATUS]) { 2315 if (cda[CTA_STATUS]) {
2283 err = ctnetlink_change_status(ct, cda); 2316 err = ctnetlink_update_status(ct, cda);
2284 if (err < 0) 2317 if (err < 0)
2285 return err; 2318 return err;
2286 } 2319 }
diff --git a/net/netfilter/nfnetlink.c b/net/netfilter/nfnetlink.c
index a2148d0bc50e..68eda920160e 100644
--- a/net/netfilter/nfnetlink.c
+++ b/net/netfilter/nfnetlink.c
@@ -279,7 +279,7 @@ static void nfnetlink_rcv_batch(struct sk_buff *skb, struct nlmsghdr *nlh,
279 struct net *net = sock_net(skb->sk); 279 struct net *net = sock_net(skb->sk);
280 const struct nfnetlink_subsystem *ss; 280 const struct nfnetlink_subsystem *ss;
281 const struct nfnl_callback *nc; 281 const struct nfnl_callback *nc;
282 static LIST_HEAD(err_list); 282 LIST_HEAD(err_list);
283 u32 status; 283 u32 status;
284 int err; 284 int err;
285 285
diff --git a/net/netfilter/xt_hashlimit.c b/net/netfilter/xt_hashlimit.c
index 26ef70c50e3b..2a6dfe8b74d3 100644
--- a/net/netfilter/xt_hashlimit.c
+++ b/net/netfilter/xt_hashlimit.c
@@ -463,23 +463,16 @@ static u32 xt_hashlimit_len_to_chunks(u32 len)
463/* Precision saver. */ 463/* Precision saver. */
464static u64 user2credits(u64 user, int revision) 464static u64 user2credits(u64 user, int revision)
465{ 465{
466 if (revision == 1) { 466 u64 scale = (revision == 1) ?
467 /* If multiplying would overflow... */ 467 XT_HASHLIMIT_SCALE : XT_HASHLIMIT_SCALE_v2;
468 if (user > 0xFFFFFFFF / (HZ*CREDITS_PER_JIFFY_v1)) 468 u64 cpj = (revision == 1) ?
469 /* Divide first. */ 469 CREDITS_PER_JIFFY_v1 : CREDITS_PER_JIFFY;
470 return div64_u64(user, XT_HASHLIMIT_SCALE)
471 * HZ * CREDITS_PER_JIFFY_v1;
472
473 return div64_u64(user * HZ * CREDITS_PER_JIFFY_v1,
474 XT_HASHLIMIT_SCALE);
475 } else {
476 if (user > 0xFFFFFFFFFFFFFFFFULL / (HZ*CREDITS_PER_JIFFY))
477 return div64_u64(user, XT_HASHLIMIT_SCALE_v2)
478 * HZ * CREDITS_PER_JIFFY;
479 470
480 return div64_u64(user * HZ * CREDITS_PER_JIFFY, 471 /* Avoid overflow: divide the constant operands first */
481 XT_HASHLIMIT_SCALE_v2); 472 if (scale >= HZ * cpj)
482 } 473 return div64_u64(user, div64_u64(scale, HZ * cpj));
474
475 return user * div64_u64(HZ * cpj, scale);
483} 476}
484 477
485static u32 user2credits_byte(u32 user) 478static u32 user2credits_byte(u32 user)