Skip to content

Commit a717932

Browse files
committed
Merge tag 'nf-24-01-24' of 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) Update nf_tables kdoc to keep it in sync with the code, from George Guo. 2) Handle NETDEV_UNREGISTER event for inet/ingress basechain. 3) Reject configuration that cause nft_limit to overflow, from Florian Westphal. 4) Restrict anonymous set/map names to 16 bytes, from Florian Westphal. 5) Disallow to encode queue number and error in verdicts. This reverts a patch which seems to have introduced an early attempt to support for nfqueue maps, which is these days supported via nft_queue expression. 6) Sanitize family via .validate for expressions that explicitly refer to NF_INET_* hooks. * tag 'nf-24-01-24' of git://git.kernel.org/pub/scm/linux/kernel/git/netfilter/nf: netfilter: nf_tables: validate NFPROTO_* family netfilter: nf_tables: reject QUEUE/DROP verdict parameters netfilter: nf_tables: restrict anonymous set and map names to 16 bytes netfilter: nft_limit: reject configurations that cause integer overflow netfilter: nft_chain_filter: handle NETDEV_UNREGISTER for inet/ingress basechain netfilter: nf_tables: cleanup documentation ==================== Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Jakub Kicinski <[email protected]>
2 parents f6cc4b6 + d0009ef commit a717932

File tree

12 files changed

+121
-31
lines changed

12 files changed

+121
-31
lines changed

include/net/netfilter/nf_tables.h

