Skip to content

MSAN interceptors validate the initialization of structure unused padding bytes #162216

@grooverdan

Description

@grooverdan

Minor, but annoying to debug is that a structure where all members are initialised, isn't initialised enough for the __interceptor_getaddrinfo (and looking at the interceptor macro probably all structs passed to interceptors with padding).

t.cpp:

#include <arpa/inet.h>
#include <netdb.h>
#include <stdio.h>

addrinfo get_addrinfo(int flags, int family, int socktype,
                                   int protocol)
{
  struct addrinfo ret = {
      flags,
      family,
      socktype,
      protocol,
      0,
      0,
      0,
      0
  };

  return ret;
}

int main() {
  addrinfo* res;
  addrinfo hints = get_addrinfo(0, AF_UNSPEC, SOCK_STREAM, 0);
  getaddrinfo("127.0.0.1", "4567", &hints, &res);
  printf("%s\n", inet_ntoa(reinterpret_cast<sockaddr_in*>(res->ai_addr)->sin_addr));
  freeaddrinfo(res);
  return 0;
}
$ ./t.exe 
Uninitialized bytes in getaddrinfo at offset 20 inside [0x7ffc8810c740, 48)
==452681==WARNING: MemorySanitizer: use-of-uninitialized-value
    #0 0x55f838beeca7 in main /build/build-galera/t.cpp:25:3
    #1 0x7fba7c85cca7  (/lib/x86_64-linux-gnu/libc.so.6+0x29ca7) (BuildId: def5460e3cee00bfee25b429c97bcc4853e5b3a8)
    #2 0x7fba7c85cd64 in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x29d64) (BuildId: def5460e3cee00bfee25b429c97bcc4853e5b3a8)
    #3 0x55f838b50320 in _start (/build/build-galera/t.exe+0x33320) (BuildId: f8ae0606c36989de972929de56f75f8b24adb75b)

  Uninitialized value was created by an allocation of 'hints' in the stack frame
    #0 0x55f838beec66 in main /build/build-galera/t.cpp:24:3

SUMMARY: MemorySanitizer: use-of-uninitialized-value /build/build-galera/t.cpp:25:3 in main
Exiting
Aborted
buildbot@d9a4aa9ffcfb:/build/build-galera$ rr record ./t.exe 
rr: Saving execution to trace directory `/home/buildbot/.local/share/rr/t.exe-4'.
Uninitialized bytes in getaddrinfo at offset 20 inside [0x7ffc267c56b0, 48)
==452696==WARNING: MemorySanitizer: use-of-uninitialized-value
    #0 0x565259f52ca7 in main /build/build-galera/t.cpp:25:3
    #1 0x7f895e26cca7  (/lib/x86_64-linux-gnu/libc.so.6+0x29ca7) (BuildId: def5460e3cee00bfee25b429c97bcc4853e5b3a8)
    #2 0x7f895e26cd64 in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x29d64) (BuildId: def5460e3cee00bfee25b429c97bcc4853e5b3a8)
    #3 0x565259eb4320 in _start (/build/build-galera/t.exe+0x33320) (BuildId: f8ae0606c36989de972929de56f75f8b24adb75b)

  Uninitialized value was created by an allocation of 'hints' in the stack frame
    #0 0x565259f52c66 in main /build/build-galera/t.cpp:24:3

SUMMARY: MemorySanitizer: use-of-uninitialized-value /build/build-galera/t.cpp:25:3 in main
Exiting
Aborted

Breakpoint 2, get_addrinfo (flags=0, family=0, socktype=1, protocol=0) at t.cpp:19
19	  return ret;
(rr) p ret
$1 = {ai_flags = 0, ai_family = 0, ai_socktype = 1, ai_protocol = 0, ai_addrlen = 0, ai_addr = 0x0, ai_canonname = 0x0, ai_next = 0x0}
(rr) p &ret
$2 = (addrinfo *) 0x7ffc267c56b0
(rr) p *(addrinfo *) 0x2ffc267c56b0
$3 = {ai_flags = 0, ai_family = 0, ai_socktype = 0, ai_protocol = 0, ai_addrlen = 0, ai_addr = 0x0, ai_canonname = 0x0, ai_next = 0x0}
(rr) x/48bx 0x2ffc267c56b0
0x2ffc267c56b0:	0x00	0x00	0x00	0x00	0x00	0x00	0x00	0x00
0x2ffc267c56b8:	0x00	0x00	0x00	0x00	0x00	0x00	0x00	0x00
0x2ffc267c56c0:	0x00	0x00	0x00	0x00	0xff	0xff	0xff	0xff
0x2ffc267c56c8:	0x00	0x00	0x00	0x00	0x00	0x00	0x00	0x00
0x2ffc267c56d0:	0x00	0x00	0x00	0x00	0x00	0x00	0x00	0x00
0x2ffc267c56d8:	0x00	0x00	0x00	0x00	0x00	0x00	0x00	0x00

(rr) bt
#0  0x00007f895e2d795c in ?? () from /lib/x86_64-linux-gnu/libc.so.6
#1  0x00007f895e282cc2 in raise () from /lib/x86_64-linux-gnu/libc.so.6
#2  0x00007f895e26b4ac in abort () from /lib/x86_64-linux-gnu/libc.so.6
#3  0x0000565259ecc7b0 in __sanitizer::Abort() ()
#4  0x0000565259eca592 in __sanitizer::Die() ()
#5  0x0000565259f05ef6 in __interceptor_getaddrinfo ()
#6  0x0000565259f52ca8 in main () at t.cpp:25

We initialise all members of the ret structure, however between ai_addrlen (of type socklen_t, 4 bytes) at 0x2ffc267c56c0 and ai_addr pointer at 0x2ffc267c56c8, is 4 bytes that remain uninitialised. __interceptor_getaddrinfo is validating they are initialised.

Is resolvable with:

        addrinfo ret{};
        ret.ai_flags = flags;
        ret.ai_family = family;
        ret.ai_socktype = socktype;
        ret.ai_protocol = protocol;
        ret.ai_addrlen = sizeof(struct sockaddr);
 clang --version
Debian clang version 21.1.0 (++20250812093504+6096d35ea93c-1~exp1~20250812093615.26)

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions