]> git.proxmox.com Git - mirror_ubuntu-eoan-kernel.git/commitdiff
Merge git://git.kernel.org/pub/scm/linux/kernel/git/pablo/nf
authorDavid S. Miller <davem@davemloft.net>
Thu, 23 Feb 2017 15:59:15 +0000 (10:59 -0500)
committerDavid S. Miller <davem@davemloft.net>
Thu, 23 Feb 2017 15:59:15 +0000 (10:59 -0500)
Pablo Neira Ayuso says:

====================
Netfilter fixes for net

The following patchset contains Netfilter fixes for your net tree,
they are:

1) Revisit warning logic when not applying default helper assignment.
   Jiri Kosina considers we are breaking existing setups and not warning
   our users accordinly now that automatic helper assignment has been
   turned off by default. So let's make him happy by spotting the warning
   by when we find a helper but we cannot attach, instead of warning on the
   former deprecated behaviour. Patch from Jiri Kosina.

2) Two patches to fix regression in ctnetlink interfaces with
   nfnetlink_queue. Specifically, perform more relaxed in CTA_STATUS
   and do not bail out if CTA_HELP indicates the same helper that we
   already have. Patches from Kevin Cernekee.

3) A couple of bugfixes for ipset via Jozsef Kadlecsik. Due to wrong
   index logic in hash set types and null pointer exception in the
   list:set type.

4) hashlimit bails out with correct userspace parameters due to wrong
   arithmetics in the code that avoids "divide by zero" when
   transforming the userspace timing in milliseconds to token credits.
   Patch from Alban Browaeys.

5) Fix incorrect NFQA_VLAN_MAX definition, patch from
   Ken-ichirou MATSUZAWA.

6) Don't not declare nfnetlink batch error list as static, since this
   may be used by several subsystems at the same time. Patch from
   Liping Zhang.
====================

Signed-off-by: David S. Miller <davem@davemloft.net>
include/uapi/linux/netfilter/nf_conntrack_common.h
include/uapi/linux/netfilter/nfnetlink_queue.h
net/netfilter/ipset/ip_set_hash_gen.h
net/netfilter/ipset/ip_set_list_set.c
net/netfilter/nf_conntrack_helper.c
net/netfilter/nf_conntrack_netlink.c
net/netfilter/nfnetlink.c
net/netfilter/xt_hashlimit.c

