0b62bd
From b29c457a6511435960115c0f548c4360d5f4801d Mon Sep 17 00:00:00 2001
0b62bd
From: Florian Westphal <fw@strlen.de>
0b62bd
Date: Wed, 7 Apr 2021 21:38:57 +0200
0b62bd
Subject: [PATCH] netfilter: x_tables: fix compat match/target pad out-of-bound
0b62bd
 write
0b62bd
Git-commit: b29c457a6511435960115c0f548c4360d5f4801d
0b62bd
Patch-mainline: v5.12-rc8
0b62bd
References: CVE-2021-22555 bsc#1188116
0b62bd
0b62bd
xt_compat_match/target_from_user doesn't check that zeroing the area
0b62bd
to start of next rule won't write past end of allocated ruleset blob.
0b62bd
0b62bd
Remove this code and zero the entire blob beforehand.
0b62bd
0b62bd
Reported-by: syzbot+cfc0247ac173f597aaaa@syzkaller.appspotmail.com
0b62bd
Reported-by: Andy Nguyen <theflow@google.com>
0b62bd
Fixes: 9fa492cdc160c ("[NETFILTER]: x_tables: simplify compat API")
0b62bd
Signed-off-by: Florian Westphal <fw@strlen.de>
0b62bd
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
0b62bd
Acked-by: Denis Kirjanov <denis.kirjanov@suse.com>
0b62bd
---
0b62bd
 net/ipv4/netfilter/arp_tables.c |  2 ++
0b62bd
 net/ipv4/netfilter/ip_tables.c  |  2 ++
0b62bd
 net/ipv6/netfilter/ip6_tables.c |  2 ++
0b62bd
 net/netfilter/x_tables.c        | 10 ++--------
0b62bd
 4 files changed, 8 insertions(+), 8 deletions(-)
0b62bd
0b62bd
diff --git a/net/ipv4/netfilter/arp_tables.c b/net/ipv4/netfilter/arp_tables.c
0b62bd
index 6c26533480dd..d6d45d820d79 100644
0b62bd
--- a/net/ipv4/netfilter/arp_tables.c
0b62bd
+++ b/net/ipv4/netfilter/arp_tables.c
0b62bd
@@ -1193,6 +1193,8 @@ static int translate_compat_table(struct net *net,
0b62bd
 	if (!newinfo)
0b62bd
 		goto out_unlock;
0b62bd
 
0b62bd
+	memset(newinfo->entries, 0, size);
0b62bd
+
0b62bd
 	newinfo->number = compatr->num_entries;
0b62bd
 	for (i = 0; i < NF_ARP_NUMHOOKS; i++) {
0b62bd
 		newinfo->hook_entry[i] = compatr->hook_entry[i];
0b62bd
diff --git a/net/ipv4/netfilter/ip_tables.c b/net/ipv4/netfilter/ip_tables.c
0b62bd
index f15bc21d7301..f77ea0dbe656 100644
0b62bd
--- a/net/ipv4/netfilter/ip_tables.c
0b62bd
+++ b/net/ipv4/netfilter/ip_tables.c
0b62bd
@@ -1428,6 +1428,8 @@ translate_compat_table(struct net *net,
0b62bd
 	if (!newinfo)
0b62bd
 		goto out_unlock;
0b62bd
 
0b62bd
+	memset(newinfo->entries, 0, size);
0b62bd
+
0b62bd
 	newinfo->number = compatr->num_entries;
0b62bd
 	for (i = 0; i < NF_INET_NUMHOOKS; i++) {
0b62bd
 		newinfo->hook_entry[i] = compatr->hook_entry[i];
0b62bd
diff --git a/net/ipv6/netfilter/ip6_tables.c b/net/ipv6/netfilter/ip6_tables.c
0b62bd
index 2e2119bfcf13..eb2b5404806c 100644
0b62bd
--- a/net/ipv6/netfilter/ip6_tables.c
0b62bd
+++ b/net/ipv6/netfilter/ip6_tables.c
0b62bd
@@ -1443,6 +1443,8 @@ translate_compat_table(struct net *net,
0b62bd
 	if (!newinfo)
0b62bd
 		goto out_unlock;
0b62bd
 
0b62bd
+	memset(newinfo->entries, 0, size);
0b62bd
+
0b62bd
 	newinfo->number = compatr->num_entries;
0b62bd
 	for (i = 0; i < NF_INET_NUMHOOKS; i++) {
0b62bd
 		newinfo->hook_entry[i] = compatr->hook_entry[i];
0b62bd
diff --git a/net/netfilter/x_tables.c b/net/netfilter/x_tables.c
0b62bd
index 6bd31a7a27fc..92e9d4ebc5e8 100644
0b62bd
--- a/net/netfilter/x_tables.c
0b62bd
+++ b/net/netfilter/x_tables.c
0b62bd
@@ -733,7 +733,7 @@ void xt_compat_match_from_user(struct xt_entry_match *m, void **dstptr,
0b62bd
 {
0b62bd
 	const struct xt_match *match = m->u.kernel.match;
0b62bd
 	struct compat_xt_entry_match *cm = (struct compat_xt_entry_match *)m;
0b62bd
-	int pad, off = xt_compat_match_offset(match);
0b62bd
+	int off = xt_compat_match_offset(match);
0b62bd
 	u_int16_t msize = cm->u.user.match_size;
0b62bd
 	char name[sizeof(m->u.user.name)];
0b62bd
 
0b62bd
@@ -743,9 +743,6 @@ void xt_compat_match_from_user(struct xt_entry_match *m, void **dstptr,
0b62bd
 		match->compat_from_user(m->data, cm->data);
0b62bd
 	else
0b62bd
 		memcpy(m->data, cm->data, msize - sizeof(*cm));
0b62bd
-	pad = XT_ALIGN(match->matchsize) - match->matchsize;
0b62bd
-	if (pad > 0)
0b62bd
-		memset(m->data + match->matchsize, 0, pad);
0b62bd
 
0b62bd
 	msize += off;
0b62bd
 	m->u.user.match_size = msize;
0b62bd
@@ -1116,7 +1113,7 @@ void xt_compat_target_from_user(struct xt_entry_target *t, void **dstptr,
0b62bd
 {
0b62bd
 	const struct xt_target *target = t->u.kernel.target;
0b62bd
 	struct compat_xt_entry_target *ct = (struct compat_xt_entry_target *)t;
0b62bd
-	int pad, off = xt_compat_target_offset(target);
0b62bd
+	int off = xt_compat_target_offset(target);
0b62bd
 	u_int16_t tsize = ct->u.user.target_size;
0b62bd
 	char name[sizeof(t->u.user.name)];
0b62bd
 
0b62bd
@@ -1126,9 +1123,6 @@ void xt_compat_target_from_user(struct xt_entry_target *t, void **dstptr,
0b62bd
 		target->compat_from_user(t->data, ct->data);
0b62bd
 	else
0b62bd
 		memcpy(t->data, ct->data, tsize - sizeof(*ct));
0b62bd
-	pad = XT_ALIGN(target->targetsize) - target->targetsize;
0b62bd
-	if (pad > 0)
0b62bd
-		memset(t->data + target->targetsize, 0, pad);
0b62bd
 
0b62bd
 	tsize += off;
0b62bd
 	t->u.user.target_size = tsize;
0b62bd
-- 
0b62bd
2.16.4
0b62bd