Skip to content

Commit 6ae8fd3

Browse files
committed
netfilter: nf_tables: Introduce NFT_MSG_GETRULE_RESET
jira VULN-430 cve-pre CVE-2023-4244 commit-author Phil Sutter <phil@nwl.cc> commit 8daa8fd upstream-diff Used the cleanly applying 9.4 backport ce1ee31 Analogous to NFT_MSG_GETOBJ_RESET, but for rules: Reset stateful expressions like counters or quotas. The latter two are the only consumers, adjust their 'dump' callbacks to respect the parameter introduced earlier. Signed-off-by: Phil Sutter <phil@nwl.cc> Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org> (cherry picked from commit 8daa8fd) Signed-off-by: Marcin Wcisło <marcin.wcislo@conclusive.pl>
1 parent fa1abba commit 6ae8fd3

File tree

6 files changed

+40
-21
lines changed

6 files changed

+40
-21
lines changed

include/net/netfilter/nf_tables.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -360,7 +360,7 @@ static inline void *nft_expr_priv(const struct nft_expr *expr)
360360
int nft_expr_clone(struct nft_expr *dst, struct nft_expr *src);
361361
void nft_expr_destroy(const struct nft_ctx *ctx, struct nft_expr *expr);
362362
int nft_expr_dump(struct sk_buff *skb, unsigned int attr,
363-
const struct nft_expr *expr);
363+
const struct nft_expr *expr, bool reset);
364364

365365
struct nft_set_ext;
366366

include/uapi/linux/netfilter/nf_tables.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,7 @@ enum nft_verdicts {
9797
* @NFT_MSG_NEWFLOWTABLE: add new flow table (enum nft_flowtable_attributes)
9898
* @NFT_MSG_GETFLOWTABLE: get flow table (enum nft_flowtable_attributes)
9999
* @NFT_MSG_DELFLOWTABLE: delete flow table (enum nft_flowtable_attributes)
100+
* @NFT_MSG_GETRULE_RESET: get rules and reset stateful expressions (enum nft_obj_attributes)
100101
*/
101102
enum nf_tables_msg_types {
102103
NFT_MSG_NEWTABLE,
@@ -124,6 +125,7 @@ enum nf_tables_msg_types {
124125
NFT_MSG_NEWFLOWTABLE,
125126
NFT_MSG_GETFLOWTABLE,
126127
NFT_MSG_DELFLOWTABLE,
128+
NFT_MSG_GETRULE_RESET,
127129
NFT_MSG_MAX,
128130
};
129131

net/netfilter/nf_tables_api.c

Lines changed: 33 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -2772,7 +2772,7 @@ static const struct nla_policy nft_expr_policy[NFTA_EXPR_MAX + 1] = {
27722772
};
27732773

27742774
static int nf_tables_fill_expr_info(struct sk_buff *skb,
2775-
const struct nft_expr *expr)
2775+
const struct nft_expr *expr, bool reset)
27762776
{
27772777
if (nla_put_string(skb, NFTA_EXPR_NAME, expr->ops->type->name))
27782778
goto nla_put_failure;
@@ -2782,7 +2782,7 @@ static int nf_tables_fill_expr_info(struct sk_buff *skb,
27822782
NFTA_EXPR_DATA);
27832783
if (data == NULL)
27842784
goto nla_put_failure;
2785-
if (expr->ops->dump(skb, expr, false) < 0)
2785+
if (expr->ops->dump(skb, expr, reset) < 0)
27862786
goto nla_put_failure;
27872787
nla_nest_end(skb, data);
27882788
}
@@ -2794,14 +2794,14 @@ static int nf_tables_fill_expr_info(struct sk_buff *skb,
27942794
};
27952795

27962796
int nft_expr_dump(struct sk_buff *skb, unsigned int attr,
2797-
const struct nft_expr *expr)
2797+
const struct nft_expr *expr, bool reset)
27982798
{
27992799
struct nlattr *nest;
28002800

28012801
nest = nla_nest_start_noflag(skb, attr);
28022802
if (!nest)
28032803
goto nla_put_failure;
2804-
if (nf_tables_fill_expr_info(skb, expr) < 0)
2804+
if (nf_tables_fill_expr_info(skb, expr, reset) < 0)
28052805
goto nla_put_failure;
28062806
nla_nest_end(skb, nest);
28072807
return 0;
@@ -3010,7 +3010,8 @@ static int nf_tables_fill_rule_info(struct sk_buff *skb, struct net *net,
30103010
u32 flags, int family,
30113011
const struct nft_table *table,
30123012
const struct nft_chain *chain,
3013-
const struct nft_rule *rule, u64 handle)
3013+
const struct nft_rule *rule, u64 handle,
3014+
bool reset)
30143015
{
30153016
struct nlmsghdr *nlh;
30163017
const struct nft_expr *expr, *next;
@@ -3043,7 +3044,7 @@ static int nf_tables_fill_rule_info(struct sk_buff *skb, struct net *net,
30433044
if (list == NULL)
30443045
goto nla_put_failure;
30453046
nft_rule_for_each_expr(expr, next, rule) {
3046-
if (nft_expr_dump(skb, NFTA_LIST_ELEM, expr) < 0)
3047+
if (nft_expr_dump(skb, NFTA_LIST_ELEM, expr, reset) < 0)
30473048
goto nla_put_failure;
30483049
}
30493050
nla_nest_end(skb, list);
@@ -3094,7 +3095,7 @@ static void nf_tables_rule_notify(const struct nft_ctx *ctx,
30943095

30953096
err = nf_tables_fill_rule_info(skb, ctx->net, ctx->portid, ctx->seq,
30963097
event, flags, ctx->family, ctx->table,
3097-
ctx->chain, rule, handle);
3098+
ctx->chain, rule, handle, false);
30983099
if (err < 0) {
30993100
kfree_skb(skb);
31003101
goto err;
@@ -3115,7 +3116,8 @@ static int __nf_tables_dump_rules(struct sk_buff *skb,
31153116
unsigned int *idx,
31163117
struct netlink_callback *cb,
31173118
const struct nft_table *table,
3118-
const struct nft_chain *chain)
3119+
const struct nft_chain *chain,
3120+
bool reset)
31193121
{
31203122
struct net *net = sock_net(skb->sk);
31213123
const struct nft_rule *rule, *prule;
@@ -3142,7 +3144,7 @@ static int __nf_tables_dump_rules(struct sk_buff *skb,
31423144
NFT_MSG_NEWRULE,
31433145
NLM_F_MULTI | NLM_F_APPEND,
31443146
table->family,
3145-
table, chain, rule, handle) < 0)
3147+
table, chain, rule, handle, reset) < 0)
31463148
return 1;
31473149

