Blob Blame History Raw
From e34e7e4a82e772c705bacee9ef5b63fec54e729c Mon Sep 17 00:00:00 2001
From: Yannick Cote <ycote@redhat.com>
Date: Tue, 29 Mar 2022 13:21:16 -0400
Subject: [KPATCH CVE-2022-25636] netfilter: kpatch fixes for CVE-2022-25636

Kernels:
4.18.0-348.el8
4.18.0-348.2.1.el8_5
4.18.0-348.7.1.el8_5
4.18.0-348.12.2.el8_5
4.18.0-348.20.1.el8_5


Kpatch-MR: https://gitlab.com/redhat/prdsc/rhel/src/kpatch/rhel-8/-/merge_requests/45
Approved-by: Joe Lawrence (@joe.lawrence)
Changes since last build:
[x86_64]:
cma.o: changed function: rdma_listen
nf_tables_api.o: changed function: __nf_tables_abort
nf_tables_api.o: changed function: __nft_release_basechain
nf_tables_api.o: changed function: nf_tables_commit
nf_tables_api.o: changed function: nf_tables_exit_net
nf_tables_api.o: changed function: nf_tables_newrule
nf_tables_api.o: changed function: nf_tables_rule_destroy
nf_tables_api.o: changed function: nft_delrule
nf_tables_api.o: new function: nft_rule_expr_deactivate
nf_tables_offload.o: changed function: nft_flow_rule_create

[ppc64le]:
cma.o: changed function: rdma_listen
nf_tables_api.o: changed function: __nf_tables_abort
nf_tables_api.o: changed function: __nft_release_basechain
nf_tables_api.o: changed function: nf_tables_commit
nf_tables_api.o: changed function: nf_tables_exit_net
nf_tables_api.o: changed function: nf_tables_newrule
nf_tables_api.o: changed function: nf_tables_trans_destroy_work
nf_tables_api.o: changed function: nft_delrule
nf_tables_offload.o: changed function: nft_flow_rule_create

---------------------------

Modifications:
- Simplify code to fixing the vulnerability root cause.
- For this, replace (netfilter: nf_tables_offload: incorrect flow
offload action array size) with localized code to make sure that
'forward' and 'dup' rules (all types really) act as having the
NFT_OFFLOAD_F_ACTION flag set.

commit 9a8d76cbd3d4321f2207bc89fdf0029fe2de3705
Author: Florian Westphal <fwestpha@redhat.com>
Date:   Tue Feb 22 00:40:19 2022 +0100

    netfilter: nftables_offload: KASAN slab-out-of-bounds Read in nft_flow_rule_create

    Bugzilla: https://bugzilla.redhat.com/2056866
    Y-Commit: c8c8daf989226dca2bab98b8c408a4967e24926d

    O-Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=2056728
    Upstream Status: commit 31cc578ae2de

    commit 31cc578ae2de19c748af06d859019dced68e325d
    Author: Saeed Mirzamohammadi <saeed.mirzamohammadi@oracle.com>
    Date:   Tue Oct 20 13:41:36 2020 +0200

        netfilter: nftables_offload: KASAN slab-out-of-bounds Read in nft_flow_rule_create

        This patch fixes the issue due to:

        BUG: KASAN: slab-out-of-bounds in nft_flow_rule_create+0x622/0x6a2
        net/netfilter/nf_tables_offload.c:40
        Read of size 8 at addr ffff888103910b58 by task syz-executor227/16244

        The error happens when expr->ops is accessed early on before performing the boundary check and after nft_expr_next() moves the expr to go out-of-bounds.

        This patch checks the boundary condition before expr->ops that fixes the slab-out-of-bounds Read issue.

        Add nft_expr_more() and use it to fix this problem.

        Signed-off-by: Saeed Mirzamohammadi <saeed.mirzamohammadi@oracle.com>
        Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>

    Signed-off-by: Florian Westphal <fwestpha@redhat.com>
    Signed-off-by: Patrick Talbert <ptalbert@redhat.com>

