Skip to content

Commit ee895a3

Browse files
committed
Merge git://git.kernel.org/pub/scm/linux/kernel/git/pablo/nf
Pablo Neira Ayuso says: ==================== Netfilter fixes for net The following patchset contains Netfilter fixes for net: 1) Flush the cleanup xtables worker to make sure destructors have completed, from Florian Westphal. 2) iifgroup is matching erroneously, also from Florian. 3) Add selftest for meta interface matching, from Florian Westphal. 4) Move nf_ct_offload_timeout() to header, from Roi Dayan. 5) Call nf_ct_offload_timeout() from flow_offload_add() to make sure garbage collection does not evict offloaded flow, from Roi Dayan. ==================== Signed-off-by: David S. Miller <[email protected]>
2 parents bab9693 + 4203b19 commit ee895a3

File tree

9 files changed

+182
-20
lines changed

9 files changed

+182
-20
lines changed

include/net/netfilter/nf_conntrack.h

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -279,6 +279,18 @@ static inline bool nf_ct_should_gc(const struct nf_conn *ct)
279279
!nf_ct_is_dying(ct);
280280
}
281281

282+
#define NF_CT_DAY (86400 * HZ)
283+
284+
/* Set an arbitrary timeout large enough not to ever expire, this save
285+
* us a check for the IPS_OFFLOAD_BIT from the packet path via
286+
* nf_ct_is_expired().
287+
*/
288+
static inline void nf_ct_offload_timeout(struct nf_conn *ct)
289+
{
290+
if (nf_ct_expires(ct) < NF_CT_DAY / 2)
291+
ct->timeout = nfct_time_stamp + NF_CT_DAY;
292+
}
293+
282294
struct kernel_param;
283295

284296
int nf_conntrack_set_hashsize(const char *val, const struct kernel_param *kp);

include/net/netfilter/nf_tables.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1507,4 +1507,6 @@ void nft_chain_filter_fini(void);
15071507

15081508
void __init nft_chain_route_init(void);
15091509
void nft_chain_route_fini(void);
1510+
1511+
void nf_tables_trans_destroy_flush_work(void);
15101512
#endif /* _NET_NF_TABLES_H */

net/netfilter/nf_conntrack_core.c

Lines changed: 0 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1344,18 +1344,6 @@ static bool gc_worker_can_early_drop(const struct nf_conn *ct)
13441344
return false;
13451345
}
13461346

1347-
#define DAY (86400 * HZ)
1348-
1349-
/* Set an arbitrary timeout large enough not to ever expire, this save
1350-
* us a check for the IPS_OFFLOAD_BIT from the packet path via
1351-
* nf_ct_is_expired().
1352-
*/
1353-
static void nf_ct_offload_timeout(struct nf_conn *ct)
1354-
{
1355-
if (nf_ct_expires(ct) < DAY / 2)
1356-
ct->timeout = nfct_time_stamp + DAY;
1357-
}
1358-
13591347
static void gc_worker(struct work_struct *work)
13601348
{
13611349
unsigned int min_interval = max(HZ / GC_MAX_BUCKETS_DIV, 1u);

net/netfilter/nf_flow_table_core.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -243,6 +243,8 @@ int flow_offload_add(struct nf_flowtable *flow_table, struct flow_offload *flow)
243243
return err;
244244
}
245245

246+
nf_ct_offload_timeout(flow->ct);
247+
246248
if (nf_flowtable_hw_offload(flow_table)) {
247249
__set_bit(NF_FLOW_HW, &flow->flags);
248250
nf_flow_offload_add(flow_table, flow);

net/netfilter/nf_tables_api.c

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7390,6 +7390,12 @@ static void nf_tables_trans_destroy_work(struct work_struct *w)
73907390
}
73917391
}
73927392

7393+
void nf_tables_trans_destroy_flush_work(void)
7394+
{
7395+
flush_work(&trans_destroy_work);
7396+
}
7397+
EXPORT_SYMBOL_GPL(nf_tables_trans_destroy_flush_work);
7398+
73937399
static int nf_tables_commit_chain_prepare(struct net *net, struct nft_chain *chain)
73947400
{
73957401
struct nft_rule *rule;
@@ -7572,9 +7578,9 @@ static void nf_tables_commit_release(struct net *net)
75727578
spin_unlock(&nf_tables_destroy_list_lock);
75737579

75747580
nf_tables_module_autoload_cleanup(net);
7575-
mutex_unlock(&net->nft.commit_mutex);
7576-
75777581
schedule_work(&trans_destroy_work);
7582+
7583+
mutex_unlock(&net->nft.commit_mutex);
75787584
}
75797585

75807586
static int nf_tables_commit(struct net *net, struct sk_buff *skb)

net/netfilter/nft_compat.c

Lines changed: 32 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,8 @@ struct nft_xt_match_priv {
2727
void *info;
2828
};
2929

