Skip to content

Commit 87b3593

Browse files
committed
netfilter: flowtable: validate pppoe header
Ensure there is sufficient room to access the protocol field of the PPPoe header. Validate it once before the flowtable lookup, then use a helper function to access protocol field. Reported-by: syzbot+b6f07e1c07ef40199081@syzkaller.appspotmail.com Fixes: 72efd58 ("netfilter: flowtable: add pppoe support") Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
1 parent 3cfc9ec commit 87b3593

File tree

3 files changed

+18
-5
lines changed

3 files changed

+18
-5
lines changed

include/net/netfilter/nf_flow_table.h

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -336,7 +336,7 @@ int nf_flow_rule_route_ipv6(struct net *net, struct flow_offload *flow,
336336
int nf_flow_table_offload_init(void);
337337
void nf_flow_table_offload_exit(void);
338338

339-
static inline __be16 nf_flow_pppoe_proto(const struct sk_buff *skb)
339+
static inline __be16 __nf_flow_pppoe_proto(const struct sk_buff *skb)
340340
{
341341
__be16 proto;
342342

@@ -352,6 +352,16 @@ static inline __be16 nf_flow_pppoe_proto(const struct sk_buff *skb)
352352
return 0;
353353
}
354354

355+
static inline bool nf_flow_pppoe_proto(struct sk_buff *skb, __be16 *inner_proto)
356+
{
357+
if (!pskb_may_pull(skb, PPPOE_SES_HLEN))
358+
return false;
359+
360+
*inner_proto = __nf_flow_pppoe_proto(skb);
361+
362+
return true;
363+
}
364+
355365
#define NF_FLOW_TABLE_STAT_INC(net, count) __this_cpu_inc((net)->ft.stat->count)
356366
#define NF_FLOW_TABLE_STAT_DEC(net, count) __this_cpu_dec((net)->ft.stat->count)
357367
#define NF_FLOW_TABLE_STAT_INC_ATOMIC(net, count) \

net/netfilter/nf_flow_table_inet.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,8 @@ nf_flow_offload_inet_hook(void *priv, struct sk_buff *skb,
2121
proto = veth->h_vlan_encapsulated_proto;
2222
break;
2323
case htons(ETH_P_PPP_SES):
24-
proto = nf_flow_pppoe_proto(skb);
24+
if (!nf_flow_pppoe_proto(skb, &proto))
25+
return NF_ACCEPT;
2526
break;
2627
default:
2728
proto = skb->protocol;

net/netfilter/nf_flow_table_ip.c

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -273,10 +273,11 @@ static unsigned int nf_flow_xmit_xfrm(struct sk_buff *skb,
273273
return NF_STOLEN;
274274
}
275275

276-
static bool nf_flow_skb_encap_protocol(const struct sk_buff *skb, __be16 proto,
276+
static bool nf_flow_skb_encap_protocol(struct sk_buff *skb, __be16 proto,
277277
u32 *offset)
278278
{
279279
struct vlan_ethhdr *veth;
280+
__be16 inner_proto;
280281

281282
switch (skb->protocol) {
282283
case htons(ETH_P_8021Q):
@@ -287,7 +288,8 @@ static bool nf_flow_skb_encap_protocol(const struct sk_buff *skb, __be16 proto,
287288
}
288289
break;
289290
case htons(ETH_P_PPP_SES):
290-
if (nf_flow_pppoe_proto(skb) == proto) {
291+
if (nf_flow_pppoe_proto(skb, &inner_proto) &&
292+
inner_proto == proto) {
291293
*offset += PPPOE_SES_HLEN;
292294
return true;
293295
}
@@ -316,7 +318,7 @@ static void nf_flow_encap_pop(struct sk_buff *skb,
316318
skb_reset_network_header(skb);
317319
break;
318320
case htons(ETH_P_PPP_SES):
319-
skb->protocol = nf_flow_pppoe_proto(skb);
321+
skb->protocol = __nf_flow_pppoe_proto(skb);
320322
skb_pull(skb, PPPOE_SES_HLEN);
321323
skb_reset_network_header(skb);
322324
break;

0 commit comments

Comments
 (0)