netdev.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* net/xfrm: stack out-of-bounds in xfrm_flowi_sport
@ 2017-02-13 14:46 Dmitry Vyukov
  2017-02-14  7:08 ` Steffen Klassert
  0 siblings, 1 reply; 8+ messages in thread
From: Dmitry Vyukov @ 2017-02-13 14:46 UTC (permalink / raw)
  To: Steffen Klassert, Herbert Xu, David Miller, Eric Dumazet, netdev, LKML
  Cc: syzkaller

Hello,

The following program triggers stack out-of-bounds in xfrm_flowi_sport:


BUG: KASAN: stack-out-of-bounds in xfrm_flowi_sport
include/net/xfrm.h:862 [inline] at addr ffff8800677df796
BUG: KASAN: stack-out-of-bounds in __xfrm6_selector_match
net/xfrm/xfrm_policy.c:89 [inline] at addr ffff8800677df796
BUG: KASAN: stack-out-of-bounds in xfrm_selector_match+0xc94/0xe40
net/xfrm/xfrm_policy.c:101 at addr ffff8800677df796
Read of size 2 by task a.out/3338
page:ffffea00016a38c8 count:0 mapcount:0 mapping:          (null) index:0x0
flags: 0x100000000000000()
raw: 0100000000000000 0000000000000000 0000000000000000 00000000ffffffff
raw: 0000000000000000 dead000000000200 0000000000000000
page dumped because: kasan: bad access detected
CPU: 0 PID: 3338 Comm: a.out Tainted: G    B           4.10.0-rc8+ #218
Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS Bochs 01/01/2011
Call Trace:
 __asan_report_load2_noabort+0x29/0x30 mm/kasan/report.c:329
 xfrm_flowi_sport include/net/xfrm.h:862 [inline]
 __xfrm6_selector_match net/xfrm/xfrm_policy.c:89 [inline]
 xfrm_selector_match+0xc94/0xe40 net/xfrm/xfrm_policy.c:101
 xfrm_sk_policy_lookup+0x1bb/0x540 net/xfrm/xfrm_policy.c:1259
 xfrm_lookup+0x215/0x10f0 net/xfrm/xfrm_policy.c:2256
 xfrm_lookup_route+0x39/0x1a0 net/xfrm/xfrm_policy.c:2390
 ip_route_output_flow+0x7f/0xa0 net/ipv4/route.c:2447
 udp_sendmsg+0x162b/0x2b80 net/ipv4/udp.c:1027
 udpv6_sendmsg+0x10a9/0x3170 net/ipv6/udp.c:1065
 inet_sendmsg+0x164/0x5b0 net/ipv4/af_inet.c:744
 sock_sendmsg_nosec net/socket.c:635 [inline]
 sock_sendmsg+0xca/0x110 net/socket.c:645
 SYSC_sendto+0x660/0x810 net/socket.c:1687
 SyS_sendto+0x40/0x50 net/socket.c:1655
 entry_SYSCALL_64_fastpath+0x1f/0xc2
RIP: 0033:0x436ed3
RSP: 002b:00007fff6d081748 EFLAGS: 00000246 ORIG_RAX: 000000000000002c
RAX: ffffffffffffffda RBX: 0000000000401860 RCX: 0000000000436ed3
RDX: 000000000000008f RSI: 0000000020003f71 RDI: 0000000000000003
RBP: 0000000000000000 R08: 0000000020003000 R09: 0000000000000010
R10: 0000000000040084 R11: 0000000000000246 R12: 00000000004002b0
R13: 0000000000401860 R14: 00000000004018f0 R15: 0000000000000000
Memory state around the buggy address:
 ffff8800677df680: f1 00 f2 f2 f2 f2 f2 f2 f2 f8 f2 f2 f2 f2 f2 f2
 ffff8800677df700: f2 00 00 00 00 f2 f2 f2 f2 00 00 00 00 00 00 00
>ffff8800677df780: f2 f2 f2 f2 f2 00 00 00 00 00 00 00 00 00 f2 f2
                         ^
 ffff8800677df800: f2 f3 f3 f3 f3 00 00 00 00 00 00 00 00 00 00 00
 ffff8800677df880: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
==================================================================


// autogenerated by syzkaller (http://github.com/google/syzkaller)
#define _GNU_SOURCE
#include <sys/mman.h>
#include <sys/socket.h>
#include <sys/stat.h>
#include <sys/syscall.h>
#include <sys/time.h>
#include <sys/types.h>
#include <linux/in.h>
#include <stddef.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>

int main()
{
  mmap((void*)0x20000000ul, 0xfff000ul, 0x3ul, 0x32ul, -1, 0);
  int sock = socket(AF_INET6, SOCK_DGRAM, IPPROTO_IP);
  (*(uint64_t*)0x20000098 = (uint64_t)0x20b50000);
  (*(uint32_t*)0x200000a0 = (uint32_t)0x1);
  (*(uint64_t*)0x20000000 = (uint64_t)0x20005000);
  (*(uint64_t*)0x20000008 = (uint64_t)0x20002fdc);
  (*(uint64_t*)0x20000010 = (uint64_t)0x20001ff8);
  (*(uint64_t*)0x20000018 = (uint64_t)0x20004ff0);
  (*(uint32_t*)0x20000020 = (uint32_t)0x1);
  (*(uint32_t*)0x20000024 = (uint32_t)0x0);
  (*(uint32_t*)0x20000028 = (uint32_t)0x2);
  (*(uint32_t*)0x2000002c = (uint32_t)0x0);
  (*(uint32_t*)0x20000030 = (uint32_t)0x0);
  (*(uint32_t*)0x20000034 = (uint32_t)0x0);
  (*(uint32_t*)0x20000038 = (uint32_t)0x0);
  (*(uint32_t*)0x2000003c = (uint32_t)0x0);
  setsockopt(sock, 0x29ul, 0x23ul, (void*)0x20000000ul, 0x264ul);
  (*(uint16_t*)0x20003000 = (uint16_t)0x2);
  (*(uint16_t*)0x20003002 = (uint16_t)0x214e);
  (*(uint32_t*)0x20003004 = (uint32_t)0x0);
  (*(uint8_t*)0x20003008 = (uint8_t)0x0);
  (*(uint8_t*)0x20003009 = (uint8_t)0x0);
  (*(uint8_t*)0x2000300a = (uint8_t)0x0);
  (*(uint8_t*)0x2000300b = (uint8_t)0x0);
  (*(uint8_t*)0x2000300c = (uint8_t)0x0);
  (*(uint8_t*)0x2000300d = (uint8_t)0x0);
  (*(uint8_t*)0x2000300e = (uint8_t)0x0);
  (*(uint8_t*)0x2000300f = (uint8_t)0x0);
  sendto(sock, (void*)0x20003f71ul, 0x8ful, 0x40084ul,
(void*)0x20003000ul, 0x10ul);
  return 0;
}


On commit 7089db84e356562f8ba737c29e472cc42d530dbc.


struct flowi4 fl4_stack allocated on stack in udp_sendmsg is being
casted to larger struct flowi and then accessed.

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: net/xfrm: stack out-of-bounds in xfrm_flowi_sport
  2017-02-13 14:46 net/xfrm: stack out-of-bounds in xfrm_flowi_sport Dmitry Vyukov
@ 2017-02-14  7:08 ` Steffen Klassert
  2017-02-14  8:41   ` Dmitry Vyukov
  0 siblings, 1 reply; 8+ messages in thread
From: Steffen Klassert @ 2017-02-14  7:08 UTC (permalink / raw)
  To: Dmitry Vyukov
  Cc: Herbert Xu, David Miller, Eric Dumazet, netdev, LKML, syzkaller

On Mon, Feb 13, 2017 at 03:46:56PM +0100, Dmitry Vyukov wrote:
> 
> On commit 7089db84e356562f8ba737c29e472cc42d530dbc.
> 
> 
> struct flowi4 fl4_stack allocated on stack in udp_sendmsg is being
> casted to larger struct flowi and then accessed.

Looks like the problem is when using IPv4-mapped IPv6 addresses.

Does the patch below help?


Subject: [PATCH RFC ipsec] xfrm: Don't use sk_family for socket policy lookups

On IPv4-mapped IPv6 addresses sk_family is AF_INET6,
but the flow informations are created based on AF_INET.
So the routing set up 'struct flowi4' but we try to
access 'struct flowi6' what leads to an out of bounds
access. Fix this by using the family we get with the
dst_entry, like we do it for the standard policy lookup.

Reported-by: Dmitry Vyukov <dvyukov@google.com>
Signed-off-by: Steffen Klassert <steffen.klassert@secunet.com>
---
 net/xfrm/xfrm_policy.c | 9 ++++-----
 1 file changed, 4 insertions(+), 5 deletions(-)

diff --git a/net/xfrm/xfrm_policy.c b/net/xfrm/xfrm_policy.c
index b5e665b..4891b7b 100644
--- a/net/xfrm/xfrm_policy.c
+++ b/net/xfrm/xfrm_policy.c
@@ -1216,7 +1216,7 @@ static inline int policy_to_flow_dir(int dir)
 }
 
 static struct xfrm_policy *xfrm_sk_policy_lookup(const struct sock *sk, int dir,
-						 const struct flowi *fl)
+						 const struct flowi *fl, u16 family)
 {
 	struct xfrm_policy *pol;
 	struct net *net = sock_net(sk);
@@ -1225,8 +1225,7 @@ static struct xfrm_policy *xfrm_sk_policy_lookup(const struct sock *sk, int dir,
 	read_lock_bh(&net->xfrm.xfrm_policy_lock);
 	pol = rcu_dereference(sk->sk_policy[dir]);
 	if (pol != NULL) {
-		bool match = xfrm_selector_match(&pol->selector, fl,
-						 sk->sk_family);
+		bool match = xfrm_selector_match(&pol->selector, fl, family);
 		int err = 0;
 
 		if (match) {
@@ -2221,7 +2220,7 @@ struct dst_entry *xfrm_lookup(struct net *net, struct dst_entry *dst_orig,
 	sk = sk_const_to_full_sk(sk);
 	if (sk && sk->sk_policy[XFRM_POLICY_OUT]) {
 		num_pols = 1;
-		pols[0] = xfrm_sk_policy_lookup(sk, XFRM_POLICY_OUT, fl);
+		pols[0] = xfrm_sk_policy_lookup(sk, XFRM_POLICY_OUT, fl, family);
 		err = xfrm_expand_policies(fl, family, pols,
 					   &num_pols, &num_xfrms);
 		if (err < 0)
@@ -2500,7 +2499,7 @@ int __xfrm_policy_check(struct sock *sk, int dir, struct sk_buff *skb,
 	pol = NULL;
 	sk = sk_to_full_sk(sk);
 	if (sk && sk->sk_policy[dir]) {
-		pol = xfrm_sk_policy_lookup(sk, dir, &fl);
+		pol = xfrm_sk_policy_lookup(sk, dir, &fl, family);
 		if (IS_ERR(pol)) {
 			XFRM_INC_STATS(net, LINUX_MIB_XFRMINPOLERROR);
 			return 0;
-- 
1.9.1

^ permalink raw reply related	[flat|nested] 8+ messages in thread

* Re: net/xfrm: stack out-of-bounds in xfrm_flowi_sport
  2017-02-14  7:08 ` Steffen Klassert
