diff mbox series

[SRU,B,F,G,H,1/1] netfilter: x_tables: fix compat match/target pad out-of-bound write

Message ID 20210507061041.25365-1-khalid.elmously@canonical.com
State New
Headers show
Series [SRU,B,F,G,H,1/1] netfilter: x_tables: fix compat match/target pad out-of-bound write | expand

Commit Message

Khalid Elmously May 7, 2021, 6:10 a.m. UTC
From: Florian Westphal <fw@strlen.de>

BugLink: https://bugs.launchpad.net/bugs/1927682

xt_compat_match/target_from_user doesn't check that zeroing the area
to start of next rule won't write past end of allocated ruleset blob.

Remove this code and zero the entire blob beforehand.

Reported-by: syzbot+cfc0247ac173f597aaaa@syzkaller.appspotmail.com
Reported-by: Andy Nguyen <theflow@google.com>
Fixes: 9fa492cdc160c ("[NETFILTER]: x_tables: simplify compat API")
Signed-off-by: Florian Westphal <fw@strlen.de>
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
(cherry picked from commit b29c457a6511435960115c0f548c4360d5f4801d)
Signed-off-by: Khalid Elmously <khalid.elmously@canonical.com>
---
 net/ipv4/netfilter/arp_tables.c |  2 ++
 net/ipv4/netfilter/ip_tables.c  |  2 ++
 net/ipv6/netfilter/ip6_tables.c |  2 ++
 net/netfilter/x_tables.c        | 10 ++--------
 4 files changed, 8 insertions(+), 8 deletions(-)

Comments

