net/xfrm: stack out-of-bounds in xfrm_flowi_sport

2017-02-13 Thread Dmitry Vyukov
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 8800677df796
BUG: KASAN: stack-out-of-bounds in __xfrm6_selector_match
net/xfrm/xfrm_policy.c:89 [inline] at addr 8800677df796
BUG: KASAN: stack-out-of-bounds in xfrm_selector_match+0xc94/0xe40
net/xfrm/xfrm_policy.c:101 at addr 8800677df796
Read of size 2 by task a.out/3338
page:ea00016a38c8 count:0 mapcount:0 mapping:  (null) index:0x0
flags: 0x100()
raw: 0100   
raw:  dead0200 
page dumped because: kasan: bad access detected
CPU: 0 PID: 3338 Comm: a.out Tainted: GB   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:7fff6d081748 EFLAGS: 0246 ORIG_RAX: 002c
RAX: ffda RBX: 00401860 RCX: 00436ed3
RDX: 008f RSI: 20003f71 RDI: 0003
RBP:  R08: 20003000 R09: 0010
R10: 00040084 R11: 0246 R12: 004002b0
R13: 00401860 R14: 004018f0 R15: 
Memory state around the buggy address:
 8800677df680: f1 00 f2 f2 f2 f2 f2 f2 f2 f8 f2 f2 f2 f2 f2 f2
 8800677df700: f2 00 00 00 00 f2 f2 f2 f2 00 00 00 00 00 00 00
>8800677df780: f2 f2 f2 f2 f2 00 00 00 00 00 00 00 00 00 f2 f2
 ^
 8800677df800: f2 f3 f3 f3 f3 00 00 00 00 00 00 00 00 00 00 00
 8800677df880: 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 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 

int main()
{
  mmap((void*)0x2000ul, 0xfff000ul, 0x3ul, 0x32ul, -1, 0);
  int sock = socket(AF_INET6, SOCK_DGRAM, IPPROTO_IP);
  (*(uint64_t*)0x2098 = (uint64_t)0x20b5);
  (*(uint32_t*)0x20a0 = (uint32_t)0x1);
  (*(uint64_t*)0x2000 = (uint64_t)0x20005000);
  (*(uint64_t*)0x2008 = (uint64_t)0x20002fdc);
  (*(uint64_t*)0x2010 = (uint64_t)0x20001ff8);
  (*(uint64_t*)0x2018 = (uint64_t)0x20004ff0);
  (*(uint32_t*)0x2020 = (uint32_t)0x1);
  (*(uint32_t*)0x2024 = (uint32_t)0x0);
  (*(uint32_t*)0x2028 = (uint32_t)0x2);
  (*(uint32_t*)0x202c = (uint32_t)0x0);
  (*(uint32_t*)0x2030 = (uint32_t)0x0);
  (*(uint32_t*)0x2034 = (uint32_t)0x0);
  (*(uint32_t*)0x2038 = (uint32_t)0x0);
  (*(uint32_t*)0x203c = (uint32_t)0x0);
  setsockopt(sock, 0x29ul, 0x23ul, (void*)0x2000ul, 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.


Re: net/xfrm: stack out-of-bounds in xfrm_flowi_sport

2017-02-28 Thread Steffen Klassert
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
>  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 
> >
> > 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.


Re: net/xfrm: stack out-of-bounds in xfrm_flowi_sport

2017-02-28 Thread Dmitry Vyukov
On Wed, Feb 15, 2017 at 7:26 AM, Steffen Klassert
 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 
>
> 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.


Re: net/xfrm: stack out-of-bounds in xfrm_flowi_sport

2017-02-13 Thread Steffen Klassert
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 
Signed-off-by: Steffen Klassert 
---
 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



Re: net/xfrm: stack out-of-bounds in xfrm_flowi_sport

2017-02-14 Thread Dmitry Vyukov
On Tue, Feb 14, 2017 at 8:08 AM, Steffen Klassert
 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 
> Signed-off-by: Steffen Klassert 
> ---
>  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
>


Re: net/xfrm: stack out-of-bounds in xfrm_flowi_sport

2017-02-14 Thread Steffen Klassert
On Tue, Feb 14, 2017 at 09:41:35AM +0100, Dmitry Vyukov wrote:
> On Tue, Feb 14, 2017 at 8:08 AM, Steffen Klassert
>  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?


Re: net/xfrm: stack out-of-bounds in xfrm_flowi_sport

2017-02-14 Thread Dmitry Vyukov
On Tue, Feb 14, 2017 at 10:08 AM, Steffen Klassert
 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
>>  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 


Re: net/xfrm: stack out-of-bounds in xfrm_flowi_sport

2017-02-14 Thread Steffen Klassert
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 

I've applied this to the ipsec tree now.

Thanks for testing!