31483150
nl_dump_check_consistent(cb, nlmsg_hdr(skb));
@@ -3165,6 +3167,10 @@ static int nf_tables_dump_rules(struct sk_buff *skb,
31653167
struct net *net = sock_net(skb->sk);
31663168
int family = nfmsg->nfgen_family;
31673169
struct nftables_pernet *nft_net;
3170+
bool reset = false;
3171+
3172+
if (NFNL_MSG_TYPE(cb->nlh->nlmsg_type) == NFT_MSG_GETRULE_RESET)
3173+
reset = true;
31683174

31693175
rcu_read_lock();
31703176
nft_net = nft_pernet(net);
@@ -3189,14 +3195,15 @@ static int nf_tables_dump_rules(struct sk_buff *skb,
31893195
if (!nft_is_active(net, chain))
31903196
continue;
31913197
__nf_tables_dump_rules(skb, &idx,
3192-
cb, table, chain);
3198+
cb, table, chain, reset);
31933199
break;
31943200
}
31953201
goto done;
31963202
}
31973203

31983204
list_for_each_entry_rcu(chain, &table->chains, list) {
3199-
if (__nf_tables_dump_rules(skb, &idx, cb, table, chain))
3205+
if (__nf_tables_dump_rules(skb, &idx,
3206+
cb, table, chain, reset))
32003207
goto done;
32013208
}
32023209

