]> git.proxmox.com Git - mirror_ubuntu-bionic-kernel.git/commitdiff
Merge git://git.kernel.org/pub/scm/linux/kernel/git/pablo/nf
authorDavid S. Miller <davem@davemloft.net>
Wed, 13 Dec 2017 19:12:20 +0000 (14:12 -0500)
committerDavid S. Miller <davem@davemloft.net>
Wed, 13 Dec 2017 19:12:20 +0000 (14:12 -0500)
Pablo Neira Ayuso says:

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

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

1) Fix compilation warning in x_tables with clang due to useless
   redundant reassignment, from Colin Ian King.

2) Add bugtrap to net_exit to catch uninitialized lists, patch
   from Vasily Averin.

3) Fix out of bounds memory reads in H323 conntrack helper, this
   comes with an initial patch to remove replace the obscure
   CHECK_BOUND macro as a dependency. From Eric Sesterhenn.

4) Reduce retransmission timeout when window is 0 in TCP conntrack,
   from Florian Westphal.

6) ctnetlink clamp timeout to INT_MAX if timeout is too large,
   otherwise timeout wraps around and it results in killing the
   entry that is being added immediately.

7) Missing CAP_NET_ADMIN checks in cthelper and xt_osf, due to
   no netns support. From Kevin Cernekee.

8) Missing maximum number of instructions checks in xt_bpf, patch
   from Jann Horn.

9) With no CONFIG_PROC_FS ipt_CLUSTERIP compilation breaks,
   patch from Arnd Bergmann.

10) Missing netlink attribute policy in nftables exthdr, from
    Florian Westphal.

11) Enable conntrack with IPv6 MASQUERADE rules, as a357b3f80bc8
    should have done in first place, from Konstantin Khlebnikov.
====================

Signed-off-by: David S. Miller <davem@davemloft.net>
16 files changed:
net/ipv4/netfilter/arp_tables.c
net/ipv4/netfilter/ip_tables.c
net/ipv4/netfilter/ipt_CLUSTERIP.c
net/ipv6/netfilter/ip6_tables.c
net/ipv6/netfilter/ip6t_MASQUERADE.c
net/netfilter/nf_conntrack_h323_asn1.c
net/netfilter/nf_conntrack_netlink.c
net/netfilter/nf_conntrack_proto_tcp.c
net/netfilter/nf_tables_api.c
net/netfilter/nfnetlink_cthelper.c
net/netfilter/nfnetlink_log.c
net/netfilter/nfnetlink_queue.c
net/netfilter/nft_exthdr.c
net/netfilter/x_tables.c
net/netfilter/xt_bpf.c
net/netfilter/xt_osf.c

