Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 64391381 authored by Andrei Makeev's avatar Andrei Makeev
Browse files

Fix stack corruption in _find_src_addr

According to man pages for sockaddr, struct sockaddr
is not guaranteed to be an equivalent of sockaddr_in6 (28 bytes)
and is usually an equivalent of sockaddr_in (16 bytes).

Therefore use of sockaddr here may lead to memory corruption
(stack corruption as it's stack allocated) when pointer
to this 16 byte struct is passed to getsockname() function that
will write 28 bytes there and overflow it.

We've seen this happening in our setup.

Solution comes from the same sockaddr man page:
using struct sockaddr_storage that guarantees to fit any
possible address size.

See https://man7.org/linux/man-pages/man3/sockaddr.3type.html



Test: cd packages/modules/DnsResolver && atest
Change-Id: I082dee7b68c6548742465bf0a34eac221401b497
Signed-off-by: default avatarAndrei Makeev <amaksoft@meta.com>
parent 80694005
Loading
Loading
Loading
Loading
+6 −4
Original line number Diff line number Diff line
@@ -227,8 +227,9 @@ static int have_ipv6(unsigned mark, uid_t uid, bool mdns) {
            .sin6_addr.s6_addr = {// 2000::
                                  0x20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}};
    sockaddr_union addr = {.sin6 = sin6_test};
    sockaddr sa;
    return _find_src_addr(&addr.sa, &sa, mark, uid, /*allow_v6_linklocal=*/mdns) == 1;
    sockaddr_storage sa;
    return _find_src_addr(&addr.sa, (struct sockaddr*)&sa, mark, uid,
                          /*allow_v6_linklocal=*/mdns) == 1;
}

static int have_ipv4(unsigned mark, uid_t uid) {
@@ -237,8 +238,9 @@ static int have_ipv4(unsigned mark, uid_t uid) {
            .sin_addr.s_addr = __constant_htonl(0x08080808L)  // 8.8.8.8
    };
    sockaddr_union addr = {.sin = sin_test};
    sockaddr sa;
    return _find_src_addr(&addr.sa, &sa, mark, uid, /*(don't care) allow_v6_linklocal=*/false) == 1;
    sockaddr_storage sa;
    return _find_src_addr(&addr.sa, (struct sockaddr*)&sa, mark, uid,
                          /*(don't care) allow_v6_linklocal=*/false) == 1;
}

// Internal version of getaddrinfo(), but limited to AI_NUMERICHOST.