diff options
Diffstat (limited to 'target/linux/generic/backport-4.9/092-netfilter-nf_tables-fix-mismatch-in-big-endian-syste.patch')
-rw-r--r-- | target/linux/generic/backport-4.9/092-netfilter-nf_tables-fix-mismatch-in-big-endian-syste.patch | 323 |
1 files changed, 0 insertions, 323 deletions
diff --git a/target/linux/generic/backport-4.9/092-netfilter-nf_tables-fix-mismatch-in-big-endian-syste.patch b/target/linux/generic/backport-4.9/092-netfilter-nf_tables-fix-mismatch-in-big-endian-syste.patch deleted file mode 100644 index 024983142c..0000000000 --- a/target/linux/generic/backport-4.9/092-netfilter-nf_tables-fix-mismatch-in-big-endian-syste.patch +++ /dev/null @@ -1,323 +0,0 @@ -From 0bc01df3df7a88258148518eb9ce7f88c16a6106 Mon Sep 17 00:00:00 2001 -From: Liping Zhang <zlpnobody@gmail.com> -Date: Wed, 8 Mar 2017 22:54:18 +0800 -Subject: netfilter: nf_tables: fix mismatch in big-endian system - -Currently, there are two different methods to store an u16 integer to -the u32 data register. For example: - u32 *dest = ®s->data[priv->dreg]; - 1. *dest = 0; *(u16 *) dest = val_u16; - 2. *dest = val_u16; - -For method 1, the u16 value will be stored like this, either in -big-endian or little-endian system: - 0 15 31 - +-+-+-+-+-+-+-+-+-+-+-+-+ - | Value | 0 | - +-+-+-+-+-+-+-+-+-+-+-+-+ - -For method 2, in little-endian system, the u16 value will be the same -as listed above. But in big-endian system, the u16 value will be stored -like this: - 0 15 31 - +-+-+-+-+-+-+-+-+-+-+-+-+ - | 0 | Value | - +-+-+-+-+-+-+-+-+-+-+-+-+ - -So later we use "memcmp(®s->data[priv->sreg], data, 2);" to do -compare in nft_cmp, nft_lookup expr ..., method 2 will get the wrong -result in big-endian system, as 0~15 bits will always be zero. - -For the similar reason, when loading an u16 value from the u32 data -register, we should use "*(u16 *) sreg;" instead of "(u16)*sreg;", -the 2nd method will get the wrong value in the big-endian system. - -So introduce some wrapper functions to store/load an u8 or u16 -integer to/from the u32 data register, and use them in the right -place. - -Signed-off-by: Liping Zhang <zlpnobody@gmail.com> -Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org> ---- - include/net/netfilter/nf_tables.h | 29 +++++++++++++++++++++++++ - net/ipv4/netfilter/nft_masq_ipv4.c | 8 +++---- - net/ipv4/netfilter/nft_redir_ipv4.c | 8 +++---- - net/ipv6/netfilter/nft_masq_ipv6.c | 8 +++---- - net/ipv6/netfilter/nft_redir_ipv6.c | 8 +++---- - net/netfilter/nft_ct.c | 10 ++++----- - net/netfilter/nft_meta.c | 42 +++++++++++++++++++------------------ - net/netfilter/nft_nat.c | 8 +++---- - 8 files changed, 76 insertions(+), 45 deletions(-) - ---- a/include/net/netfilter/nf_tables.h -+++ b/include/net/netfilter/nf_tables.h -@@ -87,6 +87,35 @@ struct nft_regs { - }; - }; - -+/* Store/load an u16 or u8 integer to/from the u32 data register. -+ * -+ * Note, when using concatenations, register allocation happens at 32-bit -+ * level. So for store instruction, pad the rest part with zero to avoid -+ * garbage values. -+ */ -+ -+static inline void nft_reg_store16(u32 *dreg, u16 val) -+{ -+ *dreg = 0; -+ *(u16 *)dreg = val; -+} -+ -+static inline void nft_reg_store8(u32 *dreg, u8 val) -+{ -+ *dreg = 0; -+ *(u8 *)dreg = val; -+} -+ -+static inline u16 nft_reg_load16(u32 *sreg) -+{ -+ return *(u16 *)sreg; -+} -+ -+static inline u8 nft_reg_load8(u32 *sreg) -+{ -+ return *(u8 *)sreg; -+} -+ - static inline void nft_data_copy(u32 *dst, const struct nft_data *src, - unsigned int len) - { ---- a/net/ipv4/netfilter/nft_masq_ipv4.c -+++ b/net/ipv4/netfilter/nft_masq_ipv4.c -@@ -26,10 +26,10 @@ static void nft_masq_ipv4_eval(const str - memset(&range, 0, sizeof(range)); - range.flags = priv->flags; - if (priv->sreg_proto_min) { -- range.min_proto.all = -- *(__be16 *)®s->data[priv->sreg_proto_min]; -- range.max_proto.all = -- *(__be16 *)®s->data[priv->sreg_proto_max]; -+ range.min_proto.all = (__force __be16)nft_reg_load16( -+ ®s->data[priv->sreg_proto_min]); -+ range.max_proto.all = (__force __be16)nft_reg_load16( -+ ®s->data[priv->sreg_proto_max]); - } - regs->verdict.code = nf_nat_masquerade_ipv4(pkt->skb, pkt->hook, - &range, pkt->out); ---- a/net/ipv4/netfilter/nft_redir_ipv4.c -+++ b/net/ipv4/netfilter/nft_redir_ipv4.c -@@ -26,10 +26,10 @@ static void nft_redir_ipv4_eval(const st - - memset(&mr, 0, sizeof(mr)); - if (priv->sreg_proto_min) { -- mr.range[0].min.all = -- *(__be16 *)®s->data[priv->sreg_proto_min]; -- mr.range[0].max.all = -- *(__be16 *)®s->data[priv->sreg_proto_max]; -+ mr.range[0].min.all = (__force __be16)nft_reg_load16( -+ ®s->data[priv->sreg_proto_min]); -+ mr.range[0].max.all = (__force __be16)nft_reg_load16( -+ ®s->data[priv->sreg_proto_max]); - mr.range[0].flags |= NF_NAT_RANGE_PROTO_SPECIFIED; - } - ---- a/net/ipv6/netfilter/nft_masq_ipv6.c -+++ b/net/ipv6/netfilter/nft_masq_ipv6.c -@@ -27,10 +27,10 @@ static void nft_masq_ipv6_eval(const str - memset(&range, 0, sizeof(range)); - range.flags = priv->flags; - if (priv->sreg_proto_min) { -- range.min_proto.all = -- *(__be16 *)®s->data[priv->sreg_proto_min]; -- range.max_proto.all = -- *(__be16 *)®s->data[priv->sreg_proto_max]; -+ range.min_proto.all = (__force __be16)nft_reg_load16( -+ ®s->data[priv->sreg_proto_min]); -+ range.max_proto.all = (__force __be16)nft_reg_load16( -+ ®s->data[priv->sreg_proto_max]); - } - regs->verdict.code = nf_nat_masquerade_ipv6(pkt->skb, &range, pkt->out); - } ---- a/net/ipv6/netfilter/nft_redir_ipv6.c -+++ b/net/ipv6/netfilter/nft_redir_ipv6.c -@@ -26,10 +26,10 @@ static void nft_redir_ipv6_eval(const st - - memset(&range, 0, sizeof(range)); - if (priv->sreg_proto_min) { -- range.min_proto.all = -- *(__be16 *)®s->data[priv->sreg_proto_min], -- range.max_proto.all = -- *(__be16 *)®s->data[priv->sreg_proto_max], -+ range.min_proto.all = (__force __be16)nft_reg_load16( -+ ®s->data[priv->sreg_proto_min]); -+ range.max_proto.all = (__force __be16)nft_reg_load16( -+ ®s->data[priv->sreg_proto_max]); - range.flags |= NF_NAT_RANGE_PROTO_SPECIFIED; - } - ---- a/net/netfilter/nft_ct.c -+++ b/net/netfilter/nft_ct.c -@@ -77,7 +77,7 @@ static void nft_ct_get_eval(const struct - - switch (priv->key) { - case NFT_CT_DIRECTION: -- *dest = CTINFO2DIR(ctinfo); -+ nft_reg_store8(dest, CTINFO2DIR(ctinfo)); - return; - case NFT_CT_STATUS: - *dest = ct->status; -@@ -129,10 +129,10 @@ static void nft_ct_get_eval(const struct - return; - } - case NFT_CT_L3PROTOCOL: -- *dest = nf_ct_l3num(ct); -+ nft_reg_store8(dest, nf_ct_l3num(ct)); - return; - case NFT_CT_PROTOCOL: -- *dest = nf_ct_protonum(ct); -+ nft_reg_store8(dest, nf_ct_protonum(ct)); - return; - default: - break; -@@ -149,10 +149,10 @@ static void nft_ct_get_eval(const struct - nf_ct_l3num(ct) == NFPROTO_IPV4 ? 4 : 16); - return; - case NFT_CT_PROTO_SRC: -- *dest = (__force __u16)tuple->src.u.all; -+ nft_reg_store16(dest, (__force u16)tuple->src.u.all); - return; - case NFT_CT_PROTO_DST: -- *dest = (__force __u16)tuple->dst.u.all; -+ nft_reg_store16(dest, (__force u16)tuple->dst.u.all); - return; - default: - break; ---- a/net/netfilter/nft_meta.c -+++ b/net/netfilter/nft_meta.c -@@ -45,16 +45,15 @@ void nft_meta_get_eval(const struct nft_ - *dest = skb->len; - break; - case NFT_META_PROTOCOL: -- *dest = 0; -- *(__be16 *)dest = skb->protocol; -+ nft_reg_store16(dest, (__force u16)skb->protocol); - break; - case NFT_META_NFPROTO: -- *dest = pkt->pf; -+ nft_reg_store8(dest, pkt->pf); - break; - case NFT_META_L4PROTO: - if (!pkt->tprot_set) - goto err; -- *dest = pkt->tprot; -+ nft_reg_store8(dest, pkt->tprot); - break; - case NFT_META_PRIORITY: - *dest = skb->priority; -@@ -85,14 +84,12 @@ void nft_meta_get_eval(const struct nft_ - case NFT_META_IIFTYPE: - if (in == NULL) - goto err; -- *dest = 0; -- *(u16 *)dest = in->type; -+ nft_reg_store16(dest, in->type); - break; - case NFT_META_OIFTYPE: - if (out == NULL) - goto err; -- *dest = 0; -- *(u16 *)dest = out->type; -+ nft_reg_store16(dest, out->type); - break; - case NFT_META_SKUID: - sk = skb_to_full_sk(skb); -@@ -142,22 +139,22 @@ void nft_meta_get_eval(const struct nft_ - #endif - case NFT_META_PKTTYPE: - if (skb->pkt_type != PACKET_LOOPBACK) { -- *dest = skb->pkt_type; -+ nft_reg_store8(dest, skb->pkt_type); - break; - } - - switch (pkt->pf) { - case NFPROTO_IPV4: - if (ipv4_is_multicast(ip_hdr(skb)->daddr)) -- *dest = PACKET_MULTICAST; -+ nft_reg_store8(dest, PACKET_MULTICAST); - else -- *dest = PACKET_BROADCAST; -+ nft_reg_store8(dest, PACKET_BROADCAST); - break; - case NFPROTO_IPV6: - if (ipv6_hdr(skb)->daddr.s6_addr[0] == 0xFF) -- *dest = PACKET_MULTICAST; -+ nft_reg_store8(dest, PACKET_MULTICAST); - else -- *dest = PACKET_BROADCAST; -+ nft_reg_store8(dest, PACKET_BROADCAST); - break; - case NFPROTO_NETDEV: - switch (skb->protocol) { -@@ -171,14 +168,14 @@ void nft_meta_get_eval(const struct nft_ - goto err; - - if (ipv4_is_multicast(iph->daddr)) -- *dest = PACKET_MULTICAST; -+ nft_reg_store8(dest, PACKET_MULTICAST); - else -- *dest = PACKET_BROADCAST; -+ nft_reg_store8(dest, PACKET_BROADCAST); - - break; - } - case htons(ETH_P_IPV6): -- *dest = PACKET_MULTICAST; -+ nft_reg_store8(dest, PACKET_MULTICAST); - break; - default: - WARN_ON_ONCE(1); -@@ -233,7 +230,9 @@ void nft_meta_set_eval(const struct nft_ - { - const struct nft_meta *meta = nft_expr_priv(expr); - struct sk_buff *skb = pkt->skb; -- u32 value = regs->data[meta->sreg]; -+ u32 *sreg = ®s->data[meta->sreg]; -+ u32 value = *sreg; -+ u8 pkt_type; - - switch (meta->key) { - case NFT_META_MARK: -@@ -243,9 +242,12 @@ void nft_meta_set_eval(const struct nft_ - skb->priority = value; - break; - case NFT_META_PKTTYPE: -- if (skb->pkt_type != value && -- skb_pkt_type_ok(value) && skb_pkt_type_ok(skb->pkt_type)) -- skb->pkt_type = value; -+ pkt_type = nft_reg_load8(sreg); -+ -+ if (skb->pkt_type != pkt_type && -+ skb_pkt_type_ok(pkt_type) && -+ skb_pkt_type_ok(skb->pkt_type)) -+ skb->pkt_type = pkt_type; - break; - case NFT_META_NFTRACE: - skb->nf_trace = !!value; ---- a/net/netfilter/nft_nat.c -+++ b/net/netfilter/nft_nat.c -@@ -65,10 +65,10 @@ static void nft_nat_eval(const struct nf - } - - if (priv->sreg_proto_min) { -- range.min_proto.all = -- *(__be16 *)®s->data[priv->sreg_proto_min]; -- range.max_proto.all = -- *(__be16 *)®s->data[priv->sreg_proto_max]; -+ range.min_proto.all = (__force __be16)nft_reg_load16( -+ ®s->data[priv->sreg_proto_min]); -+ range.max_proto.all = (__force __be16)nft_reg_load16( -+ ®s->data[priv->sreg_proto_max]); - range.flags |= NF_NAT_RANGE_PROTO_SPECIFIED; - } - |