Blame SOURCES/CVE-2023-32233-full.patch

f1789a
From 432fd316587463b7ecb99dd24807776bea6f3c22 Mon Sep 17 00:00:00 2001
f1789a
From: Joe Lawrence <joe.lawrence@redhat.com>
f1789a
Date: Thu, 10 Aug 2023 15:16:18 -0400
f1789a
Subject: [KPATCH CVE-2023-32233] kpatch fixes for CVE-2023-32233
f1789a
f1789a
Kernels:
f1789a
3.10.0-1160.83.1.el7
f1789a
3.10.0-1160.88.1.el7
f1789a
3.10.0-1160.90.1.el7
f1789a
3.10.0-1160.92.1.el7
f1789a
f1789a
f1789a
Kpatch-MR: https://gitlab.com/redhat/prdsc/rhel/src/kpatch/rhel-7/-/merge_requests/58
f1789a
Approved-by: Yannick Cote (@ycote1)
f1789a
Changes since last build:
f1789a
[x86_64]:
f1789a
cls_u32.o: changed function: u32_set_parms.isra.21
f1789a
nf_tables_api.o: changed function: nf_tables_newsetelem
f1789a
nf_tables_api.o: changed function: nf_tables_set_lookup
f1789a
nf_tables_api.o: changed function: nf_tables_set_lookup_byid
f1789a
nft_byteorder.o: changed function: nft_byteorder_eval
f1789a
nft_dynset.o: changed function: nft_dynset_init
f1789a
nft_lookup.o: changed function: nft_lookup_init
f1789a
f1789a
[ppc64le]:
f1789a
cls_u32.o: changed function: u32_set_parms.isra.21
f1789a
nf_tables_api.o: changed function: nf_tables_delset
f1789a
nf_tables_api.o: changed function: nf_tables_dump_set
f1789a
nf_tables_api.o: changed function: nf_tables_getset
f1789a
nf_tables_api.o: changed function: nf_tables_getsetelem
f1789a
nf_tables_api.o: changed function: nf_tables_newsetelem
f1789a
nf_tables_api.o: changed function: nf_tables_set_lookup
f1789a
nf_tables_api.o: changed function: nf_tables_set_lookup_byid
f1789a
nft_byteorder.o: changed function: nft_byteorder_eval
f1789a
nft_dynset.o: changed function: nft_dynset_init
f1789a
nft_lookup.o: changed function: nft_lookup_init
f1789a
f1789a
---------------------------
f1789a
f1789a
Modifications:
f1789a
- Use KLP_CVE_2023_32233 shadow variable for set->removed
f1789a
- For ppc64le, add -fno-optimize-sibling-calls attribute for
f1789a
  nf_tables_api.c :: nf_tables_getsetelem()
f1789a
f1789a
commit cde71785485c5f12520ed90f93e3e2f78270a7b7
f1789a
Author: Florian Westphal <fwestpha@redhat.com>
f1789a
Date:   Thu Jul 13 16:10:39 2023 +0200
f1789a
f1789a
    netfilter: nf_tables: do not allow SET_ID to refer to another table
f1789a
f1789a
    Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=2196159
f1789a
    Upstream Status: commit 470ee20e069a6
f1789a
f1789a
    Conflicts:
f1789a
    net/netfilter/nf_tables_api.c
f1789a
f1789a
    We lack commit 6ab3443e9e796 ("netfilter: nf_tables: pass ctx to nf_tables_expr_destroy()"),
f1789a
    which added the "nft_table" pointer to struct nft_set.
f1789a
    We can't easily pick this one up becaue it makes the kabi checker trip over
f1789a
    the nft_set layout change, and RH_KABI_EXTEND can't be used at the structures
f1789a
    end because nft_set last member is a VLA.
f1789a
f1789a
    Fortunately we can work around it by changing
f1789a
    "set->table" to "trans->ctx.table", we only need this check in the transaction phase.
f1789a
f1789a
    commit 470ee20e069a6d05ae549f7d0ef2bdbcee6a81b2
f1789a
    Author: Thadeu Lima de Souza Cascardo <cascardo@canonical.com>
f1789a
    Date:   Tue Aug 9 14:01:46 2022 -0300
f1789a
f1789a
        netfilter: nf_tables: do not allow SET_ID to refer to another table
f1789a
f1789a
        When doing lookups for sets on the same batch by using its ID, a set from a
f1789a
        different table can be used.
f1789a
f1789a
        Then, when the table is removed, a reference to the set may be kept after
f1789a
        the set is freed, leading to a potential use-after-free.
f1789a
f1789a
        When looking for sets by ID, use the table that was used for the lookup by
f1789a
        name, and only return sets belonging to that same table.
f1789a
f1789a
        This fixes CVE-2022-2586, also reported as ZDI-CAN-17470.
f1789a
f1789a
        Reported-by: Team Orca of Sea Security (@seasecresponse)
