From: Sasha Levin Date: Mon, 22 May 2023 18:28:28 +0000 (-0400) Subject: Fixes for 4.19 X-Git-Tag: v6.3.4~13 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=864361371e5363e11710b599764998a4efcf3fd4;p=thirdparty%2Fkernel%2Fstable-queue.git Fixes for 4.19 Signed-off-by: Sasha Levin --- diff --git a/queue-4.19/netfilter-nf_tables-add-nft_setelem_parse_key.patch b/queue-4.19/netfilter-nf_tables-add-nft_setelem_parse_key.patch new file mode 100644 index 00000000000..7e8db19dec8 --- /dev/null +++ b/queue-4.19/netfilter-nf_tables-add-nft_setelem_parse_key.patch @@ -0,0 +1,250 @@ +From f94534f5e7ea596eb8bd571c5bf68ac19d7b6049 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 16 May 2023 17:06:09 +0200 +Subject: netfilter: nf_tables: add nft_setelem_parse_key() + +From: Pablo Neira Ayuso + +[ 20a1452c35425b2cef76f21f8395ef069dfddfa9 ] + +Add helper function to parse the set element key netlink attribute. + +v4: No changes +v3: New patch + +[sbrivio: refactor error paths and labels; use NFT_DATA_VALUE_MAXLEN + instead of sizeof(*key) in helper, value can be longer than that; + rebase] +Signed-off-by: Pablo Neira Ayuso +Signed-off-by: Sasha Levin +--- + net/netfilter/nf_tables_api.c | 91 +++++++++++++++++------------------ + 1 file changed, 45 insertions(+), 46 deletions(-) + +diff --git a/net/netfilter/nf_tables_api.c b/net/netfilter/nf_tables_api.c +index 48f8d3d2b6d7c..acd0566a35860 100644 +--- a/net/netfilter/nf_tables_api.c ++++ b/net/netfilter/nf_tables_api.c +@@ -4140,11 +4140,28 @@ static int nft_setelem_parse_flags(const struct nft_set *set, + return 0; + } + ++static int nft_setelem_parse_key(struct nft_ctx *ctx, struct nft_set *set, ++ struct nft_data *key, struct nlattr *attr) ++{ ++ struct nft_data_desc desc; ++ int err; ++ ++ err = nft_data_init(ctx, key, NFT_DATA_VALUE_MAXLEN, &desc, attr); ++ if (err < 0) ++ return err; ++ ++ if (desc.type != NFT_DATA_VALUE || desc.len != set->klen) { ++ nft_data_release(key, desc.type); ++ return -EINVAL; ++ } ++ ++ return 0; ++} ++ + static int nft_get_set_elem(struct nft_ctx *ctx, struct nft_set *set, + const struct nlattr *attr) + { + struct nlattr *nla[NFTA_SET_ELEM_MAX + 1]; +- struct nft_data_desc desc; + struct nft_set_elem elem; + struct sk_buff *skb; + uint32_t flags = 0; +@@ -4163,17 +4180,11 @@ static int nft_get_set_elem(struct nft_ctx *ctx, struct nft_set *set, + if (err < 0) + return err; + +- err = nft_data_init(ctx, &elem.key.val, sizeof(elem.key), &desc, +- nla[NFTA_SET_ELEM_KEY]); ++ err = nft_setelem_parse_key(ctx, set, &elem.key.val, ++ nla[NFTA_SET_ELEM_KEY]); + if (err < 0) + return err; + +- err = -EINVAL; +- if (desc.type != NFT_DATA_VALUE || desc.len != set->klen) { +- nft_data_release(&elem.key.val, desc.type); +- return err; +- } +- + priv = set->ops->get(ctx->net, set, &elem, flags); + if (IS_ERR(priv)) + return PTR_ERR(priv); +@@ -4364,13 +4375,13 @@ static int nft_add_set_elem(struct nft_ctx *ctx, struct nft_set *set, + { + struct nlattr *nla[NFTA_SET_ELEM_MAX + 1]; + u8 genmask = nft_genmask_next(ctx->net); +- struct nft_data_desc d1, d2; + struct nft_set_ext_tmpl tmpl; + struct nft_set_ext *ext, *ext2; + struct nft_set_elem elem; + struct nft_set_binding *binding; + struct nft_object *obj = NULL; + struct nft_userdata *udata; ++ struct nft_data_desc desc; + struct nft_data data; + enum nft_registers dreg; + struct nft_trans *trans; +@@ -4425,15 +4436,12 @@ static int nft_add_set_elem(struct nft_ctx *ctx, struct nft_set *set, + timeout = set->timeout; + } + +- err = nft_data_init(ctx, &elem.key.val, sizeof(elem.key), &d1, +- nla[NFTA_SET_ELEM_KEY]); ++ err = nft_setelem_parse_key(ctx, set, &elem.key.val, ++ nla[NFTA_SET_ELEM_KEY]); + if (err < 0) + goto err1; +- err = -EINVAL; +- if (d1.type != NFT_DATA_VALUE || d1.len != set->klen) +- goto err2; + +- nft_set_ext_add_length(&tmpl, NFT_SET_EXT_KEY, d1.len); ++ nft_set_ext_add_length(&tmpl, NFT_SET_EXT_KEY, set->klen); + if (timeout > 0) { + nft_set_ext_add(&tmpl, NFT_SET_EXT_EXPIRATION); + if (timeout != set->timeout) +@@ -4455,13 +4463,13 @@ static int nft_add_set_elem(struct nft_ctx *ctx, struct nft_set *set, + } + + if (nla[NFTA_SET_ELEM_DATA] != NULL) { +- err = nft_data_init(ctx, &data, sizeof(data), &d2, ++ err = nft_data_init(ctx, &data, sizeof(data), &desc, + nla[NFTA_SET_ELEM_DATA]); + if (err < 0) + goto err2; + + err = -EINVAL; +- if (set->dtype != NFT_DATA_VERDICT && d2.len != set->dlen) ++ if (set->dtype != NFT_DATA_VERDICT && desc.len != set->dlen) + goto err3; + + dreg = nft_type_to_reg(set->dtype); +@@ -4478,18 +4486,18 @@ static int nft_add_set_elem(struct nft_ctx *ctx, struct nft_set *set, + + err = nft_validate_register_store(&bind_ctx, dreg, + &data, +- d2.type, d2.len); ++ desc.type, desc.len); + if (err < 0) + goto err3; + +- if (d2.type == NFT_DATA_VERDICT && ++ if (desc.type == NFT_DATA_VERDICT && + (data.verdict.code == NFT_GOTO || + data.verdict.code == NFT_JUMP)) + nft_validate_state_update(ctx->net, + NFT_VALIDATE_NEED); + } + +- nft_set_ext_add_length(&tmpl, NFT_SET_EXT_DATA, d2.len); ++ nft_set_ext_add_length(&tmpl, NFT_SET_EXT_DATA, desc.len); + } + + /* The full maximum length of userdata can exceed the maximum +@@ -4572,9 +4580,9 @@ static int nft_add_set_elem(struct nft_ctx *ctx, struct nft_set *set, + kfree(elem.priv); + err3: + if (nla[NFTA_SET_ELEM_DATA] != NULL) +- nft_data_release(&data, d2.type); ++ nft_data_release(&data, desc.type); + err2: +- nft_data_release(&elem.key.val, d1.type); ++ nft_data_release(&elem.key.val, NFT_DATA_VALUE); + err1: + return err; + } +@@ -4670,7 +4678,6 @@ static int nft_del_setelem(struct nft_ctx *ctx, struct nft_set *set, + { + struct nlattr *nla[NFTA_SET_ELEM_MAX + 1]; + struct nft_set_ext_tmpl tmpl; +- struct nft_data_desc desc; + struct nft_set_elem elem; + struct nft_set_ext *ext; + struct nft_trans *trans; +@@ -4681,11 +4688,10 @@ static int nft_del_setelem(struct nft_ctx *ctx, struct nft_set *set, + err = nla_parse_nested(nla, NFTA_SET_ELEM_MAX, attr, + nft_set_elem_policy, NULL); + if (err < 0) +- goto err1; ++ return err; + +- err = -EINVAL; + if (nla[NFTA_SET_ELEM_KEY] == NULL) +- goto err1; ++ return -EINVAL; + + nft_set_ext_prepare(&tmpl); + +@@ -4695,37 +4701,31 @@ static int nft_del_setelem(struct nft_ctx *ctx, struct nft_set *set, + if (flags != 0) + nft_set_ext_add(&tmpl, NFT_SET_EXT_FLAGS); + +- err = nft_data_init(ctx, &elem.key.val, sizeof(elem.key), &desc, +- nla[NFTA_SET_ELEM_KEY]); ++ err = nft_setelem_parse_key(ctx, set, &elem.key.val, ++ nla[NFTA_SET_ELEM_KEY]); + if (err < 0) +- goto err1; +- +- err = -EINVAL; +- if (desc.type != NFT_DATA_VALUE || desc.len != set->klen) +- goto err2; ++ return err; + +- nft_set_ext_add_length(&tmpl, NFT_SET_EXT_KEY, desc.len); ++ nft_set_ext_add_length(&tmpl, NFT_SET_EXT_KEY, set->klen); + + err = -ENOMEM; + elem.priv = nft_set_elem_init(set, &tmpl, elem.key.val.data, NULL, 0, + GFP_KERNEL); + if (elem.priv == NULL) +- goto err2; ++ goto fail_elem; + + ext = nft_set_elem_ext(set, elem.priv); + if (flags) + *nft_set_ext_flags(ext) = flags; + + trans = nft_trans_elem_alloc(ctx, NFT_MSG_DELSETELEM, set); +- if (trans == NULL) { +- err = -ENOMEM; +- goto err3; +- } ++ if (trans == NULL) ++ goto fail_trans; + + priv = set->ops->deactivate(ctx->net, set, &elem); + if (priv == NULL) { + err = -ENOENT; +- goto err4; ++ goto fail_ops; + } + kfree(elem.priv); + elem.priv = priv; +@@ -4736,13 +4736,12 @@ static int nft_del_setelem(struct nft_ctx *ctx, struct nft_set *set, + list_add_tail(&trans->list, &ctx->net->nft.commit_list); + return 0; + +-err4: ++fail_ops: + kfree(trans); +-err3: ++fail_trans: + kfree(elem.priv); +-err2: +- nft_data_release(&elem.key.val, desc.type); +-err1: ++fail_elem: ++ nft_data_release(&elem.key.val, NFT_DATA_VALUE); + return err; + } + +-- +2.39.2 + diff --git a/queue-4.19/netfilter-nf_tables-allow-up-to-64-bytes-in-the-set-.patch b/queue-4.19/netfilter-nf_tables-allow-up-to-64-bytes-in-the-set-.patch new file mode 100644 index 00000000000..683798c995c --- /dev/null +++ b/queue-4.19/netfilter-nf_tables-allow-up-to-64-bytes-in-the-set-.patch @@ -0,0 +1,130 @@ +From 845fb6f66565390250f29ac0d65e0855f6a5c760 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 16 May 2023 17:06:10 +0200 +Subject: netfilter: nf_tables: allow up to 64 bytes in the set element data + area + +From: Pablo Neira Ayuso + +[ fdb9c405e35bdc6e305b9b4e20ebc141ed14fc81 ] + +So far, the set elements could store up to 128-bits in the data area. + +Signed-off-by: Pablo Neira Ayuso +Signed-off-by: Sasha Levin +--- + include/net/netfilter/nf_tables.h | 4 ++++ + net/netfilter/nf_tables_api.c | 39 +++++++++++++++++++++---------- + 2 files changed, 31 insertions(+), 12 deletions(-) + +diff --git a/include/net/netfilter/nf_tables.h b/include/net/netfilter/nf_tables.h +index 2cd847212a048..1b4f47a878060 100644 +--- a/include/net/netfilter/nf_tables.h ++++ b/include/net/netfilter/nf_tables.h +@@ -225,6 +225,10 @@ struct nft_set_elem { + u32 buf[NFT_DATA_VALUE_MAXLEN / sizeof(u32)]; + struct nft_data val; + } key; ++ union { ++ u32 buf[NFT_DATA_VALUE_MAXLEN / sizeof(u32)]; ++ struct nft_data val; ++ } data; + void *priv; + }; + +diff --git a/net/netfilter/nf_tables_api.c b/net/netfilter/nf_tables_api.c +index acd0566a35860..c1cbcfb58b476 100644 +--- a/net/netfilter/nf_tables_api.c ++++ b/net/netfilter/nf_tables_api.c +@@ -4158,6 +4158,25 @@ static int nft_setelem_parse_key(struct nft_ctx *ctx, struct nft_set *set, + return 0; + } + ++static int nft_setelem_parse_data(struct nft_ctx *ctx, struct nft_set *set, ++ struct nft_data_desc *desc, ++ struct nft_data *data, ++ struct nlattr *attr) ++{ ++ int err; ++ ++ err = nft_data_init(ctx, data, NFT_DATA_VALUE_MAXLEN, desc, attr); ++ if (err < 0) ++ return err; ++ ++ if (desc->type != NFT_DATA_VERDICT && desc->len != set->dlen) { ++ nft_data_release(data, desc->type); ++ return -EINVAL; ++ } ++ ++ return 0; ++} ++ + static int nft_get_set_elem(struct nft_ctx *ctx, struct nft_set *set, + const struct nlattr *attr) + { +@@ -4382,7 +4401,6 @@ static int nft_add_set_elem(struct nft_ctx *ctx, struct nft_set *set, + struct nft_object *obj = NULL; + struct nft_userdata *udata; + struct nft_data_desc desc; +- struct nft_data data; + enum nft_registers dreg; + struct nft_trans *trans; + u32 flags = 0; +@@ -4463,15 +4481,11 @@ static int nft_add_set_elem(struct nft_ctx *ctx, struct nft_set *set, + } + + if (nla[NFTA_SET_ELEM_DATA] != NULL) { +- err = nft_data_init(ctx, &data, sizeof(data), &desc, +- nla[NFTA_SET_ELEM_DATA]); ++ err = nft_setelem_parse_data(ctx, set, &desc, &elem.data.val, ++ nla[NFTA_SET_ELEM_DATA]); + if (err < 0) + goto err2; + +- err = -EINVAL; +- if (set->dtype != NFT_DATA_VERDICT && desc.len != set->dlen) +- goto err3; +- + dreg = nft_type_to_reg(set->dtype); + list_for_each_entry(binding, &set->bindings, list) { + struct nft_ctx bind_ctx = { +@@ -4485,14 +4499,14 @@ static int nft_add_set_elem(struct nft_ctx *ctx, struct nft_set *set, + continue; + + err = nft_validate_register_store(&bind_ctx, dreg, +- &data, ++ &elem.data.val, + desc.type, desc.len); + if (err < 0) + goto err3; + + if (desc.type == NFT_DATA_VERDICT && +- (data.verdict.code == NFT_GOTO || +- data.verdict.code == NFT_JUMP)) ++ (elem.data.val.verdict.code == NFT_GOTO || ++ elem.data.val.verdict.code == NFT_JUMP)) + nft_validate_state_update(ctx->net, + NFT_VALIDATE_NEED); + } +@@ -4513,7 +4527,8 @@ static int nft_add_set_elem(struct nft_ctx *ctx, struct nft_set *set, + } + + err = -ENOMEM; +- elem.priv = nft_set_elem_init(set, &tmpl, elem.key.val.data, data.data, ++ elem.priv = nft_set_elem_init(set, &tmpl, elem.key.val.data, ++ elem.data.val.data, + timeout, GFP_KERNEL); + if (elem.priv == NULL) + goto err3; +@@ -4580,7 +4595,7 @@ static int nft_add_set_elem(struct nft_ctx *ctx, struct nft_set *set, + kfree(elem.priv); + err3: + if (nla[NFTA_SET_ELEM_DATA] != NULL) +- nft_data_release(&data, desc.type); ++ nft_data_release(&elem.data.val, desc.type); + err2: + nft_data_release(&elem.key.val, NFT_DATA_VALUE); + err1: +-- +2.39.2 + diff --git a/queue-4.19/netfilter-nf_tables-do-not-allow-rule_id-to-refer-to.patch b/queue-4.19/netfilter-nf_tables-do-not-allow-rule_id-to-refer-to.patch new file mode 100644 index 00000000000..f5d2976f32a --- /dev/null +++ b/queue-4.19/netfilter-nf_tables-do-not-allow-rule_id-to-refer-to.patch @@ -0,0 +1,61 @@ +From de1a1cdba5dfd25a98b1476e1f544e7331b24854 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 16 May 2023 17:06:13 +0200 +Subject: netfilter: nf_tables: do not allow RULE_ID to refer to another chain + +From: Pablo Neira Ayuso + +[ 36d5b2913219ac853908b0f1c664345e04313856 ] + +When doing lookups for rules on the same batch by using its ID, a rule from +a different chain can be used. If a rule is added to a chain but tries to +be positioned next to a rule from a different chain, it will be linked to +chain2, but the use counter on chain1 would be the one to be incremented. + +When looking for rules by ID, use the chain that was used for the lookup by +name. The chain used in the context copied to the transaction needs to +match that same chain. That way, struct nft_rule does not need to get +enlarged with another member. + +Fixes: 1a94e38d254b ("netfilter: nf_tables: add NFTA_RULE_ID attribute") +Fixes: 75dd48e2e420 ("netfilter: nf_tables: Support RULE_ID reference in new rule") +Signed-off-by: Thadeu Lima de Souza Cascardo +Cc: +Signed-off-by: Pablo Neira Ayuso +Signed-off-by: Sasha Levin +--- + net/netfilter/nf_tables_api.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +diff --git a/net/netfilter/nf_tables_api.c b/net/netfilter/nf_tables_api.c +index 5cafa90f9d807..62bc4cd0b7bec 100644 +--- a/net/netfilter/nf_tables_api.c ++++ b/net/netfilter/nf_tables_api.c +@@ -2769,6 +2769,7 @@ static int nf_tables_newrule(struct net *net, struct sock *nlsk, + } + + static struct nft_rule *nft_rule_lookup_byid(const struct net *net, ++ const struct nft_chain *chain, + const struct nlattr *nla) + { + u32 id = ntohl(nla_get_be32(nla)); +@@ -2778,6 +2779,7 @@ static struct nft_rule *nft_rule_lookup_byid(const struct net *net, + struct nft_rule *rule = nft_trans_rule(trans); + + if (trans->msg_type == NFT_MSG_NEWRULE && ++ trans->ctx.chain == chain && + id == nft_trans_rule_id(trans)) + return rule; + } +@@ -2824,7 +2826,7 @@ static int nf_tables_delrule(struct net *net, struct sock *nlsk, + + err = nft_delrule(&ctx, rule); + } else if (nla[NFTA_RULE_ID]) { +- rule = nft_rule_lookup_byid(net, nla[NFTA_RULE_ID]); ++ rule = nft_rule_lookup_byid(net, chain, nla[NFTA_RULE_ID]); + if (IS_ERR(rule)) { + NL_SET_BAD_ATTR(extack, nla[NFTA_RULE_ID]); + return PTR_ERR(rule); +-- +2.39.2 + diff --git a/queue-4.19/netfilter-nf_tables-stricter-validation-of-element-d.patch b/queue-4.19/netfilter-nf_tables-stricter-validation-of-element-d.patch new file mode 100644 index 00000000000..dfb28ebfe59 --- /dev/null +++ b/queue-4.19/netfilter-nf_tables-stricter-validation-of-element-d.patch @@ -0,0 +1,49 @@ +From 59d3ea150fe52ea1089c5f2fb4f1a2ab3e6fbba8 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 16 May 2023 17:06:11 +0200 +Subject: netfilter: nf_tables: stricter validation of element data + +From: Pablo Neira Ayuso + +[ 7e6bc1f6cabcd30aba0b11219d8e01b952eacbb6 ] + +Make sure element data type and length do not mismatch the one specified +by the set declaration. + +Fixes: 7d7402642eaf ("netfilter: nf_tables: variable sized set element keys / data") +Reported-by: Hugues ANGUELKOV +Signed-off-by: Pablo Neira Ayuso +Signed-off-by: Sasha Levin +--- + net/netfilter/nf_tables_api.c | 9 ++++++++- + 1 file changed, 8 insertions(+), 1 deletion(-) + +diff --git a/net/netfilter/nf_tables_api.c b/net/netfilter/nf_tables_api.c +index c1cbcfb58b476..ab1e0f0962a2b 100644 +--- a/net/netfilter/nf_tables_api.c ++++ b/net/netfilter/nf_tables_api.c +@@ -4163,13 +4163,20 @@ static int nft_setelem_parse_data(struct nft_ctx *ctx, struct nft_set *set, + struct nft_data *data, + struct nlattr *attr) + { ++ u32 dtype; + int err; + + err = nft_data_init(ctx, data, NFT_DATA_VALUE_MAXLEN, desc, attr); + if (err < 0) + return err; + +- if (desc->type != NFT_DATA_VERDICT && desc->len != set->dlen) { ++ if (set->dtype == NFT_DATA_VERDICT) ++ dtype = NFT_DATA_VERDICT; ++ else ++ dtype = NFT_DATA_VALUE; ++ ++ if (dtype != desc->type || ++ set->dlen != desc->len) { + nft_data_release(data, desc->type); + return -EINVAL; + } +-- +2.39.2 + diff --git a/queue-4.19/netfilter-nf_tables-validate-nfta_set_elem_objref-ba.patch b/queue-4.19/netfilter-nf_tables-validate-nfta_set_elem_objref-ba.patch new file mode 100644 index 00000000000..065d9565596 --- /dev/null +++ b/queue-4.19/netfilter-nf_tables-validate-nfta_set_elem_objref-ba.patch @@ -0,0 +1,57 @@ +From 5fc53006c93357c0d1ecfda17fd1b983e12d576b Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 16 May 2023 17:06:12 +0200 +Subject: netfilter: nf_tables: validate NFTA_SET_ELEM_OBJREF based on + NFT_SET_OBJECT flag + +From: Pablo Neira Ayuso + +[ 5a2f3dc31811e93be15522d9eb13ed61460b76c8 ] + +If the NFTA_SET_ELEM_OBJREF netlink attribute is present and +NFT_SET_OBJECT flag is set on, report EINVAL. + +Move existing sanity check earlier to validate that NFT_SET_OBJECT +requires NFTA_SET_ELEM_OBJREF. + +Fixes: 8aeff920dcc9 ("netfilter: nf_tables: add stateful object reference to set elements") +Signed-off-by: Pablo Neira Ayuso +Signed-off-by: Sasha Levin +--- + net/netfilter/nf_tables_api.c | 13 +++++++++---- + 1 file changed, 9 insertions(+), 4 deletions(-) + +diff --git a/net/netfilter/nf_tables_api.c b/net/netfilter/nf_tables_api.c +index ab1e0f0962a2b..5cafa90f9d807 100644 +--- a/net/netfilter/nf_tables_api.c ++++ b/net/netfilter/nf_tables_api.c +@@ -4440,6 +4440,15 @@ static int nft_add_set_elem(struct nft_ctx *ctx, struct nft_set *set, + return -EINVAL; + } + ++ if (set->flags & NFT_SET_OBJECT) { ++ if (!nla[NFTA_SET_ELEM_OBJREF] && ++ !(flags & NFT_SET_ELEM_INTERVAL_END)) ++ return -EINVAL; ++ } else { ++ if (nla[NFTA_SET_ELEM_OBJREF]) ++ return -EINVAL; ++ } ++ + if ((flags & NFT_SET_ELEM_INTERVAL_END) && + (nla[NFTA_SET_ELEM_DATA] || + nla[NFTA_SET_ELEM_OBJREF] || +@@ -4474,10 +4483,6 @@ static int nft_add_set_elem(struct nft_ctx *ctx, struct nft_set *set, + } + + if (nla[NFTA_SET_ELEM_OBJREF] != NULL) { +- if (!(set->flags & NFT_SET_OBJECT)) { +- err = -EINVAL; +- goto err2; +- } + obj = nft_obj_lookup(ctx->table, nla[NFTA_SET_ELEM_OBJREF], + set->objtype, genmask); + if (IS_ERR(obj)) { +-- +2.39.2 + diff --git a/queue-4.19/netfilter-nf_tables-validate-registers-coming-from-u.patch b/queue-4.19/netfilter-nf_tables-validate-registers-coming-from-u.patch new file mode 100644 index 00000000000..ea5055c3a6c --- /dev/null +++ b/queue-4.19/netfilter-nf_tables-validate-registers-coming-from-u.patch @@ -0,0 +1,85 @@ +From c833032b7cae0331325827ee7978b5798acad5c0 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 16 May 2023 17:06:08 +0200 +Subject: netfilter: nf_tables: validate registers coming from userspace. + +From: Pablo Neira Ayuso + +[ 6e1acfa387b9ff82cfc7db8cc3b6959221a95851 ] + +Bail out in case userspace uses unsupported registers. + +Fixes: 49499c3e6e18 ("netfilter: nf_tables: switch registers to 32 bit addressing") +Signed-off-by: Pablo Neira Ayuso +Signed-off-by: Sasha Levin +--- + net/netfilter/nf_tables_api.c | 31 +++++++++++++++++-------------- + 1 file changed, 17 insertions(+), 14 deletions(-) + +diff --git a/net/netfilter/nf_tables_api.c b/net/netfilter/nf_tables_api.c +index dacdb1feb2e9a..48f8d3d2b6d7c 100644 +--- a/net/netfilter/nf_tables_api.c ++++ b/net/netfilter/nf_tables_api.c +@@ -6978,26 +6978,23 @@ int nft_parse_u32_check(const struct nlattr *attr, int max, u32 *dest) + } + EXPORT_SYMBOL_GPL(nft_parse_u32_check); + +-/** +- * nft_parse_register - parse a register value from a netlink attribute +- * +- * @attr: netlink attribute +- * +- * Parse and translate a register value from a netlink attribute. +- * Registers used to be 128 bit wide, these register numbers will be +- * mapped to the corresponding 32 bit register numbers. +- */ +-static unsigned int nft_parse_register(const struct nlattr *attr) ++static int nft_parse_register(const struct nlattr *attr, u32 *preg) + { + unsigned int reg; + + reg = ntohl(nla_get_be32(attr)); + switch (reg) { + case NFT_REG_VERDICT...NFT_REG_4: +- return reg * NFT_REG_SIZE / NFT_REG32_SIZE; ++ *preg = reg * NFT_REG_SIZE / NFT_REG32_SIZE; ++ break; ++ case NFT_REG32_00...NFT_REG32_15: ++ *preg = reg + NFT_REG_SIZE / NFT_REG32_SIZE - NFT_REG32_00; ++ break; + default: +- return reg + NFT_REG_SIZE / NFT_REG32_SIZE - NFT_REG32_00; ++ return -ERANGE; + } ++ ++ return 0; + } + + /** +@@ -7048,7 +7045,10 @@ int nft_parse_register_load(const struct nlattr *attr, u8 *sreg, u32 len) + u32 reg; + int err; + +- reg = nft_parse_register(attr); ++ err = nft_parse_register(attr, ®); ++ if (err < 0) ++ return err; ++ + err = nft_validate_register_load(reg, len); + if (err < 0) + return err; +@@ -7117,7 +7117,10 @@ int nft_parse_register_store(const struct nft_ctx *ctx, + int err; + u32 reg; + +- reg = nft_parse_register(attr); ++ err = nft_parse_register(attr, ®); ++ if (err < 0) ++ return err; ++ + err = nft_validate_register_store(ctx, reg, data, type, len); + if (err < 0) + return err; +-- +2.39.2 + diff --git a/queue-4.19/netfilter-nftables-add-nft_parse_register_load-and-u.patch b/queue-4.19/netfilter-nftables-add-nft_parse_register_load-and-u.patch new file mode 100644 index 00000000000..ed7bfd0a36d --- /dev/null +++ b/queue-4.19/netfilter-nftables-add-nft_parse_register_load-and-u.patch @@ -0,0 +1,850 @@ +From e08d65023b8039bb1ad6b28e931debb8229569a4 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 16 May 2023 17:06:05 +0200 +Subject: netfilter: nftables: add nft_parse_register_load() and use it +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Pablo Neira Ayuso + +[ 4f16d25c68ec844299a4df6ecbb0234eaf88a935 ] + +This new function combines the netlink register attribute parser +and the load validation function. + +This update requires to replace: + + enum nft_registers sreg:8; + +in many of the expression private areas otherwise compiler complains +with: + + error: cannot take address of bit-field ‘sreg’ + +when passing the register field as reference. + +Signed-off-by: Pablo Neira Ayuso +Signed-off-by: Sasha Levin +--- + include/net/netfilter/nf_tables.h | 2 +- + include/net/netfilter/nf_tables_core.h | 5 ++-- + include/net/netfilter/nft_masq.h | 4 +-- + include/net/netfilter/nft_redir.h | 4 +-- + net/ipv4/netfilter/nft_dup_ipv4.c | 18 ++++++------- + net/ipv6/netfilter/nft_dup_ipv6.c | 18 ++++++------- + net/netfilter/nf_tables_api.c | 18 +++++++++++-- + net/netfilter/nft_bitwise.c | 6 ++--- + net/netfilter/nft_byteorder.c | 6 ++--- + net/netfilter/nft_cmp.c | 8 +++--- + net/netfilter/nft_ct.c | 5 ++-- + net/netfilter/nft_dup_netdev.c | 6 ++--- + net/netfilter/nft_dynset.c | 12 ++++----- + net/netfilter/nft_exthdr.c | 6 ++--- + net/netfilter/nft_fwd_netdev.c | 18 ++++++------- + net/netfilter/nft_hash.c | 10 +++++--- + net/netfilter/nft_lookup.c | 6 ++--- + net/netfilter/nft_masq.c | 14 ++++------- + net/netfilter/nft_meta.c | 5 ++-- + net/netfilter/nft_nat.c | 35 +++++++++++--------------- + net/netfilter/nft_objref.c | 6 ++--- + net/netfilter/nft_payload.c | 4 +-- + net/netfilter/nft_queue.c | 12 ++++----- + net/netfilter/nft_range.c | 6 ++--- + net/netfilter/nft_redir.c | 14 ++++------- + net/netfilter/nft_tproxy.c | 14 +++++------ + 26 files changed, 130 insertions(+), 132 deletions(-) + +diff --git a/include/net/netfilter/nf_tables.h b/include/net/netfilter/nf_tables.h +index 78f5f0426e6b6..e7b1e241f6f6e 100644 +--- a/include/net/netfilter/nf_tables.h ++++ b/include/net/netfilter/nf_tables.h +@@ -194,7 +194,7 @@ int nft_parse_u32_check(const struct nlattr *attr, int max, u32 *dest); + unsigned int nft_parse_register(const struct nlattr *attr); + int nft_dump_register(struct sk_buff *skb, unsigned int attr, unsigned int reg); + +-int nft_validate_register_load(enum nft_registers reg, unsigned int len); ++int nft_parse_register_load(const struct nlattr *attr, u8 *sreg, u32 len); + int nft_validate_register_store(const struct nft_ctx *ctx, + enum nft_registers reg, + const struct nft_data *data, +diff --git a/include/net/netfilter/nf_tables_core.h b/include/net/netfilter/nf_tables_core.h +index 8da837d2aaf99..c81c12a825de4 100644 +--- a/include/net/netfilter/nf_tables_core.h ++++ b/include/net/netfilter/nf_tables_core.h +@@ -21,7 +21,8 @@ void nf_tables_core_module_exit(void); + + struct nft_cmp_fast_expr { + u32 data; +- enum nft_registers sreg:8; ++ u32 mask; ++ u8 sreg; + u8 len; + }; + +@@ -54,7 +55,7 @@ struct nft_payload_set { + enum nft_payload_bases base:8; + u8 offset; + u8 len; +- enum nft_registers sreg:8; ++ u8 sreg; + u8 csum_type; + u8 csum_offset; + u8 csum_flags; +diff --git a/include/net/netfilter/nft_masq.h b/include/net/netfilter/nft_masq.h +index e51ab3815797b..e69a8277b70b3 100644 +--- a/include/net/netfilter/nft_masq.h ++++ b/include/net/netfilter/nft_masq.h +@@ -4,8 +4,8 @@ + + struct nft_masq { + u32 flags; +- enum nft_registers sreg_proto_min:8; +- enum nft_registers sreg_proto_max:8; ++ u8 sreg_proto_min; ++ u8 sreg_proto_max; + }; + + extern const struct nla_policy nft_masq_policy[]; +diff --git a/include/net/netfilter/nft_redir.h b/include/net/netfilter/nft_redir.h +index 4a970737c03c8..2b4036c94cb3e 100644 +--- a/include/net/netfilter/nft_redir.h ++++ b/include/net/netfilter/nft_redir.h +@@ -3,8 +3,8 @@ + #define _NFT_REDIR_H_ + + struct nft_redir { +- enum nft_registers sreg_proto_min:8; +- enum nft_registers sreg_proto_max:8; ++ u8 sreg_proto_min; ++ u8 sreg_proto_max; + u16 flags; + }; + +diff --git a/net/ipv4/netfilter/nft_dup_ipv4.c b/net/ipv4/netfilter/nft_dup_ipv4.c +index 0af3d8df70dd7..157bca240edce 100644 +--- a/net/ipv4/netfilter/nft_dup_ipv4.c ++++ b/net/ipv4/netfilter/nft_dup_ipv4.c +@@ -16,8 +16,8 @@ + #include + + struct nft_dup_ipv4 { +- enum nft_registers sreg_addr:8; +- enum nft_registers sreg_dev:8; ++ u8 sreg_addr; ++ u8 sreg_dev; + }; + + static void nft_dup_ipv4_eval(const struct nft_expr *expr, +@@ -43,16 +43,16 @@ static int nft_dup_ipv4_init(const struct nft_ctx *ctx, + if (tb[NFTA_DUP_SREG_ADDR] == NULL) + return -EINVAL; + +- priv->sreg_addr = nft_parse_register(tb[NFTA_DUP_SREG_ADDR]); +- err = nft_validate_register_load(priv->sreg_addr, sizeof(struct in_addr)); ++ err = nft_parse_register_load(tb[NFTA_DUP_SREG_ADDR], &priv->sreg_addr, ++ sizeof(struct in_addr)); + if (err < 0) + return err; + +- if (tb[NFTA_DUP_SREG_DEV] != NULL) { +- priv->sreg_dev = nft_parse_register(tb[NFTA_DUP_SREG_DEV]); +- return nft_validate_register_load(priv->sreg_dev, sizeof(int)); +- } +- return 0; ++ if (tb[NFTA_DUP_SREG_DEV]) ++ err = nft_parse_register_load(tb[NFTA_DUP_SREG_DEV], ++ &priv->sreg_dev, sizeof(int)); ++ ++ return err; + } + + static int nft_dup_ipv4_dump(struct sk_buff *skb, const struct nft_expr *expr) +diff --git a/net/ipv6/netfilter/nft_dup_ipv6.c b/net/ipv6/netfilter/nft_dup_ipv6.c +index d8b5b60b7d531..d8bb7c85287cb 100644 +--- a/net/ipv6/netfilter/nft_dup_ipv6.c ++++ b/net/ipv6/netfilter/nft_dup_ipv6.c +@@ -16,8 +16,8 @@ + #include + + struct nft_dup_ipv6 { +- enum nft_registers sreg_addr:8; +- enum nft_registers sreg_dev:8; ++ u8 sreg_addr; ++ u8 sreg_dev; + }; + + static void nft_dup_ipv6_eval(const struct nft_expr *expr, +@@ -41,16 +41,16 @@ static int nft_dup_ipv6_init(const struct nft_ctx *ctx, + if (tb[NFTA_DUP_SREG_ADDR] == NULL) + return -EINVAL; + +- priv->sreg_addr = nft_parse_register(tb[NFTA_DUP_SREG_ADDR]); +- err = nft_validate_register_load(priv->sreg_addr, sizeof(struct in6_addr)); ++ err = nft_parse_register_load(tb[NFTA_DUP_SREG_ADDR], &priv->sreg_addr, ++ sizeof(struct in6_addr)); + if (err < 0) + return err; + +- if (tb[NFTA_DUP_SREG_DEV] != NULL) { +- priv->sreg_dev = nft_parse_register(tb[NFTA_DUP_SREG_DEV]); +- return nft_validate_register_load(priv->sreg_dev, sizeof(int)); +- } +- return 0; ++ if (tb[NFTA_DUP_SREG_DEV]) ++ err = nft_parse_register_load(tb[NFTA_DUP_SREG_DEV], ++ &priv->sreg_dev, sizeof(int)); ++ ++ return err; + } + + static int nft_dup_ipv6_dump(struct sk_buff *skb, const struct nft_expr *expr) +diff --git a/net/netfilter/nf_tables_api.c b/net/netfilter/nf_tables_api.c +index e20bde9cc7b12..3b4cb6a9e85d5 100644 +--- a/net/netfilter/nf_tables_api.c ++++ b/net/netfilter/nf_tables_api.c +@@ -7026,7 +7026,7 @@ EXPORT_SYMBOL_GPL(nft_dump_register); + * Validate that the input register is one of the general purpose + * registers and that the length of the load is within the bounds. + */ +-int nft_validate_register_load(enum nft_registers reg, unsigned int len) ++static int nft_validate_register_load(enum nft_registers reg, unsigned int len) + { + if (reg < NFT_REG_1 * NFT_REG_SIZE / NFT_REG32_SIZE) + return -EINVAL; +@@ -7037,7 +7037,21 @@ int nft_validate_register_load(enum nft_registers reg, unsigned int len) + + return 0; + } +-EXPORT_SYMBOL_GPL(nft_validate_register_load); ++ ++int nft_parse_register_load(const struct nlattr *attr, u8 *sreg, u32 len) ++{ ++ u32 reg; ++ int err; ++ ++ reg = nft_parse_register(attr); ++ err = nft_validate_register_load(reg, len); ++ if (err < 0) ++ return err; ++ ++ *sreg = reg; ++ return 0; ++} ++EXPORT_SYMBOL_GPL(nft_parse_register_load); + + /** + * nft_validate_register_store - validate an expressions' register store +diff --git a/net/netfilter/nft_bitwise.c b/net/netfilter/nft_bitwise.c +index 058ee84ea531b..23a8a9d119876 100644 +--- a/net/netfilter/nft_bitwise.c ++++ b/net/netfilter/nft_bitwise.c +@@ -18,7 +18,7 @@ + #include + + struct nft_bitwise { +- enum nft_registers sreg:8; ++ u8 sreg; + enum nft_registers dreg:8; + u8 len; + struct nft_data mask; +@@ -68,8 +68,8 @@ static int nft_bitwise_init(const struct nft_ctx *ctx, + + priv->len = len; + +- priv->sreg = nft_parse_register(tb[NFTA_BITWISE_SREG]); +- err = nft_validate_register_load(priv->sreg, priv->len); ++ err = nft_parse_register_load(tb[NFTA_BITWISE_SREG], &priv->sreg, ++ priv->len); + if (err < 0) + return err; + +diff --git a/net/netfilter/nft_byteorder.c b/net/netfilter/nft_byteorder.c +index 13d4e421a6b33..c81d618137ce8 100644 +--- a/net/netfilter/nft_byteorder.c ++++ b/net/netfilter/nft_byteorder.c +@@ -19,7 +19,7 @@ + #include + + struct nft_byteorder { +- enum nft_registers sreg:8; ++ u8 sreg; + enum nft_registers dreg:8; + enum nft_byteorder_ops op:8; + u8 len; +@@ -133,14 +133,14 @@ static int nft_byteorder_init(const struct nft_ctx *ctx, + return -EINVAL; + } + +- priv->sreg = nft_parse_register(tb[NFTA_BYTEORDER_SREG]); + err = nft_parse_u32_check(tb[NFTA_BYTEORDER_LEN], U8_MAX, &len); + if (err < 0) + return err; + + priv->len = len; + +- err = nft_validate_register_load(priv->sreg, priv->len); ++ err = nft_parse_register_load(tb[NFTA_BYTEORDER_SREG], &priv->sreg, ++ priv->len); + if (err < 0) + return err; + +diff --git a/net/netfilter/nft_cmp.c b/net/netfilter/nft_cmp.c +index 7007045c08498..36bf64ebc8926 100644 +--- a/net/netfilter/nft_cmp.c ++++ b/net/netfilter/nft_cmp.c +@@ -19,7 +19,7 @@ + + struct nft_cmp_expr { + struct nft_data data; +- enum nft_registers sreg:8; ++ u8 sreg; + u8 len; + enum nft_cmp_ops op:8; + }; +@@ -88,8 +88,7 @@ static int nft_cmp_init(const struct nft_ctx *ctx, const struct nft_expr *expr, + return err; + } + +- priv->sreg = nft_parse_register(tb[NFTA_CMP_SREG]); +- err = nft_validate_register_load(priv->sreg, desc.len); ++ err = nft_parse_register_load(tb[NFTA_CMP_SREG], &priv->sreg, desc.len); + if (err < 0) + return err; + +@@ -139,8 +138,7 @@ static int nft_cmp_fast_init(const struct nft_ctx *ctx, + if (err < 0) + return err; + +- priv->sreg = nft_parse_register(tb[NFTA_CMP_SREG]); +- err = nft_validate_register_load(priv->sreg, desc.len); ++ err = nft_parse_register_load(tb[NFTA_CMP_SREG], &priv->sreg, desc.len); + if (err < 0) + return err; + +diff --git a/net/netfilter/nft_ct.c b/net/netfilter/nft_ct.c +index 5dd87748afa8a..045e350ba03ea 100644 +--- a/net/netfilter/nft_ct.c ++++ b/net/netfilter/nft_ct.c +@@ -30,7 +30,7 @@ struct nft_ct { + enum ip_conntrack_dir dir:8; + union { + enum nft_registers dreg:8; +- enum nft_registers sreg:8; ++ u8 sreg; + }; + }; + +@@ -581,8 +581,7 @@ static int nft_ct_set_init(const struct nft_ctx *ctx, + } + } + +- priv->sreg = nft_parse_register(tb[NFTA_CT_SREG]); +- err = nft_validate_register_load(priv->sreg, len); ++ err = nft_parse_register_load(tb[NFTA_CT_SREG], &priv->sreg, len); + if (err < 0) + goto err1; + +diff --git a/net/netfilter/nft_dup_netdev.c b/net/netfilter/nft_dup_netdev.c +index 2cc1e0ef56e88..e862f916efa09 100644 +--- a/net/netfilter/nft_dup_netdev.c ++++ b/net/netfilter/nft_dup_netdev.c +@@ -16,7 +16,7 @@ + #include + + struct nft_dup_netdev { +- enum nft_registers sreg_dev:8; ++ u8 sreg_dev; + }; + + static void nft_dup_netdev_eval(const struct nft_expr *expr, +@@ -42,8 +42,8 @@ static int nft_dup_netdev_init(const struct nft_ctx *ctx, + if (tb[NFTA_DUP_SREG_DEV] == NULL) + return -EINVAL; + +- priv->sreg_dev = nft_parse_register(tb[NFTA_DUP_SREG_DEV]); +- return nft_validate_register_load(priv->sreg_dev, sizeof(int)); ++ return nft_parse_register_load(tb[NFTA_DUP_SREG_DEV], &priv->sreg_dev, ++ sizeof(int)); + } + + static const struct nft_expr_ops nft_dup_netdev_ingress_ops; +diff --git a/net/netfilter/nft_dynset.c b/net/netfilter/nft_dynset.c +index ea73130427eb8..c5d42e704f043 100644 +--- a/net/netfilter/nft_dynset.c ++++ b/net/netfilter/nft_dynset.c +@@ -20,8 +20,8 @@ struct nft_dynset { + struct nft_set *set; + struct nft_set_ext_tmpl tmpl; + enum nft_dynset_ops op:8; +- enum nft_registers sreg_key:8; +- enum nft_registers sreg_data:8; ++ u8 sreg_key; ++ u8 sreg_data; + bool invert; + u64 timeout; + struct nft_expr *expr; +@@ -166,8 +166,8 @@ static int nft_dynset_init(const struct nft_ctx *ctx, + tb[NFTA_DYNSET_TIMEOUT]))); + } + +- priv->sreg_key = nft_parse_register(tb[NFTA_DYNSET_SREG_KEY]); +- err = nft_validate_register_load(priv->sreg_key, set->klen); ++ err = nft_parse_register_load(tb[NFTA_DYNSET_SREG_KEY], &priv->sreg_key, ++ set->klen); + if (err < 0) + return err; + +@@ -177,8 +177,8 @@ static int nft_dynset_init(const struct nft_ctx *ctx, + if (set->dtype == NFT_DATA_VERDICT) + return -EOPNOTSUPP; + +- priv->sreg_data = nft_parse_register(tb[NFTA_DYNSET_SREG_DATA]); +- err = nft_validate_register_load(priv->sreg_data, set->dlen); ++ err = nft_parse_register_load(tb[NFTA_DYNSET_SREG_DATA], ++ &priv->sreg_data, set->dlen); + if (err < 0) + return err; + } else if (set->flags & NFT_SET_MAP) +diff --git a/net/netfilter/nft_exthdr.c b/net/netfilter/nft_exthdr.c +index 93fee41060192..340520f10b686 100644 +--- a/net/netfilter/nft_exthdr.c ++++ b/net/netfilter/nft_exthdr.c +@@ -23,7 +23,7 @@ struct nft_exthdr { + u8 len; + u8 op; + enum nft_registers dreg:8; +- enum nft_registers sreg:8; ++ u8 sreg; + u8 flags; + }; + +@@ -308,11 +308,11 @@ static int nft_exthdr_tcp_set_init(const struct nft_ctx *ctx, + priv->type = nla_get_u8(tb[NFTA_EXTHDR_TYPE]); + priv->offset = offset; + priv->len = len; +- priv->sreg = nft_parse_register(tb[NFTA_EXTHDR_SREG]); + priv->flags = flags; + priv->op = op; + +- return nft_validate_register_load(priv->sreg, priv->len); ++ return nft_parse_register_load(tb[NFTA_EXTHDR_SREG], &priv->sreg, ++ priv->len); + } + + static int nft_exthdr_dump_common(struct sk_buff *skb, const struct nft_exthdr *priv) +diff --git a/net/netfilter/nft_fwd_netdev.c b/net/netfilter/nft_fwd_netdev.c +index 10a12e0949299..2efbe78de3b22 100644 +--- a/net/netfilter/nft_fwd_netdev.c ++++ b/net/netfilter/nft_fwd_netdev.c +@@ -20,7 +20,7 @@ + #include + + struct nft_fwd_netdev { +- enum nft_registers sreg_dev:8; ++ u8 sreg_dev; + }; + + static void nft_fwd_netdev_eval(const struct nft_expr *expr, +@@ -49,8 +49,8 @@ static int nft_fwd_netdev_init(const struct nft_ctx *ctx, + if (tb[NFTA_FWD_SREG_DEV] == NULL) + return -EINVAL; + +- priv->sreg_dev = nft_parse_register(tb[NFTA_FWD_SREG_DEV]); +- return nft_validate_register_load(priv->sreg_dev, sizeof(int)); ++ return nft_parse_register_load(tb[NFTA_FWD_SREG_DEV], &priv->sreg_dev, ++ sizeof(int)); + } + + static const struct nft_expr_ops nft_fwd_netdev_ingress_ops; +@@ -69,8 +69,8 @@ static int nft_fwd_netdev_dump(struct sk_buff *skb, const struct nft_expr *expr) + } + + struct nft_fwd_neigh { +- enum nft_registers sreg_dev:8; +- enum nft_registers sreg_addr:8; ++ u8 sreg_dev; ++ u8 sreg_addr; + u8 nfproto; + }; + +@@ -148,8 +148,6 @@ static int nft_fwd_neigh_init(const struct nft_ctx *ctx, + !tb[NFTA_FWD_NFPROTO]) + return -EINVAL; + +- priv->sreg_dev = nft_parse_register(tb[NFTA_FWD_SREG_DEV]); +- priv->sreg_addr = nft_parse_register(tb[NFTA_FWD_SREG_ADDR]); + priv->nfproto = ntohl(nla_get_be32(tb[NFTA_FWD_NFPROTO])); + + switch (priv->nfproto) { +@@ -163,11 +161,13 @@ static int nft_fwd_neigh_init(const struct nft_ctx *ctx, + return -EOPNOTSUPP; + } + +- err = nft_validate_register_load(priv->sreg_dev, sizeof(int)); ++ err = nft_parse_register_load(tb[NFTA_FWD_SREG_DEV], &priv->sreg_dev, ++ sizeof(int)); + if (err < 0) + return err; + +- return nft_validate_register_load(priv->sreg_addr, addr_len); ++ return nft_parse_register_load(tb[NFTA_FWD_SREG_ADDR], &priv->sreg_addr, ++ addr_len); + } + + static const struct nft_expr_ops nft_fwd_netdev_ingress_ops; +diff --git a/net/netfilter/nft_hash.c b/net/netfilter/nft_hash.c +index b8f23f75aea6c..d08a14cfe56b7 100644 +--- a/net/netfilter/nft_hash.c ++++ b/net/netfilter/nft_hash.c +@@ -18,7 +18,7 @@ + #include + + struct nft_jhash { +- enum nft_registers sreg:8; ++ u8 sreg; + enum nft_registers dreg:8; + u8 len; + bool autogen_seed:1; +@@ -136,7 +136,6 @@ static int nft_jhash_init(const struct nft_ctx *ctx, + if (tb[NFTA_HASH_OFFSET]) + priv->offset = ntohl(nla_get_be32(tb[NFTA_HASH_OFFSET])); + +- priv->sreg = nft_parse_register(tb[NFTA_HASH_SREG]); + priv->dreg = nft_parse_register(tb[NFTA_HASH_DREG]); + + err = nft_parse_u32_check(tb[NFTA_HASH_LEN], U8_MAX, &len); +@@ -147,6 +146,10 @@ static int nft_jhash_init(const struct nft_ctx *ctx, + + priv->len = len; + ++ err = nft_parse_register_load(tb[NFTA_HASH_SREG], &priv->sreg, len); ++ if (err < 0) ++ return err; ++ + priv->modulus = ntohl(nla_get_be32(tb[NFTA_HASH_MODULUS])); + if (priv->modulus < 1) + return -ERANGE; +@@ -161,8 +164,7 @@ static int nft_jhash_init(const struct nft_ctx *ctx, + get_random_bytes(&priv->seed, sizeof(priv->seed)); + } + +- return nft_validate_register_load(priv->sreg, len) && +- nft_validate_register_store(ctx, priv->dreg, NULL, ++ return nft_validate_register_store(ctx, priv->dreg, NULL, + NFT_DATA_VALUE, sizeof(u32)); + } + +diff --git a/net/netfilter/nft_lookup.c b/net/netfilter/nft_lookup.c +index cb9e937a5ce02..671f124d56b34 100644 +--- a/net/netfilter/nft_lookup.c ++++ b/net/netfilter/nft_lookup.c +@@ -20,7 +20,7 @@ + + struct nft_lookup { + struct nft_set *set; +- enum nft_registers sreg:8; ++ u8 sreg; + enum nft_registers dreg:8; + bool invert; + struct nft_set_binding binding; +@@ -76,8 +76,8 @@ static int nft_lookup_init(const struct nft_ctx *ctx, + if (IS_ERR(set)) + return PTR_ERR(set); + +- priv->sreg = nft_parse_register(tb[NFTA_LOOKUP_SREG]); +- err = nft_validate_register_load(priv->sreg, set->klen); ++ err = nft_parse_register_load(tb[NFTA_LOOKUP_SREG], &priv->sreg, ++ set->klen); + if (err < 0) + return err; + +diff --git a/net/netfilter/nft_masq.c b/net/netfilter/nft_masq.c +index 9d8655bc1bea6..4ecfebc2fdc4a 100644 +--- a/net/netfilter/nft_masq.c ++++ b/net/netfilter/nft_masq.c +@@ -53,19 +53,15 @@ int nft_masq_init(const struct nft_ctx *ctx, + } + + if (tb[NFTA_MASQ_REG_PROTO_MIN]) { +- priv->sreg_proto_min = +- nft_parse_register(tb[NFTA_MASQ_REG_PROTO_MIN]); +- +- err = nft_validate_register_load(priv->sreg_proto_min, plen); ++ err = nft_parse_register_load(tb[NFTA_MASQ_REG_PROTO_MIN], ++ &priv->sreg_proto_min, plen); + if (err < 0) + return err; + + if (tb[NFTA_MASQ_REG_PROTO_MAX]) { +- priv->sreg_proto_max = +- nft_parse_register(tb[NFTA_MASQ_REG_PROTO_MAX]); +- +- err = nft_validate_register_load(priv->sreg_proto_max, +- plen); ++ err = nft_parse_register_load(tb[NFTA_MASQ_REG_PROTO_MAX], ++ &priv->sreg_proto_max, ++ plen); + if (err < 0) + return err; + } else { +diff --git a/net/netfilter/nft_meta.c b/net/netfilter/nft_meta.c +index 297fe7d97c182..7af90ed221113 100644 +--- a/net/netfilter/nft_meta.c ++++ b/net/netfilter/nft_meta.c +@@ -31,7 +31,7 @@ struct nft_meta { + enum nft_meta_keys key:8; + union { + enum nft_registers dreg:8; +- enum nft_registers sreg:8; ++ u8 sreg; + }; + }; + +@@ -448,8 +448,7 @@ static int nft_meta_set_init(const struct nft_ctx *ctx, + return -EOPNOTSUPP; + } + +- priv->sreg = nft_parse_register(tb[NFTA_META_SREG]); +- err = nft_validate_register_load(priv->sreg, len); ++ err = nft_parse_register_load(tb[NFTA_META_SREG], &priv->sreg, len); + if (err < 0) + return err; + +diff --git a/net/netfilter/nft_nat.c b/net/netfilter/nft_nat.c +index 2c3d7ff6f58a7..aa6149cc8c87c 100644 +--- a/net/netfilter/nft_nat.c ++++ b/net/netfilter/nft_nat.c +@@ -27,10 +27,10 @@ + #include + + struct nft_nat { +- enum nft_registers sreg_addr_min:8; +- enum nft_registers sreg_addr_max:8; +- enum nft_registers sreg_proto_min:8; +- enum nft_registers sreg_proto_max:8; ++ u8 sreg_addr_min; ++ u8 sreg_addr_max; ++ u8 sreg_proto_min; ++ u8 sreg_proto_max; + enum nf_nat_manip_type type:8; + u8 family; + u16 flags; +@@ -160,18 +160,15 @@ static int nft_nat_init(const struct nft_ctx *ctx, const struct nft_expr *expr, + priv->family = family; + + if (tb[NFTA_NAT_REG_ADDR_MIN]) { +- priv->sreg_addr_min = +- nft_parse_register(tb[NFTA_NAT_REG_ADDR_MIN]); +- err = nft_validate_register_load(priv->sreg_addr_min, alen); ++ err = nft_parse_register_load(tb[NFTA_NAT_REG_ADDR_MIN], ++ &priv->sreg_addr_min, alen); + if (err < 0) + return err; + + if (tb[NFTA_NAT_REG_ADDR_MAX]) { +- priv->sreg_addr_max = +- nft_parse_register(tb[NFTA_NAT_REG_ADDR_MAX]); +- +- err = nft_validate_register_load(priv->sreg_addr_max, +- alen); ++ err = nft_parse_register_load(tb[NFTA_NAT_REG_ADDR_MAX], ++ &priv->sreg_addr_max, ++ alen); + if (err < 0) + return err; + } else { +@@ -181,19 +178,15 @@ static int nft_nat_init(const struct nft_ctx *ctx, const struct nft_expr *expr, + + plen = FIELD_SIZEOF(struct nf_nat_range, min_addr.all); + if (tb[NFTA_NAT_REG_PROTO_MIN]) { +- priv->sreg_proto_min = +- nft_parse_register(tb[NFTA_NAT_REG_PROTO_MIN]); +- +- err = nft_validate_register_load(priv->sreg_proto_min, plen); ++ err = nft_parse_register_load(tb[NFTA_NAT_REG_PROTO_MIN], ++ &priv->sreg_proto_min, plen); + if (err < 0) + return err; + + if (tb[NFTA_NAT_REG_PROTO_MAX]) { +- priv->sreg_proto_max = +- nft_parse_register(tb[NFTA_NAT_REG_PROTO_MAX]); +- +- err = nft_validate_register_load(priv->sreg_proto_max, +- plen); ++ err = nft_parse_register_load(tb[NFTA_NAT_REG_PROTO_MAX], ++ &priv->sreg_proto_max, ++ plen); + if (err < 0) + return err; + } else { +diff --git a/net/netfilter/nft_objref.c b/net/netfilter/nft_objref.c +index eff2173db7e4b..615f0fcf711c6 100644 +--- a/net/netfilter/nft_objref.c ++++ b/net/netfilter/nft_objref.c +@@ -97,7 +97,7 @@ static const struct nft_expr_ops nft_objref_ops = { + + struct nft_objref_map { + struct nft_set *set; +- enum nft_registers sreg:8; ++ u8 sreg; + struct nft_set_binding binding; + }; + +@@ -139,8 +139,8 @@ static int nft_objref_map_init(const struct nft_ctx *ctx, + if (!(set->flags & NFT_SET_OBJECT)) + return -EINVAL; + +- priv->sreg = nft_parse_register(tb[NFTA_OBJREF_SET_SREG]); +- err = nft_validate_register_load(priv->sreg, set->klen); ++ err = nft_parse_register_load(tb[NFTA_OBJREF_SET_SREG], &priv->sreg, ++ set->klen); + if (err < 0) + return err; + +diff --git a/net/netfilter/nft_payload.c b/net/netfilter/nft_payload.c +index 5732b32ab9320..6c5312fecac5c 100644 +--- a/net/netfilter/nft_payload.c ++++ b/net/netfilter/nft_payload.c +@@ -338,7 +338,6 @@ static int nft_payload_set_init(const struct nft_ctx *ctx, + priv->base = ntohl(nla_get_be32(tb[NFTA_PAYLOAD_BASE])); + priv->offset = ntohl(nla_get_be32(tb[NFTA_PAYLOAD_OFFSET])); + priv->len = ntohl(nla_get_be32(tb[NFTA_PAYLOAD_LEN])); +- priv->sreg = nft_parse_register(tb[NFTA_PAYLOAD_SREG]); + + if (tb[NFTA_PAYLOAD_CSUM_TYPE]) + csum_type = ntohl(nla_get_be32(tb[NFTA_PAYLOAD_CSUM_TYPE])); +@@ -369,7 +368,8 @@ static int nft_payload_set_init(const struct nft_ctx *ctx, + } + priv->csum_type = csum_type; + +- return nft_validate_register_load(priv->sreg, priv->len); ++ return nft_parse_register_load(tb[NFTA_PAYLOAD_SREG], &priv->sreg, ++ priv->len); + } + + static int nft_payload_set_dump(struct sk_buff *skb, const struct nft_expr *expr) +diff --git a/net/netfilter/nft_queue.c b/net/netfilter/nft_queue.c +index 98613658d4ac5..de5f1bda9d6f1 100644 +--- a/net/netfilter/nft_queue.c ++++ b/net/netfilter/nft_queue.c +@@ -22,10 +22,10 @@ + static u32 jhash_initval __read_mostly; + + struct nft_queue { +- enum nft_registers sreg_qnum:8; +- u16 queuenum; +- u16 queues_total; +- u16 flags; ++ u8 sreg_qnum; ++ u16 queuenum; ++ u16 queues_total; ++ u16 flags; + }; + + static void nft_queue_eval(const struct nft_expr *expr, +@@ -114,8 +114,8 @@ static int nft_queue_sreg_init(const struct nft_ctx *ctx, + struct nft_queue *priv = nft_expr_priv(expr); + int err; + +- priv->sreg_qnum = nft_parse_register(tb[NFTA_QUEUE_SREG_QNUM]); +- err = nft_validate_register_load(priv->sreg_qnum, sizeof(u32)); ++ err = nft_parse_register_load(tb[NFTA_QUEUE_SREG_QNUM], ++ &priv->sreg_qnum, sizeof(u32)); + if (err < 0) + return err; + +diff --git a/net/netfilter/nft_range.c b/net/netfilter/nft_range.c +index 2e1d2ec2f52a4..a5f74e5b8184f 100644 +--- a/net/netfilter/nft_range.c ++++ b/net/netfilter/nft_range.c +@@ -18,7 +18,7 @@ + struct nft_range_expr { + struct nft_data data_from; + struct nft_data data_to; +- enum nft_registers sreg:8; ++ u8 sreg; + u8 len; + enum nft_range_ops op:8; + }; +@@ -90,8 +90,8 @@ static int nft_range_init(const struct nft_ctx *ctx, const struct nft_expr *expr + goto err2; + } + +- priv->sreg = nft_parse_register(tb[NFTA_RANGE_SREG]); +- err = nft_validate_register_load(priv->sreg, desc_from.len); ++ err = nft_parse_register_load(tb[NFTA_RANGE_SREG], &priv->sreg, ++ desc_from.len); + if (err < 0) + goto err2; + +diff --git a/net/netfilter/nft_redir.c b/net/netfilter/nft_redir.c +index c64cbe78dee7b..08a05bd1e8178 100644 +--- a/net/netfilter/nft_redir.c ++++ b/net/netfilter/nft_redir.c +@@ -49,19 +49,15 @@ int nft_redir_init(const struct nft_ctx *ctx, + + plen = FIELD_SIZEOF(struct nf_nat_range, min_addr.all); + if (tb[NFTA_REDIR_REG_PROTO_MIN]) { +- priv->sreg_proto_min = +- nft_parse_register(tb[NFTA_REDIR_REG_PROTO_MIN]); +- +- err = nft_validate_register_load(priv->sreg_proto_min, plen); ++ err = nft_parse_register_load(tb[NFTA_REDIR_REG_PROTO_MIN], ++ &priv->sreg_proto_min, plen); + if (err < 0) + return err; + + if (tb[NFTA_REDIR_REG_PROTO_MAX]) { +- priv->sreg_proto_max = +- nft_parse_register(tb[NFTA_REDIR_REG_PROTO_MAX]); +- +- err = nft_validate_register_load(priv->sreg_proto_max, +- plen); ++ err = nft_parse_register_load(tb[NFTA_REDIR_REG_PROTO_MAX], ++ &priv->sreg_proto_max, ++ plen); + if (err < 0) + return err; + } else { +diff --git a/net/netfilter/nft_tproxy.c b/net/netfilter/nft_tproxy.c +index a0e30bf4a845c..db780b5985abc 100644 +--- a/net/netfilter/nft_tproxy.c ++++ b/net/netfilter/nft_tproxy.c +@@ -13,9 +13,9 @@ + #endif + + struct nft_tproxy { +- enum nft_registers sreg_addr:8; +- enum nft_registers sreg_port:8; +- u8 family; ++ u8 sreg_addr; ++ u8 sreg_port; ++ u8 family; + }; + + static void nft_tproxy_eval_v4(const struct nft_expr *expr, +@@ -254,15 +254,15 @@ static int nft_tproxy_init(const struct nft_ctx *ctx, + } + + if (tb[NFTA_TPROXY_REG_ADDR]) { +- priv->sreg_addr = nft_parse_register(tb[NFTA_TPROXY_REG_ADDR]); +- err = nft_validate_register_load(priv->sreg_addr, alen); ++ err = nft_parse_register_load(tb[NFTA_TPROXY_REG_ADDR], ++ &priv->sreg_addr, alen); + if (err < 0) + return err; + } + + if (tb[NFTA_TPROXY_REG_PORT]) { +- priv->sreg_port = nft_parse_register(tb[NFTA_TPROXY_REG_PORT]); +- err = nft_validate_register_load(priv->sreg_port, sizeof(u16)); ++ err = nft_parse_register_load(tb[NFTA_TPROXY_REG_PORT], ++ &priv->sreg_port, sizeof(u16)); + if (err < 0) + return err; + } +-- +2.39.2 + diff --git a/queue-4.19/netfilter-nftables-add-nft_parse_register_store-and-.patch b/queue-4.19/netfilter-nftables-add-nft_parse_register_store-and-.patch new file mode 100644 index 00000000000..5d7219332e0 --- /dev/null +++ b/queue-4.19/netfilter-nftables-add-nft_parse_register_store-and-.patch @@ -0,0 +1,595 @@ +From c663e11f66e0903251869d9b49f11d8710d28dfe Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 16 May 2023 17:06:06 +0200 +Subject: netfilter: nftables: add nft_parse_register_store() and use it +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Pablo Neira Ayuso + +[ 345023b0db315648ccc3c1a36aee88304a8b4d91 ] + +This new function combines the netlink register attribute parser +and the store validation function. + +This update requires to replace: + + enum nft_registers dreg:8; + +in many of the expression private areas otherwise compiler complains +with: + + error: cannot take address of bit-field ‘dreg’ + +when passing the register field as reference. + +Signed-off-by: Pablo Neira Ayuso +Signed-off-by: Sasha Levin +--- + include/net/netfilter/nf_tables.h | 8 +++--- + include/net/netfilter/nf_tables_core.h | 4 +-- + include/net/netfilter/nft_fib.h | 2 +- + net/netfilter/nf_tables_api.c | 34 ++++++++++++++++++++++---- + net/netfilter/nft_bitwise.c | 8 +++--- + net/netfilter/nft_byteorder.c | 8 +++--- + net/netfilter/nft_ct.c | 7 +++--- + net/netfilter/nft_exthdr.c | 8 +++--- + net/netfilter/nft_fib.c | 5 ++-- + net/netfilter/nft_hash.c | 17 ++++++------- + net/netfilter/nft_immediate.c | 6 ++--- + net/netfilter/nft_lookup.c | 8 +++--- + net/netfilter/nft_meta.c | 7 +++--- + net/netfilter/nft_numgen.c | 15 +++++------- + net/netfilter/nft_osf.c | 8 +++--- + net/netfilter/nft_payload.c | 6 ++--- + net/netfilter/nft_rt.c | 7 +++--- + net/netfilter/nft_socket.c | 7 +++--- + net/netfilter/nft_tunnel.c | 8 +++--- + 19 files changed, 92 insertions(+), 81 deletions(-) + +diff --git a/include/net/netfilter/nf_tables.h b/include/net/netfilter/nf_tables.h +index e7b1e241f6f6e..bf957156e9b76 100644 +--- a/include/net/netfilter/nf_tables.h ++++ b/include/net/netfilter/nf_tables.h +@@ -195,10 +195,10 @@ unsigned int nft_parse_register(const struct nlattr *attr); + int nft_dump_register(struct sk_buff *skb, unsigned int attr, unsigned int reg); + + int nft_parse_register_load(const struct nlattr *attr, u8 *sreg, u32 len); +-int nft_validate_register_store(const struct nft_ctx *ctx, +- enum nft_registers reg, +- const struct nft_data *data, +- enum nft_data_types type, unsigned int len); ++int nft_parse_register_store(const struct nft_ctx *ctx, ++ const struct nlattr *attr, u8 *dreg, ++ const struct nft_data *data, ++ enum nft_data_types type, unsigned int len); + + /** + * struct nft_userdata - user defined data associated with an object +diff --git a/include/net/netfilter/nf_tables_core.h b/include/net/netfilter/nf_tables_core.h +index c81c12a825de4..6a3f76e012be3 100644 +--- a/include/net/netfilter/nf_tables_core.h ++++ b/include/net/netfilter/nf_tables_core.h +@@ -28,7 +28,7 @@ struct nft_cmp_fast_expr { + + struct nft_immediate_expr { + struct nft_data data; +- enum nft_registers dreg:8; ++ u8 dreg; + u8 dlen; + }; + +@@ -48,7 +48,7 @@ struct nft_payload { + enum nft_payload_bases base:8; + u8 offset; + u8 len; +- enum nft_registers dreg:8; ++ u8 dreg; + }; + + struct nft_payload_set { +diff --git a/include/net/netfilter/nft_fib.h b/include/net/netfilter/nft_fib.h +index a88f92737308d..1f87267395291 100644 +--- a/include/net/netfilter/nft_fib.h ++++ b/include/net/netfilter/nft_fib.h +@@ -3,7 +3,7 @@ + #define _NFT_FIB_H_ + + struct nft_fib { +- enum nft_registers dreg:8; ++ u8 dreg; + u8 result; + u32 flags; + }; +diff --git a/net/netfilter/nf_tables_api.c b/net/netfilter/nf_tables_api.c +index 3b4cb6a9e85d5..b86d9c14cbd69 100644 +--- a/net/netfilter/nf_tables_api.c ++++ b/net/netfilter/nf_tables_api.c +@@ -3687,6 +3687,12 @@ static int nf_tables_delset(struct net *net, struct sock *nlsk, + return nft_delset(&ctx, set); + } + ++static int nft_validate_register_store(const struct nft_ctx *ctx, ++ enum nft_registers reg, ++ const struct nft_data *data, ++ enum nft_data_types type, ++ unsigned int len); ++ + static int nf_tables_bind_check_setelem(const struct nft_ctx *ctx, + struct nft_set *set, + const struct nft_set_iter *iter, +@@ -7067,10 +7073,11 @@ EXPORT_SYMBOL_GPL(nft_parse_register_load); + * A value of NULL for the data means that its runtime gathered + * data. + */ +-int nft_validate_register_store(const struct nft_ctx *ctx, +- enum nft_registers reg, +- const struct nft_data *data, +- enum nft_data_types type, unsigned int len) ++static int nft_validate_register_store(const struct nft_ctx *ctx, ++ enum nft_registers reg, ++ const struct nft_data *data, ++ enum nft_data_types type, ++ unsigned int len) + { + int err; + +@@ -7102,7 +7109,24 @@ int nft_validate_register_store(const struct nft_ctx *ctx, + return 0; + } + } +-EXPORT_SYMBOL_GPL(nft_validate_register_store); ++ ++int nft_parse_register_store(const struct nft_ctx *ctx, ++ const struct nlattr *attr, u8 *dreg, ++ const struct nft_data *data, ++ enum nft_data_types type, unsigned int len) ++{ ++ int err; ++ u32 reg; ++ ++ reg = nft_parse_register(attr); ++ err = nft_validate_register_store(ctx, reg, data, type, len); ++ if (err < 0) ++ return err; ++ ++ *dreg = reg; ++ return 0; ++} ++EXPORT_SYMBOL_GPL(nft_parse_register_store); + + static const struct nla_policy nft_verdict_policy[NFTA_VERDICT_MAX + 1] = { + [NFTA_VERDICT_CODE] = { .type = NLA_U32 }, +diff --git a/net/netfilter/nft_bitwise.c b/net/netfilter/nft_bitwise.c +index 23a8a9d119876..c1055251ebdeb 100644 +--- a/net/netfilter/nft_bitwise.c ++++ b/net/netfilter/nft_bitwise.c +@@ -19,7 +19,7 @@ + + struct nft_bitwise { + u8 sreg; +- enum nft_registers dreg:8; ++ u8 dreg; + u8 len; + struct nft_data mask; + struct nft_data xor; +@@ -73,9 +73,9 @@ static int nft_bitwise_init(const struct nft_ctx *ctx, + if (err < 0) + return err; + +- priv->dreg = nft_parse_register(tb[NFTA_BITWISE_DREG]); +- err = nft_validate_register_store(ctx, priv->dreg, NULL, +- NFT_DATA_VALUE, priv->len); ++ err = nft_parse_register_store(ctx, tb[NFTA_BITWISE_DREG], ++ &priv->dreg, NULL, NFT_DATA_VALUE, ++ priv->len); + if (err < 0) + return err; + +diff --git a/net/netfilter/nft_byteorder.c b/net/netfilter/nft_byteorder.c +index c81d618137ce8..5e1fbdd7b2846 100644 +--- a/net/netfilter/nft_byteorder.c ++++ b/net/netfilter/nft_byteorder.c +@@ -20,7 +20,7 @@ + + struct nft_byteorder { + u8 sreg; +- enum nft_registers dreg:8; ++ u8 dreg; + enum nft_byteorder_ops op:8; + u8 len; + u8 size; +@@ -144,9 +144,9 @@ static int nft_byteorder_init(const struct nft_ctx *ctx, + if (err < 0) + return err; + +- priv->dreg = nft_parse_register(tb[NFTA_BYTEORDER_DREG]); +- return nft_validate_register_store(ctx, priv->dreg, NULL, +- NFT_DATA_VALUE, priv->len); ++ return nft_parse_register_store(ctx, tb[NFTA_BYTEORDER_DREG], ++ &priv->dreg, NULL, NFT_DATA_VALUE, ++ priv->len); + } + + static int nft_byteorder_dump(struct sk_buff *skb, const struct nft_expr *expr) +diff --git a/net/netfilter/nft_ct.c b/net/netfilter/nft_ct.c +index 045e350ba03ea..f29f02805bcc0 100644 +--- a/net/netfilter/nft_ct.c ++++ b/net/netfilter/nft_ct.c +@@ -29,7 +29,7 @@ struct nft_ct { + enum nft_ct_keys key:8; + enum ip_conntrack_dir dir:8; + union { +- enum nft_registers dreg:8; ++ u8 dreg; + u8 sreg; + }; + }; +@@ -486,9 +486,8 @@ static int nft_ct_get_init(const struct nft_ctx *ctx, + } + } + +- priv->dreg = nft_parse_register(tb[NFTA_CT_DREG]); +- err = nft_validate_register_store(ctx, priv->dreg, NULL, +- NFT_DATA_VALUE, len); ++ err = nft_parse_register_store(ctx, tb[NFTA_CT_DREG], &priv->dreg, NULL, ++ NFT_DATA_VALUE, len); + if (err < 0) + return err; + +diff --git a/net/netfilter/nft_exthdr.c b/net/netfilter/nft_exthdr.c +index 340520f10b686..8d0f14cd7cc3e 100644 +--- a/net/netfilter/nft_exthdr.c ++++ b/net/netfilter/nft_exthdr.c +@@ -22,7 +22,7 @@ struct nft_exthdr { + u8 offset; + u8 len; + u8 op; +- enum nft_registers dreg:8; ++ u8 dreg; + u8 sreg; + u8 flags; + }; +@@ -258,12 +258,12 @@ static int nft_exthdr_init(const struct nft_ctx *ctx, + priv->type = nla_get_u8(tb[NFTA_EXTHDR_TYPE]); + priv->offset = offset; + priv->len = len; +- priv->dreg = nft_parse_register(tb[NFTA_EXTHDR_DREG]); + priv->flags = flags; + priv->op = op; + +- return nft_validate_register_store(ctx, priv->dreg, NULL, +- NFT_DATA_VALUE, priv->len); ++ return nft_parse_register_store(ctx, tb[NFTA_EXTHDR_DREG], ++ &priv->dreg, NULL, NFT_DATA_VALUE, ++ priv->len); + } + + static int nft_exthdr_tcp_set_init(const struct nft_ctx *ctx, +diff --git a/net/netfilter/nft_fib.c b/net/netfilter/nft_fib.c +index 21df8cccea658..ce6891337304d 100644 +--- a/net/netfilter/nft_fib.c ++++ b/net/netfilter/nft_fib.c +@@ -88,7 +88,6 @@ int nft_fib_init(const struct nft_ctx *ctx, const struct nft_expr *expr, + return -EINVAL; + + priv->result = ntohl(nla_get_be32(tb[NFTA_FIB_RESULT])); +- priv->dreg = nft_parse_register(tb[NFTA_FIB_DREG]); + + switch (priv->result) { + case NFT_FIB_RESULT_OIF: +@@ -108,8 +107,8 @@ int nft_fib_init(const struct nft_ctx *ctx, const struct nft_expr *expr, + return -EINVAL; + } + +- err = nft_validate_register_store(ctx, priv->dreg, NULL, +- NFT_DATA_VALUE, len); ++ err = nft_parse_register_store(ctx, tb[NFTA_FIB_DREG], &priv->dreg, ++ NULL, NFT_DATA_VALUE, len); + if (err < 0) + return err; + +diff --git a/net/netfilter/nft_hash.c b/net/netfilter/nft_hash.c +index d08a14cfe56b7..513419aca9c66 100644 +--- a/net/netfilter/nft_hash.c ++++ b/net/netfilter/nft_hash.c +@@ -19,7 +19,7 @@ + + struct nft_jhash { + u8 sreg; +- enum nft_registers dreg:8; ++ u8 dreg; + u8 len; + bool autogen_seed:1; + u32 modulus; +@@ -65,7 +65,7 @@ static void nft_jhash_map_eval(const struct nft_expr *expr, + } + + struct nft_symhash { +- enum nft_registers dreg:8; ++ u8 dreg; + u32 modulus; + u32 offset; + struct nft_set *map; +@@ -136,8 +136,6 @@ static int nft_jhash_init(const struct nft_ctx *ctx, + if (tb[NFTA_HASH_OFFSET]) + priv->offset = ntohl(nla_get_be32(tb[NFTA_HASH_OFFSET])); + +- priv->dreg = nft_parse_register(tb[NFTA_HASH_DREG]); +- + err = nft_parse_u32_check(tb[NFTA_HASH_LEN], U8_MAX, &len); + if (err < 0) + return err; +@@ -164,8 +162,8 @@ static int nft_jhash_init(const struct nft_ctx *ctx, + get_random_bytes(&priv->seed, sizeof(priv->seed)); + } + +- return nft_validate_register_store(ctx, priv->dreg, NULL, +- NFT_DATA_VALUE, sizeof(u32)); ++ return nft_parse_register_store(ctx, tb[NFTA_HASH_DREG], &priv->dreg, ++ NULL, NFT_DATA_VALUE, sizeof(u32)); + } + + static int nft_jhash_map_init(const struct nft_ctx *ctx, +@@ -195,8 +193,6 @@ static int nft_symhash_init(const struct nft_ctx *ctx, + if (tb[NFTA_HASH_OFFSET]) + priv->offset = ntohl(nla_get_be32(tb[NFTA_HASH_OFFSET])); + +- priv->dreg = nft_parse_register(tb[NFTA_HASH_DREG]); +- + priv->modulus = ntohl(nla_get_be32(tb[NFTA_HASH_MODULUS])); + if (priv->modulus < 1) + return -ERANGE; +@@ -204,8 +200,9 @@ static int nft_symhash_init(const struct nft_ctx *ctx, + if (priv->offset + priv->modulus - 1 < priv->offset) + return -EOVERFLOW; + +- return nft_validate_register_store(ctx, priv->dreg, NULL, +- NFT_DATA_VALUE, sizeof(u32)); ++ return nft_parse_register_store(ctx, tb[NFTA_HASH_DREG], ++ &priv->dreg, NULL, NFT_DATA_VALUE, ++ sizeof(u32)); + } + + static int nft_symhash_map_init(const struct nft_ctx *ctx, +diff --git a/net/netfilter/nft_immediate.c b/net/netfilter/nft_immediate.c +index 3f6d1d2a62818..af4e2a4bce93e 100644 +--- a/net/netfilter/nft_immediate.c ++++ b/net/netfilter/nft_immediate.c +@@ -50,9 +50,9 @@ static int nft_immediate_init(const struct nft_ctx *ctx, + + priv->dlen = desc.len; + +- priv->dreg = nft_parse_register(tb[NFTA_IMMEDIATE_DREG]); +- err = nft_validate_register_store(ctx, priv->dreg, &priv->data, +- desc.type, desc.len); ++ err = nft_parse_register_store(ctx, tb[NFTA_IMMEDIATE_DREG], ++ &priv->dreg, &priv->data, desc.type, ++ desc.len); + if (err < 0) + goto err1; + +diff --git a/net/netfilter/nft_lookup.c b/net/netfilter/nft_lookup.c +index 671f124d56b34..3c380fb326511 100644 +--- a/net/netfilter/nft_lookup.c ++++ b/net/netfilter/nft_lookup.c +@@ -21,7 +21,7 @@ + struct nft_lookup { + struct nft_set *set; + u8 sreg; +- enum nft_registers dreg:8; ++ u8 dreg; + bool invert; + struct nft_set_binding binding; + }; +@@ -100,9 +100,9 @@ static int nft_lookup_init(const struct nft_ctx *ctx, + if (!(set->flags & NFT_SET_MAP)) + return -EINVAL; + +- priv->dreg = nft_parse_register(tb[NFTA_LOOKUP_DREG]); +- err = nft_validate_register_store(ctx, priv->dreg, NULL, +- set->dtype, set->dlen); ++ err = nft_parse_register_store(ctx, tb[NFTA_LOOKUP_DREG], ++ &priv->dreg, NULL, set->dtype, ++ set->dlen); + if (err < 0) + return err; + } else if (set->flags & NFT_SET_MAP) +diff --git a/net/netfilter/nft_meta.c b/net/netfilter/nft_meta.c +index 7af90ed221113..061a29bd30661 100644 +--- a/net/netfilter/nft_meta.c ++++ b/net/netfilter/nft_meta.c +@@ -30,7 +30,7 @@ + struct nft_meta { + enum nft_meta_keys key:8; + union { +- enum nft_registers dreg:8; ++ u8 dreg; + u8 sreg; + }; + }; +@@ -358,9 +358,8 @@ static int nft_meta_get_init(const struct nft_ctx *ctx, + return -EOPNOTSUPP; + } + +- priv->dreg = nft_parse_register(tb[NFTA_META_DREG]); +- return nft_validate_register_store(ctx, priv->dreg, NULL, +- NFT_DATA_VALUE, len); ++ return nft_parse_register_store(ctx, tb[NFTA_META_DREG], &priv->dreg, ++ NULL, NFT_DATA_VALUE, len); + } + + static int nft_meta_get_validate(const struct nft_ctx *ctx, +diff --git a/net/netfilter/nft_numgen.c b/net/netfilter/nft_numgen.c +index 3cc1b3dc3c3cd..8ff82f17ecba9 100644 +--- a/net/netfilter/nft_numgen.c ++++ b/net/netfilter/nft_numgen.c +@@ -20,7 +20,7 @@ + static DEFINE_PER_CPU(struct rnd_state, nft_numgen_prandom_state); + + struct nft_ng_inc { +- enum nft_registers dreg:8; ++ u8 dreg; + u32 modulus; + atomic_t counter; + u32 offset; +@@ -70,11 +70,10 @@ static int nft_ng_inc_init(const struct nft_ctx *ctx, + if (priv->offset + priv->modulus - 1 < priv->offset) + return -EOVERFLOW; + +- priv->dreg = nft_parse_register(tb[NFTA_NG_DREG]); + atomic_set(&priv->counter, priv->modulus - 1); + +- return nft_validate_register_store(ctx, priv->dreg, NULL, +- NFT_DATA_VALUE, sizeof(u32)); ++ return nft_parse_register_store(ctx, tb[NFTA_NG_DREG], &priv->dreg, ++ NULL, NFT_DATA_VALUE, sizeof(u32)); + } + + static int nft_ng_dump(struct sk_buff *skb, enum nft_registers dreg, +@@ -104,7 +103,7 @@ static int nft_ng_inc_dump(struct sk_buff *skb, const struct nft_expr *expr) + } + + struct nft_ng_random { +- enum nft_registers dreg:8; ++ u8 dreg; + u32 modulus; + u32 offset; + }; +@@ -144,10 +143,8 @@ static int nft_ng_random_init(const struct nft_ctx *ctx, + + prandom_init_once(&nft_numgen_prandom_state); + +- priv->dreg = nft_parse_register(tb[NFTA_NG_DREG]); +- +- return nft_validate_register_store(ctx, priv->dreg, NULL, +- NFT_DATA_VALUE, sizeof(u32)); ++ return nft_parse_register_store(ctx, tb[NFTA_NG_DREG], &priv->dreg, ++ NULL, NFT_DATA_VALUE, sizeof(u32)); + } + + static int nft_ng_random_dump(struct sk_buff *skb, const struct nft_expr *expr) +diff --git a/net/netfilter/nft_osf.c b/net/netfilter/nft_osf.c +index 4fac2d9a4b885..af2ce7a8c5877 100644 +--- a/net/netfilter/nft_osf.c ++++ b/net/netfilter/nft_osf.c +@@ -5,7 +5,7 @@ + #include + + struct nft_osf { +- enum nft_registers dreg:8; ++ u8 dreg; + }; + + static const struct nla_policy nft_osf_policy[NFTA_OSF_MAX + 1] = { +@@ -55,9 +55,9 @@ static int nft_osf_init(const struct nft_ctx *ctx, + if (!tb[NFTA_OSF_DREG]) + return -EINVAL; + +- priv->dreg = nft_parse_register(tb[NFTA_OSF_DREG]); +- err = nft_validate_register_store(ctx, priv->dreg, NULL, +- NFT_DATA_VALUE, NFT_OSF_MAXGENRELEN); ++ err = nft_parse_register_store(ctx, tb[NFTA_OSF_DREG], &priv->dreg, ++ NULL, NFT_DATA_VALUE, ++ NFT_OSF_MAXGENRELEN); + if (err < 0) + return err; + +diff --git a/net/netfilter/nft_payload.c b/net/netfilter/nft_payload.c +index 6c5312fecac5c..77cfd5182784f 100644 +--- a/net/netfilter/nft_payload.c ++++ b/net/netfilter/nft_payload.c +@@ -135,10 +135,10 @@ static int nft_payload_init(const struct nft_ctx *ctx, + priv->base = ntohl(nla_get_be32(tb[NFTA_PAYLOAD_BASE])); + priv->offset = ntohl(nla_get_be32(tb[NFTA_PAYLOAD_OFFSET])); + priv->len = ntohl(nla_get_be32(tb[NFTA_PAYLOAD_LEN])); +- priv->dreg = nft_parse_register(tb[NFTA_PAYLOAD_DREG]); + +- return nft_validate_register_store(ctx, priv->dreg, NULL, +- NFT_DATA_VALUE, priv->len); ++ return nft_parse_register_store(ctx, tb[NFTA_PAYLOAD_DREG], ++ &priv->dreg, NULL, NFT_DATA_VALUE, ++ priv->len); + } + + static int nft_payload_dump(struct sk_buff *skb, const struct nft_expr *expr) +diff --git a/net/netfilter/nft_rt.c b/net/netfilter/nft_rt.c +index 76dba9f6b6f62..edce109ef4b01 100644 +--- a/net/netfilter/nft_rt.c ++++ b/net/netfilter/nft_rt.c +@@ -18,7 +18,7 @@ + + struct nft_rt { + enum nft_rt_keys key:8; +- enum nft_registers dreg:8; ++ u8 dreg; + }; + + static u16 get_tcpmss(const struct nft_pktinfo *pkt, const struct dst_entry *skbdst) +@@ -134,9 +134,8 @@ static int nft_rt_get_init(const struct nft_ctx *ctx, + return -EOPNOTSUPP; + } + +- priv->dreg = nft_parse_register(tb[NFTA_RT_DREG]); +- return nft_validate_register_store(ctx, priv->dreg, NULL, +- NFT_DATA_VALUE, len); ++ return nft_parse_register_store(ctx, tb[NFTA_RT_DREG], &priv->dreg, ++ NULL, NFT_DATA_VALUE, len); + } + + static int nft_rt_get_dump(struct sk_buff *skb, +diff --git a/net/netfilter/nft_socket.c b/net/netfilter/nft_socket.c +index 4026ec38526f6..7e4f7063f4811 100644 +--- a/net/netfilter/nft_socket.c ++++ b/net/netfilter/nft_socket.c +@@ -10,7 +10,7 @@ + struct nft_socket { + enum nft_socket_keys key:8; + union { +- enum nft_registers dreg:8; ++ u8 dreg; + }; + }; + +@@ -119,9 +119,8 @@ static int nft_socket_init(const struct nft_ctx *ctx, + return -EOPNOTSUPP; + } + +- priv->dreg = nft_parse_register(tb[NFTA_SOCKET_DREG]); +- return nft_validate_register_store(ctx, priv->dreg, NULL, +- NFT_DATA_VALUE, len); ++ return nft_parse_register_store(ctx, tb[NFTA_SOCKET_DREG], &priv->dreg, ++ NULL, NFT_DATA_VALUE, len); + } + + static int nft_socket_dump(struct sk_buff *skb, +diff --git a/net/netfilter/nft_tunnel.c b/net/netfilter/nft_tunnel.c +index 3fc55c81f16ac..ab69a34210a8d 100644 +--- a/net/netfilter/nft_tunnel.c ++++ b/net/netfilter/nft_tunnel.c +@@ -14,7 +14,7 @@ + + struct nft_tunnel { + enum nft_tunnel_keys key:8; +- enum nft_registers dreg:8; ++ u8 dreg; + }; + + static void nft_tunnel_get_eval(const struct nft_expr *expr, +@@ -72,10 +72,8 @@ static int nft_tunnel_get_init(const struct nft_ctx *ctx, + return -EOPNOTSUPP; + } + +- priv->dreg = nft_parse_register(tb[NFTA_TUNNEL_DREG]); +- +- return nft_validate_register_store(ctx, priv->dreg, NULL, +- NFT_DATA_VALUE, len); ++ return nft_parse_register_store(ctx, tb[NFTA_TUNNEL_DREG], &priv->dreg, ++ NULL, NFT_DATA_VALUE, len); + } + + static int nft_tunnel_get_dump(struct sk_buff *skb, +-- +2.39.2 + diff --git a/queue-4.19/netfilter-nftables-statify-nft_parse_register.patch b/queue-4.19/netfilter-nftables-statify-nft_parse_register.patch new file mode 100644 index 00000000000..ddb8c6d0822 --- /dev/null +++ b/queue-4.19/netfilter-nftables-statify-nft_parse_register.patch @@ -0,0 +1,54 @@ +From d2723bc54c1a9e00597d17290a9908a24c7ef6ab Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 16 May 2023 17:06:07 +0200 +Subject: netfilter: nftables: statify nft_parse_register() + +From: Pablo Neira Ayuso + +[ 08a01c11a5bb3de9b0a9c9b2685867e50eda9910 ] + +This function is not used anymore by any extension, statify it. + +Signed-off-by: Pablo Neira Ayuso +Signed-off-by: Sasha Levin +--- + include/net/netfilter/nf_tables.h | 1 - + net/netfilter/nf_tables_api.c | 3 +-- + 2 files changed, 1 insertion(+), 3 deletions(-) + +diff --git a/include/net/netfilter/nf_tables.h b/include/net/netfilter/nf_tables.h +index bf957156e9b76..2cd847212a048 100644 +--- a/include/net/netfilter/nf_tables.h ++++ b/include/net/netfilter/nf_tables.h +@@ -191,7 +191,6 @@ static inline enum nft_registers nft_type_to_reg(enum nft_data_types type) + } + + int nft_parse_u32_check(const struct nlattr *attr, int max, u32 *dest); +-unsigned int nft_parse_register(const struct nlattr *attr); + int nft_dump_register(struct sk_buff *skb, unsigned int attr, unsigned int reg); + + int nft_parse_register_load(const struct nlattr *attr, u8 *sreg, u32 len); +diff --git a/net/netfilter/nf_tables_api.c b/net/netfilter/nf_tables_api.c +index b86d9c14cbd69..dacdb1feb2e9a 100644 +--- a/net/netfilter/nf_tables_api.c ++++ b/net/netfilter/nf_tables_api.c +@@ -6987,7 +6987,7 @@ EXPORT_SYMBOL_GPL(nft_parse_u32_check); + * Registers used to be 128 bit wide, these register numbers will be + * mapped to the corresponding 32 bit register numbers. + */ +-unsigned int nft_parse_register(const struct nlattr *attr) ++static unsigned int nft_parse_register(const struct nlattr *attr) + { + unsigned int reg; + +@@ -6999,7 +6999,6 @@ unsigned int nft_parse_register(const struct nlattr *attr) + return reg + NFT_REG_SIZE / NFT_REG32_SIZE - NFT_REG32_00; + } + } +-EXPORT_SYMBOL_GPL(nft_parse_register); + + /** + * nft_dump_register - dump a register value to a netlink attribute +-- +2.39.2 + diff --git a/queue-4.19/series b/queue-4.19/series index 85b2110bb6f..1da2d9ae148 100644 --- a/queue-4.19/series +++ b/queue-4.19/series @@ -73,3 +73,12 @@ serial-add-support-for-advantech-pci-1611u-card.patch ceph-force-updating-the-msg-pointer-in-non-split-case.patch tpm-tpm_tis-disable-interrupts-for-more-lenovo-devices.patch nilfs2-fix-use-after-free-bug-of-nilfs_root-in-nilfs_evict_inode.patch +netfilter-nftables-add-nft_parse_register_load-and-u.patch +netfilter-nftables-add-nft_parse_register_store-and-.patch +netfilter-nftables-statify-nft_parse_register.patch +netfilter-nf_tables-validate-registers-coming-from-u.patch +netfilter-nf_tables-add-nft_setelem_parse_key.patch +netfilter-nf_tables-allow-up-to-64-bytes-in-the-set-.patch +netfilter-nf_tables-stricter-validation-of-element-d.patch +netfilter-nf_tables-validate-nfta_set_elem_objref-ba.patch +netfilter-nf_tables-do-not-allow-rule_id-to-refer-to.patch