index f88221aebc9d7b61cf2c09f2b3d2351c4095f64f..0c3c944a7b7201f74dace535c8a26d58b8039a1f 100644 (file)
@@ -373,7 +373,6 @@ static int mark_source_chains(const struct xt_table_info *newinfo,
                                        if (!xt_find_jump_offset(offsets, newpos,
                                                                 newinfo->number))
                                                return 0;
-                                       e = entry0 + newpos;
                                } else {
                                        /* ... this is a fallthru */
                                        newpos = pos + e->next_offset;
index 4cbe5e80f3bf079755cd08f33c24a4077c6c4a63..2e0d339028bbcb6766f92e5b87d70866a419b893 100644 (file)
@@ -439,7 +439,6 @@ mark_source_chains(const struct xt_table_info *newinfo,
                                        if (!xt_find_jump_offset(offsets, newpos,
                                                                 newinfo->number))
                                                return 0;
-                                       e = entry0 + newpos;
                                } else {
                                        /* ... this is a fallthru */
                                        newpos = pos + e->next_offset;
index 17b4ca562944c35b50015bbc40aa580ca62ddfb7..69060e3abe8598b350e6bfe5815a702c4b3d2ade 100644 (file)
@@ -813,12 +813,13 @@ static int clusterip_net_init(struct net *net)
 
 static void clusterip_net_exit(struct net *net)
 {
-#ifdef CONFIG_PROC_FS
        struct clusterip_net *cn = net_generic(net, clusterip_net_id);
+#ifdef CONFIG_PROC_FS
        proc_remove(cn->procdir);
        cn->procdir = NULL;
 #endif
        nf_unregister_net_hook(net, &cip_arp_ops);
+       WARN_ON_ONCE(!list_empty(&cn->configs));
 }
 
 static struct pernet_operations clusterip_net_ops = {
index f06e25065a342e361d7ae68ae1d60304b3f43f39..1d7ae93663351297395208f2c9a65bd5fba236e5 100644 (file)
@@ -458,7 +458,6 @@ mark_source_chains(const struct xt_table_info *newinfo,
                                        if (!xt_find_jump_offset(offsets, newpos,
                                                                 newinfo->number))
                                                return 0;
-                                       e = entry0 + newpos;
                                } else {
                                        /* ... this is a fallthru */
                                        newpos = pos + e->next_offset;
index 2b1a15846f9ac1f40d45aef52af6aab92d515408..92c0047e7e33dc5925054c41143fe200db06f125 100644 (file)
@@ -33,13 +33,19 @@ static int masquerade_tg6_checkentry(const struct xt_tgchk_param *par)
 
        if (range->flags & NF_NAT_RANGE_MAP_IPS)
                return -EINVAL;
-       return 0;
+       return nf_ct_netns_get(par->net, par->family);
+}
+
+static void masquerade_tg6_destroy(const struct xt_tgdtor_param *par)
+{
+       nf_ct_netns_put(par->net, par->family);
 }
 
 static struct xt_target masquerade_tg6_reg __read_mostly = {
        .name           = "MASQUERADE",
        .family         = NFPROTO_IPV6,
        .checkentry     = masquerade_tg6_checkentry,
+       .destroy        = masquerade_tg6_destroy,
        .target         = masquerade_tg6,
        .targetsize     = sizeof(struct nf_nat_range),
        .table          = "nat",
index cf1bf2605c1027207a86889f93da667d8b2313b9..dc6347342e34c499eaef5403f63034b137ad14e3 100644 (file)
@@ -103,7 +103,6 @@ struct bitstr {
 #define INC_BIT(bs) if((++(bs)->bit)>7){(bs)->cur++;(bs)->bit=0;}
 #define INC_BITS(bs,b) if(((bs)->bit+=(b))>7){(bs)->cur+=(bs)->bit>>3;(bs)->bit&=7;}
 #define BYTE_ALIGN(bs) if((bs)->bit){(bs)->cur++;(bs)->bit=0;}
-#define CHECK_BOUND(bs,n) if((bs)->cur+(n)>(bs)->end)return(H323_ERROR_BOUND)
 static unsigned int get_len(struct bitstr *bs);
 static unsigned int get_bit(struct bitstr *bs);
 static unsigned int get_bits(struct bitstr *bs, unsigned int b);
@@ -165,6 +164,19 @@ static unsigned int get_len(struct bitstr *bs)
        return v;
 }
 
+static int nf_h323_error_boundary(struct bitstr *bs, size_t bytes, size_t bits)
+{
+       bits += bs->bit;
+       bytes += bits / BITS_PER_BYTE;
+       if (bits % BITS_PER_BYTE > 0)
+               bytes++;
+
+       if (*bs->cur + bytes > *bs->end)
+               return 1;
+
+       return 0;
+}
+
 /****************************************************************************/
 static unsigned int get_bit(struct bitstr *bs)
 {
@@ -279,8 +291,8 @@ static int decode_bool(struct bitstr *bs, const struct field_t *f,
        PRINT("%*.s%s\n", level * TAB_SIZE, " ", f->name);
 
        INC_BIT(bs);
-
-       CHECK_BOUND(bs, 0);
+       if (nf_h323_error_boundary(bs, 0, 0))
+               return H323_ERROR_BOUND;
        return H323_ERROR_NONE;
 }
 
@@ -293,11 +305,14 @@ static int decode_oid(struct bitstr *bs, const struct field_t *f,
        PRINT("%*.s%s\n", level * TAB_SIZE, " ", f->name);
 
        BYTE_ALIGN(bs);
-       CHECK_BOUND(bs, 1);
+       if (nf_h323_error_boundary(bs, 1, 0))
+               return H323_ERROR_BOUND;
+
        len = *bs->cur++;
        bs->cur += len;
+       if (nf_h323_error_boundary(bs, 0, 0))
+               return H323_ERROR_BOUND;
 
-       CHECK_BOUND(bs, 0);
        return H323_ERROR_NONE;
 }
 
@@ -319,6 +334,8 @@ static int decode_int(struct bitstr *bs, const struct field_t *f,
                bs->cur += 2;
                break;
        case CONS:              /* 64K < Range < 4G */
+               if (nf_h323_error_boundary(bs, 0, 2))
+                       return H323_ERROR_BOUND;
                len = get_bits(bs, 2) + 1;
                BYTE_ALIGN(bs);
                if (base && (f->attr & DECODE)) {       /* timeToLive */
@@ -330,7 +347,8 @@ static int decode_int(struct bitstr *bs, const struct field_t *f,
                break;
        case UNCO:
                BYTE_ALIGN(bs);
-               CHECK_BOUND(bs, 2);
+               if (nf_h323_error_boundary(bs, 2, 0))
+                       return H323_ERROR_BOUND;
                len = get_len(bs);
                bs->cur += len;
                break;
@@ -341,7 +359,8 @@ static int decode_int(struct bitstr *bs, const struct field_t *f,
 
        PRINT("\n");
 
-       CHECK_BOUND(bs, 0);
+       if (nf_h323_error_boundary(bs, 0, 0))
+               return H323_ERROR_BOUND;
        return H323_ERROR_NONE;
 }
 
@@ -357,7 +376,8 @@ static int decode_enum(struct bitstr *bs, const struct field_t *f,
                INC_BITS(bs, f->sz);
        }
 
-       CHECK_BOUND(bs, 0);
+       if (nf_h323_error_boundary(bs, 0, 0))
+               return H323_ERROR_BOUND;
        return H323_ERROR_NONE;
 }
 
@@ -375,12 +395,14 @@ static int decode_bitstr(struct bitstr *bs, const struct field_t *f,
                len = f->lb;
                break;
        case WORD:              /* 2-byte length */
-               CHECK_BOUND(bs, 2);
+               if (nf_h323_error_boundary(bs, 2, 0))
+                       return H323_ERROR_BOUND;
                len = (*bs->cur++) << 8;
                len += (*bs->cur++) + f->lb;
                break;
        case SEMI:
-               CHECK_BOUND(bs, 2);
+               if (nf_h323_error_boundary(bs, 2, 0))
+                       return H323_ERROR_BOUND;
                len = get_len(bs);
                break;
        default:
@@ -391,7 +413,8 @@ static int decode_bitstr(struct bitstr *bs, const struct field_t *f,
        bs->cur += len >> 3;
        bs->bit = len & 7;
 
-       CHECK_BOUND(bs, 0);
+       if (nf_h323_error_boundary(bs, 0, 0))
+               return H323_ERROR_BOUND;
        return H323_ERROR_NONE;
 }
 
@@ -404,12 +427,15 @@ static int decode_numstr(struct bitstr *bs, const struct field_t *f,
        PRINT("%*.s%s\n", level * TAB_SIZE, " ", f->name);
 
        /* 2 <= Range <= 255 */
+       if (nf_h323_error_boundary(bs, 0, f->sz))
+               return H323_ERROR_BOUND;
        len = get_bits(bs, f->sz) + f->lb;
 
        BYTE_ALIGN(bs);
        INC_BITS(bs, (len << 2));
 
-       CHECK_BOUND(bs, 0);
+       if (nf_h323_error_boundary(bs, 0, 0))
+               return H323_ERROR_BOUND;
        return H323_ERROR_NONE;
 }
 
@@ -440,15 +466,19 @@ static int decode_octstr(struct bitstr *bs, const struct field_t *f,
                break;
        case BYTE:              /* Range == 256 */
                BYTE_ALIGN(bs);
-               CHECK_BOUND(bs, 1);
+               if (nf_h323_error_boundary(bs, 1, 0))
+                       return H323_ERROR_BOUND;
                len = (*bs->cur++) + f->lb;
                break;
        case SEMI:
                BYTE_ALIGN(bs);
-               CHECK_BOUND(bs, 2);
+               if (nf_h323_error_boundary(bs, 2, 0))
+                       return H323_ERROR_BOUND;
                len = get_len(bs) + f->lb;
                break;
        default:                /* 2 <= Range <= 255 */
+               if (nf_h323_error_boundary(bs, 0, f->sz))
+                       return H323_ERROR_BOUND;
                len = get_bits(bs, f->sz) + f->lb;
                BYTE_ALIGN(bs);
                break;
@@ -458,7 +488,8 @@ static int decode_octstr(struct bitstr *bs, const struct field_t *f,
 
        PRINT("\n");
 
-       CHECK_BOUND(bs, 0);
+       if (nf_h323_error_boundary(bs, 0, 0))
+               return H323_ERROR_BOUND;
        return H323_ERROR_NONE;
 }
 
@@ -473,10 +504,13 @@ static int decode_bmpstr(struct bitstr *bs, const struct field_t *f,
        switch (f->sz) {
        case BYTE:              /* Range == 256 */
                BYTE_ALIGN(bs);
-               CHECK_BOUND(bs, 1);
+               if (nf_h323_error_boundary(bs, 1, 0))
+                       return H323_ERROR_BOUND;
                len = (*bs->cur++) + f->lb;
                break;
        default:                /* 2 <= Range <= 255 */
+               if (nf_h323_error_boundary(bs, 0, f->sz))
+                       return H323_ERROR_BOUND;
                len = get_bits(bs, f->sz) + f->lb;
                BYTE_ALIGN(bs);
                break;
@@ -484,7 +518,8 @@ static int decode_bmpstr(struct bitstr *bs, const struct field_t *f,
 
        bs->cur += len << 1;
 
-       CHECK_BOUND(bs, 0);
+       if (nf_h323_error_boundary(bs, 0, 0))
+               return H323_ERROR_BOUND;
        return H323_ERROR_NONE;
 }
 
@@ -503,9 +538,13 @@ static int decode_seq(struct bitstr *bs, const struct field_t *f,
        base = (base && (f->attr & DECODE)) ? base + f->offset : NULL;
 
        /* Extensible? */
+       if (nf_h323_error_boundary(bs, 0, 1))
+               return H323_ERROR_BOUND;
        ext = (f->attr & EXT) ? get_bit(bs) : 0;
 
        /* Get fields bitmap */
+       if (nf_h323_error_boundary(bs, 0, f->sz))
+               return H323_ERROR_BOUND;
        bmp = get_bitmap(bs, f->sz);
        if (base)
                *(unsigned int *)base = bmp;
@@ -525,9 +564,11 @@ static int decode_seq(struct bitstr *bs, const struct field_t *f,
 
                /* Decode */
                if (son->attr & OPEN) { /* Open field */
-                       CHECK_BOUND(bs, 2);
+                       if (nf_h323_error_boundary(bs, 2, 0))
+                               return H323_ERROR_BOUND;
                        len = get_len(bs);
-                       CHECK_BOUND(bs, len);
+                       if (nf_h323_error_boundary(bs, len, 0))
+                               return H323_ERROR_BOUND;
                        if (!base || !(son->attr & DECODE)) {
                                PRINT("%*.s%s\n", (level + 1) * TAB_SIZE,
                                      " ", son->name);
@@ -555,8 +596,11 @@ static int decode_seq(struct bitstr *bs, const struct field_t *f,
                return H323_ERROR_NONE;
 
        /* Get the extension bitmap */
+       if (nf_h323_error_boundary(bs, 0, 7))
+               return H323_ERROR_BOUND;
        bmp2_len = get_bits(bs, 7) + 1;
-       CHECK_BOUND(bs, (bmp2_len + 7) >> 3);
+       if (nf_h323_error_boundary(bs, 0, bmp2_len))
+               return H323_ERROR_BOUND;
        bmp2 = get_bitmap(bs, bmp2_len);
        bmp |= bmp2 >> f->sz;
        if (base)
@@ -567,9 +611,11 @@ static int decode_seq(struct bitstr *bs, const struct field_t *f,
        for (opt = 0; opt < bmp2_len; opt++, i++, son++) {
                /* Check Range */
                if (i >= f->ub) {       /* Newer Version? */
-                       CHECK_BOUND(bs, 2);
+                       if (nf_h323_error_boundary(bs, 2, 0))
+                               return H323_ERROR_BOUND;
                        len = get_len(bs);
-                       CHECK_BOUND(bs, len);
+                       if (nf_h323_error_boundary(bs, len, 0))
+                               return H323_ERROR_BOUND;
                        bs->cur += len;
                        continue;
                }
@@ -583,9 +629,11 @@ static int decode_seq(struct bitstr *bs, const struct field_t *f,
                if (!((0x80000000 >> opt) & bmp2))      /* Not present */
                        continue;
 
-               CHECK_BOUND(bs, 2);
+               if (nf_h323_error_boundary(bs, 2, 0))
+                       return H323_ERROR_BOUND;
                len = get_len(bs);
-               CHECK_BOUND(bs, len);
+               if (nf_h323_error_boundary(bs, len, 0))
+                       return H323_ERROR_BOUND;
                if (!base || !(son->attr & DECODE)) {
                        PRINT("%*.s%s\n", (level + 1) * TAB_SIZE, " ",
                              son->name);
@@ -623,22 +671,27 @@ static int decode_seqof(struct bitstr *bs, const struct field_t *f,
        switch (f->sz) {
        case BYTE:
                BYTE_ALIGN(bs);
-               CHECK_BOUND(bs, 1);
+               if (nf_h323_error_boundary(bs, 1, 0))
+                       return H323_ERROR_BOUND;
                count = *bs->cur++;
                break;
        case WORD:
                BYTE_ALIGN(bs);
-               CHECK_BOUND(bs, 2);
+               if (nf_h323_error_boundary(bs, 2, 0))
+                       return H323_ERROR_BOUND;
                count = *bs->cur++;
                count <<= 8;
                count += *bs->cur++;
                break;
        case SEMI:
                BYTE_ALIGN(bs);
-               CHECK_BOUND(bs, 2);
+               if (nf_h323_error_boundary(bs, 2, 0))
+                       return H323_ERROR_BOUND;
                count = get_len(bs);
                break;
        default:
+               if (nf_h323_error_boundary(bs, 0, f->sz))
+                       return H323_ERROR_BOUND;
                count = get_bits(bs, f->sz);
                break;
        }
@@ -658,8 +711,11 @@ static int decode_seqof(struct bitstr *bs, const struct field_t *f,
        for (i = 0; i < count; i++) {
                if (son->attr & OPEN) {
                        BYTE_ALIGN(bs);
+                       if (nf_h323_error_boundary(bs, 2, 0))
+                               return H323_ERROR_BOUND;
                        len = get_len(bs);
-                       CHECK_BOUND(bs, len);
+                       if (nf_h323_error_boundary(bs, len, 0))
+                               return H323_ERROR_BOUND;
                        if (!base || !(son->attr & DECODE)) {
                                PRINT("%*.s%s\n", (level + 1) * TAB_SIZE,
                                      " ", son->name);
@@ -710,11 +766,17 @@ static int decode_choice(struct bitstr *bs, const struct field_t *f,
        base = (base && (f->attr & DECODE)) ? base + f->offset : NULL;
 
        /* Decode the choice index number */
+       if (nf_h323_error_boundary(bs, 0, 1))
+               return H323_ERROR_BOUND;
        if ((f->attr & EXT) && get_bit(bs)) {
                ext = 1;
+               if (nf_h323_error_boundary(bs, 0, 7))
+                       return H323_ERROR_BOUND;
                type = get_bits(bs, 7) + f->lb;
        } else {
                ext = 0;
+               if (nf_h323_error_boundary(bs, 0, f->sz))
+                       return H323_ERROR_BOUND;
                type = get_bits(bs, f->sz);
                if (type >= f->lb)
                        return H323_ERROR_RANGE;
@@ -727,8 +789,11 @@ static int decode_choice(struct bitstr *bs, const struct field_t *f,
        /* Check Range */
        if (type >= f->ub) {    /* Newer version? */
                BYTE_ALIGN(bs);
+               if (nf_h323_error_boundary(bs, 2, 0))
+                       return H323_ERROR_BOUND;
                len = get_len(bs);
-               CHECK_BOUND(bs, len);
+               if (nf_h323_error_boundary(bs, len, 0))
+                       return H323_ERROR_BOUND;
                bs->cur += len;
                return H323_ERROR_NONE;
        }
@@ -742,8 +807,11 @@ static int decode_choice(struct bitstr *bs, const struct field_t *f,
 
        if (ext || (son->attr & OPEN)) {
                BYTE_ALIGN(bs);
+               if (nf_h323_error_boundary(bs, len, 0))
+                       return H323_ERROR_BOUND;
                len = get_len(bs);
-               CHECK_BOUND(bs, len);
+               if (nf_h323_error_boundary(bs, len, 0))
+                       return H323_ERROR_BOUND;
                if (!base || !(son->attr & DECODE)) {
                        PRINT("%*.s%s\n", (level + 1) * TAB_SIZE, " ",
                              son->name);
index 332b51870ed7fbf6e8dcf4760df53449ec1cd7d6..382d49792f428099a1fa78ebc1f50224ba8b7d97 100644 (file)
@@ -1565,9 +1565,11 @@ static int ctnetlink_change_helper(struct nf_conn *ct,
 static int ctnetlink_change_timeout(struct nf_conn *ct,
                                    const struct nlattr * const cda[])
 {
-       u_int32_t timeout = ntohl(nla_get_be32(cda[CTA_TIMEOUT]));
+       u64 timeout = (u64)ntohl(nla_get_be32(cda[CTA_TIMEOUT])) * HZ;
 
-       ct->timeout = nfct_time_stamp + timeout * HZ;
+       if (timeout > INT_MAX)
+               timeout = INT_MAX;
+       ct->timeout = nfct_time_stamp + (u32)timeout;
 
        if (test_bit(IPS_DYING_BIT, &ct->status))
                return -ETIME;
@@ -1767,6 +1769,7 @@ ctnetlink_create_conntrack(struct net *net,
        int err = -EINVAL;
        struct nf_conntrack_helper *helper;
        struct nf_conn_tstamp *tstamp;
+       u64 timeout;
 
        ct = nf_conntrack_alloc(net, zone, otuple, rtuple, GFP_ATOMIC);
        if (IS_ERR(ct))
@@ -1775,7 +1778,10 @@ ctnetlink_create_conntrack(struct net *net,
        if (!cda[CTA_TIMEOUT])
                goto err1;
 
-       ct->timeout = nfct_time_stamp + ntohl(nla_get_be32(cda[CTA_TIMEOUT])) * HZ;
+       timeout = (u64)ntohl(nla_get_be32(cda[CTA_TIMEOUT])) * HZ;
+       if (timeout > INT_MAX)
+               timeout = INT_MAX;
+       ct->timeout = (u32)timeout + nfct_time_stamp;
 
        rcu_read_lock();
        if (cda[CTA_HELP]) {
index b12fc07111d0847b014410291df947bddc32d46a..37ef35b861f24365c843a4eec5ecc5ad8292cd22 100644 (file)
@@ -1039,6 +1039,9 @@ static int tcp_packet(struct nf_conn *ct,
                 IP_CT_TCP_FLAG_DATA_UNACKNOWLEDGED &&
                 timeouts[new_state] > timeouts[TCP_CONNTRACK_UNACK])
                timeout = timeouts[TCP_CONNTRACK_UNACK];
+       else if (ct->proto.tcp.last_win == 0 &&
+                timeouts[new_state] > timeouts[TCP_CONNTRACK_RETRANS])
+               timeout = timeouts[TCP_CONNTRACK_RETRANS];
        else
                timeout = timeouts[new_state];
        spin_unlock_bh(&ct->lock);
index d8327b43e4dce64593573178a397b160488a6355..10798b35748180746266aa0a84187dfd7f0f1ceb 100644 (file)
@@ -5847,6 +5847,12 @@ static int __net_init nf_tables_init_net(struct net *net)
        return 0;
 }
 
+static void __net_exit nf_tables_exit_net(struct net *net)
+{
+       WARN_ON_ONCE(!list_empty(&net->nft.af_info));
+       WARN_ON_ONCE(!list_empty(&net->nft.commit_list));
+}
+
 int __nft_release_basechain(struct nft_ctx *ctx)
 {
        struct nft_rule *rule, *nr;
@@ -5917,6 +5923,7 @@ static void __nft_release_afinfo(struct net *net, struct nft_af_info *afi)
 
 static struct pernet_operations nf_tables_net_ops = {
        .init   = nf_tables_init_net,
+       .exit   = nf_tables_exit_net,
 };
 
 static int __init nf_tables_module_init(void)
index 41628b3936731b77885717c27cf4dfa8e62b3c0f..d33ce6d5ebce92db2fab30cb4286c11ffd8c321a 100644 (file)
@@ -17,6 +17,7 @@
 #include <linux/types.h>
 #include <linux/list.h>
 #include <linux/errno.h>
+#include <linux/capability.h>
 #include <net/netlink.h>
 #include <net/sock.h>
 
@@ -407,6 +408,9 @@ static int nfnl_cthelper_new(struct net *net, struct sock *nfnl,
        struct nfnl_cthelper *nlcth;
        int ret = 0;
 
+       if (!capable(CAP_NET_ADMIN))
+               return -EPERM;
+
        if (!tb[NFCTH_NAME] || !tb[NFCTH_TUPLE])
                return -EINVAL;
 
@@ -611,6 +615,9 @@ static int nfnl_cthelper_get(struct net *net, struct sock *nfnl,
        struct nfnl_cthelper *nlcth;
        bool tuple_set = false;
 
+       if (!capable(CAP_NET_ADMIN))
+               return -EPERM;
+
        if (nlh->nlmsg_flags & NLM_F_DUMP) {
                struct netlink_dump_control c = {
                        .dump = nfnl_cthelper_dump_table,
@@ -678,6 +685,9 @@ static int nfnl_cthelper_del(struct net *net, struct sock *nfnl,
        struct nfnl_cthelper *nlcth, *n;
        int j = 0, ret;
 
+       if (!capable(CAP_NET_ADMIN))
+               return -EPERM;
+
        if (tb[NFCTH_NAME])
                helper_name = nla_data(tb[NFCTH_NAME]);
 
index e5afab86381ca1f1487195009ffde4b8eaeec3e2..e955bec0acc6a949a32ac8d1e6ea383b31983c73 100644 (file)
@@ -1093,10 +1093,15 @@ static int __net_init nfnl_log_net_init(struct net *net)
 
 static void __net_exit nfnl_log_net_exit(struct net *net)
 {
+       struct nfnl_log_net *log = nfnl_log_pernet(net);
+       unsigned int i;
+
 #ifdef CONFIG_PROC_FS
        remove_proc_entry("nfnetlink_log", net->nf.proc_netfilter);
 #endif
        nf_log_unset(net, &nfulnl_logger);
+       for (i = 0; i < INSTANCE_BUCKETS; i++)
+               WARN_ON_ONCE(!hlist_empty(&log->instance_table[i]));
 }
 
 static struct pernet_operations nfnl_log_net_ops = {
index a16356cacec3646a9b70a0d0b443db28a696a0a0..c09b36755ed721f45be12523c4c328c97fd0e166 100644 (file)
@@ -1512,10 +1512,15 @@ static int __net_init nfnl_queue_net_init(struct net *net)
 
 static void __net_exit nfnl_queue_net_exit(struct net *net)
 {
+       struct nfnl_queue_net *q = nfnl_queue_pernet(net);
+       unsigned int i;
+
        nf_unregister_queue_handler(net);
 #ifdef CONFIG_PROC_FS
        remove_proc_entry("nfnetlink_queue", net->nf.proc_netfilter);
 #endif
+       for (i = 0; i < INSTANCE_BUCKETS; i++)
+               WARN_ON_ONCE(!hlist_empty(&q->instance_table[i]));
 }
 
 static void nfnl_queue_net_exit_batch(struct list_head *net_exit_list)
index a0a93d987a3bd440dc19bafe9e65b023c6baf217..47ec1046ad11536e337f709d1f41a267a77cf1d3 100644 (file)
@@ -214,6 +214,8 @@ static const struct nla_policy nft_exthdr_policy[NFTA_EXTHDR_MAX + 1] = {
        [NFTA_EXTHDR_OFFSET]            = { .type = NLA_U32 },
        [NFTA_EXTHDR_LEN]               = { .type = NLA_U32 },
        [NFTA_EXTHDR_FLAGS]             = { .type = NLA_U32 },
+       [NFTA_EXTHDR_OP]                = { .type = NLA_U32 },
+       [NFTA_EXTHDR_SREG]              = { .type = NLA_U32 },
 };
 
 static int nft_exthdr_init(const struct nft_ctx *ctx,
index a77dd514297c9627d6103dbcb6428bb6bdd165ad..55802e97f906d1987ed78b4296584deb38e5f876 100644 (file)
@@ -1729,8 +1729,17 @@ static int __net_init xt_net_init(struct net *net)
        return 0;
 }
 
+static void __net_exit xt_net_exit(struct net *net)
+{
+       int i;
+
+       for (i = 0; i < NFPROTO_NUMPROTO; i++)
+               WARN_ON_ONCE(!list_empty(&net->xt.tables[i]));
+}
+
 static struct pernet_operations xt_net_ops = {
        .init = xt_net_init,
+       .exit = xt_net_exit,
 };
 
 static int __init xt_init(void)
index 041da0d9c06f2b1c2ecb31851932ac5a350122a9..1f7fbd3c7e5a6de0cbe7e0bb5c847a98df371aff 100644 (file)
@@ -27,6 +27,9 @@ static int __bpf_mt_check_bytecode(struct sock_filter *insns, __u16 len,
 {
        struct sock_fprog_kern program;
 
+       if (len > XT_BPF_MAX_NUM_INSTR)
+               return -EINVAL;
+
        program.len = len;
        program.filter = insns;
 
@@ -55,6 +58,9 @@ static int __bpf_mt_check_path(const char *path, struct bpf_prog **ret)
        mm_segment_t oldfs = get_fs();
        int retval, fd;
 
+       if (strnlen(path, XT_BPF_PATH_MAX) == XT_BPF_PATH_MAX)
+               return -EINVAL;
+
        set_fs(KERNEL_DS);
        fd = bpf_obj_get_user(path, 0);
        set_fs(oldfs);
index 36e14b1f061ddf7eb77327a3e717e15b6af83bfb..a34f314a8c2380e6b6a223dd6d38dcc88ca2c1ac 100644 (file)
@@ -19,6 +19,7 @@
 #include <linux/module.h>
 #include <linux/kernel.h>
 
+#include <linux/capability.h>
 #include <linux/if.h>
 #include <linux/inetdevice.h>
 #include <linux/ip.h>
@@ -70,6 +71,9 @@ static int xt_osf_add_callback(struct net *net, struct sock *ctnl,
        struct xt_osf_finger *kf = NULL, *sf;
        int err = 0;
 
+       if (!capable(CAP_NET_ADMIN))
+               return -EPERM;
+
        if (!osf_attrs[OSF_ATTR_FINGER])
                return -EINVAL;
 
@@ -115,6 +119,9 @@ static int xt_osf_remove_callback(struct net *net, struct sock *ctnl,
        struct xt_osf_finger *sf;
        int err = -ENOENT;
 
+       if (!capable(CAP_NET_ADMIN))
+               return -EPERM;
+
        if (!osf_attrs[OSF_ATTR_FINGER])
                return -EINVAL;