net/sctp: out-of-bounds access in sctp_add_bind_addr

62 views
Skip to first unread message

Dmitry Vyukov

unread,
Jan 25, 2016, 9:02:58 AM1/25/16
to Vlad Yasevich, Neil Horman, David S. Miller, linux...@vger.kernel.org, netdev, LKML, Marcelo Ricardo Leitner, syzkaller, Kostya Serebryany, Alexander Potapenko, Sasha Levin, Eric Dumazet
Hello,

I've git the following error report while running syzkaller fuzzer:

==================================================================
BUG: KASAN: slab-out-of-bounds in memcpy+0x1d/0x40 at addr ffff88006c6361e8
Read of size 28 by task syz-executor/12551
=============================================================================
BUG kmalloc-16 (Not tainted): kasan: bad access detected
-----------------------------------------------------------------------------

INFO: Allocated in sctp_setsockopt_bindx+0xd2/0x3e0 age=12 cpu=2 pid=12551
[< inline >] kmalloc include/linux/slab.h:468
[< none >] sctp_setsockopt_bindx+0xd2/0x3e0 net/sctp/socket.c:975
[< none >] sctp_setsockopt+0x1493/0x3630 net/sctp/socket.c:3711
[< none >] sock_common_setsockopt+0x97/0xd0 net/core/sock.c:2620
[< inline >] SYSC_setsockopt net/socket.c:1752
[< none >] SyS_setsockopt+0x15b/0x250 net/socket.c:1731
[< none >] entry_SYSCALL_64_fastpath+0x16/0x7a
arch/x86/entry/entry_64.S:185

INFO: Slab 0xffffea0001b18d80 objects=16 used=4 fp=0xffff88006c6376e0
flags=0x5fffc0000004080
INFO: Object 0xffff88006c6361e8 @offset=488 fp=0x0000000000000002
Bytes b4 ffff88006c6361d8: 00 00 00 00 00 00 00 00 2f 98 34 88 ff ff
ff ff ......../.4.....
Object ffff88006c6361e8: 02 00 00 00 00 00 00 00 02 00 ab 07 7f 00 00
01 ................
CPU: 2 PID: 12551 Comm: syz-executor Tainted: G B 4.5.0-rc1+ #278
Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS Bochs 01/01/2011
00000000ffffffff ffff880036397928 ffffffff8299a02d ffff88003e807900
ffff88006c6361e8 ffff88006c636000 ffff880036397958 ffffffff81752814
ffff88003e807900 ffffea0001b18d80 ffff88006c6361e8 ffff88006c6361e8

Call Trace:
[<ffffffff8175ad54>] __asan_loadN+0x124/0x1a0 mm/kasan/kasan.c:512
[<ffffffff8175b2dd>] memcpy+0x1d/0x40 mm/kasan/kasan.c:297
[<ffffffff85dcb249>] sctp_add_bind_addr+0xa9/0x270 net/sctp/bind_addr.c:162
[<ffffffff85dcfd66>] sctp_do_bind+0x336/0x580 net/sctp/socket.c:389
[<ffffffff85dd16ec>] sctp_bindx_add+0xac/0x1a0 net/sctp/socket.c:471
[<ffffffff85dd5cc8>] sctp_setsockopt_bindx+0x2f8/0x3e0 net/sctp/socket.c:1010
[<ffffffff85dde283>] sctp_setsockopt+0x1493/0x3630 net/sctp/socket.c:3711
[<ffffffff851f5ae7>] sock_common_setsockopt+0x97/0xd0 net/core/sock.c:2620
[< inline >] SYSC_setsockopt net/socket.c:1752
[<ffffffff851f2c3b>] SyS_setsockopt+0x15b/0x250 net/socket.c:1731
[<ffffffff863595f6>] entry_SYSCALL_64_fastpath+0x16/0x7a
arch/x86/entry/entry_64.S:185

Memory state around the buggy address:
ffff88006c636080: fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc
ffff88006c636100: fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc
>ffff88006c636180: fc fc fc fc fc fc fc fc fc fc fc fc fc 00 00 fc
^
ffff88006c636200: fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc
ffff88006c636280: fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc
==================================================================


sctp_setsockopt_bindx verifies that the user-passed address has valid
len for the specified family, but then sctp_add_bind_addr copies whole
sctp_addr from there. This causes heap out-of-bounds access and can
crash kernel. Not sure if it is possible to copy out the trailing
garbage to user-space later.

On commit 92e963f50fc74041b5e9e744c330dca48e04f08d (Jan 25).