f1789a
        Fixes: 958bee14d071 ("netfilter: nf_tables: use new transaction infrastructure to handle sets")
f1789a
        Signed-off-by: Thadeu Lima de Souza Cascardo <cascardo@canonical.com>
f1789a
        Cc: <stable@vger.kernel.org>
f1789a
        Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
f1789a
f1789a
    Signed-off-by: Florian Westphal <fwestpha@redhat.com>
f1789a
f1789a
commit 6a38a385344448ab2f4e68e833fcf9a7e3d62128
f1789a
Author: Florian Westphal <fwestpha@redhat.com>
f1789a
Date:   Thu Jul 13 16:11:38 2023 +0200
f1789a
f1789a
    netfilter: nf_tables: skip deactivated anonymous sets during lookups
f1789a
f1789a
    Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=2196159
f1789a
    Upstream Status: RHEL7 only
f1789a
    CVE: CVE-2023-32233
f1789a
f1789a
    The fix for the above CVE was incomplete in *RHEL7*.
f1789a
    its not enough to check if the set is scheduled for removal when
f1789a
    an element is supposed to be deleted, this check needs to be done
f1789a
    for all other element operations too, e.g. when an element is
f1789a
    supposed to be *added* to a set.
f1789a
f1789a
    Move the check to the two functions that do the set lookup.
f1789a
    sets that are scheduled for removal/pending in the transaction
f1789a
    are no longer found if they have the "removed" bit set.
f1789a
f1789a
    Fixes: ffb7eb4b21c69 ("netfilter: nf_tables: deactivate anonymous set from preparation phase")
f1789a
    Reported-by: Phil Sutter <psutter@redhat.com>
f1789a
    Signed-off-by: Florian Westphal <fwestpha@redhat.com>
f1789a
f1789a
Signed-off-by: Joe Lawrence <joe.lawrence@redhat.com>
f1789a
---
f1789a
 include/net/netfilter/nf_tables.h |  1 +
f1789a
 net/netfilter/nf_tables_api.c     | 40 +++++++++++++++++++++++--------
f1789a
 net/netfilter/nft_dynset.c        |  1 +
f1789a
 net/netfilter/nft_lookup.c        |  1 +
f1789a
 4 files changed, 33 insertions(+), 10 deletions(-)
f1789a
f1789a
diff --git a/include/net/netfilter/nf_tables.h b/include/net/netfilter/nf_tables.h
f1789a
index 2ea0683b5860..3e356aba44ea 100644
f1789a
--- a/include/net/netfilter/nf_tables.h
f1789a
+++ b/include/net/netfilter/nf_tables.h
f1789a
@@ -390,6 +390,7 @@ static inline struct nft_set *nft_set_container_of(const void *priv)
f1789a
 struct nft_set *nf_tables_set_lookup(const struct nft_table *table,
f1789a
 				     const struct nlattr *nla);
f1789a
 struct nft_set *nf_tables_set_lookup_byid(const struct net *net,
f1789a
+					  const struct nft_table *table,
f1789a
 					  const struct nlattr *nla);
f1789a
 
f1789a
 static inline unsigned long nft_set_gc_interval(const struct nft_set *set)
f1789a
diff --git a/net/netfilter/nf_tables_api.c b/net/netfilter/nf_tables_api.c
f1789a
index feff3b92a617..ed8a787ac400 100644
f1789a
--- a/net/netfilter/nf_tables_api.c
f1789a
+++ b/net/netfilter/nf_tables_api.c
f1789a
@@ -2450,22 +2450,45 @@ struct nft_set *nf_tables_set_lookup(const struct nft_table *table,
f1789a
 		return ERR_PTR(-EINVAL);
f1789a
 
f1789a
 	list_for_each_entry(set, &table->sets, list) {
f1789a
-		if (!nla_strcmp(nla, set->name))
f1789a
-			return set;
f1789a
+
f1789a
+		u16 *klp_removed;
f1789a
+
f1789a
+		klp_removed = klp_shadow_get(set, KLP_CVE_2023_32233);
f1789a
+		if (klp_removed) {
f1789a
+			if (!nla_strcmp(nla, set->name) && !(*klp_removed))
f1789a
+				return set;
f1789a
+		} else {
f1789a
+			if (!nla_strcmp(nla, set->name))
f1789a
+				return set;
f1789a
+		}
f1789a
 	}
f1789a
 	return ERR_PTR(-ENOENT);
f1789a
 }
f1789a
 
f1789a
 struct nft_set *nf_tables_set_lookup_byid(const struct net *net,
f1789a
+					  const struct nft_table *table,
f1789a
 					  const struct nlattr *nla)