index 6d074d14ee274309f9e35b967e1728f26506fd6e..6a8e33dd4ecbd83b0d254d4cf2486dfe5cacfd34 100644 (file)
@@ -82,6 +82,10 @@ enum ip_conntrack_status {
        IPS_DYING_BIT = 9,
        IPS_DYING = (1 << IPS_DYING_BIT),
 
+       /* Bits that cannot be altered from userland. */
+       IPS_UNCHANGEABLE_MASK = (IPS_NAT_DONE_MASK | IPS_NAT_MASK |
+                                IPS_EXPECTED | IPS_CONFIRMED | IPS_DYING),
+
        /* Connection has fixed timeout. */
        IPS_FIXED_TIMEOUT_BIT = 10,
        IPS_FIXED_TIMEOUT = (1 << IPS_FIXED_TIMEOUT_BIT),
index ae30841ff94e4ffbbae6536609be3b431606b40f..d42f0396fe30841474082fb708b9e3540b3f5d80 100644 (file)
@@ -36,7 +36,7 @@ enum nfqnl_vlan_attr {
        NFQA_VLAN_TCI,                  /* __be16 skb htons(vlan_tci) */
        __NFQA_VLAN_MAX,
 };
-#define NFQA_VLAN_MAX (__NFQA_VLAN_MAX + 1)
+#define NFQA_VLAN_MAX (__NFQA_VLAN_MAX - 1)
 
 enum nfqnl_attr_type {
        NFQA_UNSPEC,
index 1b05d4a7d5a13e3a3eb42a56fdac186bb40451b2..f236c0bc7b3f3e171e4303dd7c5379f34011812f 100644 (file)
@@ -897,7 +897,7 @@ mtype_del(struct ip_set *set, void *value, const struct ip_set_ext *ext,
                                        continue;
                                data = ahash_data(n, j, dsize);
                                memcpy(tmp->value + k * dsize, data, dsize);
-                               set_bit(j, tmp->used);
+                               set_bit(k, tmp->used);
                                k++;
                        }
                        tmp->pos = k;
index 51077c53d76b1f00bc96e5f708fcd398b58afd22..178d4eba013b480ede5a54e121e5b0b92fc2edc1 100644 (file)
@@ -260,11 +260,14 @@ list_set_uadd(struct ip_set *set, void *value, const struct ip_set_ext *ext,
                else
                        prev = e;
        }
+
+       /* If before/after is used on an empty set */
+       if ((d->before > 0 && !next) ||
+           (d->before < 0 && !prev))
+               return -IPSET_ERR_REF_EXIST;
+
        /* Re-add already existing element */
        if (n) {
-               if ((d->before > 0 && !next) ||
-                   (d->before < 0 && !prev))
-                       return -IPSET_ERR_REF_EXIST;
                if (!flag_exist)
                        return -IPSET_ERR_EXIST;
                /* Update extensions */
index 7341adf7059d3232f458bc02528d9631107ebfce..6dc44d9b41900bea12f487e5a044259e92a47f7e 100644 (file)
@@ -188,6 +188,26 @@ nf_ct_helper_ext_add(struct nf_conn *ct,
 }
 EXPORT_SYMBOL_GPL(nf_ct_helper_ext_add);
 
+static struct nf_conntrack_helper *
+nf_ct_lookup_helper(struct nf_conn *ct, struct net *net)
+{
+       if (!net->ct.sysctl_auto_assign_helper) {
+               if (net->ct.auto_assign_helper_warned)
+                       return NULL;
+               if (!__nf_ct_helper_find(&ct->tuplehash[IP_CT_DIR_REPLY].tuple))
+                       return NULL;
+               pr_info("nf_conntrack: default automatic helper assignment "
+                       "has been turned off for security reasons and CT-based "
+                       " firewall rule not found. Use the iptables CT target "
+                       "to attach helpers instead.\n");
+               net->ct.auto_assign_helper_warned = 1;
+               return NULL;
+       }
+
+       return __nf_ct_helper_find(&ct->tuplehash[IP_CT_DIR_REPLY].tuple);
+}
+
+
 int __nf_ct_try_assign_helper(struct nf_conn *ct, struct nf_conn *tmpl,
                              gfp_t flags)
 {
@@ -213,21 +233,14 @@ int __nf_ct_try_assign_helper(struct nf_conn *ct, struct nf_conn *tmpl,
        }
 
        help = nfct_help(ct);
-       if (net->ct.sysctl_auto_assign_helper && helper == NULL) {
-               helper = __nf_ct_helper_find(&ct->tuplehash[IP_CT_DIR_REPLY].tuple);
-               if (unlikely(!net->ct.auto_assign_helper_warned && helper)) {
-                       pr_info("nf_conntrack: automatic helper "
-                               "assignment is deprecated and it will "
-                               "be removed soon. Use the iptables CT target "
-                               "to attach helpers instead.\n");
-                       net->ct.auto_assign_helper_warned = true;
-               }
-       }
 
        if (helper == NULL) {
-               if (help)
-                       RCU_INIT_POINTER(help->helper, NULL);
-               return 0;
+               helper = nf_ct_lookup_helper(ct, net);
+               if (helper == NULL) {
+                       if (help)
+                               RCU_INIT_POINTER(help->helper, NULL);
+                       return 0;
+               }
        }
 
        if (help == NULL) {
index 27540455dc62a3e827e2267a0b25e8ed210f8cb9..6806b5e73567bb0220b248682abed3e5e34f780e 100644 (file)
@@ -1478,14 +1478,23 @@ static int ctnetlink_change_helper(struct nf_conn *ct,
        struct nlattr *helpinfo = NULL;
        int err;
 
-       /* don't change helper of sibling connections */
-       if (ct->master)
-               return -EBUSY;
-
        err = ctnetlink_parse_help(cda[CTA_HELP], &helpname, &helpinfo);
        if (err < 0)
                return err;
 
+       /* don't change helper of sibling connections */
+       if (ct->master) {
+               /* If we try to change the helper to the same thing twice,
+                * treat the second attempt as a no-op instead of returning
+                * an error.
+                */
+               if (help && help->helper &&
+                   !strcmp(help->helper->name, helpname))
+                       return 0;
+               else
+                       return -EBUSY;
+       }
+
        if (!strcmp(helpname, "")) {
                if (help && help->helper) {
                        /* we had a helper before ... */
@@ -2269,6 +2278,30 @@ nla_put_failure:
        return -ENOSPC;
 }
 
+static int
+ctnetlink_update_status(struct nf_conn *ct, const struct nlattr * const cda[])
+{
+       unsigned int status = ntohl(nla_get_be32(cda[CTA_STATUS]));
+       unsigned long d = ct->status ^ status;
+
+       if (d & IPS_SEEN_REPLY && !(status & IPS_SEEN_REPLY))
+               /* SEEN_REPLY bit can only be set */
+               return -EBUSY;
+
+       if (d & IPS_ASSURED && !(status & IPS_ASSURED))
+               /* ASSURED bit can only be set */
+               return -EBUSY;
+
+       /* This check is less strict than ctnetlink_change_status()
+        * because callers often flip IPS_EXPECTED bits when sending
+        * an NFQA_CT attribute to the kernel.  So ignore the
+        * unchangeable bits but do not error out.
+        */
+       ct->status = (status & ~IPS_UNCHANGEABLE_MASK) |
+                    (ct->status & IPS_UNCHANGEABLE_MASK);
+       return 0;
+}
+
 static int
 ctnetlink_glue_parse_ct(const struct nlattr *cda[], struct nf_conn *ct)
 {
@@ -2280,7 +2313,7 @@ ctnetlink_glue_parse_ct(const struct nlattr *cda[], struct nf_conn *ct)
                        return err;
        }
        if (cda[CTA_STATUS]) {
-               err = ctnetlink_change_status(ct, cda);
+               err = ctnetlink_update_status(ct, cda);
                if (err < 0)
                        return err;
        }
index a2148d0bc50ec4af1ae324549f058710b5266ada..68eda920160e12f3cb904dad08b7f6cc9422571e 100644 (file)
@@ -279,7 +279,7 @@ static void nfnetlink_rcv_batch(struct sk_buff *skb, struct nlmsghdr *nlh,
        struct net *net = sock_net(skb->sk);
        const struct nfnetlink_subsystem *ss;
        const struct nfnl_callback *nc;
-       static LIST_HEAD(err_list);
+       LIST_HEAD(err_list);
        u32 status;
        int err;
 
index 26ef70c50e3b3e6b1b2fa71f76a3ecb25768f140..2a6dfe8b74d37f7d3d8ed0569650f6417b76d58a 100644 (file)
@@ -463,23 +463,16 @@ static u32 xt_hashlimit_len_to_chunks(u32 len)
 /* Precision saver. */
 static u64 user2credits(u64 user, int revision)
 {
-       if (revision == 1) {
-               /* If multiplying would overflow... */
-               if (user > 0xFFFFFFFF / (HZ*CREDITS_PER_JIFFY_v1))
-                       /* Divide first. */
-                       return div64_u64(user, XT_HASHLIMIT_SCALE)
-                               * HZ * CREDITS_PER_JIFFY_v1;
-
-               return div64_u64(user * HZ * CREDITS_PER_JIFFY_v1,
-                                XT_HASHLIMIT_SCALE);
-       } else {
-               if (user > 0xFFFFFFFFFFFFFFFFULL / (HZ*CREDITS_PER_JIFFY))
-                       return div64_u64(user, XT_HASHLIMIT_SCALE_v2)
-                               * HZ * CREDITS_PER_JIFFY;
+       u64 scale = (revision == 1) ?
+               XT_HASHLIMIT_SCALE : XT_HASHLIMIT_SCALE_v2;
+       u64 cpj = (revision == 1) ?
+               CREDITS_PER_JIFFY_v1 : CREDITS_PER_JIFFY;
 
-               return div64_u64(user * HZ * CREDITS_PER_JIFFY,
-                                XT_HASHLIMIT_SCALE_v2);
-       }
+       /* Avoid overflow: divide the constant operands first */
+       if (scale >= HZ * cpj)
+               return div64_u64(user, div64_u64(scale, HZ * cpj));
+
+       return user * div64_u64(HZ * cpj, scale);
 }
 
 static u32 user2credits_byte(u32 user)