Skip to content

Commit 92e8c73

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) Unbreak br_netfilter physdev match support, from Florian Westphal. 2) Use GFP_KERNEL_ACCOUNT for stateful/policy objects, from Chen Aotian. 3) Use IS_ENABLED() in nf_reset_trace(), from Florian Westphal. 4) Fix validation of catch-all set element. 5) Tighten requirements for catch-all set elements. * git://git.kernel.org/pub/scm/linux/kernel/git/netfilter/nf: netfilter: nf_tables: tighten netlink attribute requirements for catch-all elements netfilter: nf_tables: validate catch-all set elements netfilter: nf_tables: fix ifdef to also consider nf_tables=m netfilter: nf_tables: Modify nla_memdup's flag to GFP_KERNEL_ACCOUNT netfilter: br_netfilter: fix recent physdev match breakage ==================== Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Jakub Kicinski <[email protected]>
2 parents c0e7327 + d4eb7e3 commit 92e8c73

File tree

5 files changed

+83
-48
lines changed

5 files changed

+83
-48
lines changed

include/linux/skbuff.h

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -294,6 +294,7 @@ struct nf_bridge_info {
294294
u8 pkt_otherhost:1;
295295
u8 in_prerouting:1;
296296
u8 bridged_dnat:1;
297+
u8 sabotage_in_done:1;
297298
__u16 frag_max_size;
298299
struct net_device *physindev;
299300

@@ -4712,7 +4713,7 @@ static inline void nf_reset_ct(struct sk_buff *skb)
47124713

47134714
static inline void nf_reset_trace(struct sk_buff *skb)
47144715
{
4715-
#if IS_ENABLED(CONFIG_NETFILTER_XT_TARGET_TRACE) || defined(CONFIG_NF_TABLES)
4716+
#if IS_ENABLED(CONFIG_NETFILTER_XT_TARGET_TRACE) || IS_ENABLED(CONFIG_NF_TABLES)
47164717
skb->nf_trace = 0;
47174718
#endif
47184719
}
@@ -4732,7 +4733,7 @@ static inline void __nf_copy(struct sk_buff *dst, const struct sk_buff *src,
47324733
dst->_nfct = src->_nfct;
47334734
nf_conntrack_get(skb_nfct(src));
47344735
#endif
4735-
#if IS_ENABLED(CONFIG_NETFILTER_XT_TARGET_TRACE) || defined(CONFIG_NF_TABLES)
4736+
#if IS_ENABLED(CONFIG_NETFILTER_XT_TARGET_TRACE) || IS_ENABLED(CONFIG_NF_TABLES)
47364737
if (copy)
47374738
dst->nf_trace = src->nf_trace;
47384739
#endif

include/net/netfilter/nf_tables.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1085,6 +1085,10 @@ struct nft_chain {
10851085
};
10861086

10871087
int nft_chain_validate(const struct nft_ctx *ctx, const struct nft_chain *chain);
1088+
int nft_setelem_validate(const struct nft_ctx *ctx, struct nft_set *set,
1089+
const struct nft_set_iter *iter,
1090+
struct nft_set_elem *elem);
1091+
int nft_set_catchall_validate(const struct nft_ctx *ctx, struct nft_set *set);
10881092

10891093
enum nft_chain_types {
10901094
NFT_CHAIN_T_DEFAULT = 0,

net/bridge/br_netfilter_hooks.c

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -868,12 +868,17 @@ static unsigned int ip_sabotage_in(void *priv,
868868
{
869869
struct nf_bridge_info *nf_bridge = nf_bridge_info_get(skb);
870870

871-
if (nf_bridge && !nf_bridge->in_prerouting &&
872-
!netif_is_l3_master(skb->dev) &&
873-
!netif_is_l3_slave(skb->dev)) {
874-
nf_bridge_info_free(skb);
875-
state->okfn(state->net, state->sk, skb);
876-
return NF_STOLEN;
871+
if (nf_bridge) {
872+
if (nf_bridge->sabotage_in_done)
873+
return NF_ACCEPT;
874+
875+
if (!nf_bridge->in_prerouting &&
876+
!netif_is_l3_master(skb->dev) &&
877+
!netif_is_l3_slave(skb->dev)) {
878+
nf_bridge->sabotage_in_done = 1;
879+
state->okfn(state->net, state->sk, skb);
880+
return NF_STOLEN;
881+
}
877882
}
878883

879884
return NF_ACCEPT;

net/netfilter/nf_tables_api.c

Lines changed: 61 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -3447,6 +3447,64 @@ static int nft_table_validate(struct net *net, const struct nft_table *table)
34473447
return 0;
34483448
}
34493449

3450+
int nft_setelem_validate(const struct nft_ctx *ctx, struct nft_set *set,
3451+
const struct nft_set_iter *iter,
3452+
struct nft_set_elem *elem)
3453+
{
3454+
const struct nft_set_ext *ext = nft_set_elem_ext(set, elem->priv);
3455+
struct nft_ctx *pctx = (struct nft_ctx *)ctx;
3456+
const struct nft_data *data;
3457+
int err;
3458+
3459+
if (nft_set_ext_exists(ext, NFT_SET_EXT_FLAGS) &&
3460+
*nft_set_ext_flags(ext) & NFT_SET_ELEM_INTERVAL_END)
3461+
return 0;
3462+
3463+
data = nft_set_ext_data(ext);
3464+
switch (data->verdict.code) {
3465+
case NFT_JUMP:
3466+
case NFT_GOTO:
3467+
pctx->level++;
3468+
err = nft_chain_validate(ctx, data->verdict.chain);
3469+
if (err < 0)
3470+
return err;
3471+
pctx->level--;
3472+
break;
3473+
default:
3474+
break;
3475+
}
3476+
3477+
return 0;
3478+
}
3479+
3480+
struct nft_set_elem_catchall {
3481+
struct list_head list;
3482+
struct rcu_head rcu;
3483+
void *elem;
3484+
};
3485+
3486+
int nft_set_catchall_validate(const struct nft_ctx *ctx, struct nft_set *set)
3487+
{
3488+
u8 genmask = nft_genmask_next(ctx->net);
3489+
struct nft_set_elem_catchall *catchall;
3490+
struct nft_set_elem elem;
3491+
struct nft_set_ext *ext;
3492+
int ret = 0;
3493+
3494+
list_for_each_entry_rcu(catchall, &set->catchall_list, list) {
3495+
ext = nft_set_elem_ext(set, catchall->elem);
3496+
if (!nft_set_elem_active(ext, genmask))
3497+
continue;
3498+
3499+
elem.priv = catchall->elem;
3500+
ret = nft_setelem_validate(ctx, set, NULL, &elem);
3501+
if (ret < 0)
3502+
return ret;
3503+
}
3504+
3505+
return ret;
3506+
}
3507+
34503508
static struct nft_rule *nft_rule_lookup_byid(const struct net *net,
34513509
const struct nft_chain *chain,
34523510
const struct nlattr *nla);
@@ -4759,12 +4817,6 @@ static int nf_tables_newset(struct sk_buff *skb, const struct nfnl_info *info,
47594817
return err;
47604818
}
47614819

4762-
struct nft_set_elem_catchall {
4763-
struct list_head list;
4764-
struct rcu_head rcu;
4765-
void *elem;
4766-
};
4767-
47684820
static void nft_set_catchall_destroy(const struct nft_ctx *ctx,
47694821
struct nft_set *set)
47704822
{
@@ -6056,7 +6108,8 @@ static int nft_add_set_elem(struct nft_ctx *ctx, struct nft_set *set,
60566108
if (err < 0)
60576109
return err;
60586110

6059-
if (!nla[NFTA_SET_ELEM_KEY] && !(flags & NFT_SET_ELEM_CATCHALL))
6111+
if (((flags & NFT_SET_ELEM_CATCHALL) && nla[NFTA_SET_ELEM_KEY]) ||
6112+
(!(flags & NFT_SET_ELEM_CATCHALL) && !nla[NFTA_SET_ELEM_KEY]))
60606113
return -EINVAL;
60616114

60626115
if (flags != 0) {
@@ -7052,7 +7105,7 @@ static int nf_tables_newobj(struct sk_buff *skb, const struct nfnl_info *info,
70527105
}
70537106

70547107
if (nla[NFTA_OBJ_USERDATA]) {
7055-
obj->udata = nla_memdup(nla[NFTA_OBJ_USERDATA], GFP_KERNEL);
7108+
obj->udata = nla_memdup(nla[NFTA_OBJ_USERDATA], GFP_KERNEL_ACCOUNT);
70567109
if (obj->udata == NULL)
70577110
goto err_userdata;
70587111

net/netfilter/nft_lookup.c

Lines changed: 4 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -199,37 +199,6 @@ static int nft_lookup_dump(struct sk_buff *skb,
199199
return -1;
200200
}
201201

202-
static int nft_lookup_validate_setelem(const struct nft_ctx *ctx,
203-
struct nft_set *set,
204-
const struct nft_set_iter *iter,
205-
struct nft_set_elem *elem)
206-
{
207-
const struct nft_set_ext *ext = nft_set_elem_ext(set, elem->priv);
208-
struct nft_ctx *pctx = (struct nft_ctx *)ctx;
209-
const struct nft_data *data;
210-
int err;
211-
212-
if (nft_set_ext_exists(ext, NFT_SET_EXT_FLAGS) &&
213-
*nft_set_ext_flags(ext) & NFT_SET_ELEM_INTERVAL_END)
214-
return 0;
215-
216-
data = nft_set_ext_data(ext);
217-
switch (data->verdict.code) {
218-
case NFT_JUMP:
219-
case NFT_GOTO:
220-
pctx->level++;
221-
err = nft_chain_validate(ctx, data->verdict.chain);
222-
if (err < 0)
223-
return err;
224-
pctx->level--;
225-
break;
226-
default:
227-
break;
228-
}
229-
230-
return 0;
231-
}
232-
233202
static int nft_lookup_validate(const struct nft_ctx *ctx,
234203
const struct nft_expr *expr,
235204
const struct nft_data **d)
@@ -245,9 +214,12 @@ static int nft_lookup_validate(const struct nft_ctx *ctx,
245214
iter.skip = 0;
246215
iter.count = 0;
247216
iter.err = 0;
248-
iter.fn = nft_lookup_validate_setelem;
217+
iter.fn = nft_setelem_validate;
249218

250219
priv->set->ops->walk(ctx, priv->set, &iter);
220+
if (!iter.err)
221+
iter.err = nft_set_catchall_validate(ctx, priv->set);
222+
251223
if (iter.err < 0)
252224
return iter.err;
253225

0 commit comments

Comments
 (0)