Skip to content

Commit 4fa331b

Browse files
committed
Merge git://git.kernel.org/pub/scm/linux/kernel/git/netfilter/nf
Pablo Neira Ayuso says: ==================== Netfilter fixes for net The following patchset contains Netfilter fixes for net: 1) Fix PPPoE and QinQ with flowtable inet family. 2) Missing register validation in nf_tables. 3) Initialize registers to avoid stack memleak to userspace. ==================== Signed-off-by: David S. Miller <davem@davemloft.net>
2 parents 551acdc + 4c905f6 commit 4fa331b

5 files changed

Lines changed: 53 additions & 24 deletions

File tree

include/net/netfilter/nf_flow_table.h

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@
1010
#include <linux/netfilter/nf_conntrack_tuple_common.h>
1111
#include <net/flow_offload.h>
1212
#include <net/dst.h>
13+
#include <linux/if_pppox.h>
14+
#include <linux/ppp_defs.h>
1315

1416
struct nf_flowtable;
1517
struct nf_flow_rule;
@@ -317,4 +319,20 @@ int nf_flow_rule_route_ipv6(struct net *net, const struct flow_offload *flow,
317319
int nf_flow_table_offload_init(void);
318320
void nf_flow_table_offload_exit(void);
319321

322+
static inline __be16 nf_flow_pppoe_proto(const struct sk_buff *skb)
323+
{
324+
__be16 proto;
325+
326+
proto = *((__be16 *)(skb_mac_header(skb) + ETH_HLEN +
327+
sizeof(struct pppoe_hdr)));
328+
switch (proto) {
329+
case htons(PPP_IP):
330+
return htons(ETH_P_IP);
331+
case htons(PPP_IPV6):
332+
return htons(ETH_P_IPV6);
333+
}
334+
335+
return 0;
336+
}
337+
320338
#endif /* _NF_FLOW_TABLE_H */

net/netfilter/nf_flow_table_inet.c

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,12 +6,29 @@
66
#include <linux/rhashtable.h>
77
#include <net/netfilter/nf_flow_table.h>
88
#include <net/netfilter/nf_tables.h>
9+
#include <linux/if_vlan.h>
910

1011
static unsigned int
1112
nf_flow_offload_inet_hook(void *priv, struct sk_buff *skb,
1213
const struct nf_hook_state *state)
1314
{
15+
struct vlan_ethhdr *veth;
16+
__be16 proto;
17+
1418
switch (skb->protocol) {
19+
case htons(ETH_P_8021Q):
20+
veth = (struct vlan_ethhdr *)skb_mac_header(skb);
21+
proto = veth->h_vlan_encapsulated_proto;
22+
break;
23+
case htons(ETH_P_PPP_SES):
24+
proto = nf_flow_pppoe_proto(skb);
25+
break;
26+
default:
27+
proto = skb->protocol;
28+
break;
29+
}
30+
31+
switch (proto) {
1532
case htons(ETH_P_IP):
1633
return nf_flow_offload_ip_hook(priv, skb, state);
1734
case htons(ETH_P_IPV6):

net/netfilter/nf_flow_table_ip.c

Lines changed: 0 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,6 @@
88
#include <linux/ipv6.h>
99
#include <linux/netdevice.h>
1010
#include <linux/if_ether.h>
11-
#include <linux/if_pppox.h>
12-
#include <linux/ppp_defs.h>
1311
#include <net/ip.h>
1412
#include <net/ipv6.h>
1513
#include <net/ip6_route.h>
@@ -239,22 +237,6 @@ static unsigned int nf_flow_xmit_xfrm(struct sk_buff *skb,
239237
return NF_STOLEN;
240238
}
241239

242-
static inline __be16 nf_flow_pppoe_proto(const struct sk_buff *skb)
243-
{
244-
__be16 proto;
245-
246-
proto = *((__be16 *)(skb_mac_header(skb) + ETH_HLEN +
247-
sizeof(struct pppoe_hdr)));
248-
switch (proto) {
249-
case htons(PPP_IP):
250-
return htons(ETH_P_IP);
251-
case htons(PPP_IPV6):
252-
return htons(ETH_P_IPV6);
253-
}
254-
255-
return 0;
256-
}
257-
258240
static bool nf_flow_skb_encap_protocol(const struct sk_buff *skb, __be16 proto,
259241
u32 *offset)
260242
{

net/netfilter/nf_tables_api.c

Lines changed: 17 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -9275,17 +9275,23 @@ int nft_parse_u32_check(const struct nlattr *attr, int max, u32 *dest)
92759275
}
92769276
EXPORT_SYMBOL_GPL(nft_parse_u32_check);
92779277

9278-
static unsigned int nft_parse_register(const struct nlattr *attr)
9278+
static unsigned int nft_parse_register(const struct nlattr *attr, u32 *preg)
92799279
{
92809280
unsigned int reg;
92819281

92829282
reg = ntohl(nla_get_be32(attr));
92839283
switch (reg) {
92849284
case NFT_REG_VERDICT...NFT_REG_4:
9285-
return reg * NFT_REG_SIZE / NFT_REG32_SIZE;
9285+
*preg = reg * NFT_REG_SIZE / NFT_REG32_SIZE;
9286+
break;
9287+
case NFT_REG32_00...NFT_REG32_15:
9288+
*preg = reg + NFT_REG_SIZE / NFT_REG32_SIZE - NFT_REG32_00;
9289+
break;
92869290
default:
9287-
return reg + NFT_REG_SIZE / NFT_REG32_SIZE - NFT_REG32_00;
9291+
return -ERANGE;
92889292
}
9293+
9294+
return 0;
92899295
}
92909296

92919297
/**
@@ -9327,7 +9333,10 @@ int nft_parse_register_load(const struct nlattr *attr, u8 *sreg, u32 len)
93279333
u32 reg;
93289334
int err;
93299335

9330-
reg = nft_parse_register(attr);
9336+
err = nft_parse_register(attr, &reg);
9337+
if (err < 0)
9338+
return err;
9339+
93319340
err = nft_validate_register_load(reg, len);
93329341
if (err < 0)
93339342
return err;
@@ -9382,7 +9391,10 @@ int nft_parse_register_store(const struct nft_ctx *ctx,
93829391
int err;
93839392
u32 reg;
93849393

9385-
reg = nft_parse_register(attr);
9394+
err = nft_parse_register(attr, &reg);
9395+
if (err < 0)
9396+
return err;
9397+
93869398
err = nft_validate_register_store(ctx, reg, data, type, len);
93879399
if (err < 0)
93889400
return err;

net/netfilter/nf_tables_core.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -201,7 +201,7 @@ nft_do_chain(struct nft_pktinfo *pkt, void *priv)
201201
const struct nft_rule_dp *rule, *last_rule;
202202
const struct net *net = nft_net(pkt);
203203
const struct nft_expr *expr, *last;
204-
struct nft_regs regs;
204+
struct nft_regs regs = {};
205205
unsigned int stackptr = 0;
206206
struct nft_jumpstack jumpstack[NFT_JUMP_STACK_SIZE];
207207
bool genbit = READ_ONCE(net->nft.gencursor);

0 commit comments

Comments
 (0)