f1789a
 {
f1789a
 	struct nft_trans *trans;
f1789a
 	u32 id = ntohl(nla_get_be32(nla));
f1789a
 
f1789a
 	list_for_each_entry(trans, &net->nft.commit_list, list) {
f1789a
-		if (trans->msg_type == NFT_MSG_NEWSET &&
f1789a
-		    id == nft_trans_set_id(trans))
f1789a
-			return nft_trans_set(trans);
f1789a
+		if (trans->msg_type == NFT_MSG_NEWSET) {
f1789a
+			struct nft_set *set = nft_trans_set(trans);
f1789a
+			u16 *klp_removed;
f1789a
+			klp_removed = klp_shadow_get(set, KLP_CVE_2023_32233);
f1789a
+
f1789a
+			if (klp_removed) {
f1789a
+				if (id == nft_trans_set_id(trans) &&
f1789a
+				    trans->ctx.table == table &&
f1789a
+				    !(*klp_removed))
f1789a
+					return set;
f1789a
+			} else {
f1789a
+				if (id == nft_trans_set_id(trans) &&
f1789a
+				    trans->ctx.table == table)
f1789a
+					return set;
f1789a
+			}
f1789a
+		}
f1789a
 	}
f1789a
 	return ERR_PTR(-ENOENT);
f1789a
 }
f1789a
@@ -3335,6 +3358,7 @@ nla_put_failure:
f1789a
 	return -ENOSPC;
f1789a
 }
f1789a
 
f1789a
+__attribute__((optimize("-fno-optimize-sibling-calls")))
f1789a
 static int nf_tables_getsetelem(struct sock *nlsk, struct sk_buff *skb,
f1789a
 				const struct nlmsghdr *nlh,
f1789a
 				const struct nlattr * const nla[])
f1789a
@@ -3680,6 +3704,7 @@ static int nf_tables_newsetelem(struct net *net, struct sock *nlsk,
f1789a
 	if (IS_ERR(set)) {
f1789a
 		if (nla[NFTA_SET_ELEM_LIST_SET_ID]) {
f1789a
 			set = nf_tables_set_lookup_byid(net,
f1789a
+					ctx.table,
f1789a
 					nla[NFTA_SET_ELEM_LIST_SET_ID]);
f1789a
 		}
f1789a
 		if (IS_ERR(set))
f1789a
@@ -3791,7 +3816,6 @@ static int nf_tables_delsetelem(struct net *net, struct sock *nlsk,
f1789a
 	struct nft_set *set;
f1789a
 	struct nft_ctx ctx;
f1789a
 	int rem, err = 0;
f1789a
-	u16 *klp_removed;
f1789a
 
f1789a
 	err = nft_ctx_init_from_elemattr(&ctx, net, skb, nlh, nla);
f1789a
 	if (err < 0)
f1789a
@@ -3803,10 +3827,6 @@ static int nf_tables_delsetelem(struct net *net, struct sock *nlsk,
f1789a
 	if (!list_empty(&set->bindings) && set->flags & NFT_SET_CONSTANT)
f1789a
 		return -EBUSY;
f1789a
 
f1789a
-	klp_removed = klp_shadow_get(set, KLP_CVE_2023_32233);
f1789a
-	if (klp_removed && *klp_removed)
f1789a
-		return -ENOENT;
f1789a
-
f1789a
 	if (nla[NFTA_SET_ELEM_LIST_ELEMENTS] == NULL) {
f1789a
 		struct nft_set_dump_args args = {
f1789a
 			.iter	= {
f1789a
diff --git a/net/netfilter/nft_dynset.c b/net/netfilter/nft_dynset.c
f1789a
index 4d6d3af26a5b..211e5beab83f 100644
f1789a
--- a/net/netfilter/nft_dynset.c
f1789a
+++ b/net/netfilter/nft_dynset.c
f1789a
@@ -119,6 +119,7 @@ static int nft_dynset_init(const struct nft_ctx *ctx,
f1789a
 	if (IS_ERR(set)) {
f1789a
 		if (tb[NFTA_DYNSET_SET_ID])
f1789a
 			set = nf_tables_set_lookup_byid(ctx->net,
f1789a
+							ctx->table,
f1789a
 							tb[NFTA_DYNSET_SET_ID]);
f1789a
 		if (IS_ERR(set))
f1789a
 			return PTR_ERR(set);
f1789a
diff --git a/net/netfilter/nft_lookup.c b/net/netfilter/nft_lookup.c
f1789a
index ab98a5cb7128..63eff5caae5a 100644
f1789a
--- a/net/netfilter/nft_lookup.c
f1789a
+++ b/net/netfilter/nft_lookup.c
f1789a
@@ -74,6 +74,7 @@ static int nft_lookup_init(const struct nft_ctx *ctx,
f1789a
 	if (IS_ERR(set)) {
f1789a
 		if (tb[NFTA_LOOKUP_SET_ID]) {
f1789a
 			set = nf_tables_set_lookup_byid(ctx->net,
f1789a
+							ctx->table,
f1789a
 							tb[NFTA_LOOKUP_SET_ID]);
f1789a
 		}
f1789a
 		if (IS_ERR(set))
f1789a
-- 
f1789a
2.40.1
f1789a
f1789a