From: Paul Floyd Date: Tue, 4 Feb 2025 19:34:57 +0000 (+0100) Subject: FreeBSD syscall: improve utrace wrapper X-Git-Tag: VALGRIND_3_25_0~156 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=6f6025d53a8f53a85c74d03d7b177792f62ac147;p=thirdparty%2Fvalgrind.git FreeBSD syscall: improve utrace wrapper The public wrapper is just a void pointer and length. Internally, the struct used has holes which generate errors (since ld.so which is probably the only user of this syscall doesn't memset the struct to zero). Added the struct definition and PRE_MEM_READ for each field. --- diff --git a/.gitignore b/.gitignore index 483b077ca..c5a2b0592 100644 --- a/.gitignore +++ b/.gitignore @@ -1452,6 +1452,7 @@ /memcheck/tests/freebsd/timing_safe /memcheck/tests/freebsd/utimens /memcheck/tests/freebsd/utimes +/memcheck/tests/freebsd/utrace # /memcheck/tests/amd64-freebsd /memcheck/tests/amd64-freebsd/*.stderr.diff diff --git a/coregrind/m_syswrap/syswrap-freebsd.c b/coregrind/m_syswrap/syswrap-freebsd.c index 339724938..6fd4367a8 100644 --- a/coregrind/m_syswrap/syswrap-freebsd.c +++ b/coregrind/m_syswrap/syswrap-freebsd.c @@ -3109,13 +3109,40 @@ POST(sys_sched_rr_get_interval) POST_MEM_WRITE(ARG2, sizeof(struct vki_timespec)); } +/* + * Putting this here rather than in vki-freebsd.h because this is a workaround + * (see https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=284563) + * The syscall interface doesn't allow us to properly validate the memory, + * and struct utrace_rtld isn't public. + */ +#define VKI_RTLD_UTRACE_SIG_SZ 4 + +struct vki_utrace_rtld { + char sig[VKI_RTLD_UTRACE_SIG_SZ]; + int event; + void *handle; + void *mapbase; + size_t mapsize; + int refcnt; + char name[VKI_PATH_MAX]; +}; + // SYS_utrace 335 // int utrace(const void *addr, size_t len); PRE(sys_utrace) { PRINT("sys_utrace ( %#" FMT_REGWORD "x, %" FMT_REGWORD "u )", ARG1, ARG2); PRE_REG_READ2(int, "utrace", const void *, addr, vki_size_t, len); - PRE_MEM_READ( "utrace(addr)", ARG1, ARG2 ); + if (ARG1 && ARG2 >= sizeof(struct vki_utrace_rtld) && ML_(safe_to_deref)((const void*)ARG1, ARG2)) { + struct vki_utrace_rtld* ut = (struct vki_utrace_rtld*)ARG1; + PRE_MEM_READ("utrace(addr.sig)", (Addr)&ut->sig, VKI_RTLD_UTRACE_SIG_SZ*sizeof(char)); + PRE_MEM_READ("utrace(addr.event)", (Addr)&ut->event, sizeof(int)); + PRE_MEM_READ("utrace(addr.handle)", (Addr)&ut->handle, sizeof(void*)); + PRE_MEM_READ("utrace(addr.mapbase)", (Addr)&ut->mapbase, sizeof(void*)); + PRE_MEM_READ("utrace(addr.mapsize)", (Addr)&ut->mapsize, sizeof(size_t)); + PRE_MEM_READ("utrace(addr.refcnt)", (Addr)&ut->handle, sizeof(int)); + PRE_MEM_READ("utrace(addr.name)", (Addr)&ut->name, VKI_PATH_MAX*sizeof(char)); + } } // SYS_kldsym 337 diff --git a/memcheck/tests/freebsd/Makefile.am b/memcheck/tests/freebsd/Makefile.am index 4b6b36c6c..1213b3189 100644 --- a/memcheck/tests/freebsd/Makefile.am +++ b/memcheck/tests/freebsd/Makefile.am @@ -137,7 +137,10 @@ EXTRA_DIST = \ utimens.stderr.exp \ utimes.vgtest \ utimes.stderr.exp-x86 \ - utimes.stderr.exp + utimes.stderr.exp \ + utrace.vgtest \ + utrace.stderr.exp + check_PROGRAMS = \ access aio aio_read aligned_alloc bug464476 bug470713 \ diff --git a/memcheck/tests/freebsd/scalar.stderr.exp b/memcheck/tests/freebsd/scalar.stderr.exp index 4a57e002a..0e47fe1aa 100644 --- a/memcheck/tests/freebsd/scalar.stderr.exp +++ b/memcheck/tests/freebsd/scalar.stderr.exp @@ -2391,10 +2391,6 @@ Syscall param utrace(addr) contains uninitialised byte(s) Syscall param utrace(len) contains uninitialised byte(s) ... -Syscall param utrace(addr) points to unaddressable byte(s) - ... - Address 0x........ is not stack'd, malloc'd or (recently) free'd - --------------------------------------------------------- 337: SYS_kldsym 3s 1m --------------------------------------------------------- diff --git a/memcheck/tests/freebsd/scalar.stderr.exp-x86 b/memcheck/tests/freebsd/scalar.stderr.exp-x86 index 86599836d..6a532ae8e 100644 --- a/memcheck/tests/freebsd/scalar.stderr.exp-x86 +++ b/memcheck/tests/freebsd/scalar.stderr.exp-x86 @@ -2397,10 +2397,6 @@ Syscall param utrace(addr) contains uninitialised byte(s) Syscall param utrace(len) contains uninitialised byte(s) ... -Syscall param utrace(addr) points to unaddressable byte(s) - ... - Address 0x........ is not stack'd, malloc'd or (recently) free'd - --------------------------------------------------------- 337: SYS_kldsym 3s 1m --------------------------------------------------------- diff --git a/memcheck/tests/freebsd/utrace.stderr.exp b/memcheck/tests/freebsd/utrace.stderr.exp new file mode 100644 index 000000000..e69de29bb diff --git a/memcheck/tests/freebsd/utrace.vgtest b/memcheck/tests/freebsd/utrace.vgtest new file mode 100644 index 000000000..2b6957298 --- /dev/null +++ b/memcheck/tests/freebsd/utrace.vgtest @@ -0,0 +1,6 @@ +# This produces no output (only does so under truss or ktrace) +# but there was an issue with the syscall that generated false positives +# due to holes in the struct used +env: LD_UTRACE=1 +prog: ../../../tests/true +vgopts: -q