From 6f6025d53a8f53a85c74d03d7b177792f62ac147 Mon Sep 17 00:00:00 2001 From: Paul Floyd Date: Tue, 4 Feb 2025 20:34:57 +0100 Subject: [PATCH] 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. --- .gitignore | 1 + coregrind/m_syswrap/syswrap-freebsd.c | 29 +++++++++++++++++++- memcheck/tests/freebsd/Makefile.am | 5 +++- memcheck/tests/freebsd/scalar.stderr.exp | 4 --- memcheck/tests/freebsd/scalar.stderr.exp-x86 | 4 --- memcheck/tests/freebsd/utrace.stderr.exp | 0 memcheck/tests/freebsd/utrace.vgtest | 6 ++++ 7 files changed, 39 insertions(+), 10 deletions(-) create mode 100644 memcheck/tests/freebsd/utrace.stderr.exp create mode 100644 memcheck/tests/freebsd/utrace.vgtest diff --git a/.gitignore b/.gitignore index 483b077ca3..c5a2b0592c 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 3397249383..6fd4367a83 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 4b6b36c6ce..1213b31898 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 4a57e002aa..0e47fe1aac 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 86599836de..6a532ae8e0 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 0000000000..e69de29bb2 diff --git a/memcheck/tests/freebsd/utrace.vgtest b/memcheck/tests/freebsd/utrace.vgtest new file mode 100644 index 0000000000..2b69572982 --- /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 -- 2.47.2