@ 2017-02-14  8:41   ` Dmitry Vyukov
  2017-02-14  9:08     ` Steffen Klassert
  0 siblings, 1 reply; 8+ messages in thread
From: Dmitry Vyukov @ 2017-02-14  8:41 UTC (permalink / raw)
  To: Steffen Klassert
  Cc: Herbert Xu, David Miller, Eric Dumazet, netdev, LKML, syzkaller

On Tue, Feb 14, 2017 at 8:08 AM, Steffen Klassert
<steffen.klassert@secunet.com> wrote:
> On Mon, Feb 13, 2017 at 03:46:56PM +0100, Dmitry Vyukov wrote:
>>
>> On commit 7089db84e356562f8ba737c29e472cc42d530dbc.
>>
>>
>> struct flowi4 fl4_stack allocated on stack in udp_sendmsg is being
>> casted to larger struct flowi and then accessed.
>
> Looks like the problem is when using IPv4-mapped IPv6 addresses.
>
> Does the patch below help?


Steffen, can you please run the reproducer I provided?
I specifically spent time to supply you with a simple, reliable
reproducer. I am not even saying about adding a test case for the bug.
Kernel development practices seem to encourage developers to not
bother with tests. But at least testing a patch that you are sending
looks like a reasonable thing to do.
Thanks


