From: Pablo Neira Ayuso <pablo@netfilter.org>
To: netfilter-devel@vger.kernel.org
Cc: davem@davemloft.net, netdev@vger.kernel.org
Subject: [PATCH 04/10] netfilter: nft_set_bitmap: fetch the element key based on the set->klen
Date: Wed, 15 Mar 2017 18:01:06 +0100 [thread overview]
Message-ID: <1489597272-30347-5-git-send-email-pablo@netfilter.org> (raw)
In-Reply-To: <1489597272-30347-1-git-send-email-pablo@netfilter.org>
From: Liping Zhang <zlpnobody@gmail.com>
Currently we just assume the element key as a u32 integer, regardless of
the set key length.
This is incorrect, for example, the tcp port number is only 16 bits.
So when we use the nft_payload expr to get the tcp dport and store
it to dreg, the dport will be stored at 0~15 bits, and 16~31 bits
will be padded with zero.
So the reg->data[dreg] will be looked like as below:
0 15 31
+-+-+-+-+-+-+-+-+-+-+-+-+
| tcp dport | 0 |
+-+-+-+-+-+-+-+-+-+-+-+-+
But for these big-endian systems, if we treate this register as a u32
integer, the element key will be larger than 65535, so the following
lookup in bitmap set will cause out of bound access.
Another issue is that if we add element with comments in bitmap
set(although the comments will be ignored eventually), the element will
vanish strangely. Because we treate the element key as a u32 integer, so
the comments will become the part of the element key, then the element
key will also be larger than 65535 and out of bound access will happen:
# nft add element t s { 1 comment test }
Since set->klen is 1 or 2, it's fine to treate the element key as a u8 or
u16 integer.
Fixes: 665153ff5752 ("netfilter: nf_tables: add bitmap set type")
Signed-off-by: Liping Zhang <zlpnobody@gmail.com>
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
---
net/netfilter/nft_set_bitmap.c | 27 +++++++++++++++++----------
1 file changed, 17 insertions(+), 10 deletions(-)
diff --git a/net/netfilter/nft_set_bitmap.c b/net/netfilter/nft_set_bitmap.c
index 152d226552c1..9b024e22717b 100644
--- a/net/netfilter/nft_set_bitmap.c
+++ b/net/netfilter/nft_set_bitmap.c
@@ -45,9 +45,17 @@ struct nft_bitmap {
u8 bitmap[];
};
-static inline void nft_bitmap_location(u32 key, u32 *idx, u32 *off)
+static inline void nft_bitmap_location(const struct nft_set *set,
+ const void *key,
+ u32 *idx, u32 *off)
{
- u32 k = (key << 1);
+ u32 k;
+
+ if (set->klen == 2)
+ k = *(u16 *)key;
+ else
+ k = *(u8 *)key;
+ k <<= 1;
*idx = k / BITS_PER_BYTE;
*off = k % BITS_PER_BYTE;
@@ -69,7 +77,7 @@ static bool nft_bitmap_lookup(const struct net *net, const struct nft_set *set,
u8 genmask = nft_genmask_cur(net);
u32 idx, off;
- nft_bitmap_location(*key, &idx, &off);
+ nft_bitmap_location(set, key, &idx, &off);
return nft_bitmap_active(priv->bitmap, idx, off, genmask);
}
@@ -83,7 +91,7 @@ static int nft_bitmap_insert(const struct net *net, const struct nft_set *set,
u8 genmask = nft_genmask_next(net);
u32 idx, off;
- nft_bitmap_location(nft_set_ext_key(ext)->data[0], &idx, &off);
+ nft_bitmap_location(set, nft_set_ext_key(ext), &idx, &off);
if (nft_bitmap_active(priv->bitmap, idx, off, genmask))
return -EEXIST;
@@ -102,7 +110,7 @@ static void nft_bitmap_remove(const struct net *net,
u8 genmask = nft_genmask_next(net);
u32 idx, off;
- nft_bitmap_location(nft_set_ext_key(ext)->data[0], &idx, &off);
+ nft_bitmap_location(set, nft_set_ext_key(ext), &idx, &off);
/* Enter 00 state. */
priv->bitmap[idx] &= ~(genmask << off);
}
@@ -116,7 +124,7 @@ static void nft_bitmap_activate(const struct net *net,
u8 genmask = nft_genmask_next(net);
u32 idx, off;
- nft_bitmap_location(nft_set_ext_key(ext)->data[0], &idx, &off);
+ nft_bitmap_location(set, nft_set_ext_key(ext), &idx, &off);
/* Enter 11 state. */
priv->bitmap[idx] |= (genmask << off);
}
@@ -128,7 +136,7 @@ static bool nft_bitmap_flush(const struct net *net,
u8 genmask = nft_genmask_next(net);
u32 idx, off;
- nft_bitmap_location(nft_set_ext_key(ext)->data[0], &idx, &off);
+ nft_bitmap_location(set, nft_set_ext_key(ext), &idx, &off);
/* Enter 10 state, similar to deactivation. */
priv->bitmap[idx] &= ~(genmask << off);
@@ -161,10 +169,9 @@ static void *nft_bitmap_deactivate(const struct net *net,
struct nft_bitmap *priv = nft_set_priv(set);
u8 genmask = nft_genmask_next(net);
struct nft_set_ext *ext;
- u32 idx, off, key = 0;
+ u32 idx, off;
- memcpy(&key, elem->key.val.data, set->klen);
- nft_bitmap_location(key, &idx, &off);
+ nft_bitmap_location(set, elem->key.val.data, &idx, &off);
if (!nft_bitmap_active(priv->bitmap, idx, off, genmask))
return NULL;
--
2.1.4
next prev parent reply other threads:[~2017-03-15 17:01 UTC|newest]
Thread overview: 15+ messages / expand[flat|nested] mbox.gz Atom feed top
2017-03-15 17:01 [PATCH 00/10] Netfilter fixes for net Pablo Neira Ayuso
2017-03-15 17:01 ` [PATCH 01/10] netfilter: don't track fragmented packets Pablo Neira Ayuso
2017-03-15 17:01 ` [PATCH 02/10] netfilter: nf_nat_sctp: fix ICMP packet to be dropped accidently Pablo Neira Ayuso
2017-03-15 17:01 ` [PATCH 03/10] netfilter: nf_tables: set pktinfo->thoff at AH header if found Pablo Neira Ayuso
2017-03-15 17:01 ` Pablo Neira Ayuso [this message]
2017-03-15 17:01 ` [PATCH 05/10] netfilter: nf_tables: fix mismatch in big-endian system Pablo Neira Ayuso
2017-03-16 10:58 ` David Laight
2017-03-17 4:31 ` Liping Zhang
2017-03-15 17:01 ` [PATCH 06/10] netfilter: bridge: honor frag_max_size when refragmenting Pablo Neira Ayuso
2017-03-15 17:01 ` [PATCH 07/10] netfilter: Force fake conntrack entry to be at least 8 bytes aligned Pablo Neira Ayuso
2017-03-16 9:55 ` David Laight
2017-03-15 17:01 ` [PATCH 08/10] netfilter: nft_set_bitmap: keep a list of dummy elements Pablo Neira Ayuso
2017-03-15 17:01 ` [PATCH 09/10] Revert "netfilter: nf_tables: add flush field to struct nft_set_iter" Pablo Neira Ayuso
2017-03-15 17:01 ` [PATCH 10/10] netfilter: nft_ct: do cleanup work when NFTA_CT_DIRECTION is invalid Pablo Neira Ayuso
2017-03-15 22:13 ` [PATCH 00/10] Netfilter fixes for net David Miller
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1489597272-30347-5-git-send-email-pablo@netfilter.org \
--to=pablo@netfilter.org \
--cc=davem@davemloft.net \
--cc=netdev@vger.kernel.org \
--cc=netfilter-devel@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).