Closed paulfloyd closed 2 years ago
And on FreeBSD 14.0 more diff
--- dw4.stderr.exp-freebsd 2022-04-03 13:49:47.961688000 +0200
+++ dw4.stderr.out 2022-05-31 22:51:08.784810000 +0200
@@ -25,12 +25,12 @@
Uninitialised byte(s) found during client check request
at 0x........: croak (dw4.c:32)
by 0x........: main (dw4.c:82)
- Address 0x........ is in a rw- mapped file valgrind-dw4-test.PID segment
+ Address 0x........ is in a rw- mapped file [unknown] segment
This should be coming from the filter
$SED "s/file .*valgrind-dw4-test.[1-9][0-9]*/file valgrind-dw4-test.PID/"
so for some reason the file is not found :-(((
Got it.
At the end of initimg-linux.c there is this
/ Tell the tool about the client data segment and then kill it which will make it inaccessible/unaddressable. / const NSegment seg = VG_(am_findnsegment)(VG(brk_base)); vg_assert(seg); vg_assert(seg->kind == SkAnonC); VG_TRACK(new_membrk, VG(brkbase), seg->end + 1 - VG(brk_base), 1/tid*/); VG_TRACK(die_membrk, VG(brkbase), seg->end + 1 - VG(brk_base));
which is missing from FreeBSD.
It is also missing from Solaris and Darwin. Hmm. I wonder if they pass this test?
commit 7b0cd3ac2884d2557a476e5010d44e60ff531846 (HEAD -> master, origin/master, origin/HEAD) Author: Paul Floyd pjfloyd@wanadoo.fr Date: Thu Jun 2 20:31:12 2022 +0200
Add code that makes 1st page after brk inaccessible.
Also remove FreeBSD expected.
Note: this code is also mssing from Solaris and macOS initimg's.
I added an expected
This is some peculiarity about accessing after brk. Seems to work on FreeBSD with clang.
In this test
I get Uninit until I ads 4096 to addr.
That means that either clang/FreeBSD is putting a page after brk, of the Valgrind code is out by 1 page.
If I try to write to addr I get a coredump.
So it looks like a Valgrind errror.
Run with -d -d and add a printf of
addr
to the testcase and compare the two brks.The printf says
brk is 0x4020000
and aspacem
What are those two 4k pages at the end?
What does Linux say?
RHEL7.6, GCC 12ish
Standalone ./dw4 addr is 0x426000 Segmentation fault
Under Valgrind nullgrind
addr is 0x4245000
and
Just a few comments. The Linux map has a fair number of differences. core.so is mapped lower than SmLower RSVN, ld.so is split.
Linus has this just before the free space
--28937:1: aspacem 23: anon 0004224000-0004244fff 135168 rwx--
That's 128k and brk is just after that.
So why on Linux is it correctly after the 128k anon rwx mapping but on FreeBSD it is wrong and not after the 4k anon rwx mapping? Lower case anon means client mapping.
There are (at least) 3 places that could be mapping this
VG_(am_notify_client_mmap)( Addr a, SizeT len, UInt prot, UInt flags,
SysRes VG_(am_mmap_anon_fixed_client) ( Addr start, SizeT length, UInt prot )
static SysRes am_mmap_anon_float_client ( SizeT length, Int prot, Bool isCH )
am_mmap_anon_fixedclient is called twice, SysRes VG(am_mmap_anon_floatclient) ( SizeT length, Int prot ) and SysRes VG(am_mmap_client_heap) ( SizeT length, Int prot )
can't be the second cos that would make the segment be marked with 'H' for heap can't be the first cos that is only called on macos
VG_(am_mmap_anon_fixed_client) is called twice from initimg-freebsd and once from elf.c
elf.c is from mapelf when memsz > filesz. This does involve brkaddr.
On Linux the elf call does get used, but it looks like it is just padding after the ld.so RW PT_LOAD.
before
after
final
So that is the page before the mystery RWX page, but not the one that I want.
elf.c has some nice ifs that make this easy to trace.
@TODO check if this is changing brk correctly
split RW PT_LOAD does not affect this
init-img stack allocation nah
setup_client_dataseg
BINGO
On Linux before
after
with
DEBUG: setup_client_dataseg ok is 0 resvn start 0x406000 DEBUG: setup_client_dataseg ok is 1 new resvn start 0x4225000
that first attempt seems hopeless, it's where part of ld.so is already mapped
the second one looks OK, before the client heap gets grown
So where does the 4k RWX mapping get extended by 128k to 132k? Can't see any client mmaps doing it
Back on Freebsd, similar, first attempt at am_create_reservation fails so get advisory and try again.
That succeeds.
DEBUG: setup_client_dataseg ok is 0 resvn_start 0x206000 DEBUG: setup_client_dataseg ok is 1 try again resvn_start 0x4021000 anon_start 0x4020000
I think that this is wrong
brk_limit should be anaon_start+anaon_size.
Ned to debug in do_brk. Modify debug flag, enable show segments.
Back to Linux
Calls to sbrk From _dl_sysdep_start with a size of 0 From sysmalloc From _int_malloc From malloc From main
Hmm. OK. And what about with memcheck? What does FreeBSD malloc do? @TODO gdb FreeBSD b sbrk
I guess this is a difference between Linux malloc and FreeBSD malloc. To me it looks like the 32bye malloc on Linux is using sbrk for 132k which then gets used for small allocations (?)
memcheck on Linux, obviously now there is memcheck.so
DEBUG: setup_client_dataseg ok is 0 resvn start 0x406000 DEBUG: setup_client_dataseg ok is 1 new resvn start 0x4225000 anon_start 0x4224000
SYSCALL8864,1 sys_brk ( 0x0 ) SYSCALL8864,1 sys_brk ( 0x0 ) SYSCALL8864,1 sys_brk ( 0x0 ) SYSCALL8864,1 sys_brk ( 0x4225000 ) SYSCALL8864,1 sys_brk ( 0x0 ) SYSCALL8864,1 sys_brk ( 0x4224400 )