> Subject: [PATCH RFC ipsec] xfrm: Don't use sk_family for socket policy lookups
>
> On IPv4-mapped IPv6 addresses sk_family is AF_INET6,
> but the flow informations are created based on AF_INET.
> So the routing set up 'struct flowi4' but we try to
> access 'struct flowi6' what leads to an out of bounds
> access. Fix this by using the family we get with the
> dst_entry, like we do it for the standard policy lookup.
>
> Reported-by: Dmitry Vyukov <dvyukov@google.com>
> Signed-off-by: Steffen Klassert <steffen.klassert@secunet.com>
> ---
>  net/xfrm/xfrm_policy.c | 9 ++++-----
>  1 file changed, 4 insertions(+), 5 deletions(-)
>
> diff --git a/net/xfrm/xfrm_policy.c b/net/xfrm/xfrm_policy.c
> index b5e665b..4891b7b 100644
> --- a/net/xfrm/xfrm_policy.c
> +++ b/net/xfrm/xfrm_policy.c
> @@ -1216,7 +1216,7 @@ static inline int policy_to_flow_dir(int dir)
>  }
>
>  static struct xfrm_policy *xfrm_sk_policy_lookup(const struct sock *sk, int dir,
> -                                                const struct flowi *fl)
> +                                                const struct flowi *fl, u16 family)
>  {
>         struct xfrm_policy *pol;
>         struct net *net = sock_net(sk);
> @@ -1225,8 +1225,7 @@ static struct xfrm_policy *xfrm_sk_policy_lookup(const struct sock *sk, int dir,
>         read_lock_bh(&net->xfrm.xfrm_policy_lock);
>         pol = rcu_dereference(sk->sk_policy[dir]);
>         if (pol != NULL) {
> -               bool match = xfrm_selector_match(&pol->selector, fl,
> -                                                sk->sk_family);
> +               bool match = xfrm_selector_match(&pol->selector, fl, family);
>                 int err = 0;
>
>                 if (match) {
> @@ -2221,7 +2220,7 @@ struct dst_entry *xfrm_lookup(struct net *net, struct dst_entry *dst_orig,
>         sk = sk_const_to_full_sk(sk);
>         if (sk && sk->sk_policy[XFRM_POLICY_OUT]) {
>                 num_pols = 1;
> -               pols[0] = xfrm_sk_policy_lookup(sk, XFRM_POLICY_OUT, fl);
> +               pols[0] = xfrm_sk_policy_lookup(sk, XFRM_POLICY_OUT, fl, family);
>                 err = xfrm_expand_policies(fl, family, pols,
>                                            &num_pols, &num_xfrms);
>                 if (err < 0)
> @@ -2500,7 +2499,7 @@ int __xfrm_policy_check(struct sock *sk, int dir, struct sk_buff *skb,
>         pol = NULL;
>         sk = sk_to_full_sk(sk);
>         if (sk && sk->sk_policy[dir]) {
> -               pol = xfrm_sk_policy_lookup(sk, dir, &fl);
> +               pol = xfrm_sk_policy_lookup(sk, dir, &fl, family);
>                 if (IS_ERR(pol)) {
>                         XFRM_INC_STATS(net, LINUX_MIB_XFRMINPOLERROR);
>                         return 0;
> --
> 1.9.1
>

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: net/xfrm: stack out-of-bounds in xfrm_flowi_sport
  2017-02-14  8:41   ` Dmitry Vyukov
@ 2017-02-14  9:08     ` Steffen Klassert
  2017-02-14  9:16       ` Dmitry Vyukov
  0 siblings, 1 reply; 8+ messages in thread
From: Steffen Klassert @ 2017-02-14  9:08 UTC (permalink / raw)
  To: Dmitry Vyukov
  Cc: Herbert Xu, David Miller, Eric Dumazet, netdev, LKML, syzkaller

On Tue, Feb 14, 2017 at 09:41:35AM +0100, Dmitry Vyukov wrote:
> On Tue, Feb 14, 2017 at 8:08 AM, Steffen Klassert
> <steffen.klassert@secunet.com> wrote:
> > On Mon, Feb 13, 2017 at 03:46:56PM +0100, Dmitry Vyukov wrote:
> >>
> >> On commit 7089db84e356562f8ba737c29e472cc42d530dbc.
> >>
> >>
> >> struct flowi4 fl4_stack allocated on stack in udp_sendmsg is being
> >> casted to larger struct flowi and then accessed.
> >
> > Looks like the problem is when using IPv4-mapped IPv6 addresses.
> >
> > Does the patch below help?
> 
> 
> Steffen, can you please run the reproducer I provided?
> I specifically spent time to supply you with a simple, reliable
> reproducer. I am not even saying about adding a test case for the bug.
> Kernel development practices seem to encourage developers to not
> bother with tests. But at least testing a patch that you are sending
> looks like a reasonable thing to do.

I tested this with my socket policy testcases of course.
I dont have a IPv4-mapped IPv6 addresses testcase and
changing userspace in my test setup means to rebuild
the system iso image.

Asking for a test is not so uncommon. You have the
testcase, why not running it again?

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: net/xfrm: stack out-of-bounds in xfrm_flowi_sport
  2017-02-14  9:08     ` Steffen Klassert
@ 2017-02-14  9:16       ` Dmitry Vyukov
  2017-02-15  6:26         ` Steffen Klassert
  0 siblings, 1 reply; 8+ messages in thread
From: Dmitry Vyukov @ 2017-02-14  9:16 UTC (permalink / raw)
  To: Steffen Klassert
  Cc: Herbert Xu, David Miller, Eric Dumazet, netdev, LKML, syzkaller

On Tue, Feb 14, 2017 at 10:08 AM, Steffen Klassert
<steffen.klassert@secunet.com> wrote:
> On Tue, Feb 14, 2017 at 09:41:35AM +0100, Dmitry Vyukov wrote:
>> On Tue, Feb 14, 2017 at 8:08 AM, Steffen Klassert
>> <steffen.klassert@secunet.com> wrote:
>> > On Mon, Feb 13, 2017 at 03:46:56PM +0100, Dmitry Vyukov wrote:
>> >>
>> >> On commit 7089db84e356562f8ba737c29e472cc42d530dbc.
>> >>
>> >>
>> >> struct flowi4 fl4_stack allocated on stack in udp_sendmsg is being
>> >> casted to larger struct flowi and then accessed.
>> >
>> > Looks like the problem is when using IPv4-mapped IPv6 addresses.
>> >
>> > Does the patch below help?
>>
>>
>> Steffen, can you please run the reproducer I provided?
>> I specifically spent time to supply you with a simple, reliable
>> reproducer. I am not even saying about adding a test case for the bug.
>> Kernel development practices seem to encourage developers to not
>> bother with tests. But at least testing a patch that you are sending
>> looks like a reasonable thing to do.
>
> I tested this with my socket policy testcases of course.
> I dont have a IPv4-mapped IPv6 addresses testcase and
> changing userspace in my test setup means to rebuild
> the system iso image.
>
> Asking for a test is not so uncommon. You have the
> testcase, why not running it again?


Because there are too many kernel subsystems and bugs. I need more
than 24h per day to reports and retest them.

I've run the repro with you patch and don't see the bug any more:

Tested-by: Dmitry Vyukov <dvyukov@google.com>

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: net/xfrm: stack out-of-bounds in xfrm_flowi_sport
  2017-02-14  9:16       ` Dmitry Vyukov
@ 2017-02-15  6:26         ` Steffen Klassert
  2017-02-28 13:39           ` Dmitry Vyukov
  0 siblings, 1 reply; 8+ messages in thread
From: Steffen Klassert @ 2017-02-15  6:26 UTC (permalink / raw)
  To: Dmitry Vyukov
  Cc: Herbert Xu, David Miller, Eric Dumazet, netdev, LKML, syzkaller

On Tue, Feb 14, 2017 at 10:16:44AM +0100, Dmitry Vyukov wrote:
> 
> I've run the repro with you patch and don't see the bug any more:
> 
> Tested-by: Dmitry Vyukov <dvyukov@google.com>

I've applied this to the ipsec tree now.

Thanks for testing!

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: net/xfrm: stack out-of-bounds in xfrm_flowi_sport
  2017-02-15  6:26         ` Steffen Klassert
@ 2017-02-28 13:39           ` Dmitry Vyukov
  2017-02-28 13:43             ` Steffen Klassert
  0 siblings, 1 reply; 8+ messages in thread
From: Dmitry Vyukov @ 2017-02-28 13:39 UTC (permalink / raw)
  To: Steffen Klassert
  Cc: Herbert Xu, David Miller, Eric Dumazet, netdev, LKML, syzkaller

On Wed, Feb 15, 2017 at 7:26 AM, Steffen Klassert
<steffen.klassert@secunet.com> wrote:
> On Tue, Feb 14, 2017 at 10:16:44AM +0100, Dmitry Vyukov wrote:
>>
>> I've run the repro with you patch and don't see the bug any more:
>>
>> Tested-by: Dmitry Vyukov <dvyukov@google.com>
>
> I've applied this to the ipsec tree now.
>
> Thanks for testing!


Hi Steffen,

Are you going to push this to Linus in this release? Still happens on
upstream branch.

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: net/xfrm: stack out-of-bounds in xfrm_flowi_sport
  2017-02-28 13:39           ` Dmitry Vyukov
@ 2017-02-28 13:43             ` Steffen Klassert
  0 siblings, 0 replies; 8+ messages in thread
From: Steffen Klassert @ 2017-02-28 13:43 UTC (permalink / raw)
  To: Dmitry Vyukov
  Cc: Herbert Xu, David Miller, Eric Dumazet, netdev, LKML, syzkaller

Hi Dmitry.

On Tue, Feb 28, 2017 at 02:39:17PM +0100, Dmitry Vyukov wrote:
> On Wed, Feb 15, 2017 at 7:26 AM, Steffen Klassert
> <steffen.klassert@secunet.com> wrote:
> > On Tue, Feb 14, 2017 at 10:16:44AM +0100, Dmitry Vyukov wrote:
> >>
> >> I've run the repro with you patch and don't see the bug any more:
> >>
> >> Tested-by: Dmitry Vyukov <dvyukov@google.com>
> >
> > I've applied this to the ipsec tree now.
> >
> > Thanks for testing!
> 
> 
> Hi Steffen,
> 
> Are you going to push this to Linus in this release? Still happens on
> upstream branch.

I'll do a pull request for the ipsec tree this week, should
go the way upstream then.

^ permalink raw reply	[flat|nested] 8+ messages in thread

end of thread, other threads:[~2017-02-28 13:47 UTC | newest]

Thread overview: 8+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2017-02-13 14:46 net/xfrm: stack out-of-bounds in xfrm_flowi_sport Dmitry Vyukov
2017-02-14  7:08 ` Steffen Klassert
2017-02-14  8:41   ` Dmitry Vyukov
2017-02-14  9:08     ` Steffen Klassert
2017-02-14  9:16       ` Dmitry Vyukov
2017-02-15  6:26         ` Steffen Klassert
2017-02-28 13:39           ` Dmitry Vyukov
2017-02-28 13:43             ` Steffen Klassert

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).