@@ -3267,6 +3274,7 @@ static int nf_tables_getrule(struct sk_buff *skb, const struct nfnl_info *info,
32673274
struct net *net = info->net;
32683275
struct nft_table *table;
32693276
struct sk_buff *skb2;
3277+
bool reset = false;
32703278
int err;
32713279

32723280
if (info->nlh->nlmsg_flags & NLM_F_DUMP) {
@@ -3303,9 +3311,12 @@ static int nf_tables_getrule(struct sk_buff *skb, const struct nfnl_info *info,
33033311
if (!skb2)
33043312
return -ENOMEM;
33053313

3314+
if (NFNL_MSG_TYPE(info->nlh->nlmsg_type) == NFT_MSG_GETRULE_RESET)
3315+
reset = true;
3316+
33063317
err = nf_tables_fill_rule_info(skb2, net, NETLINK_CB(skb).portid,
33073318
info->nlh->nlmsg_seq, NFT_MSG_NEWRULE, 0,
3308-
family, table, chain, rule, 0);
3319+
family, table, chain, rule, 0, reset);
33093320
if (err < 0)
33103321
goto err_fill_rule_info;
33113322

@@ -4139,7 +4150,7 @@ static int nf_tables_fill_set(struct sk_buff *skb, const struct nft_ctx *ctx,
41394150

41404151
if (set->num_exprs == 1) {
41414152
nest = nla_nest_start_noflag(skb, NFTA_SET_EXPR);
4142-
if (nf_tables_fill_expr_info(skb, set->exprs[0]) < 0)
4153+
if (nf_tables_fill_expr_info(skb, set->exprs[0], false) < 0)
41434154
goto nla_put_failure;
41444155

41454156
nla_nest_end(skb, nest);
@@ -4150,7 +4161,7 @@ static int nf_tables_fill_set(struct sk_buff *skb, const struct nft_ctx *ctx,
41504161

41514162
for (i = 0; i < set->num_exprs; i++) {
41524163
if (nft_expr_dump(skb, NFTA_LIST_ELEM,
4153-
set->exprs[i]) < 0)
4164+
set->exprs[i], false) < 0)
41544165
goto nla_put_failure;
41554166
}
41564167
nla_nest_end(skb, nest);
@@ -5062,7 +5073,7 @@ static int nft_set_elem_expr_dump(struct sk_buff *skb,
50625073

50635074
if (num_exprs == 1) {
50645075
expr = nft_setelem_expr_at(elem_expr, 0);
5065-
if (nft_expr_dump(skb, NFTA_SET_ELEM_EXPR, expr) < 0)
5076+
if (nft_expr_dump(skb, NFTA_SET_ELEM_EXPR, expr, false) < 0)
50665077
return -1;
50675078

50685079
return 0;
@@ -5073,7 +5084,7 @@ static int nft_set_elem_expr_dump(struct sk_buff *skb,
50735084

50745085
nft_setelem_expr_foreach(expr, elem_expr, size) {
50755086
expr = nft_setelem_expr_at(elem_expr, size);
5076-
if (nft_expr_dump(skb, NFTA_LIST_ELEM, expr) < 0)
5087+
if (nft_expr_dump(skb, NFTA_LIST_ELEM, expr, false) < 0)
50775088
goto nla_put_failure;
50785089
}
50795090
nla_nest_end(skb, nest);
@@ -8375,6 +8386,12 @@ static const struct nfnl_callback nf_tables_cb[NFT_MSG_MAX] = {
83758386
.attr_count = NFTA_RULE_MAX,
83768387
.policy = nft_rule_policy,
83778388
},
8389+
[NFT_MSG_GETRULE_RESET] = {
8390+
.call = nf_tables_getrule,
8391+
.type = NFNL_CB_RCU,
8392+
.attr_count = NFTA_RULE_MAX,
8393+
.policy = nft_rule_policy,
8394+
},
83788395
[NFT_MSG_DELRULE] = {
83798396
.call = nf_tables_delrule,
83808397
.type = NFNL_CB_BATCH,

net/netfilter/nft_counter.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -206,7 +206,7 @@ static int nft_counter_dump(struct sk_buff *skb,
206206
{
207207
struct nft_counter_percpu_priv *priv = nft_expr_priv(expr);
208208

209-
return nft_counter_do_dump(skb, priv, false);
209+
return nft_counter_do_dump(skb, priv, reset);
210210
}
211211

212212
static int nft_counter_init(const struct nft_ctx *ctx,

net/netfilter/nft_dynset.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -380,7 +380,7 @@ static int nft_dynset_dump(struct sk_buff *skb,
380380
if (priv->set->num_exprs == 0) {
381381
if (priv->num_exprs == 1) {
382382
if (nft_expr_dump(skb, NFTA_DYNSET_EXPR,
383-
priv->expr_array[0]))
383+
priv->expr_array[0], reset))
384384
goto nla_put_failure;
385385
} else if (priv->num_exprs > 1) {
386386
struct nlattr *nest;
@@ -391,7 +391,7 @@ static int nft_dynset_dump(struct sk_buff *skb,
391391

392392
for (i = 0; i < priv->num_exprs; i++) {
393393
if (nft_expr_dump(skb, NFTA_LIST_ELEM,
394-
priv->expr_array[i]))
394+
priv->expr_array[i], reset))
395395
goto nla_put_failure;
396396
}
397397
nla_nest_end(skb, nest);

net/netfilter/nft_quota.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -203,7 +203,7 @@ static int nft_quota_dump(struct sk_buff *skb,
203203
{
204204
struct nft_quota *priv = nft_expr_priv(expr);
205205

206-
return nft_quota_do_dump(skb, priv, false);
206+
return nft_quota_do_dump(skb, priv, reset);
207207
}
208208

209209
static struct nft_expr_type nft_quota_type;

0 commit comments

Comments
 (0)