Bug 1659276

Summary: glibc: Test suite failure: malloc/tst-malloc-usable-tunables (ppc64le)
Product: [Fedora] Fedora Reporter: Carlos O'Donell <codonell>
Component: glibcAssignee: Carlos O'Donell <codonell>
Status: CLOSED UPSTREAM QA Contact: Fedora Extras Quality Assurance <extras-qa>
Severity: medium Docs Contact:
Priority: medium    
Version: 29CC: arjun, codonell, dj, fweimer, law, mfabian, pfrankli, rth, siddhesh
Target Milestone: ---   
Target Release: ---   
Hardware: ppc64le   
OS: Linux   
Whiteboard:
Fixed In Version: Doc Type: If docs needed, set a value
Doc Text:
Story Points: ---
Clone Of: Environment:
Last Closed: 2019-10-01 13:45:26 UTC Type: Bug
Regression: --- Mount Type: ---
Documentation: --- CRM:
Verified Versions: Category: ---
oVirt Team: --- RHEL 7.3 requirements from Atomic Host:
Cloudforms Team: --- Target Upstream Version:
Embargoed:

Description Carlos O'Donell 2018-12-14 00:28:06 UTC
Only on ppc64le.

The tst-malloc-usable-tunables test failed in glibc-2.28-26.fc29.

FAIL: malloc/tst-malloc-usable-tunables

=====FAIL: malloc/tst-malloc-usable-tunables.out=====
malloc_usable_size: expected 7 but got 24
=====FAIL: malloc/tst-malloc-usable-tunables.test-result=====
FAIL: malloc/tst-malloc-usable-tunables
original exit status 1

This looks like the hooks were not installed and we did not get the real usable size of the chunk.

Comment 1 DJ Delorie 2019-09-25 20:07:07 UTC
I did an RCA on this for an internal bug reporting the same issue, I'll paste the result here for posterity...

tl;dr it's address space randomization, but glibc should handle it better...

A normal run of my instrumented libc.so looks like this:

i 36 in 'GLIBC_TUNABLES=glibc.malloc.check=3' out 7fffc2120000 0
sbrk(0) 7fffc2120024
7fff8b0f0000-7fff8b110000 r-xp 00000000 00:00 0                          [vdso]
7fff8b110000-7fff8b140000 r-xp 00000000 fd:00 102121442                  /root/rpmbuild/BUILD/glibc-2.28/build-ppc64le-redhat-linux/elf/ld.so
7fff8b140000-7fff8b160000 rw-p 00020000 fd:00 102121442                  /root/rpmbuild/BUILD/glibc-2.28/build-ppc64le-redhat-linux/elf/ld.so
7fffc2120000-7fffc2130000 rw-p 00000000 00:00 0                          [heap]
7fffe7de0000-7fffe7e10000 rw-p 00000000 00:00 0                          [stack]
ne1
ne1
dj: test malloc
dj: ptmalloc_init
dj: ptmalloc GLIBC_TUNABLES = 'glibc.malloc.check=3'
dj: tune mallopt 3

The first part is in dl-tunables.c:tunables_strdup().  __sbrk(36)
returns something reasonable in the heap, "ne1" means new_env is set
in __tunables_init, and the dj: lines show that we initialize the
tunable correctly.


i 36 in 'GLIBC_TUNABLES=glibc.malloc.check=3' out ffffffffffffffff 12
sbrk(0) 7fffc18d0000
7fffaf0d0000-7fffaf0f0000 r-xp 00000000 00:00 0                          [vdso]
7fffaf0f0000-7fffaf120000 r-xp 00000000 fd:00 102121442                  /root/rpmbuild/BUILD/glibc-2.28/build-ppc64le-redhat-linux/elf/ld.so
7fffaf120000-7fffaf140000 rw-p 00020000 fd:00 102121442                  /root/rpmbuild/BUILD/glibc-2.28/build-ppc64le-redhat-linux/elf/ld.so
7fffc2540000-7fffc2570000 rw-p 00000000 00:00 0                          [stack]
strdup NULL
ne0
ne0
dj: test malloc
dj: ptmalloc_init
dj: ptmalloc GLIBC_TUNABLES = '(null)'
malloc_usable_size: expected 7 but got 24

In this case, __sbrk(36) returns -1.  I dumped the process map at that
point.  Note there is no [heap] map.  I don't know if it's the kernel
or libc that has to set that, but it *only* happens if
/proc/sys/kernel/randomize_va_space is set to 2

randomize_va_space:
0: disabled
1: Conservative: Shared libraries and PIE binaries are randomized.
2: Conservative and start of brk area is randomized, too

Yay, start of brk area is randomized - and sometimes that's fatal.


Moving on, though... the sbrk() fails, NULL is returned, and that
"string" is injected into the environ[] list, effectively removing
that variable - and all variables following it - from the environment.

	  if (new_env != NULL)
	    parse_tunables (new_env + len + 1, envval);
	  /* Put in the updated envval.  */
	  *prev_envp = new_env;

We shouldn't put new_env into *prev_envp if new_env is NULL.

But that won't fix the randomization problem; sbrk still fails and
tunables are still not parsed.

More:  I was able to strace one of the failures:

execve("./elf/ld64.so.2", ["./elf/ld64.so.2", "--library-path", ".:./math:./elf:./dlfcn:./nss:./n"..., "malloc/tst-malloc-usable-tunable"...], 0x10003ae52c0 /* 44 vars */) = 0
brk(NULL)                               = 0x7fffcaa00000
brk(0x7fffcaa00024)                     = 0x7fffcaa00000


Full reproduction steps:
* Get the glibc SPRM and install it; rpmbuild -ba glibc.spec
* cd rpmbuild/BUILD/glibc*/build*
* while GLIBC_TUNABLES=glibc.malloc.check=3 strace -f /bin/bash ./testrun.sh malloc/tst-malloc-usable-tunables; do echo; done

Comment 2 Carlos O'Donell 2019-10-01 13:45:26 UTC
We are not going to fix this in Fedora, this needs to be fixed in upstream via:
https://sourceware.org/bugzilla/show_bug.cgi?id=25035

The kernel also needs to fix this issue, and we've filed kernel bugs for that.