Neil Horman

unread,
Jan 25, 2016, 9:32:02 AM1/25/16
to Dmitry Vyukov, Vlad Yasevich, David S. Miller, linux...@vger.kernel.org, netdev, LKML, Marcelo Ricardo Leitner, syzkaller, Kostya Serebryany, Alexander Potapenko, Sasha Levin, Eric Dumazet
It does more than that though. sctp_setsockopt_bindx checks the following:
1) That passed addr_size is greater than zero
2) that the entire range of memory between addrs and addrs+addr_size is readable
3) That at least one address structure worth of data is available (implicit in
the while (walk_size < addr_size) loop).

Could one of the sockaddr_len fields in one of the addresses have been mangled
so that it appeared shorter in the the while loop from (3), so that a copy of
sizeof(sctp_addr in sctp_add_bind_addr overrun the allocated memory?

Neil

> On commit 92e963f50fc74041b5e9e744c330dca48e04f08d (Jan 25).
> --
> To unsubscribe from this list: send the line "unsubscribe linux-sctp" in
> the body of a message to majo...@vger.kernel.org
> More majordomo info at http://vger.kernel.org/majordomo-info.html
>

Dmitry Vyukov

unread,
Jan 25, 2016, 9:42:35 AM1/25/16
to Neil Horman, Vlad Yasevich, David S. Miller, linux...@vger.kernel.org, netdev, LKML, Marcelo Ricardo Leitner, syzkaller, Kostya Serebryany, Alexander Potapenko, Sasha Levin, Eric Dumazet
I may be missing something, but what I see is:

1. we check that there is at least family:
if (walk_size + sizeof(sa_family_t) > addrs_size) {

2. get family descriptor:
af = sctp_get_af_specific(sa_addr->sa_family);

3. check that the address size is enough to hold the declared family:
if (!af || (walk_size + af->sockaddr_len) > addrs_size) {

4. then we do sctp_add_bind_addr, which copies whole sctp_addr from addr:

int sctp_add_bind_addr(struct sctp_bind_addr *bp, union sctp_addr *new,
...
memcpy(&addr->a, new, sizeof(*new));

Now imagine that the addr is ipv4 (16 or so bytes, that's what we
checked) and we copy 28 bytes (ipv6) from addr.

Marcelo Ricardo Leitner

unread,
Jan 25, 2016, 9:48:09 AM1/25/16
to Dmitry Vyukov, Neil Horman, Vlad Yasevich, David S. Miller, linux...@vger.kernel.org, netdev, LKML, syzkaller, Kostya Serebryany, Alexander Potapenko, Sasha Levin, Eric Dumazet
Yes, that's pretty much it I think. That memcpy should be limited to
af->sockaddr_len, it's just that af is not readily available in that
function.

Marcelo

Neil Horman

unread,
Jan 25, 2016, 11:05:57 AM1/25/16
to Marcelo Ricardo Leitner, Dmitry Vyukov, Vlad Yasevich, David S. Miller, linux...@vger.kernel.org, netdev, LKML, syzkaller, Kostya Serebryany, Alexander Potapenko, Sasha Levin, Eric Dumazet
Yeah, ok, we're on the same page. If the size of the sctp_addr struct is larger
than the size that the address family specifies, we're up the creek. We should
augment sctp_add_bind_addr to take the family length as a parameter and either
limit the copy to the min of the sruct size and the family size

Neil

> Marcelo

Marcelo Ricardo Leitner

unread,
Jan 25, 2016, 11:16:12 AM1/25/16
to dvy...@google.com, Neil Horman, Vlad Yasevich, net...@vger.kernel.org, linux...@vger.kernel.org, linux-...@vger.kernel.org, da...@davemloft.net, syzk...@googlegroups.com, k...@google.com, gli...@google.com, sasha...@oracle.com, edum...@google.com
Something like this. Builds, but UNTESTED.
Uses union sizeof where possible but when reading from a buffer that is
not aligned to it, like that user supplied one. Then relies on
af->sockaddr_len

--8<--

---
include/net/sctp/structs.h | 2 +-
net/sctp/bind_addr.c | 14 ++++++++------
net/sctp/protocol.c | 1 +
net/sctp/sm_make_chunk.c | 2 +-
net/sctp/socket.c | 5 +++--
5 files changed, 14 insertions(+), 10 deletions(-)

diff --git a/include/net/sctp/structs.h b/include/net/sctp/structs.h
index 20e72129be1ce0063eeafcbaadcee1f37e0c614c..97ba8a8c466f5c50bdc87ec578792e56553baa91 100644
--- a/include/net/sctp/structs.h
+++ b/include/net/sctp/structs.h
@@ -1099,7 +1099,7 @@ int sctp_bind_addr_dup(struct sctp_bind_addr *dest,
const struct sctp_bind_addr *src,
gfp_t gfp);
int sctp_add_bind_addr(struct sctp_bind_addr *, union sctp_addr *,
- __u8 addr_state, gfp_t gfp);
+ int new_size, __u8 addr_state, gfp_t gfp);
int sctp_del_bind_addr(struct sctp_bind_addr *, union sctp_addr *);
int sctp_bind_addr_match(struct sctp_bind_addr *, const union sctp_addr *,
struct sctp_sock *);
diff --git a/net/sctp/bind_addr.c b/net/sctp/bind_addr.c
index 871cdf9567e6bc9c13cb1077dc6866a67e6e4367..80129d10a0af9c33e7348b79d010b9e5e948e584 100644
--- a/net/sctp/bind_addr.c
+++ b/net/sctp/bind_addr.c
@@ -111,7 +111,8 @@ int sctp_bind_addr_dup(struct sctp_bind_addr *dest,
dest->port = src->port;

list_for_each_entry(addr, &src->address_list, list) {
- error = sctp_add_bind_addr(dest, &addr->a, 1, gfp);
+ error = sctp_add_bind_addr(dest, &addr->a, sizeof(addr->a),
+ 1, gfp);
if (error < 0)
break;
}
@@ -150,7 +151,7 @@ void sctp_bind_addr_free(struct sctp_bind_addr *bp)

/* Add an address to the bind address list in the SCTP_bind_addr structure. */
int sctp_add_bind_addr(struct sctp_bind_addr *bp, union sctp_addr *new,
- __u8 addr_state, gfp_t gfp)
+ int new_size, __u8 addr_state, gfp_t gfp)
{
struct sctp_sockaddr_entry *addr;

@@ -159,7 +160,7 @@ int sctp_add_bind_addr(struct sctp_bind_addr *bp, union sctp_addr *new,
if (!addr)
return -ENOMEM;

- memcpy(&addr->a, new, sizeof(*new));
+ memcpy(&addr->a, new, min_t(size_t, sizeof(*new), new_size));

/* Fix up the port if it has not yet been set.
* Both v4 and v6 have the port at the same offset.
@@ -291,7 +292,8 @@ int sctp_raw_to_bind_addrs(struct sctp_bind_addr *bp, __u8 *raw_addr_list,
}

af->from_addr_param(&addr, rawaddr, htons(port), 0);
- retval = sctp_add_bind_addr(bp, &addr, SCTP_ADDR_SRC, gfp);
+ retval = sctp_add_bind_addr(bp, &addr, sizeof(addr),
+ SCTP_ADDR_SRC, gfp);
if (retval) {
/* Can't finish building the list, clean up. */
sctp_bind_addr_clean(bp);
@@ -453,8 +455,8 @@ static int sctp_copy_one_addr(struct net *net, struct sctp_bind_addr *dest,
(((AF_INET6 == addr->sa.sa_family) &&
(flags & SCTP_ADDR6_ALLOWED) &&
(flags & SCTP_ADDR6_PEERSUPP))))
- error = sctp_add_bind_addr(dest, addr, SCTP_ADDR_SRC,
- gfp);
+ error = sctp_add_bind_addr(dest, addr, sizeof(addr),
+ SCTP_ADDR_SRC, gfp);
}

return error;
diff --git a/net/sctp/protocol.c b/net/sctp/protocol.c
index ab0d538a74ed593571cfaef02cd1bb7ce872abe6..2fb609008311f51344704d82f21b4de9f08253da 100644
--- a/net/sctp/protocol.c
+++ b/net/sctp/protocol.c
@@ -214,6 +214,7 @@ int sctp_copy_local_addr_list(struct net *net, struct sctp_bind_addr *bp,
(copy_flags & SCTP_ADDR6_ALLOWED) &&
(copy_flags & SCTP_ADDR6_PEERSUPP)))) {
error = sctp_add_bind_addr(bp, &addr->a,
+ sizeof(addr->a),
SCTP_ADDR_SRC, GFP_ATOMIC);
if (error)
goto end_copy;
diff --git a/net/sctp/sm_make_chunk.c b/net/sctp/sm_make_chunk.c
index 5d6a03fad3789a12290f5f14c5a7efa69c98f41a..1b91e9760fe514db6d89457e1d5da9e02800745e 100644
--- a/net/sctp/sm_make_chunk.c
+++ b/net/sctp/sm_make_chunk.c
@@ -1830,7 +1830,7 @@ no_hmac:
/* Also, add the destination address. */
if (list_empty(&retval->base.bind_addr.address_list)) {
sctp_add_bind_addr(&retval->base.bind_addr, &chunk->dest,
- SCTP_ADDR_SRC, GFP_ATOMIC);
+ sizeof(chunk->dest), SCTP_ADDR_SRC, GFP_ATOMIC);
}

retval->next_tsn = retval->c.initial_tsn;
diff --git a/net/sctp/socket.c b/net/sctp/socket.c
index 9bb80ec4c08ff06f6e629078c5a926c3def3ce23..3765f1fd06aac253ec5ee8e8bd18fffefda64d62 100644
--- a/net/sctp/socket.c
+++ b/net/sctp/socket.c
@@ -386,7 +386,8 @@ static int sctp_do_bind(struct sock *sk, union sctp_addr *addr, int len)
/* Add the address to the bind address list.
* Use GFP_ATOMIC since BHs will be disabled.
*/
- ret = sctp_add_bind_addr(bp, addr, SCTP_ADDR_SRC, GFP_ATOMIC);
+ ret = sctp_add_bind_addr(bp, addr, af->sockaddr_len,
+ SCTP_ADDR_SRC, GFP_ATOMIC);

/* Copy back into socket for getsockname() use. */
if (!ret) {
@@ -576,7 +577,7 @@ static int sctp_send_asconf_add_ip(struct sock *sk,
addr = addr_buf;
af = sctp_get_af_specific(addr->v4.sin_family);
memcpy(&saveaddr, addr, af->sockaddr_len);
- retval = sctp_add_bind_addr(bp, &saveaddr,
+ retval = sctp_add_bind_addr(bp, &saveaddr, sizeof(saveaddr),
SCTP_ADDR_NEW, GFP_ATOMIC);
addr_buf += af->sockaddr_len;
}
--
2.5.0

Neil Horman

unread,
Jan 25, 2016, 12:29:29 PM1/25/16
to Marcelo Ricardo Leitner, dvy...@google.com, Vlad Yasevich, net...@vger.kernel.org, linux...@vger.kernel.org, linux-...@vger.kernel.org, da...@davemloft.net, syzk...@googlegroups.com, k...@google.com, gli...@google.com, sasha...@oracle.com, edum...@google.com
> --
> To unsubscribe from this list: send the line "unsubscribe linux-sctp" in
> the body of a message to majo...@vger.kernel.org
> More majordomo info at http://vger.kernel.org/majordomo-info.html
>
Agreed, that looks correct
Neil

Marcelo Ricardo Leitner

unread,
Jan 25, 2016, 12:53:05 PM1/25/16
to dvy...@google.com, Neil Horman, Vlad Yasevich, net...@vger.kernel.org, linux...@vger.kernel.org, linux-...@vger.kernel.org, da...@davemloft.net, syzk...@googlegroups.com, k...@google.com, gli...@google.com, sasha...@oracle.com, edum...@google.com
Great. Dmitry, please give this a run. Local tests looked good but who
knows what syzkaller may find.

Thanks

--8<--

Dmitry reported that sctp_add_bind_addr may read more bytes than
expected in case the parameter is a IPv4 addr supplied by the user
through calls such as sctp_bindx_add(), because it always copies
sizeof(union sctp_addr) while the buffer may be just a struct
sockaddr_in, which is smaller.

This patch then fixes it by limiting the memcpy to the min between the
union size and a (new parameter) provided addr size. Where possible this
parameter still is the size of that union, except for reading from
user-provided buffers, which then it accounts for protocol type.

Reported-by: Dmitry Vyukov <dvy...@google.com>
Signed-off-by: Marcelo Ricardo Leitner <marcelo...@gmail.com>
index 5ca2ebfe0be83882fcb841de6fa8029b6455ef85..213be3821a1d49e0c469c4ad4e9ff055a03205c5 100644

Dmitry Vyukov

unread,
Jan 26, 2016, 8:29:09 AM1/26/16
to Marcelo Ricardo Leitner, Neil Horman, Vlad Yasevich, netdev, linux...@vger.kernel.org, LKML, David Miller, syzkaller, Kostya Serebryany, Alexander Potapenko, Sasha Levin, Eric Dumazet
On Mon, Jan 25, 2016 at 6:52 PM, Marcelo Ricardo Leitner
<marcelo...@gmail.com> wrote:
> Great. Dmitry, please give this a run. Local tests looked good but who
> knows what syzkaller may find.

Now running with this patch.

Marcelo Ricardo Leitner

unread,
Mar 7, 2016, 2:44:11 PM3/7/16
to Dmitry Vyukov, Neil Horman, Vlad Yasevich, netdev, linux...@vger.kernel.org, LKML, David Miller, syzkaller, Kostya Serebryany, Alexander Potapenko, Sasha Levin, Eric Dumazet
On Tue, Jan 26, 2016 at 02:28:48PM +0100, Dmitry Vyukov wrote:
> On Mon, Jan 25, 2016 at 6:52 PM, Marcelo Ricardo Leitner
> <marcelo...@gmail.com> wrote:
> > Great. Dmitry, please give this a run. Local tests looked good but who
> > knows what syzkaller may find.
>
> Now running with this patch.

Hi Dmitry, do you remember if this one succeeded?

Dmitry Vyukov

unread,
Mar 7, 2016, 2:45:41 PM3/7/16
to Marcelo Ricardo Leitner, Neil Horman, Vlad Yasevich, netdev, linux...@vger.kernel.org, LKML, David Miller, syzkaller, Kostya Serebryany, Alexander Potapenko, Sasha Levin, Eric Dumazet
Yes, it is. I never saw this bug again. Forgot to update this thread. Sorry.

On Mon, Mar 7, 2016 at 8:44 PM, Marcelo Ricardo Leitner

Marcelo Ricardo Leitner

unread,
Mar 7, 2016, 2:51:22 PM3/7/16
to Dmitry Vyukov, Neil Horman, Vlad Yasevich, netdev, linux...@vger.kernel.org, LKML, David Miller, syzkaller, Kostya Serebryany, Alexander Potapenko, Sasha Levin, Eric Dumazet
On Mon, Mar 07, 2016 at 08:45:20PM +0100, Dmitry Vyukov wrote:
> Yes, it is. I never saw this bug again. Forgot to update this thread. Sorry.

Cool, thanks. The patch isn't applied yet, so either some other patch
fixed it and this patch not necessary anymore or you kept the patch
applied. Please confirm which one :-)

Dmitry Vyukov

unread,
Mar 7, 2016, 2:56:29 PM3/7/16
to Marcelo Ricardo Leitner, Neil Horman, Vlad Yasevich, netdev, linux...@vger.kernel.org, LKML, David Miller, syzkaller, Kostya Serebryany, Alexander Potapenko, Sasha Levin, Eric Dumazet
I kept the patch applied.

On Mon, Mar 7, 2016 at 8:51 PM, Marcelo Ricardo Leitner

Marcelo Ricardo Leitner

unread,
Mar 7, 2016, 3:00:13 PM3/7/16
to Dmitry Vyukov, Neil Horman, Vlad Yasevich, netdev, linux...@vger.kernel.org, LKML, David Miller, syzkaller, Kostya Serebryany, Alexander Potapenko, Sasha Levin, Eric Dumazet
On Mon, Mar 07, 2016 at 08:56:08PM +0100, Dmitry Vyukov wrote:
> I kept the patch applied.

Then Dave, please consider applying this patch.

Thanks.

David Miller

unread,
Mar 7, 2016, 3:21:26 PM3/7/16
to marcelo...@gmail.com, dvy...@google.com, nho...@tuxdriver.com, vyas...@gmail.com, net...@vger.kernel.org, linux...@vger.kernel.org, linux-...@vger.kernel.org, syzk...@googlegroups.com, k...@google.com, gli...@google.com, sasha...@oracle.com, edum...@google.com
From: Marcelo Ricardo Leitner <marcelo...@gmail.com>
Date: Mon, 7 Mar 2016 17:00:08 -0300

> On Mon, Mar 07, 2016 at 08:56:08PM +0100, Dmitry Vyukov wrote:
>> I kept the patch applied.
>
> Then Dave, please consider applying this patch.

Please submit the patch properly, as a fresh mailing list posting, and
integrating Tested-by: et al. tags as necessary.

Thanks.

Marcelo Ricardo Leitner

unread,
Mar 7, 2016, 4:17:40 PM3/7/16
to net...@vger.kernel.org, dvy...@google.com, nho...@tuxdriver.com, vyas...@gmail.com, linux...@vger.kernel.org, linux-...@vger.kernel.org, syzk...@googlegroups.com, k...@google.com, gli...@google.com, sasha...@oracle.com, edum...@google.com, da...@davemloft.net
Dmitry reported that sctp_add_bind_addr may read more bytes than
expected in case the parameter is a IPv4 addr supplied by the user
through calls such as sctp_bindx_add(), because it always copies
sizeof(union sctp_addr) while the buffer may be just a struct
sockaddr_in, which is smaller.

This patch then fixes it by limiting the memcpy to the min between the
union size and a (new parameter) provided addr size. Where possible this
parameter still is the size of that union, except for reading from
user-provided buffers, which then it accounts for protocol type.

Reported-by: Dmitry Vyukov <dvy...@google.com>
Tested-by: Dmitry Vyukov <dvy...@google.com>
Signed-off-by: Marcelo Ricardo Leitner <marcelo...@gmail.com>
---
include/net/sctp/structs.h | 2 +-
net/sctp/bind_addr.c | 14 ++++++++------
net/sctp/protocol.c | 1 +
net/sctp/sm_make_chunk.c | 3 ++-
net/sctp/socket.c | 4 +++-
5 files changed, 15 insertions(+), 9 deletions(-)

diff --git a/include/net/sctp/structs.h b/include/net/sctp/structs.h
index 205630bb5010b8ac76b84651b302e488fc1c76ff..f816344f65f2dc47d5a3088d92d77e68aa6fd5c3 100644
--- a/include/net/sctp/structs.h
+++ b/include/net/sctp/structs.h
@@ -1098,7 +1098,7 @@ int sctp_bind_addr_dup(struct sctp_bind_addr *dest,
index 1099e99a53c485402ddd9c0693ff5cdd707accca..d3d50daa248b06d7a4306d903b2dad89e9d2acbd 100644
--- a/net/sctp/protocol.c
+++ b/net/sctp/protocol.c
@@ -216,6 +216,7 @@ int sctp_copy_local_addr_list(struct net *net, struct sctp_bind_addr *bp,
(copy_flags & SCTP_ADDR6_ALLOWED) &&
(copy_flags & SCTP_ADDR6_PEERSUPP)))) {
error = sctp_add_bind_addr(bp, &addr->a,
+ sizeof(addr->a),
SCTP_ADDR_SRC, GFP_ATOMIC);
if (error)
goto end_copy;
diff --git a/net/sctp/sm_make_chunk.c b/net/sctp/sm_make_chunk.c
index 5d6a03fad3789a12290f5f14c5a7efa69c98f41a..7fe971e30ad6b60e21bfa2986f1c9909a0dabc21 100644
--- a/net/sctp/sm_make_chunk.c
+++ b/net/sctp/sm_make_chunk.c
@@ -1830,7 +1830,8 @@ no_hmac:
/* Also, add the destination address. */
if (list_empty(&retval->base.bind_addr.address_list)) {
sctp_add_bind_addr(&retval->base.bind_addr, &chunk->dest,
- SCTP_ADDR_SRC, GFP_ATOMIC);
+ sizeof(chunk->dest), SCTP_ADDR_SRC,
+ GFP_ATOMIC);
}

retval->next_tsn = retval->c.initial_tsn;
diff --git a/net/sctp/socket.c b/net/sctp/socket.c
index e878da0949dbfc0012d2e7985bf6e28386678d0f..0e3de0c71137c9ae823bebd7b827561826792d4a 100644
--- a/net/sctp/socket.c
+++ b/net/sctp/socket.c
@@ -386,7 +386,8 @@ static int sctp_do_bind(struct sock *sk, union sctp_addr *addr, int len)
/* Add the address to the bind address list.
* Use GFP_ATOMIC since BHs will be disabled.
*/
- ret = sctp_add_bind_addr(bp, addr, SCTP_ADDR_SRC, GFP_ATOMIC);
+ ret = sctp_add_bind_addr(bp, addr, af->sockaddr_len,
+ SCTP_ADDR_SRC, GFP_ATOMIC);

/* Copy back into socket for getsockname() use. */
if (!ret) {
@@ -577,6 +578,7 @@ static int sctp_send_asconf_add_ip(struct sock *sk,
af = sctp_get_af_specific(addr->v4.sin_family);
memcpy(&saveaddr, addr, af->sockaddr_len);
retval = sctp_add_bind_addr(bp, &saveaddr,
+ sizeof(saveaddr),

kbuild test robot

unread,
Mar 7, 2016, 6:18:56 PM3/7/16
to Marcelo Ricardo Leitner, kbuil...@01.org, net...@vger.kernel.org, dvy...@google.com, nho...@tuxdriver.com, vyas...@gmail.com, linux...@vger.kernel.org, linux-...@vger.kernel.org, syzk...@googlegroups.com, k...@google.com, gli...@google.com, sasha...@oracle.com, edum...@google.com, da...@davemloft.net
net/sctp/bind_addr.c:458:42-48: ERROR: application of sizeof to pointer

sizeof when applied to a pointer typed expression gives the size of
the pointer

Generated by: scripts/coccinelle/misc/noderef.cocci

CC: Marcelo Ricardo Leitner <marcelo...@gmail.com>
Signed-off-by: Fengguang Wu <fenggu...@intel.com>
---

bind_addr.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)

--- a/net/sctp/bind_addr.c
+++ b/net/sctp/bind_addr.c
@@ -455,7 +455,7 @@ static int sctp_copy_one_addr(struct net
(((AF_INET6 == addr->sa.sa_family) &&
(flags & SCTP_ADDR6_ALLOWED) &&
(flags & SCTP_ADDR6_PEERSUPP))))
- error = sctp_add_bind_addr(dest, addr, sizeof(addr),
+ error = sctp_add_bind_addr(dest, addr, sizeof(*addr),
SCTP_ADDR_SRC, gfp);
}

kbuild test robot

unread,
Mar 7, 2016, 6:19:05 PM3/7/16
to Marcelo Ricardo Leitner, kbuil...@01.org, net...@vger.kernel.org, dvy...@google.com, nho...@tuxdriver.com, vyas...@gmail.com, linux...@vger.kernel.org, linux-...@vger.kernel.org, syzk...@googlegroups.com, k...@google.com, gli...@google.com, sasha...@oracle.com, edum...@google.com, da...@davemloft.net
Hi Marcelo,

[auto build test WARNING on net/master]

url: https://github.com/0day-ci/linux/commits/Marcelo-Ricardo-Leitner/sctp-fix-copying-more-bytes-than-expected-in-sctp_add_bind_addr/20160308-052009


coccinelle warnings: (new ones prefixed by >>)

>> net/sctp/bind_addr.c:458:42-48: ERROR: application of sizeof to pointer

Please review and possibly fold the followup patch.

---
0-DAY kernel test infrastructure Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all Intel Corporation

Marcelo Ricardo Leitner

unread,
Mar 7, 2016, 6:27:16 PM3/7/16
to kbuild test robot, kbuil...@01.org, net...@vger.kernel.org, dvy...@google.com, nho...@tuxdriver.com, vyas...@gmail.com, linux...@vger.kernel.org, linux-...@vger.kernel.org, syzk...@googlegroups.com, k...@google.com, gli...@google.com, sasha...@oracle.com, edum...@google.com, da...@davemloft.net
Hi,

Em 07-03-2016 20:17, kbuild test robot escreveu:
> Hi Marcelo,
>
> [auto build test WARNING on net/master]
>
> url: https://github.com/0day-ci/linux/commits/Marcelo-Ricardo-Leitner/sctp-fix-copying-more-bytes-than-expected-in-sctp_add_bind_addr/20160308-052009
>
>
> coccinelle warnings: (new ones prefixed by >>)
>
>>> net/sctp/bind_addr.c:458:42-48: ERROR: application of sizeof to pointer
>
> Please review and possibly fold the followup patch.

Oops, nice catch, thanks.

I can fold it if Dave prefers, no problem. I'll wait for a confirmation.

Marcelo

David Miller

unread,
Mar 7, 2016, 11:15:17 PM3/7/16
to marcelo...@gmail.com, l...@intel.com, kbuil...@01.org, net...@vger.kernel.org, dvy...@google.com, nho...@tuxdriver.com, vyas...@gmail.com, linux...@vger.kernel.org, linux-...@vger.kernel.org, syzk...@googlegroups.com, k...@google.com, gli...@google.com, sasha...@oracle.com, edum...@google.com
From: Marcelo Ricardo Leitner <marcelo...@gmail.com>
Date: Mon, 7 Mar 2016 20:27:11 -0300
Please respin your patch with this folded into it, thanks.

Marcelo Ricardo Leitner

unread,
Mar 8, 2016, 8:34:39 AM3/8/16
to net...@vger.kernel.org, dvy...@google.com, nho...@tuxdriver.com, vyas...@gmail.com, linux...@vger.kernel.org, linux-...@vger.kernel.org, syzk...@googlegroups.com, k...@google.com, gli...@google.com, sasha...@oracle.com, edum...@google.com, da...@davemloft.net, l...@intel.com, fenggu...@intel.com
Dmitry reported that sctp_add_bind_addr may read more bytes than
expected in case the parameter is a IPv4 addr supplied by the user
through calls such as sctp_bindx_add(), because it always copies
sizeof(union sctp_addr) while the buffer may be just a struct
sockaddr_in, which is smaller.

This patch then fixes it by limiting the memcpy to the min between the
union size and a (new parameter) provided addr size. Where possible this
parameter still is the size of that union, except for reading from
user-provided buffers, which then it accounts for protocol type.

Reported-by: Dmitry Vyukov <dvy...@google.com>
Tested-by: Dmitry Vyukov <dvy...@google.com>
Signed-off-by: Marcelo Ricardo Leitner <marcelo...@gmail.com>
---
v1->v2:
Fixed sizeof() at a pointer, reported by Fengguang Wu

include/net/sctp/structs.h | 2 +-
net/sctp/bind_addr.c | 14 ++++++++------
net/sctp/protocol.c | 1 +
net/sctp/sm_make_chunk.c | 3 ++-
net/sctp/socket.c | 4 +++-
5 files changed, 15 insertions(+), 9 deletions(-)

diff --git a/include/net/sctp/structs.h b/include/net/sctp/structs.h
index 205630bb5010b8ac76b84651b302e488fc1c76ff..f816344f65f2dc47d5a3088d92d77e68aa6fd5c3 100644
--- a/include/net/sctp/structs.h
+++ b/include/net/sctp/structs.h
@@ -1098,7 +1098,7 @@ int sctp_bind_addr_dup(struct sctp_bind_addr *dest,
const struct sctp_bind_addr *src,
gfp_t gfp);
int sctp_add_bind_addr(struct sctp_bind_addr *, union sctp_addr *,
- __u8 addr_state, gfp_t gfp);
+ int new_size, __u8 addr_state, gfp_t gfp);
int sctp_del_bind_addr(struct sctp_bind_addr *, union sctp_addr *);
int sctp_bind_addr_match(struct sctp_bind_addr *, const union sctp_addr *,
struct sctp_sock *);
diff --git a/net/sctp/bind_addr.c b/net/sctp/bind_addr.c
index 871cdf9567e6bc9c13cb1077dc6866a67e6e4367..401c60750b206c00f9fb14f6b635d15a4342ae0f 100644
--- a/net/sctp/bind_addr.c
+++ b/net/sctp/bind_addr.c
@@ -453,8 +455,8 @@ static int sctp_copy_one_addr(struct net *net, struct sctp_bind_addr *dest,
(((AF_INET6 == addr->sa.sa_family) &&
(flags & SCTP_ADDR6_ALLOWED) &&
(flags & SCTP_ADDR6_PEERSUPP))))
- error = sctp_add_bind_addr(dest, addr, SCTP_ADDR_SRC,
- gfp);
+ error = sctp_add_bind_addr(dest, addr, sizeof(*addr),

David Miller

unread,
Mar 8, 2016, 3:05:23 PM3/8/16
to marcelo...@gmail.com, net...@vger.kernel.org, dvy...@google.com, nho...@tuxdriver.com, vyas...@gmail.com, linux...@vger.kernel.org, linux-...@vger.kernel.org, syzk...@googlegroups.com, k...@google.com, gli...@google.com, sasha...@oracle.com, edum...@google.com, l...@intel.com, fenggu...@intel.com
From: Marcelo Ricardo Leitner <marcelo...@gmail.com>
Date: Tue, 8 Mar 2016 10:34:28 -0300

> Dmitry reported that sctp_add_bind_addr may read more bytes than
> expected in case the parameter is a IPv4 addr supplied by the user
> through calls such as sctp_bindx_add(), because it always copies
> sizeof(union sctp_addr) while the buffer may be just a struct
> sockaddr_in, which is smaller.
>
> This patch then fixes it by limiting the memcpy to the min between the
> union size and a (new parameter) provided addr size. Where possible this
> parameter still is the size of that union, except for reading from
> user-provided buffers, which then it accounts for protocol type.
>
> Reported-by: Dmitry Vyukov <dvy...@google.com>
> Tested-by: Dmitry Vyukov <dvy...@google.com>
> Signed-off-by: Marcelo Ricardo Leitner <marcelo...@gmail.com>

Applied, thanks.
Reply all
Reply to author
Forward
0 new messages