Lines changed: 39 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -205,6 +205,7 @@ static inline void nft_data_copy(u32 *dst, const struct nft_data *src,
205205
* @nla: netlink attributes
206206
* @portid: netlink portID of the original message
207207
* @seq: netlink sequence number
208+
* @flags: modifiers to new request
208209
* @family: protocol family
209210
* @level: depth of the chains
210211
* @report: notify via unicast netlink message
@@ -282,6 +283,7 @@ struct nft_elem_priv { };
282283
*
283284
* @key: element key
284285
* @key_end: closing element key
286+
* @data: element data
285287
* @priv: element private data and extensions
286288
*/
287289
struct nft_set_elem {
@@ -325,10 +327,10 @@ struct nft_set_iter {
325327
* @dtype: data type
326328
* @dlen: data length
327329
* @objtype: object type
328-
* @flags: flags
329330
* @size: number of set elements
330331
* @policy: set policy
331332
* @gc_int: garbage collector interval
333+
* @timeout: element timeout
332334
* @field_len: length of each field in concatenation, bytes
333335
* @field_count: number of concatenated fields in element
334336
* @expr: set must support for expressions
@@ -351,9 +353,9 @@ struct nft_set_desc {
351353
/**
352354
* enum nft_set_class - performance class
353355
*
354-
* @NFT_LOOKUP_O_1: constant, O(1)
355-
* @NFT_LOOKUP_O_LOG_N: logarithmic, O(log N)
356-
* @NFT_LOOKUP_O_N: linear, O(N)
356+
* @NFT_SET_CLASS_O_1: constant, O(1)
357+
* @NFT_SET_CLASS_O_LOG_N: logarithmic, O(log N)
358+
* @NFT_SET_CLASS_O_N: linear, O(N)
357359
*/
358360
enum nft_set_class {
359361
NFT_SET_CLASS_O_1,
@@ -422,9 +424,13 @@ struct nft_set_ext;
422424
* @remove: remove element from set
423425
* @walk: iterate over all set elements
424426
* @get: get set elements
427+
* @commit: commit set elements
428+
* @abort: abort set elements
425429
* @privsize: function to return size of set private data
430+
* @estimate: estimate the required memory size and the lookup complexity class
426431
* @init: initialize private data of new set instance
427432
* @destroy: destroy private data of set instance
433+
* @gc_init: initialize garbage collection
428434
* @elemsize: element private size
429435
*
430436
* Operations lookup, update and delete have simpler interfaces, are faster
@@ -540,13 +546,16 @@ struct nft_set_elem_expr {
540546
* @policy: set parameterization (see enum nft_set_policies)
541547
* @udlen: user data length
542548
* @udata: user data
543-
* @expr: stateful expression
549+
* @pending_update: list of pending update set element
544550
* @ops: set ops
545551
* @flags: set flags
546552
* @dead: set will be freed, never cleared
547553
* @genmask: generation mask
548554
* @klen: key length
549555
* @dlen: data length
556+
* @num_exprs: numbers of exprs
557+
* @exprs: stateful expression
558+
* @catchall_list: list of catch-all set element
550559
* @data: private set data
551560
*/
552561
struct nft_set {
@@ -692,6 +701,7 @@ extern const struct nft_set_ext_type nft_set_ext_types[];
692701
*
693702
* @len: length of extension area
694703
* @offset: offsets of individual extension types
704+
* @ext_len: length of the expected extension(used to sanity check)
695705
*/
696706
struct nft_set_ext_tmpl {
697707
u16 len;
@@ -840,6 +850,7 @@ struct nft_expr_ops;
840850
* @select_ops: function to select nft_expr_ops
841851
* @release_ops: release nft_expr_ops
842852
* @ops: default ops, used when no select_ops functions is present
853+
* @inner_ops: inner ops, used for inner packet operation
843854
* @list: used internally
844855
* @name: Identifier
845856
* @owner: module reference
@@ -881,14 +892,22 @@ struct nft_offload_ctx;
881892
* struct nft_expr_ops - nf_tables expression operations
882893
*
883894
* @eval: Expression evaluation function
895+
* @clone: Expression clone function
884896
* @size: full expression size, including private data size
885897
* @init: initialization function
886898
* @activate: activate expression in the next generation
887899
* @deactivate: deactivate expression in next generation
888900
* @destroy: destruction function, called after synchronize_rcu
901+
* @destroy_clone: destruction clone function
889902
* @dump: function to dump parameters
890-
* @type: expression type
891903
* @validate: validate expression, called during loop detection
904+
* @reduce: reduce expression
905+
* @gc: garbage collection expression
906+
* @offload: hardware offload expression
907+
* @offload_action: function to report true/false to allocate one slot or not in the flow
908+
* offload array
909+
* @offload_stats: function to synchronize hardware stats via updating the counter expression
910+
* @type: expression type
892911
* @data: extra data to attach to this expression operation
893912
*/
894913
struct nft_expr_ops {
@@ -1041,14 +1060,21 @@ struct nft_rule_blob {
10411060
/**
10421061
* struct nft_chain - nf_tables chain
10431062
*
1063+
* @blob_gen_0: rule blob pointer to the current generation
1064+
* @blob_gen_1: rule blob pointer to the future generation
10441065
* @rules: list of rules in the chain
10451066
* @list: used internally
10461067
* @rhlhead: used internally
10471068
* @table: table that this chain belongs to
10481069
* @handle: chain handle
10491070
* @use: number of jump references to this chain
1050-
* @flags: bitmask of enum nft_chain_flags
1071+
* @flags: bitmask of enum NFTA_CHAIN_FLAGS
1072+
* @bound: bind or not
1073+
* @genmask: generation mask
10511074
* @name: name of the chain
1075+
* @udlen: user data length
1076+
* @udata: user data in the chain
1077+
* @blob_next: rule blob pointer to the next in the chain
10521078
*/
10531079
struct nft_chain {
10541080
struct nft_rule_blob __rcu *blob_gen_0;
@@ -1146,6 +1172,7 @@ struct nft_hook {
11461172
* @hook_list: list of netfilter hooks (for NFPROTO_NETDEV family)
11471173
* @type: chain type
11481174
* @policy: default policy
1175+
* @flags: indicate the base chain disabled or not
11491176
* @stats: per-cpu chain stats
11501177
* @chain: the chain
11511178
* @flow_block: flow block (for hardware offload)
@@ -1274,11 +1301,13 @@ struct nft_object_hash_key {
12741301
* struct nft_object - nf_tables stateful object
12751302
*
12761303
* @list: table stateful object list node
1277-
* @key: keys that identify this object
12781304
* @rhlhead: nft_objname_ht node
1305+
* @key: keys that identify this object
12791306
* @genmask: generation mask
12801307
* @use: number of references to this stateful object
12811308
* @handle: unique object handle
1309+
* @udlen: length of user data
1310+
* @udata: user data
12821311
* @ops: object operations
12831312
* @data: object data, layout depends on type
12841313
*/
@@ -1344,6 +1373,7 @@ struct nft_object_type {
13441373
* @destroy: release existing stateful object
13451374
* @dump: netlink dump stateful object
13461375
* @update: update stateful object
1376+
* @type: pointer to object type
13471377
*/
13481378
struct nft_object_ops {
13491379
void (*eval)(struct nft_object *obj,
@@ -1379,9 +1409,8 @@ void nft_unregister_obj(struct nft_object_type *obj_type);
13791409
* @genmask: generation mask
13801410
* @use: number of references to this flow table
13811411
* @handle: unique object handle
1382-
* @dev_name: array of device names
1412+
* @hook_list: hook list for hooks per net_device in flowtables
13831413
* @data: rhashtable and garbage collector
1384-
* @ops: array of hooks
13851414
*/
13861415
struct nft_flowtable {
13871416
struct list_head list;

net/netfilter/nf_tables_api.c

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
#include <net/sock.h>
2525

2626
#define NFT_MODULE_AUTOLOAD_LIMIT (MODULE_NAME_LEN - sizeof("nft-expr-255-"))
27+
#define NFT_SET_MAX_ANONLEN 16
2728

2829
unsigned int nf_tables_net_id __read_mostly;
2930

@@ -4413,6 +4414,9 @@ static int nf_tables_set_alloc_name(struct nft_ctx *ctx, struct nft_set *set,
44134414
if (p[1] != 'd' || strchr(p + 2, '%'))
44144415
return -EINVAL;
44154416

4417+
if (strnlen(name, NFT_SET_MAX_ANONLEN) >= NFT_SET_MAX_ANONLEN)
4418+
return -EINVAL;
4419+
44164420
inuse = (unsigned long *)get_zeroed_page(GFP_KERNEL);
44174421
if (inuse == NULL)
44184422
return -ENOMEM;
@@ -10988,16 +10992,10 @@ static int nft_verdict_init(const struct nft_ctx *ctx, struct nft_data *data,
1098810992
data->verdict.code = ntohl(nla_get_be32(tb[NFTA_VERDICT_CODE]));
1098910993

1099010994
switch (data->verdict.code) {
10991-
default:
10992-
switch (data->verdict.code & NF_VERDICT_MASK) {
10993-
case NF_ACCEPT:
10994-
case NF_DROP:
10995-
case NF_QUEUE:
10996-
break;
10997-
default:
10998-
return -EINVAL;
10999-
}
11000-
fallthrough;
10995+
case NF_ACCEPT:
10996+
case NF_DROP:
10997+
case NF_QUEUE:
10998+
break;
1100110999
case NFT_CONTINUE:
1100211000
case NFT_BREAK:
1100311001
case NFT_RETURN:
@@ -11032,6 +11030,8 @@ static int nft_verdict_init(const struct nft_ctx *ctx, struct nft_data *data,
1103211030

1103311031
data->verdict.chain = chain;
1103411032
break;
11033+
default:
11034+
return -EINVAL;
1103511035
}
1103611036

1103711037
desc->len = sizeof(data->verdict);

net/netfilter/nft_chain_filter.c

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -357,9 +357,10 @@ static int nf_tables_netdev_event(struct notifier_block *this,
357357
unsigned long event, void *ptr)
358358
{
359359
struct net_device *dev = netdev_notifier_info_to_dev(ptr);
360+
struct nft_base_chain *basechain;
360361
struct nftables_pernet *nft_net;
361-
struct nft_table *table;
362362
struct nft_chain *chain, *nr;
363+
struct nft_table *table;
363364
struct nft_ctx ctx = {
364365
.net = dev_net(dev),
365366
};
@@ -371,7 +372,8 @@ static int nf_tables_netdev_event(struct notifier_block *this,
371372
nft_net = nft_pernet(ctx.net);
372373
mutex_lock(&nft_net->commit_mutex);
373374
list_for_each_entry(table, &nft_net->tables, list) {
374-
if (table->family != NFPROTO_NETDEV)
375+
if (table->family != NFPROTO_NETDEV &&
376+
table->family != NFPROTO_INET)
375377
continue;
376378

377379
ctx.family = table->family;
@@ -380,6 +382,11 @@ static int nf_tables_netdev_event(struct notifier_block *this,
380382
if (!nft_is_base_chain(chain))
381383
continue;
382384

385+
basechain = nft_base_chain(chain);
386+
if (table->family == NFPROTO_INET &&
387+
basechain->ops.hooknum != NF_INET_INGRESS)
388+
continue;
389+
383390
ctx.chain = chain;
384391
nft_netdev_event(event, dev, &ctx);
385392
}

net/netfilter/nft_compat.c

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -350,6 +350,12 @@ static int nft_target_validate(const struct nft_ctx *ctx,
350350
unsigned int hook_mask = 0;
351351
int ret;
352352

353+
if (ctx->family != NFPROTO_IPV4 &&
354+
ctx->family != NFPROTO_IPV6 &&
355+
ctx->family != NFPROTO_BRIDGE &&
356+
ctx->family != NFPROTO_ARP)
357+
return -EOPNOTSUPP;
358+
353359
if (nft_is_base_chain(ctx->chain)) {
354360
const struct nft_base_chain *basechain =
355361
nft_base_chain(ctx->chain);
@@ -595,6 +601,12 @@ static int nft_match_validate(const struct nft_ctx *ctx,
595601
unsigned int hook_mask = 0;
596602
int ret;
597603

604+
if (ctx->family != NFPROTO_IPV4 &&
605+
ctx->family != NFPROTO_IPV6 &&
606+
ctx->family != NFPROTO_BRIDGE &&
607+
ctx->family != NFPROTO_ARP)
608+
return -EOPNOTSUPP;
609+
598610
if (nft_is_base_chain(ctx->chain)) {
599611
const struct nft_base_chain *basechain =
600612
nft_base_chain(ctx->chain);

net/netfilter/nft_flow_offload.c

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -384,6 +384,11 @@ static int nft_flow_offload_validate(const struct nft_ctx *ctx,
384384
{
385385
unsigned int hook_mask = (1 << NF_INET_FORWARD);
386386

387+
if (ctx->family != NFPROTO_IPV4 &&
388+
ctx->family != NFPROTO_IPV6 &&
389+
ctx->family != NFPROTO_INET)
390+
return -EOPNOTSUPP;
391+
387392
return nft_chain_validate_hooks(ctx->chain, hook_mask);
388393
}
389394

net/netfilter/nft_limit.c

Lines changed: 16 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -58,17 +58,19 @@ static inline bool nft_limit_eval(struct nft_limit_priv *priv, u64 cost)
5858
static int nft_limit_init(struct nft_limit_priv *priv,
5959
const struct nlattr * const tb[], bool pkts)
6060
{
61+
u64 unit, tokens, rate_with_burst;
6162
bool invert = false;
62-
u64 unit, tokens;
6363

6464
if (tb[NFTA_LIMIT_RATE] == NULL ||
6565
tb[NFTA_LIMIT_UNIT] == NULL)
6666
return -EINVAL;
6767

6868
priv->rate = be64_to_cpu(nla_get_be64(tb[NFTA_LIMIT_RATE]));
69+
if (priv->rate == 0)
70+
return -EINVAL;
71+
6972
unit = be64_to_cpu(nla_get_be64(tb[NFTA_LIMIT_UNIT]));
70-
priv->nsecs = unit * NSEC_PER_SEC;
71-
if (priv->rate == 0 || priv->nsecs < unit)
73+
if (check_mul_overflow(unit, NSEC_PER_SEC, &priv->nsecs))
7274
return -EOVERFLOW;
7375

7476
if (tb[NFTA_LIMIT_BURST])
@@ -77,18 +79,25 @@ static int nft_limit_init(struct nft_limit_priv *priv,
7779
if (pkts && priv->burst == 0)
7880
priv->burst = NFT_LIMIT_PKT_BURST_DEFAULT;
7981

80-
if (priv->rate + priv->burst < priv->rate)
82+
if (check_add_overflow(priv->rate, priv->burst, &rate_with_burst))
8183
return -EOVERFLOW;
8284

8385
if (pkts) {
84-
tokens = div64_u64(priv->nsecs, priv->rate) * priv->burst;
86+
u64 tmp = div64_u64(priv->nsecs, priv->rate);
87+
88+
if (check_mul_overflow(tmp, priv->burst, &tokens))
89+
return -EOVERFLOW;
8590
} else {
91+
u64 tmp;
92+
8693
/* The token bucket size limits the number of tokens can be
8794
* accumulated. tokens_max specifies the bucket size.
8895
* tokens_max = unit * (rate + burst) / rate.
8996
*/
90-
tokens = div64_u64(priv->nsecs * (priv->rate + priv->burst),
91-
priv->rate);
97+
if (check_mul_overflow(priv->nsecs, rate_with_burst, &tmp))
98+
return -EOVERFLOW;
99+
100+
tokens = div64_u64(tmp, priv->rate);
92101
}
93102

94103
if (tb[NFTA_LIMIT_FLAGS]) {

net/netfilter/nft_nat.c

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -143,6 +143,11 @@ static int nft_nat_validate(const struct nft_ctx *ctx,
143143
struct nft_nat *priv = nft_expr_priv(expr);
144144
int err;
145145

146+
if (ctx->family != NFPROTO_IPV4 &&
147+
ctx->family != NFPROTO_IPV6 &&
148+
ctx->family != NFPROTO_INET)
149+
return -EOPNOTSUPP;
150+
146151
err = nft_chain_validate_dependency(ctx->chain, NFT_CHAIN_T_NAT);
147152
if (err < 0)
148153
return err;

net/netfilter/nft_rt.c

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -166,6 +166,11 @@ static int nft_rt_validate(const struct nft_ctx *ctx, const struct nft_expr *exp
166166
const struct nft_rt *priv = nft_expr_priv(expr);
167167
unsigned int hooks;
168168

169+
if (ctx->family != NFPROTO_IPV4 &&
170+
ctx->family != NFPROTO_IPV6 &&
171+
ctx->family != NFPROTO_INET)
172+
return -EOPNOTSUPP;
173+
169174
switch (priv->key) {
170175
case NFT_RT_NEXTHOP4:
171176
case NFT_RT_NEXTHOP6:

net/netfilter/nft_socket.c

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -242,6 +242,11 @@ static int nft_socket_validate(const struct nft_ctx *ctx,
242242
const struct nft_expr *expr,
243243
const struct nft_data **data)
244244
{
245+
if (ctx->family != NFPROTO_IPV4 &&
246+
ctx->family != NFPROTO_IPV6 &&
247+
ctx->family != NFPROTO_INET)
248+
return -EOPNOTSUPP;
249+
245250
return nft_chain_validate_hooks(ctx->chain,
246251
(1 << NF_INET_PRE_ROUTING) |
247252
(1 << NF_INET_LOCAL_IN) |

0 commit comments

Comments
 (0)