Stefan Bader May 7, 2021, 8:05 a.m. UTC | #1
On 07.05.21 08:10, Khalid Elmously wrote:
> From: Florian Westphal <fw@strlen.de>
> 
> BugLink: https://bugs.launchpad.net/bugs/1927682
> 
> xt_compat_match/target_from_user doesn't check that zeroing the area
> to start of next rule won't write past end of allocated ruleset blob.
> 
> Remove this code and zero the entire blob beforehand.
> 
> Reported-by: syzbot+cfc0247ac173f597aaaa@syzkaller.appspotmail.com
> Reported-by: Andy Nguyen <theflow@google.com>
> Fixes: 9fa492cdc160c ("[NETFILTER]: x_tables: simplify compat API")
> Signed-off-by: Florian Westphal <fw@strlen.de>
> Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
> (cherry picked from commit b29c457a6511435960115c0f548c4360d5f4801d)
> Signed-off-by: Khalid Elmously <khalid.elmously@canonical.com>
Acked-by: Stefan Bader <stefan.bader@canonical.com>
> ---
>   net/ipv4/netfilter/arp_tables.c |  2 ++
>   net/ipv4/netfilter/ip_tables.c  |  2 ++
>   net/ipv6/netfilter/ip6_tables.c |  2 ++
>   net/netfilter/x_tables.c        | 10 ++--------
>   4 files changed, 8 insertions(+), 8 deletions(-)
> 
> diff --git a/net/ipv4/netfilter/arp_tables.c b/net/ipv4/netfilter/arp_tables.c
> index e81eeb2389f92a..fc769df15c100b 100644
> --- a/net/ipv4/netfilter/arp_tables.c
> +++ b/net/ipv4/netfilter/arp_tables.c
> @@ -1230,6 +1230,8 @@ static int translate_compat_table(struct net *net,
>   	if (!newinfo)
>   		goto out_unlock;
>   
> +	memset(newinfo->entries, 0, size);
> +
>   	newinfo->number = compatr->num_entries;
>   	for (i = 0; i < NF_ARP_NUMHOOKS; i++) {
>   		newinfo->hook_entry[i] = compatr->hook_entry[i];
> diff --git a/net/ipv4/netfilter/ip_tables.c b/net/ipv4/netfilter/ip_tables.c
> index d5bd759a7ebaed..986d8538fb4ced 100644
> --- a/net/ipv4/netfilter/ip_tables.c
> +++ b/net/ipv4/netfilter/ip_tables.c
> @@ -1467,6 +1467,8 @@ translate_compat_table(struct net *net,
>   	if (!newinfo)
>   		goto out_unlock;
>   
> +	memset(newinfo->entries, 0, size);
> +
>   	newinfo->number = compatr->num_entries;
>   	for (i = 0; i < NF_INET_NUMHOOKS; i++) {
>   		newinfo->hook_entry[i] = compatr->hook_entry[i];
> diff --git a/net/ipv6/netfilter/ip6_tables.c b/net/ipv6/netfilter/ip6_tables.c
> index 8e2985fc1ebc01..2cfce6eb98b43d 100644
> --- a/net/ipv6/netfilter/ip6_tables.c
> +++ b/net/ipv6/netfilter/ip6_tables.c
> @@ -1483,6 +1483,8 @@ translate_compat_table(struct net *net,
>   	if (!newinfo)
>   		goto out_unlock;
>   
> +	memset(newinfo->entries, 0, size);
> +
>   	newinfo->number = compatr->num_entries;
>   	for (i = 0; i < NF_INET_NUMHOOKS; i++) {
>   		newinfo->hook_entry[i] = compatr->hook_entry[i];
> diff --git a/net/netfilter/x_tables.c b/net/netfilter/x_tables.c
> index 4638d42a22e405..d40acfce300764 100644
> --- a/net/netfilter/x_tables.c
> +++ b/net/netfilter/x_tables.c
> @@ -636,7 +636,7 @@ void xt_compat_match_from_user(struct xt_entry_match *m, void **dstptr,
>   {
>   	const struct xt_match *match = m->u.kernel.match;
>   	struct compat_xt_entry_match *cm = (struct compat_xt_entry_match *)m;
> -	int pad, off = xt_compat_match_offset(match);
> +	int off = xt_compat_match_offset(match);
>   	u_int16_t msize = cm->u.user.match_size;
>   	char name[sizeof(m->u.user.name)];
>   
> @@ -646,9 +646,6 @@ void xt_compat_match_from_user(struct xt_entry_match *m, void **dstptr,
>   		match->compat_from_user(m->data, cm->data);
>   	else
>   		memcpy(m->data, cm->data, msize - sizeof(*cm));
> -	pad = XT_ALIGN(match->matchsize) - match->matchsize;
> -	if (pad > 0)
> -		memset(m->data + match->matchsize, 0, pad);
>   
>   	msize += off;
>   	m->u.user.match_size = msize;
> @@ -991,7 +988,7 @@ void xt_compat_target_from_user(struct xt_entry_target *t, void **dstptr,
>   {
>   	const struct xt_target *target = t->u.kernel.target;
>   	struct compat_xt_entry_target *ct = (struct compat_xt_entry_target *)t;
> -	int pad, off = xt_compat_target_offset(target);
> +	int off = xt_compat_target_offset(target);
>   	u_int16_t tsize = ct->u.user.target_size;
>   	char name[sizeof(t->u.user.name)];
>   
> @@ -1001,9 +998,6 @@ void xt_compat_target_from_user(struct xt_entry_target *t, void **dstptr,
>   		target->compat_from_user(t->data, ct->data);
>   	else
>   		memcpy(t->data, ct->data, tsize - sizeof(*ct));
> -	pad = XT_ALIGN(target->targetsize) - target->targetsize;
> -	if (pad > 0)
> -		memset(t->data + target->targetsize, 0, pad);
>   
>   	tsize += off;
>   	t->u.user.target_size = tsize;
>
Kleber Sacilotto de Souza May 7, 2021, 10:32 a.m. UTC | #2
On 07.05.21 08:10, Khalid Elmously wrote:
> From: Florian Westphal <fw@strlen.de>
> 
> BugLink: https://bugs.launchpad.net/bugs/1927682
> 
> xt_compat_match/target_from_user doesn't check that zeroing the area
> to start of next rule won't write past end of allocated ruleset blob.
> 
> Remove this code and zero the entire blob beforehand.
> 
> Reported-by: syzbot+cfc0247ac173f597aaaa@syzkaller.appspotmail.com
> Reported-by: Andy Nguyen <theflow@google.com>
> Fixes: 9fa492cdc160c ("[NETFILTER]: x_tables: simplify compat API")
> Signed-off-by: Florian Westphal <fw@strlen.de>
> Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
> (cherry picked from commit b29c457a6511435960115c0f548c4360d5f4801d)
> Signed-off-by: Khalid Elmously <khalid.elmously@canonical.com>

Looks good, clean cherry-pick.

Acked-by: Kleber Sacilotto de Souza <kleber.souza@canonical.com>

Thanks

> ---
>   net/ipv4/netfilter/arp_tables.c |  2 ++
>   net/ipv4/netfilter/ip_tables.c  |  2 ++
>   net/ipv6/netfilter/ip6_tables.c |  2 ++
>   net/netfilter/x_tables.c        | 10 ++--------
>   4 files changed, 8 insertions(+), 8 deletions(-)
> 
> diff --git a/net/ipv4/netfilter/arp_tables.c b/net/ipv4/netfilter/arp_tables.c
> index e81eeb2389f92a..fc769df15c100b 100644
> --- a/net/ipv4/netfilter/arp_tables.c
> +++ b/net/ipv4/netfilter/arp_tables.c
> @@ -1230,6 +1230,8 @@ static int translate_compat_table(struct net *net,
>   	if (!newinfo)
>   		goto out_unlock;
>   
> +	memset(newinfo->entries, 0, size);
> +
>   	newinfo->number = compatr->num_entries;
>   	for (i = 0; i < NF_ARP_NUMHOOKS; i++) {
>   		newinfo->hook_entry[i] = compatr->hook_entry[i];
> diff --git a/net/ipv4/netfilter/ip_tables.c b/net/ipv4/netfilter/ip_tables.c
> index d5bd759a7ebaed..986d8538fb4ced 100644
> --- a/net/ipv4/netfilter/ip_tables.c
> +++ b/net/ipv4/netfilter/ip_tables.c
> @@ -1467,6 +1467,8 @@ translate_compat_table(struct net *net,
>   	if (!newinfo)
>   		goto out_unlock;
>   
> +	memset(newinfo->entries, 0, size);
> +
>   	newinfo->number = compatr->num_entries;
>   	for (i = 0; i < NF_INET_NUMHOOKS; i++) {
>   		newinfo->hook_entry[i] = compatr->hook_entry[i];
> diff --git a/net/ipv6/netfilter/ip6_tables.c b/net/ipv6/netfilter/ip6_tables.c
> index 8e2985fc1ebc01..2cfce6eb98b43d 100644
> --- a/net/ipv6/netfilter/ip6_tables.c
> +++ b/net/ipv6/netfilter/ip6_tables.c
> @@ -1483,6 +1483,8 @@ translate_compat_table(struct net *net,
>   	if (!newinfo)
>   		goto out_unlock;
>   
> +	memset(newinfo->entries, 0, size);
> +
>   	newinfo->number = compatr->num_entries;
>   	for (i = 0; i < NF_INET_NUMHOOKS; i++) {
>   		newinfo->hook_entry[i] = compatr->hook_entry[i];
> diff --git a/net/netfilter/x_tables.c b/net/netfilter/x_tables.c
> index 4638d42a22e405..d40acfce300764 100644
> --- a/net/netfilter/x_tables.c
> +++ b/net/netfilter/x_tables.c
> @@ -636,7 +636,7 @@ void xt_compat_match_from_user(struct xt_entry_match *m, void **dstptr,
>   {
>   	const struct xt_match *match = m->u.kernel.match;
>   	struct compat_xt_entry_match *cm = (struct compat_xt_entry_match *)m;
> -	int pad, off = xt_compat_match_offset(match);
> +	int off = xt_compat_match_offset(match);
>   	u_int16_t msize = cm->u.user.match_size;
>   	char name[sizeof(m->u.user.name)];
>   
> @@ -646,9 +646,6 @@ void xt_compat_match_from_user(struct xt_entry_match *m, void **dstptr,
>   		match->compat_from_user(m->data, cm->data);
>   	else
>   		memcpy(m->data, cm->data, msize - sizeof(*cm));
> -	pad = XT_ALIGN(match->matchsize) - match->matchsize;
> -	if (pad > 0)
> -		memset(m->data + match->matchsize, 0, pad);
>   
>   	msize += off;
>   	m->u.user.match_size = msize;
> @@ -991,7 +988,7 @@ void xt_compat_target_from_user(struct xt_entry_target *t, void **dstptr,
>   {
>   	const struct xt_target *target = t->u.kernel.target;
>   	struct compat_xt_entry_target *ct = (struct compat_xt_entry_target *)t;
> -	int pad, off = xt_compat_target_offset(target);
> +	int off = xt_compat_target_offset(target);
>   	u_int16_t tsize = ct->u.user.target_size;
>   	char name[sizeof(t->u.user.name)];
>   
> @@ -1001,9 +998,6 @@ void xt_compat_target_from_user(struct xt_entry_target *t, void **dstptr,
>   		target->compat_from_user(t->data, ct->data);
>   	else
>   		memcpy(t->data, ct->data, tsize - sizeof(*ct));
> -	pad = XT_ALIGN(target->targetsize) - target->targetsize;
> -	if (pad > 0)
> -		memset(t->data + target->targetsize, 0, pad);
>   
>   	tsize += off;
>   	t->u.user.target_size = tsize;
>
Stefan Bader May 7, 2021, 12:11 p.m. UTC | #3
On 07.05.21 08:10, Khalid Elmously wrote:
> From: Florian Westphal <fw@strlen.de>
> 
> BugLink: https://bugs.launchpad.net/bugs/1927682
> 
> xt_compat_match/target_from_user doesn't check that zeroing the area
> to start of next rule won't write past end of allocated ruleset blob.
> 
> Remove this code and zero the entire blob beforehand.
> 
> Reported-by: syzbot+cfc0247ac173f597aaaa@syzkaller.appspotmail.com
> Reported-by: Andy Nguyen <theflow@google.com>
> Fixes: 9fa492cdc160c ("[NETFILTER]: x_tables: simplify compat API")
> Signed-off-by: Florian Westphal <fw@strlen.de>
> Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
> (cherry picked from commit b29c457a6511435960115c0f548c4360d5f4801d)
> Signed-off-by: Khalid Elmously <khalid.elmously@canonical.com>
> ---

This is already applied to Hirsute via v5.11.15 stable.

-Stefan

>   net/ipv4/netfilter/arp_tables.c |  2 ++
>   net/ipv4/netfilter/ip_tables.c  |  2 ++
>   net/ipv6/netfilter/ip6_tables.c |  2 ++
>   net/netfilter/x_tables.c        | 10 ++--------
>   4 files changed, 8 insertions(+), 8 deletions(-)
> 
> diff --git a/net/ipv4/netfilter/arp_tables.c b/net/ipv4/netfilter/arp_tables.c
> index e81eeb2389f92a..fc769df15c100b 100644
> --- a/net/ipv4/netfilter/arp_tables.c
> +++ b/net/ipv4/netfilter/arp_tables.c
> @@ -1230,6 +1230,8 @@ static int translate_compat_table(struct net *net,
>   	if (!newinfo)
>   		goto out_unlock;
>   
> +	memset(newinfo->entries, 0, size);
> +
>   	newinfo->number = compatr->num_entries;
>   	for (i = 0; i < NF_ARP_NUMHOOKS; i++) {
>   		newinfo->hook_entry[i] = compatr->hook_entry[i];
> diff --git a/net/ipv4/netfilter/ip_tables.c b/net/ipv4/netfilter/ip_tables.c
> index d5bd759a7ebaed..986d8538fb4ced 100644
> --- a/net/ipv4/netfilter/ip_tables.c
> +++ b/net/ipv4/netfilter/ip_tables.c
> @@ -1467,6 +1467,8 @@ translate_compat_table(struct net *net,
>   	if (!newinfo)
>   		goto out_unlock;
>   
> +	memset(newinfo->entries, 0, size);
> +
>   	newinfo->number = compatr->num_entries;
>   	for (i = 0; i < NF_INET_NUMHOOKS; i++) {
>   		newinfo->hook_entry[i] = compatr->hook_entry[i];
> diff --git a/net/ipv6/netfilter/ip6_tables.c b/net/ipv6/netfilter/ip6_tables.c
> index 8e2985fc1ebc01..2cfce6eb98b43d 100644
> --- a/net/ipv6/netfilter/ip6_tables.c
> +++ b/net/ipv6/netfilter/ip6_tables.c
> @@ -1483,6 +1483,8 @@ translate_compat_table(struct net *net,
>   	if (!newinfo)
>   		goto out_unlock;
>   
> +	memset(newinfo->entries, 0, size);
> +
>   	newinfo->number = compatr->num_entries;
>   	for (i = 0; i < NF_INET_NUMHOOKS; i++) {
>   		newinfo->hook_entry[i] = compatr->hook_entry[i];
> diff --git a/net/netfilter/x_tables.c b/net/netfilter/x_tables.c
> index 4638d42a22e405..d40acfce300764 100644
> --- a/net/netfilter/x_tables.c
> +++ b/net/netfilter/x_tables.c
> @@ -636,7 +636,7 @@ void xt_compat_match_from_user(struct xt_entry_match *m, void **dstptr,
>   {
>   	const struct xt_match *match = m->u.kernel.match;
>   	struct compat_xt_entry_match *cm = (struct compat_xt_entry_match *)m;
> -	int pad, off = xt_compat_match_offset(match);
> +	int off = xt_compat_match_offset(match);
>   	u_int16_t msize = cm->u.user.match_size;
>   	char name[sizeof(m->u.user.name)];
>   
> @@ -646,9 +646,6 @@ void xt_compat_match_from_user(struct xt_entry_match *m, void **dstptr,
>   		match->compat_from_user(m->data, cm->data);
>   	else
>   		memcpy(m->data, cm->data, msize - sizeof(*cm));
> -	pad = XT_ALIGN(match->matchsize) - match->matchsize;
> -	if (pad > 0)
> -		memset(m->data + match->matchsize, 0, pad);
>   
>   	msize += off;
>   	m->u.user.match_size = msize;
> @@ -991,7 +988,7 @@ void xt_compat_target_from_user(struct xt_entry_target *t, void **dstptr,
>   {
>   	const struct xt_target *target = t->u.kernel.target;
>   	struct compat_xt_entry_target *ct = (struct compat_xt_entry_target *)t;
> -	int pad, off = xt_compat_target_offset(target);
> +	int off = xt_compat_target_offset(target);
>   	u_int16_t tsize = ct->u.user.target_size;
>   	char name[sizeof(t->u.user.name)];
>   
> @@ -1001,9 +998,6 @@ void xt_compat_target_from_user(struct xt_entry_target *t, void **dstptr,
>   		target->compat_from_user(t->data, ct->data);
>   	else
>   		memcpy(t->data, ct->data, tsize - sizeof(*ct));
> -	pad = XT_ALIGN(target->targetsize) - target->targetsize;
> -	if (pad > 0)
> -		memset(t->data + target->targetsize, 0, pad);
>   
>   	tsize += off;
>   	t->u.user.target_size = tsize;
>
Stefan Bader May 7, 2021, 1:20 p.m. UTC | #4
On 07.05.21 08:10, Khalid Elmously wrote:
> From: Florian Westphal <fw@strlen.de>
> 
> BugLink: https://bugs.launchpad.net/bugs/1927682
> 
> xt_compat_match/target_from_user doesn't check that zeroing the area
> to start of next rule won't write past end of allocated ruleset blob.
> 
> Remove this code and zero the entire blob beforehand.
> 
> Reported-by: syzbot+cfc0247ac173f597aaaa@syzkaller.appspotmail.com
> Reported-by: Andy Nguyen <theflow@google.com>
> Fixes: 9fa492cdc160c ("[NETFILTER]: x_tables: simplify compat API")
> Signed-off-by: Florian Westphal <fw@strlen.de>
> Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
> (cherry picked from commit b29c457a6511435960115c0f548c4360d5f4801d)
> Signed-off-by: Khalid Elmously <khalid.elmously@canonical.com>
> ---

Applied to groovy:linux (prep). Thanks.

-Stefan
>   net/ipv4/netfilter/arp_tables.c |  2 ++
>   net/ipv4/netfilter/ip_tables.c  |  2 ++
>   net/ipv6/netfilter/ip6_tables.c |  2 ++
>   net/netfilter/x_tables.c        | 10 ++--------
>   4 files changed, 8 insertions(+), 8 deletions(-)
> 
> diff --git a/net/ipv4/netfilter/arp_tables.c b/net/ipv4/netfilter/arp_tables.c
> index e81eeb2389f92a..fc769df15c100b 100644
> --- a/net/ipv4/netfilter/arp_tables.c
> +++ b/net/ipv4/netfilter/arp_tables.c
> @@ -1230,6 +1230,8 @@ static int translate_compat_table(struct net *net,
>   	if (!newinfo)
>   		goto out_unlock;
>   
> +	memset(newinfo->entries, 0, size);
> +
>   	newinfo->number = compatr->num_entries;
>   	for (i = 0; i < NF_ARP_NUMHOOKS; i++) {
>   		newinfo->hook_entry[i] = compatr->hook_entry[i];
> diff --git a/net/ipv4/netfilter/ip_tables.c b/net/ipv4/netfilter/ip_tables.c
> index d5bd759a7ebaed..986d8538fb4ced 100644
> --- a/net/ipv4/netfilter/ip_tables.c
> +++ b/net/ipv4/netfilter/ip_tables.c
> @@ -1467,6 +1467,8 @@ translate_compat_table(struct net *net,
>   	if (!newinfo)
>   		goto out_unlock;
>   
> +	memset(newinfo->entries, 0, size);
> +
>   	newinfo->number = compatr->num_entries;
>   	for (i = 0; i < NF_INET_NUMHOOKS; i++) {
>   		newinfo->hook_entry[i] = compatr->hook_entry[i];
> diff --git a/net/ipv6/netfilter/ip6_tables.c b/net/ipv6/netfilter/ip6_tables.c
> index 8e2985fc1ebc01..2cfce6eb98b43d 100644
> --- a/net/ipv6/netfilter/ip6_tables.c
> +++ b/net/ipv6/netfilter/ip6_tables.c
> @@ -1483,6 +1483,8 @@ translate_compat_table(struct net *net,
>   	if (!newinfo)
>   		goto out_unlock;
>   
> +	memset(newinfo->entries, 0, size);
> +
>   	newinfo->number = compatr->num_entries;
>   	for (i = 0; i < NF_INET_NUMHOOKS; i++) {
>   		newinfo->hook_entry[i] = compatr->hook_entry[i];
> diff --git a/net/netfilter/x_tables.c b/net/netfilter/x_tables.c
> index 4638d42a22e405..d40acfce300764 100644
> --- a/net/netfilter/x_tables.c
> +++ b/net/netfilter/x_tables.c
> @@ -636,7 +636,7 @@ void xt_compat_match_from_user(struct xt_entry_match *m, void **dstptr,
>   {
>   	const struct xt_match *match = m->u.kernel.match;
>   	struct compat_xt_entry_match *cm = (struct compat_xt_entry_match *)m;
> -	int pad, off = xt_compat_match_offset(match);
> +	int off = xt_compat_match_offset(match);
>   	u_int16_t msize = cm->u.user.match_size;
>   	char name[sizeof(m->u.user.name)];
>   
> @@ -646,9 +646,6 @@ void xt_compat_match_from_user(struct xt_entry_match *m, void **dstptr,
>   		match->compat_from_user(m->data, cm->data);
>   	else
>   		memcpy(m->data, cm->data, msize - sizeof(*cm));
> -	pad = XT_ALIGN(match->matchsize) - match->matchsize;
> -	if (pad > 0)
> -		memset(m->data + match->matchsize, 0, pad);
>   
>   	msize += off;
>   	m->u.user.match_size = msize;
> @@ -991,7 +988,7 @@ void xt_compat_target_from_user(struct xt_entry_target *t, void **dstptr,
>   {
>   	const struct xt_target *target = t->u.kernel.target;
>   	struct compat_xt_entry_target *ct = (struct compat_xt_entry_target *)t;
> -	int pad, off = xt_compat_target_offset(target);
> +	int off = xt_compat_target_offset(target);
>   	u_int16_t tsize = ct->u.user.target_size;
>   	char name[sizeof(t->u.user.name)];
>   
> @@ -1001,9 +998,6 @@ void xt_compat_target_from_user(struct xt_entry_target *t, void **dstptr,
>   		target->compat_from_user(t->data, ct->data);
>   	else
>   		memcpy(t->data, ct->data, tsize - sizeof(*ct));
> -	pad = XT_ALIGN(target->targetsize) - target->targetsize;
> -	if (pad > 0)
> -		memset(t->data + target->targetsize, 0, pad);
>   
>   	tsize += off;
>   	t->u.user.target_size = tsize;
>
Kelsey Skunberg May 8, 2021, 12:07 a.m. UTC | #5
This was applied via an upstream patchset on F/B master-next. Thank you! 

-Kelsey

On 2021-05-07 02:10:41 , Khalid Elmously wrote:
> From: Florian Westphal <fw@strlen.de>
> 
> BugLink: https://bugs.launchpad.net/bugs/1927682
> 
> xt_compat_match/target_from_user doesn't check that zeroing the area
> to start of next rule won't write past end of allocated ruleset blob.
> 
> Remove this code and zero the entire blob beforehand.
> 
> Reported-by: syzbot+cfc0247ac173f597aaaa@syzkaller.appspotmail.com
> Reported-by: Andy Nguyen <theflow@google.com>
> Fixes: 9fa492cdc160c ("[NETFILTER]: x_tables: simplify compat API")
> Signed-off-by: Florian Westphal <fw@strlen.de>
> Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
> (cherry picked from commit b29c457a6511435960115c0f548c4360d5f4801d)
> Signed-off-by: Khalid Elmously <khalid.elmously@canonical.com>
> ---
>  net/ipv4/netfilter/arp_tables.c |  2 ++
>  net/ipv4/netfilter/ip_tables.c  |  2 ++
>  net/ipv6/netfilter/ip6_tables.c |  2 ++
>  net/netfilter/x_tables.c        | 10 ++--------
>  4 files changed, 8 insertions(+), 8 deletions(-)
> 
> diff --git a/net/ipv4/netfilter/arp_tables.c b/net/ipv4/netfilter/arp_tables.c
> index e81eeb2389f92a..fc769df15c100b 100644
> --- a/net/ipv4/netfilter/arp_tables.c
> +++ b/net/ipv4/netfilter/arp_tables.c
> @@ -1230,6 +1230,8 @@ static int translate_compat_table(struct net *net,
>  	if (!newinfo)
>  		goto out_unlock;
>  
> +	memset(newinfo->entries, 0, size);
> +
>  	newinfo->number = compatr->num_entries;
>  	for (i = 0; i < NF_ARP_NUMHOOKS; i++) {
>  		newinfo->hook_entry[i] = compatr->hook_entry[i];
> diff --git a/net/ipv4/netfilter/ip_tables.c b/net/ipv4/netfilter/ip_tables.c
> index d5bd759a7ebaed..986d8538fb4ced 100644
> --- a/net/ipv4/netfilter/ip_tables.c
> +++ b/net/ipv4/netfilter/ip_tables.c
> @@ -1467,6 +1467,8 @@ translate_compat_table(struct net *net,
>  	if (!newinfo)
>  		goto out_unlock;
>  
> +	memset(newinfo->entries, 0, size);
> +
>  	newinfo->number = compatr->num_entries;
>  	for (i = 0; i < NF_INET_NUMHOOKS; i++) {
>  		newinfo->hook_entry[i] = compatr->hook_entry[i];
> diff --git a/net/ipv6/netfilter/ip6_tables.c b/net/ipv6/netfilter/ip6_tables.c
> index 8e2985fc1ebc01..2cfce6eb98b43d 100644
> --- a/net/ipv6/netfilter/ip6_tables.c
> +++ b/net/ipv6/netfilter/ip6_tables.c
> @@ -1483,6 +1483,8 @@ translate_compat_table(struct net *net,
>  	if (!newinfo)
>  		goto out_unlock;
>  
> +	memset(newinfo->entries, 0, size);
> +
>  	newinfo->number = compatr->num_entries;
>  	for (i = 0; i < NF_INET_NUMHOOKS; i++) {
>  		newinfo->hook_entry[i] = compatr->hook_entry[i];
> diff --git a/net/netfilter/x_tables.c b/net/netfilter/x_tables.c
> index 4638d42a22e405..d40acfce300764 100644
> --- a/net/netfilter/x_tables.c
> +++ b/net/netfilter/x_tables.c
> @@ -636,7 +636,7 @@ void xt_compat_match_from_user(struct xt_entry_match *m, void **dstptr,
>  {
>  	const struct xt_match *match = m->u.kernel.match;
>  	struct compat_xt_entry_match *cm = (struct compat_xt_entry_match *)m;
> -	int pad, off = xt_compat_match_offset(match);
> +	int off = xt_compat_match_offset(match);
>  	u_int16_t msize = cm->u.user.match_size;
>  	char name[sizeof(m->u.user.name)];
>  
> @@ -646,9 +646,6 @@ void xt_compat_match_from_user(struct xt_entry_match *m, void **dstptr,
>  		match->compat_from_user(m->data, cm->data);
>  	else
>  		memcpy(m->data, cm->data, msize - sizeof(*cm));
> -	pad = XT_ALIGN(match->matchsize) - match->matchsize;
> -	if (pad > 0)
> -		memset(m->data + match->matchsize, 0, pad);
>  
>  	msize += off;
>  	m->u.user.match_size = msize;
> @@ -991,7 +988,7 @@ void xt_compat_target_from_user(struct xt_entry_target *t, void **dstptr,
>  {
>  	const struct xt_target *target = t->u.kernel.target;
>  	struct compat_xt_entry_target *ct = (struct compat_xt_entry_target *)t;
> -	int pad, off = xt_compat_target_offset(target);
> +	int off = xt_compat_target_offset(target);
>  	u_int16_t tsize = ct->u.user.target_size;
>  	char name[sizeof(t->u.user.name)];
>  
> @@ -1001,9 +998,6 @@ void xt_compat_target_from_user(struct xt_entry_target *t, void **dstptr,
>  		target->compat_from_user(t->data, ct->data);
>  	else
>  		memcpy(t->data, ct->data, tsize - sizeof(*ct));
> -	pad = XT_ALIGN(target->targetsize) - target->targetsize;
> -	if (pad > 0)
> -		memset(t->data + target->targetsize, 0, pad);
>  
>  	tsize += off;
>  	t->u.user.target_size = tsize;
> -- 
> 2.17.1
> 
> 
> -- 
> kernel-team mailing list
> kernel-team@lists.ubuntu.com
> https://lists.ubuntu.com/mailman/listinfo/kernel-team
diff mbox series

Patch

diff --git a/net/ipv4/netfilter/arp_tables.c b/net/ipv4/netfilter/arp_tables.c
index e81eeb2389f92a..fc769df15c100b 100644
--- a/net/ipv4/netfilter/arp_tables.c
+++ b/net/ipv4/netfilter/arp_tables.c
@@ -1230,6 +1230,8 @@  static int translate_compat_table(struct net *net,
 	if (!newinfo)
 		goto out_unlock;
 
+	memset(newinfo->entries, 0, size);
+
 	newinfo->number = compatr->num_entries;
 	for (i = 0; i < NF_ARP_NUMHOOKS; i++) {
 		newinfo->hook_entry[i] = compatr->hook_entry[i];
diff --git a/net/ipv4/netfilter/ip_tables.c b/net/ipv4/netfilter/ip_tables.c
index d5bd759a7ebaed..986d8538fb4ced 100644
--- a/net/ipv4/netfilter/ip_tables.c
+++ b/net/ipv4/netfilter/ip_tables.c
@@ -1467,6 +1467,8 @@  translate_compat_table(struct net *net,
 	if (!newinfo)
 		goto out_unlock;
 
+	memset(newinfo->entries, 0, size);
+
 	newinfo->number = compatr->num_entries;
 	for (i = 0; i < NF_INET_NUMHOOKS; i++) {
 		newinfo->hook_entry[i] = compatr->hook_entry[i];
diff --git a/net/ipv6/netfilter/ip6_tables.c b/net/ipv6/netfilter/ip6_tables.c
index 8e2985fc1ebc01..2cfce6eb98b43d 100644
--- a/net/ipv6/netfilter/ip6_tables.c
+++ b/net/ipv6/netfilter/ip6_tables.c
@@ -1483,6 +1483,8 @@  translate_compat_table(struct net *net,
 	if (!newinfo)
 		goto out_unlock;
 
+	memset(newinfo->entries, 0, size);
+
 	newinfo->number = compatr->num_entries;
 	for (i = 0; i < NF_INET_NUMHOOKS; i++) {
 		newinfo->hook_entry[i] = compatr->hook_entry[i];
diff --git a/net/netfilter/x_tables.c b/net/netfilter/x_tables.c
index 4638d42a22e405..d40acfce300764 100644
--- a/net/netfilter/x_tables.c
+++ b/net/netfilter/x_tables.c
@@ -636,7 +636,7 @@  void xt_compat_match_from_user(struct xt_entry_match *m, void **dstptr,
 {
 	const struct xt_match *match = m->u.kernel.match;
 	struct compat_xt_entry_match *cm = (struct compat_xt_entry_match *)m;
-	int pad, off = xt_compat_match_offset(match);
+	int off = xt_compat_match_offset(match);
 	u_int16_t msize = cm->u.user.match_size;
 	char name[sizeof(m->u.user.name)];
 
@@ -646,9 +646,6 @@  void xt_compat_match_from_user(struct xt_entry_match *m, void **dstptr,
 		match->compat_from_user(m->data, cm->data);
 	else
 		memcpy(m->data, cm->data, msize - sizeof(*cm));
-	pad = XT_ALIGN(match->matchsize) - match->matchsize;
-	if (pad > 0)
-		memset(m->data + match->matchsize, 0, pad);
 
 	msize += off;
 	m->u.user.match_size = msize;
@@ -991,7 +988,7 @@  void xt_compat_target_from_user(struct xt_entry_target *t, void **dstptr,
 {
 	const struct xt_target *target = t->u.kernel.target;
 	struct compat_xt_entry_target *ct = (struct compat_xt_entry_target *)t;
-	int pad, off = xt_compat_target_offset(target);
+	int off = xt_compat_target_offset(target);
 	u_int16_t tsize = ct->u.user.target_size;
 	char name[sizeof(t->u.user.name)];
 
@@ -1001,9 +998,6 @@  void xt_compat_target_from_user(struct xt_entry_target *t, void **dstptr,
 		target->compat_from_user(t->data, ct->data);
 	else
 		memcpy(t->data, ct->data, tsize - sizeof(*ct));
-	pad = XT_ALIGN(target->targetsize) - target->targetsize;
-	if (pad > 0)
-		memset(t->data + target->targetsize, 0, pad);
 
 	tsize += off;
 	t->u.user.target_size = tsize;