30+
static refcount_t nft_compat_pending_destroy = REFCOUNT_INIT(1);
31+
3032
static int nft_compat_chain_validate_dependency(const struct nft_ctx *ctx,
3133
const char *tablename)
3234
{
@@ -236,6 +238,15 @@ nft_target_init(const struct nft_ctx *ctx, const struct nft_expr *expr,
236238

237239
nft_target_set_tgchk_param(&par, ctx, target, info, &e, proto, inv);
238240

241+
/* xtables matches or targets can have side effects, e.g.
242+
* creation/destruction of /proc files.
243+
* The xt ->destroy functions are run asynchronously from
244+
* work queue. If we have pending invocations we thus
245+
* need to wait for those to finish.
246+
*/
247+
if (refcount_read(&nft_compat_pending_destroy) > 1)
248+
nf_tables_trans_destroy_flush_work();
249+
239250
ret = xt_check_target(&par, size, proto, inv);
240251
if (ret < 0)
241252
return ret;
@@ -247,6 +258,13 @@ nft_target_init(const struct nft_ctx *ctx, const struct nft_expr *expr,
247258
return 0;
248259
}
249260

261+
static void __nft_mt_tg_destroy(struct module *me, const struct nft_expr *expr)
262+
{
263+
refcount_dec(&nft_compat_pending_destroy);
264+
module_put(me);
265+
kfree(expr->ops);
266+
}
267+
250268
static void
251269
nft_target_destroy(const struct nft_ctx *ctx, const struct nft_expr *expr)
252270
{
@@ -262,8 +280,7 @@ nft_target_destroy(const struct nft_ctx *ctx, const struct nft_expr *expr)
262280
if (par.target->destroy != NULL)
263281
par.target->destroy(&par);
264282

265-
module_put(me);
266-
kfree(expr->ops);
283+
__nft_mt_tg_destroy(me, expr);
267284
}
268285

269286
static int nft_extension_dump_info(struct sk_buff *skb, int attr,
@@ -494,8 +511,7 @@ __nft_match_destroy(const struct nft_ctx *ctx, const struct nft_expr *expr,
494511
if (par.match->destroy != NULL)
495512
par.match->destroy(&par);
496513

497-
module_put(me);
498-
kfree(expr->ops);
514+
__nft_mt_tg_destroy(me, expr);
499515
}
500516

501517
static void
@@ -700,6 +716,14 @@ static const struct nfnetlink_subsystem nfnl_compat_subsys = {
700716

701717
static struct nft_expr_type nft_match_type;
702718

719+
static void nft_mt_tg_deactivate(const struct nft_ctx *ctx,
720+
const struct nft_expr *expr,
721+
enum nft_trans_phase phase)
722+
{
723+
if (phase == NFT_TRANS_COMMIT)
724+
refcount_inc(&nft_compat_pending_destroy);
725+
}
726+
703727
static const struct nft_expr_ops *
704728
nft_match_select_ops(const struct nft_ctx *ctx,
705729
const struct nlattr * const tb[])
@@ -738,6 +762,7 @@ nft_match_select_ops(const struct nft_ctx *ctx,
738762
ops->type = &nft_match_type;
739763
ops->eval = nft_match_eval;
740764
ops->init = nft_match_init;
765+
ops->deactivate = nft_mt_tg_deactivate,
741766
ops->destroy = nft_match_destroy;
742767
ops->dump = nft_match_dump;
743768
ops->validate = nft_match_validate;
@@ -828,6 +853,7 @@ nft_target_select_ops(const struct nft_ctx *ctx,
828853
ops->size = NFT_EXPR_SIZE(XT_ALIGN(target->targetsize));
829854
ops->init = nft_target_init;
830855
ops->destroy = nft_target_destroy;
856+
ops->deactivate = nft_mt_tg_deactivate,
831857
ops->dump = nft_target_dump;
832858
ops->validate = nft_target_validate;
833859
ops->data = target;
@@ -891,6 +917,8 @@ static void __exit nft_compat_module_exit(void)
891917
nfnetlink_subsys_unregister(&nfnl_compat_subsys);
892918
nft_unregister_expr(&nft_target_type);
893919
nft_unregister_expr(&nft_match_type);
920+
921+
WARN_ON_ONCE(refcount_read(&nft_compat_pending_destroy) != 1);
894922
}
895923

896924
MODULE_ALIAS_NFNL_SUBSYS(NFNL_SUBSYS_NFT_COMPAT);

net/netfilter/nft_meta.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -253,7 +253,7 @@ static bool nft_meta_get_eval_ifname(enum nft_meta_keys key, u32 *dest,
253253
return false;
254254
break;
255255
case NFT_META_IIFGROUP:
256-
if (!nft_meta_store_ifgroup(dest, nft_out(pkt)))
256+
if (!nft_meta_store_ifgroup(dest, nft_in(pkt)))
257257
return false;
258258
break;
259259
case NFT_META_OIFGROUP:

tools/testing/selftests/netfilter/Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
TEST_PROGS := nft_trans_stress.sh nft_nat.sh bridge_brouter.sh \
55
conntrack_icmp_related.sh nft_flowtable.sh ipvs.sh \
66
nft_concat_range.sh nft_conntrack_helper.sh \
7-
nft_queue.sh
7+
nft_queue.sh nft_meta.sh
88

99
LDLIBS = -lmnl
1010
TEST_GEN_FILES = nf-queue
Lines changed: 124 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,124 @@
1+
#!/bin/bash
2+
3+
# check iif/iifname/oifgroup/iiftype match.
4+
5+
# Kselftest framework requirement - SKIP code is 4.
6+
ksft_skip=4
7+
sfx=$(mktemp -u "XXXXXXXX")
8+
ns0="ns0-$sfx"
9+
10+
nft --version > /dev/null 2>&1
11+
if [ $? -ne 0 ];then
12+
echo "SKIP: Could not run test without nft tool"
13+
exit $ksft_skip
14+
fi
15+
16+
cleanup()
17+
{
18+
ip netns del "$ns0"
19+
}
20+
21+
ip netns add "$ns0"
22+
ip -net "$ns0" link set lo up
23+
ip -net "$ns0" addr add 127.0.0.1 dev lo
24+
25+
trap cleanup EXIT
26+
27+
ip netns exec "$ns0" nft -f /dev/stdin <<EOF
28+
table inet filter {
29+
counter iifcount {}
30+
counter iifnamecount {}
31+
counter iifgroupcount {}
32+
counter iiftypecount {}
33+
counter infproto4count {}
34+
counter il4protocounter {}
35+
counter imarkcounter {}
36+
37+
counter oifcount {}
38+
counter oifnamecount {}
39+
counter oifgroupcount {}
40+
counter oiftypecount {}
41+
counter onfproto4count {}
42+
counter ol4protocounter {}
43+
counter oskuidcounter {}
44+
counter oskgidcounter {}
45+
counter omarkcounter {}
46+
47+
chain input {
48+
type filter hook input priority 0; policy accept;
49+
50+
meta iif lo counter name "iifcount"
51+
meta iifname "lo" counter name "iifnamecount"
52+
meta iifgroup "default" counter name "iifgroupcount"
53+
meta iiftype "loopback" counter name "iiftypecount"
54+
meta nfproto ipv4 counter name "infproto4count"
55+
meta l4proto icmp counter name "il4protocounter"
56+
meta mark 42 counter name "imarkcounter"
57+
}
58+
59+
chain output {
60+
type filter hook output priority 0; policy accept;
61+
meta oif lo counter name "oifcount" counter
62+
meta oifname "lo" counter name "oifnamecount"
63+
meta oifgroup "default" counter name "oifgroupcount"
64+
meta oiftype "loopback" counter name "oiftypecount"
65+
meta nfproto ipv4 counter name "onfproto4count"
66+
meta l4proto icmp counter name "ol4protocounter"
67+
meta skuid 0 counter name "oskuidcounter"
68+
meta skgid 0 counter name "oskgidcounter"
69+
meta mark 42 counter name "omarkcounter"
70+
}
71+
}
72+
EOF
73+
74+
if [ $? -ne 0 ]; then
75+
echo "SKIP: Could not add test ruleset"
76+
exit $ksft_skip
77+
fi
78+
79+
ret=0
80+
81+
check_one_counter()
82+
{
83+
local cname="$1"
84+
local want="packets $2"
85+
local verbose="$3"
86+
87+
cnt=$(ip netns exec "$ns0" nft list counter inet filter $cname | grep -q "$want")
88+
if [ $? -ne 0 ];then
89+
echo "FAIL: $cname, want \"$want\", got"
90+
ret=1
91+
ip netns exec "$ns0" nft list counter inet filter $counter
92+
fi
93+
}
94+
95+
check_lo_counters()
96+
{
97+
local want="$1"
98+
local verbose="$2"
99+
local counter
100+
101+
for counter in iifcount iifnamecount iifgroupcount iiftypecount infproto4count \
102+
oifcount oifnamecount oifgroupcount oiftypecount onfproto4count \
103+
il4protocounter \
104+
ol4protocounter \
105+
; do
106+
check_one_counter "$counter" "$want" "$verbose"
107+
done
108+
}
109+
110+
check_lo_counters "0" false
111+
ip netns exec "$ns0" ping -q -c 1 127.0.0.1 -m 42 > /dev/null
112+
113+
check_lo_counters "2" true
114+
115+
check_one_counter oskuidcounter "1" true
116+
check_one_counter oskgidcounter "1" true
117+
check_one_counter imarkcounter "1" true
118+
check_one_counter omarkcounter "1" true
119+
120+
if [ $ret -eq 0 ];then
121+
echo "OK: nftables meta iif/oif counters at expected values"
122+
fi
123+
124+
exit $ret

0 commit comments

Comments
 (0)