commit bd5cf01bee78b2d9c5356021d7f9bfed8d0cbe27
Author: Florian Westphal <fwestpha@redhat.com>
Date:   Tue Feb 22 00:40:20 2022 +0100

    netfilter: nf_tables_offload: incorrect flow offload action array size

    Bugzilla: https://bugzilla.redhat.com/2056866
    CVE: CVE-2022-25636
    Y-Commit: fa41e65b922a9f624d51fdd9f698c096e340a6b7

    O-Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=2056728
    O-CVE: CVE-2022-25636
    Upstream Status: nf.git commit b1a5983f56e3

    Conflicts:
            include/net/netfilter/nf_tables.h

    Context only, RHEL8 lacks the offload_stats callback.

    commit b1a5983f56e371046dcf164f90bfaf704d2b89f6
    Author: Pablo Neira Ayuso <pablo@netfilter.org>
    Date:   Thu Feb 17 23:41:20 2022 +0100

        netfilter: nf_tables_offload: incorrect flow offload action array size

        immediate verdict expression needs to allocate one slot in the flow offload
        action array, however, immediate data expression does not need to do so.

        fwd and dup expression need to allocate one slot, this is missing.

        Add a new offload_action interface to report if this expression needs to
        allocate one slot in the flow offload action array.

        Fixes: be2861dc36d7 ("netfilter: nft_{fwd,dup}_netdev: add offload support")
        Reported-and-tested-by: Nick Gregory <Nick.Gregory@Sophos.com>
        Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>

    Signed-off-by: Florian Westphal <fwestpha@redhat.com>
    Signed-off-by: Patrick Talbert <ptalbert@redhat.com>

Signed-off-by: Yannick Cote <ycote@redhat.com>
---
 include/net/netfilter/nf_tables.h | 6 ++++++
 net/netfilter/nf_tables_api.c     | 6 +++---
 net/netfilter/nf_tables_offload.c | 6 +++---
 3 files changed, 12 insertions(+), 6 deletions(-)

diff --git a/include/net/netfilter/nf_tables.h b/include/net/netfilter/nf_tables.h
index aa5b025771b4..2f6d9959d695 100644
--- a/include/net/netfilter/nf_tables.h
+++ b/include/net/netfilter/nf_tables.h
@@ -896,6 +896,12 @@ static inline struct nft_expr *nft_expr_last(const struct nft_rule *rule)
 	return (struct nft_expr *)&rule->data[rule->dlen];
 }
 
+static inline bool nft_expr_more(const struct nft_rule *rule,
+				 const struct nft_expr *expr)
+{
+	return expr != nft_expr_last(rule) && expr->ops;
+}
+
 static inline struct nft_userdata *nft_userdata(const struct nft_rule *rule)
 {
 	return (void *)&rule->data[rule->dlen];
diff --git a/net/netfilter/nf_tables_api.c b/net/netfilter/nf_tables_api.c
index 353201d81205..9620daa81a15 100644
--- a/net/netfilter/nf_tables_api.c
+++ b/net/netfilter/nf_tables_api.c
@@ -335,7 +335,7 @@ static void nft_rule_expr_activate(const struct nft_ctx *ctx,
 	struct nft_expr *expr;
 
 	expr = nft_expr_first(rule);
-	while (expr != nft_expr_last(rule) && expr->ops) {
+	while (nft_expr_more(rule, expr)) {
 		if (expr->ops->activate)
 			expr->ops->activate(ctx, expr);
 
@@ -350,7 +350,7 @@ static void nft_rule_expr_deactivate(const struct nft_ctx *ctx,
 	struct nft_expr *expr;
 
 	expr = nft_expr_first(rule);
-	while (expr != nft_expr_last(rule) && expr->ops) {
+	while (nft_expr_more(rule, expr)) {
 		if (expr->ops->deactivate)
 			expr->ops->deactivate(ctx, expr, phase);
 
@@ -2951,7 +2951,7 @@ static void nf_tables_rule_destroy(const struct nft_ctx *ctx,
 	 * is called on error from nf_tables_newrule().
 	 */
 	expr = nft_expr_first(rule);
-	while (expr != nft_expr_last(rule) && expr->ops) {
+	while (nft_expr_more(rule, expr)) {
 		next = nft_expr_next(expr);
 		nf_tables_expr_destroy(ctx, expr);
 		expr = next;
diff --git a/net/netfilter/nf_tables_offload.c b/net/netfilter/nf_tables_offload.c
index 499e5c51da22..091640fcc2f6 100644
--- a/net/netfilter/nf_tables_offload.c
+++ b/net/netfilter/nf_tables_offload.c
@@ -93,8 +93,8 @@ struct nft_flow_rule *nft_flow_rule_create(struct net *net,
 	struct nft_expr *expr;
 
 	expr = nft_expr_first(rule);
-	while (expr->ops && expr != nft_expr_last(rule)) {
-		if (expr->ops->offload_flags & NFT_OFFLOAD_F_ACTION)
+	while (nft_expr_more(rule, expr)) {
+		if (expr->ops->offload)
 			num_actions++;
 
 		expr = nft_expr_next(expr);
@@ -117,7 +117,7 @@ struct nft_flow_rule *nft_flow_rule_create(struct net *net,
 	ctx->net = net;
 	ctx->dep.type = NFT_OFFLOAD_DEP_UNSPEC;
 
-	while (expr->ops && expr != nft_expr_last(rule)) {
+	while (nft_expr_more(rule, expr)) {
 		if (!expr->ops->offload) {
 			err = -EOPNOTSUPP;
 			goto err_out;
-- 
2.34.1