From: Paul Floyd Date: Sun, 3 Jul 2022 11:58:18 +0000 (+0200) Subject: Improve FreeBSD sysctl kern.usrstack X-Git-Tag: VALGRIND_3_20_0~26 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=b29a1e1cf5f36a347275bcc4f6135705e4dedba9;p=thirdparty%2Fvalgrind.git Improve FreeBSD sysctl kern.usrstack This was handled by sysctl but not sysctlbyname. The value returned was wrong. Added a regtest. --- diff --git a/.gitignore b/.gitignore index b749c130c9..d816acf815 100644 --- a/.gitignore +++ b/.gitignore @@ -2083,6 +2083,7 @@ /none/tests/freebsd/fexecve /none/tests/freebsd/hello_world /none/tests/freebsd/452275 +/none/tests/freebsd/usrstack # /none/tests/x86/ /none/tests/x86/*.dSYM diff --git a/coregrind/m_main.c b/coregrind/m_main.c index d0fbc0c56c..f12ba01b5f 100644 --- a/coregrind/m_main.c +++ b/coregrind/m_main.c @@ -3897,7 +3897,7 @@ UWord voucher_mach_msg_set ( UWord arg1 ) Word VG_(get_usrstack)(void) { - return VG_PGROUNDDN(the_iicii.clstack_end - the_iifii.clstack_max_size); + return VG_PGROUNDDN(the_iicii.clstack_end) + VKI_PAGE_SIZE; } diff --git a/coregrind/m_syswrap/syswrap-freebsd.c b/coregrind/m_syswrap/syswrap-freebsd.c index aeb2a1cd62..b963f56763 100644 --- a/coregrind/m_syswrap/syswrap-freebsd.c +++ b/coregrind/m_syswrap/syswrap-freebsd.c @@ -1960,6 +1960,12 @@ static Bool sysctl_kern_ps_strings(SizeT* out, SizeT* outlen) return False; } +static void sysctl_kern_usrstack(SizeT* out, SizeT* outlen) +{ + *out = VG_(get_usrstack)(); + *outlen = sizeof(ULong); +} + // SYS___sysctl 202 /* int __sysctl(int *name, u_int namelen, void *oldp, size_t *oldlenp, void *newp, size_t newlen); */ /* ARG1 ARG2 ARG3 ARG4 ARG5 ARG6 */ @@ -2028,11 +2034,7 @@ PRE(sys___sysctl) if (SARG2 >= 2 && ML_(safe_to_deref)(name, 2*sizeof(int))) { if (name[0] == 1 && name[1] == 33) { // kern.userstack - Word tmp = VG_(get_usrstack)(); - size_t* out = (size_t*)ARG3; - size_t* outlen = (size_t*)ARG4; - *out = tmp; - *outlen = sizeof(ULong); + sysctl_kern_usrstack((size_t*)ARG3, (size_t*)ARG4); SET_STATUS_Success(0); } } @@ -6281,10 +6283,16 @@ PRE(sys___sysctlbyname) if (ML_(safe_to_deref)(name, sizeof("kern.ps_strings")) && VG_(strcmp)(name, "kern.ps_strings") == 0) { if (sysctl_kern_ps_strings((SizeT*)ARG3, (SizeT*)ARG4)) { - SET_STATUS_Success(0); + SET_STATUS_Success(0); } } + if (ML_(safe_to_deref)(name, sizeof("kern.usrstack")) && + VG_(strcmp)(name, "kern.usrstack") == 0) { + sysctl_kern_usrstack((size_t*)ARG3, (size_t*)ARG4); + SET_STATUS_Success(0); + } + // read number of ints specified in ARG2 from mem pointed to by ARG1 PRE_MEM_READ("__sysctlbyname(name)", (Addr)ARG1, ARG2 * sizeof(int)); diff --git a/none/tests/freebsd/Makefile.am b/none/tests/freebsd/Makefile.am index 4a29928238..f1f8a5628b 100644 --- a/none/tests/freebsd/Makefile.am +++ b/none/tests/freebsd/Makefile.am @@ -30,10 +30,13 @@ EXTRA_DIST = \ fexecve_txt.vgtest \ fexecve_txt.stderr.exp \ 452275.vgtest \ - 452275.stderr.exp + 452275.stderr.exp \ + usrstack.vgtest \ + usrstack.stderr.exp \ + usrstack.stdout.exp check_PROGRAMS = \ - auxv osrel swapcontext hello_world fexecve 452275 + auxv osrel swapcontext hello_world fexecve 452275 usrstack AM_CFLAGS += $(AM_FLAG_M3264_PRI) AM_CXXFLAGS += $(AM_FLAG_M3264_PRI) diff --git a/none/tests/freebsd/usrstack.c b/none/tests/freebsd/usrstack.c new file mode 100644 index 0000000000..4f3d69225a --- /dev/null +++ b/none/tests/freebsd/usrstack.c @@ -0,0 +1,43 @@ +#include +#include +#include +#include +#include +#include + +int main(void) +{ + int stack_variable = 1; + unsigned long v1; + unsigned long v2; + int name[] = {CTL_KERN, KERN_USRSTACK}; + size_t len = sizeof(unsigned long); + + if (sysctlbyname("kern.usrstack", &v1, &len, NULL, 0) < 0) { + perror("sysctlbyname failed:"); + exit(-1); + } + + if (sysctl(name, 2, &v2, &len, NULL, 0) < 0) { + perror("sysctl failed:"); + exit(-1); + } + + if (v1 == v2) { + printf("OK 1\n"); + } else { + printf("FAIL usrstack different\n"); + printf("v1 %lx v2 %lx\n", v1, v2); + } + + + /* the purpose of this is to check that the sysctl isn't + returning the host stack. I expec the difference to be less than 0x1000 */ + if (v1 - (unsigned long)&stack_variable > 0x2000U) { + printf("FAIL usrstack fishy\n"); + printf("v1 %lx stack_variable %p diff %lx\n", v1, &stack_variable, v1 - (unsigned long)&stack_variable); + } else { + printf("OK 2\n"); + } +} + diff --git a/none/tests/freebsd/usrstack.stderr.exp b/none/tests/freebsd/usrstack.stderr.exp new file mode 100644 index 0000000000..e69de29bb2 diff --git a/none/tests/freebsd/usrstack.stdout.exp b/none/tests/freebsd/usrstack.stdout.exp new file mode 100644 index 0000000000..58ff19a75f --- /dev/null +++ b/none/tests/freebsd/usrstack.stdout.exp @@ -0,0 +1,2 @@ +OK 1 +OK 2 diff --git a/none/tests/freebsd/usrstack.vgtest b/none/tests/freebsd/usrstack.vgtest new file mode 100644 index 0000000000..fd256549e4 --- /dev/null +++ b/none/tests/freebsd/usrstack.vgtest @@ -0,0 +1,3 @@ +prog: usrstack +vgopts: -q +