aboutsummaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
authorLiping Zhang <liping.zhang@spreadtrum.com>2016-09-17 02:31:20 -0400
committerPablo Neira Ayuso <pablo@netfilter.org>2016-09-23 03:30:26 -0400
commita20877b5edec4d2b62560b5245199af04846476c (patch)
treeda43d9f571eb5a6c41b013645c831564e2f7b534 /net
parent8dc3c2b86bb16e8f345b80a8af69696e9a7edb65 (diff)
netfilter: nf_tables: check tprot_set first when we use xt.thoff
pkt->xt.thoff is not always set properly, but we use it without any check. For payload expr, it will cause wrong results. For nftrace, we may notify the wrong network or transport header to the user space, furthermore, input the following nft rules, warning message will be printed out: # nft add rule arp filter output meta nftrace set 1 WARNING: CPU: 0 PID: 13428 at net/netfilter/nf_tables_trace.c:263 nft_trace_notify+0x4a3/0x5e0 [nf_tables] Call Trace: [<ffffffff813d58ae>] dump_stack+0x63/0x85 [<ffffffff810a4c0b>] __warn+0xcb/0xf0 [<ffffffff810a4d3d>] warn_slowpath_null+0x1d/0x20 [<ffffffffa0589703>] nft_trace_notify+0x4a3/0x5e0 [nf_tables] [ ... ] [<ffffffffa05690a8>] nft_do_chain_arp+0x78/0x90 [nf_tables_arp] [<ffffffff816f4aa2>] nf_iterate+0x62/0x80 [<ffffffff816f4b33>] nf_hook_slow+0x73/0xd0 [<ffffffff81732bbf>] arp_xmit+0x8f/0xb0 [ ... ] [<ffffffff81732d36>] arp_solicit+0x106/0x2c0 So before we use pkt->xt.thoff, check the tprot_set first. Signed-off-by: Liping Zhang <liping.zhang@spreadtrum.com> Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
Diffstat (limited to 'net')
-rw-r--r--net/netfilter/nf_tables_core.c5
-rw-r--r--net/netfilter/nf_tables_trace.c20
-rw-r--r--net/netfilter/nft_payload.c4
3 files changed, 19 insertions, 10 deletions
diff --git a/net/netfilter/nf_tables_core.c b/net/netfilter/nf_tables_core.c
index 36ba4e55d84e..67259cefef06 100644
--- a/net/netfilter/nf_tables_core.c
+++ b/net/netfilter/nf_tables_core.c
@@ -93,8 +93,11 @@ static bool nft_payload_fast_eval(const struct nft_expr *expr,
93 93
94 if (priv->base == NFT_PAYLOAD_NETWORK_HEADER) 94 if (priv->base == NFT_PAYLOAD_NETWORK_HEADER)
95 ptr = skb_network_header(skb); 95 ptr = skb_network_header(skb);
96 else 96 else {
97 if (!pkt->tprot_set)
98 return false;
97 ptr = skb_network_header(skb) + pkt->xt.thoff; 99 ptr = skb_network_header(skb) + pkt->xt.thoff;
100 }
98 101
99 ptr += priv->offset; 102 ptr += priv->offset;
100 103
diff --git a/net/netfilter/nf_tables_trace.c b/net/netfilter/nf_tables_trace.c
index 39eb1cc62e91..696fe8f6f2f2 100644
--- a/net/netfilter/nf_tables_trace.c
+++ b/net/netfilter/nf_tables_trace.c
@@ -113,20 +113,22 @@ static int nf_trace_fill_pkt_info(struct sk_buff *nlskb,
113 const struct nft_pktinfo *pkt) 113 const struct nft_pktinfo *pkt)
114{ 114{
115 const struct sk_buff *skb = pkt->skb; 115 const struct sk_buff *skb = pkt->skb;
116 unsigned int len = min_t(unsigned int,
117 pkt->xt.thoff - skb_network_offset(skb),
118 NFT_TRACETYPE_NETWORK_HSIZE);
119 int off = skb_network_offset(skb); 116 int off = skb_network_offset(skb);
117 unsigned int len, nh_end;
120 118
119 nh_end = pkt->tprot_set ? pkt->xt.thoff : skb->len;
120 len = min_t(unsigned int, nh_end - skb_network_offset(skb),
121 NFT_TRACETYPE_NETWORK_HSIZE);
121 if (trace_fill_header(nlskb, NFTA_TRACE_NETWORK_HEADER, skb, off, len)) 122 if (trace_fill_header(nlskb, NFTA_TRACE_NETWORK_HEADER, skb, off, len))
122 return -1; 123 return -1;
123 124
124 len = min_t(unsigned int, skb->len - pkt->xt.thoff, 125 if (pkt->tprot_set) {
125 NFT_TRACETYPE_TRANSPORT_HSIZE); 126 len = min_t(unsigned int, skb->len - pkt->xt.thoff,
126 127 NFT_TRACETYPE_TRANSPORT_HSIZE);
127 if (trace_fill_header(nlskb, NFTA_TRACE_TRANSPORT_HEADER, skb, 128 if (trace_fill_header(nlskb, NFTA_TRACE_TRANSPORT_HEADER, skb,
128 pkt->xt.thoff, len)) 129 pkt->xt.thoff, len))
129 return -1; 130 return -1;
131 }
130 132
131 if (!skb_mac_header_was_set(skb)) 133 if (!skb_mac_header_was_set(skb))
132 return 0; 134 return 0;
diff --git a/net/netfilter/nft_payload.c b/net/netfilter/nft_payload.c
index 12cd4bf16d17..b2f88617611a 100644
--- a/net/netfilter/nft_payload.c
+++ b/net/netfilter/nft_payload.c
@@ -92,6 +92,8 @@ static void nft_payload_eval(const struct nft_expr *expr,
92 offset = skb_network_offset(skb); 92 offset = skb_network_offset(skb);
93 break; 93 break;
94 case NFT_PAYLOAD_TRANSPORT_HEADER: 94 case NFT_PAYLOAD_TRANSPORT_HEADER:
95 if (!pkt->tprot_set)
96 goto err;
95 offset = pkt->xt.thoff; 97 offset = pkt->xt.thoff;
96 break; 98 break;
97 default: 99 default:
@@ -184,6 +186,8 @@ static void nft_payload_set_eval(const struct nft_expr *expr,
184 offset = skb_network_offset(skb); 186 offset = skb_network_offset(skb);
185 break; 187 break;
186 case NFT_PAYLOAD_TRANSPORT_HEADER: 188 case NFT_PAYLOAD_TRANSPORT_HEADER:
189 if (!pkt->tprot_set)
190 goto err;
187 offset = pkt->xt.thoff; 191 offset = pkt->xt.thoff;
188 break; 192 break;
189 default: 193 default: