From: Paul Floyd Date: Sun, 3 Nov 2024 09:17:17 +0000 (+0100) Subject: Bug 495488 - Add FreeBSD getrlimitusage syscall wrapper X-Git-Tag: VALGRIND_3_25_0~260 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=0b6c1515d158745e97ad206bf1cd3caceb8ed4dd;p=thirdparty%2Fvalgrind.git Bug 495488 - Add FreeBSD getrlimitusage syscall wrapper --- diff --git a/.gitignore b/.gitignore index e38537a9a..cfd943bfc 100644 --- a/.gitignore +++ b/.gitignore @@ -1421,6 +1421,7 @@ /memcheck/tests/freebsd/get_set_login /memcheck/tests/freebsd/getfh /memcheck/tests/freebsd/getfsstat +/memcheck/tests/freebsd/getrlimitusage /memcheck/tests/freebsd/inlinfo /memcheck/tests/freebsd/inlinfo_nested.so /memcheck/tests/freebsd/kqueue diff --git a/NEWS b/NEWS index 70fa86bc0..972470509 100644 --- a/NEWS +++ b/NEWS @@ -23,6 +23,7 @@ bugzilla (https://bugs.kde.org/enter_bug.cgi?product=valgrind) rather than mailing the developers (or mailing lists) directly -- bugs that are not entered into bugzilla tend to get forgotten about or ignored. +495488 Add FreeBSD getrlimitusage syscall wrapper To see details of a given bug, visit https://bugs.kde.org/show_bug.cgi?id=XXXXXX diff --git a/configure.ac b/configure.ac index 96b19d2aa..ee18cc83a 100755 --- a/configure.ac +++ b/configure.ac @@ -4955,7 +4955,8 @@ AC_CHECK_FUNCS([ \ sem_timedwait \ sem_clockwait_np \ fdatasync \ - getrandom + getrandom \ + getrlimitusage ]) # AC_CHECK_LIB adds any library found to the variable LIBS, and links these @@ -5009,6 +5010,8 @@ AM_CONDITIONAL([HAVE_FDATASYNC], [test x$ac_cv_func_fdatasync = xyes]) AM_CONDITIONAL([HAVE_GETRANDOM], [test x$ac_cv_func_getrandom = xyes]) +AM_CONDITIONAL([HAVE_GETRLIMITUSAGE], + [test x$ac_cv_func_getrlimitusage = xyes]) if test x$VGCONF_PLATFORM_PRI_CAPS = xMIPS32_LINUX \ -o x$VGCONF_PLATFORM_PRI_CAPS = xMIPS64_LINUX \ diff --git a/coregrind/m_debuginfo/debuginfo.c b/coregrind/m_debuginfo/debuginfo.c index ad05b9928..11ab47354 100644 --- a/coregrind/m_debuginfo/debuginfo.c +++ b/coregrind/m_debuginfo/debuginfo.c @@ -65,6 +65,9 @@ # include "priv_readmacho.h" # include "priv_readpdb.h" #endif +#if defined(VGO_freebsd) +#include "pub_core_clientstate.h" +#endif /* Set this to 1 to enable somewhat minimal debug printing for the @@ -5145,6 +5148,19 @@ void VG_(load_all_debuginfo) (void) VG_(di_load_di)(di); } } + +SizeT VG_(data_size)(void) +{ + HChar resolved[1000]; + VG_(realpath)( VG_(args_the_exename), resolved); + + for (DebugInfo* di = debugInfo_list; di; di = di->next) { + if (di->data_size && VG_(strcmp)(di->soname, "NONE") == 0 && VG_(strcmp)(resolved, di->fsm.filename) == 0) { + return VG_PGROUNDUP(di->data_size); + } + } + return 0U; +} #endif /*--------------------------------------------------------------------*/ diff --git a/coregrind/m_main.c b/coregrind/m_main.c index 22b4fea0f..85e744d15 100644 --- a/coregrind/m_main.c +++ b/coregrind/m_main.c @@ -3543,6 +3543,10 @@ void _start_in_C_freebsd ( UWord* pArgc, UWord *initial_sp ) # error "Unknown OS" #endif +SizeT VG_(get_client_stack_max_size)(void) +{ + return the_iifii.clstack_max_size; +} Addr VG_(get_initial_client_SP)( void ) { diff --git a/coregrind/m_syswrap/priv_syswrap-freebsd.h b/coregrind/m_syswrap/priv_syswrap-freebsd.h index 5b7186640..8b78c5d74 100644 --- a/coregrind/m_syswrap/priv_syswrap-freebsd.h +++ b/coregrind/m_syswrap/priv_syswrap-freebsd.h @@ -538,6 +538,7 @@ DECL_TEMPLATE(freebsd, sys_timerfd_settime) // 587 // __FreeBSD_version 1400507 and 1500012 DECL_TEMPLATE(freebsd, sys_kcmp) // 588 +DECL_TEMPLATE(freebsd, sys_getrlimitusage) // 589 DECL_TEMPLATE(freebsd, sys_fake_sigreturn) diff --git a/coregrind/m_syswrap/priv_syswrap-generic.h b/coregrind/m_syswrap/priv_syswrap-generic.h index ec174a152..b888a167c 100644 --- a/coregrind/m_syswrap/priv_syswrap-generic.h +++ b/coregrind/m_syswrap/priv_syswrap-generic.h @@ -60,6 +60,7 @@ Bool ML_(fd_allowed)(Int fd, const HChar *syscallname, ThreadId tid, Bool isNewFD); extern void ML_(record_fd_close) (ThreadId tid, Int fd); +extern Int ML_(get_fd_count) (void); extern void ML_(record_fd_close_range) (ThreadId tid, Int fd); extern void ML_(record_fd_open_named) (ThreadId tid, Int fd); extern void ML_(record_fd_open_nameless) (ThreadId tid, Int fd); diff --git a/coregrind/m_syswrap/syswrap-freebsd.c b/coregrind/m_syswrap/syswrap-freebsd.c index 85b60c8f3..f5516420f 100644 --- a/coregrind/m_syswrap/syswrap-freebsd.c +++ b/coregrind/m_syswrap/syswrap-freebsd.c @@ -6915,6 +6915,54 @@ PRE(sys_kcmp) } } +// SYS_getrlimitusage 589 +// from syscalls.master +// int getrlimitusage(u_int which, int flags, _Out_ rlim_t *res); +PRE(sys_getrlimitusage) +{ + PRINT("sys_getrlimitusage(%lu, %ld, %#" FMT_REGWORD "x )", ARG1, SARG2, ARG3); + PRE_REG_READ3(int, "getrlimitusage", u_int, which, int, flags, vki_rlim_t*, res); + + PRE_MEM_WRITE("getrlimitusage(res)", ARG3, sizeof(vki_rlim_t)); +} + +POST(sys_getrlimitusage) +{ + POST_MEM_WRITE(ARG3, sizeof(vki_rlim_t)); + + // flags can be GETRLIMITUSAGE_EUID or not + // not sure what that means? + + // we need to set the values for NOFILE DATA and STACK + vki_rlim_t* res = (vki_rlim_t*)ARG3; + switch (ARG1) { + case VKI_RLIMIT_NOFILE: + *res = ML_(get_fd_count)() + 3; + break; + case VKI_RLIMIT_DATA: + /* + * The OS initializes this the the size of the .data for the exe. + * We read this in readelf.c. + */ + *res = VG_(data_size)() + VG_(brk_limit) - VG_(brk_base); + break; + case VKI_RLIMIT_STACK: + /* + * The main client stack is quite different when running under Valgrind. + * See aspacemg-linux.c for details, but in short on 64bit systems + * the main stack starts with 128k reserved and a 512M limit. + * Valgrind just has one value, 16M by default (can be changed with + * --main-stacksize). Maybe we should use something more like the OS + * but it doesn't seem that important. + */ + *res = VG_(get_client_stack_max_size)(); + break; + default: + // do nothing + break; + } +} + #undef PRE #undef POST @@ -7606,6 +7654,7 @@ const SyscallTableEntry ML_(syscall_table)[] = { BSDXY(__NR_timerfd_settime, sys_timerfd_settime), // 586 BSDXY(__NR_timerfd_gettime, sys_timerfd_gettime), // 587 BSDX_(__NR_kcmp, sys_kcmp), // 588 + BSDXY(__NR_getrlimitusage, sys_getrlimitusage), // 589 BSDX_(__NR_fake_sigreturn, sys_fake_sigreturn), // 1000, fake sigreturn diff --git a/coregrind/m_syswrap/syswrap-generic.c b/coregrind/m_syswrap/syswrap-generic.c index 1d80d0928..d6b10780d 100644 --- a/coregrind/m_syswrap/syswrap-generic.c +++ b/coregrind/m_syswrap/syswrap-generic.c @@ -553,6 +553,12 @@ static OpenFd *allocated_fds = NULL; /* Count of open file descriptors. */ static Int fd_count = 0; + +Int ML_(get_fd_count)(void) +{ + return fd_count; +} + /* Close_range caller might want to close very wide range of file descriptors, up to 0U. We want to avoid iterating through such a range in a normall close_range, just up to any open file descriptor. Also, unlike diff --git a/coregrind/pub_core_clientstate.h b/coregrind/pub_core_clientstate.h index dceece9b9..06d0fe343 100644 --- a/coregrind/pub_core_clientstate.h +++ b/coregrind/pub_core_clientstate.h @@ -98,6 +98,9 @@ extern Addr VG_(client_freeres_wrapper); VG_(get_StackTrace) in m_stacktrace.c for further info. */ extern Addr VG_(client__dl_sysinfo_int80); +/* Get the maximum client stacksize. */ +extern SizeT VG_(get_client_stack_max_size)(void); + /* Obtains the initial client stack pointer from the finalised image info. */ extern Addr VG_(get_initial_client_SP)(void); diff --git a/coregrind/pub_core_debuginfo.h b/coregrind/pub_core_debuginfo.h index 4d6ebda81..64fcd3428 100644 --- a/coregrind/pub_core_debuginfo.h +++ b/coregrind/pub_core_debuginfo.h @@ -158,6 +158,8 @@ extern UInt VG_(debuginfo_generation) (void); we can't open executable files to get the debuginfo after entering capability mode. */ extern void VG_(load_all_debuginfo) (void); +/* Get the size of .data for the client exe */ +extern SizeT VG_(data_size)(void); #endif diff --git a/include/vki/vki-freebsd.h b/include/vki/vki-freebsd.h index 7b35428a3..a49650b2b 100644 --- a/include/vki/vki-freebsd.h +++ b/include/vki/vki-freebsd.h @@ -1230,6 +1230,8 @@ struct vki_rlimit { #define VKI_RLIMIT_CORE 4 /* max core file size */ #define VKI_RLIMIT_NOFILE 8 /* max number of open files */ +#define VKI_GETRLIMITUSAGE_EUID 0x0001 + struct vki___wrusage { struct vki_rusage wru_self; struct vki_rusage wru_children; diff --git a/include/vki/vki-scnums-freebsd.h b/include/vki/vki-scnums-freebsd.h index 852f9833a..098b722f4 100644 --- a/include/vki/vki-scnums-freebsd.h +++ b/include/vki/vki-scnums-freebsd.h @@ -626,6 +626,8 @@ // __FreeBSD_version 1400507 and 1500012 #define __NR_kcmp 588 +#define __NR_getrlimitusage 589 + #define __NR_fake_sigreturn 1000 #endif /* VKI_UNISTD_FREEBSD_H */ diff --git a/memcheck/tests/freebsd/Makefile.am b/memcheck/tests/freebsd/Makefile.am index b2e84fc03..4b6b36c6c 100644 --- a/memcheck/tests/freebsd/Makefile.am +++ b/memcheck/tests/freebsd/Makefile.am @@ -67,6 +67,7 @@ EXTRA_DIST = \ getfsstat.stderr.exp \ getfsstat.supp \ getfsstat.stderr.exp-x86 \ + getrlimitusage.vgtest getrlimitusage.stderr.exp \ kqueue.vgtest \ kqueue.stderr.exp \ kqueue.stdout.exp \ @@ -172,6 +173,10 @@ if HAVE_AIO_READV check_PROGRAMS += aiov endif +if HAVE_GETRLIMITUSAGE +check_PROGRAMS += getrlimitusage +endif + inlinfo_SOURCES = inlinfo.c inlinfo_DEPENDENCIES = inlinfo_nested.so inlinfo_LDFLAGS = -Wl,-rpath,$(top_builddir)/memcheck/tests/freebsd diff --git a/memcheck/tests/freebsd/getrlimitusage.c b/memcheck/tests/freebsd/getrlimitusage.c new file mode 100644 index 000000000..123ab18ad --- /dev/null +++ b/memcheck/tests/freebsd/getrlimitusage.c @@ -0,0 +1,106 @@ +/*- + * SPDX-License-Identifier: BSD-2-Clause + * + * Copyright (c) 2024 The FreeBSD Foundation + * + * This software was developed by Konstantin Belousov + * under sponsorship from the FreeBSD Foundation. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include +#define _RLIMIT_IDENT +#include +#include +#include +#include +#include +#include + +static void usage(void) +{ + fprintf(stderr, "usage: getrlimitusage [-e] [-p pid]\n"); + exit(2); +} + +int main(int argc, char *argv[]) +{ + rlim_t res; + int c, flags; + + flags = 0; + while ((c = getopt(argc, argv, "e")) != -1) + { + switch (c) + { + case 'e': + flags |= GETRLIMITUSAGE_EUID; + break; + case '?': + default: + usage(); + } + } + argc -= optind; + argv += optind; + if (argc != 0) + usage(); + + for (unsigned i = 0;; i++) + { + if (getrlimitusage(i, flags, &res) == -1) + { + if (errno == ENXIO) + { + res = -1; + } + else + { + if (errno != EINVAL) + err(1, "getrlimitusage(%d)", errno); + break; + } + } + // add some rounding to try to make regtest stable + switch (i) + { + case 7: + case 9: + case 12: + case 15: + res = 0U; + break; + case 5: + res = res/100000 * 100000; + break; + case 10: + res = res/1000 * 1000; + break; + default: + break; + } + fprintf(stderr, "%s (%d):\t%jd\n", i < nitems(rlimit_ident) ? rlimit_ident[i] : "unknown", i, (uintmax_t)res +); + } + exit(0); +} diff --git a/memcheck/tests/freebsd/getrlimitusage.stderr.exp b/memcheck/tests/freebsd/getrlimitusage.stderr.exp new file mode 100644 index 000000000..2a1ecb3ea --- /dev/null +++ b/memcheck/tests/freebsd/getrlimitusage.stderr.exp @@ -0,0 +1,16 @@ +cpu (0): 0 +fsize (1): -1 +data (2): 4096 +stack (3): 16777216 +core (4): -1 +rss (5): 41800000 +memlock (6): 0 +nproc (7): 0 +nofile (8): 3 +sbsize (9): 0 +vmem (10): 106414000 +npts (11): 0 +swap (12): 0 +kqueues (13): 0 +umtx (14): 0 +pipebuf (15): 0 diff --git a/memcheck/tests/freebsd/getrlimitusage.vgtest b/memcheck/tests/freebsd/getrlimitusage.vgtest new file mode 100644 index 000000000..dbcd3334d --- /dev/null +++ b/memcheck/tests/freebsd/getrlimitusage.vgtest @@ -0,0 +1,3 @@ +prereq: test -e ./getrlimitusage +prog: getrlimitusage +vgopts: -q diff --git a/memcheck/tests/freebsd/scalar.c b/memcheck/tests/freebsd/scalar.c index 5aecfebac..7ad3099a0 100644 --- a/memcheck/tests/freebsd/scalar.c +++ b/memcheck/tests/freebsd/scalar.c @@ -2408,6 +2408,50 @@ int main(void) FAKE_SY("\n"); #endif + /* SYS_kcmp 588 */ +#if defined(SYS_kcmp) + GO(SYS_kcmp, "5s 0m"); + SY(SYS_kcmp, x0+1, x0+2, x0+3, x0+4, x0+5); +#else + FAKE_GO("588: SYS_kcmp 5s 0m"); + FAKE_SY("Syscall param kcmp(pid1) contains uninitialised byte(s)\n"); + FAKE_SY(" ...\n"); + FAKE_SY("\n"); + FAKE_SY("Syscall param kcmp(pid2) contains uninitialised byte(s)\n"); + FAKE_SY(" ...\n"); + FAKE_SY("\n"); + FAKE_SY("Syscall param kcmp(type) contains uninitialised byte(s)\n"); + FAKE_SY(" ...\n"); + FAKE_SY("\n"); + FAKE_SY("Syscall param kcmp(idx1) contains uninitialised byte(s)\n"); + FAKE_SY(" ...\n"); + FAKE_SY("\n"); + FAKE_SY("Syscall param kcmp(idx2) contains uninitialised byte(s)\n"); + FAKE_SY(" ...\n"); + FAKE_SY("\n"); +#endif + + /* SYS_getrlimitusage 589 */ +#if defined(SYS_getrlimitusage) + GO(SYS_getrlimitusage, "3s, 1m"); + SY(SYS_getrlimitusage, x0+3, x0, x0+2); +#else + FAKE_GO("589: SYS_getrlimitusage 3s, 1m"); + FAKE_SY("Syscall param getrlimitusage(which) contains uninitialised byte(s)\n"); + FAKE_SY(" ...\n"); + FAKE_SY("\n"); + FAKE_SY("Syscall param getrlimitusage(flags) contains uninitialised byte(s)\n"); + FAKE_SY(" ...\n"); + FAKE_SY("\n"); + FAKE_SY("Syscall param getrlimitusage(res) contains uninitialised byte(s)\n"); + FAKE_SY(" ...\n"); + FAKE_SY("\n"); + FAKE_SY("Syscall param getrlimitusage(res) points to unaddressable byte(s)\n"); + FAKE_SY(" ...\n"); + FAKE_SY(" Address 0x........ is not stack'd, malloc'd or (recently) free'd\n"); + FAKE_SY("\n"); +#endif + /* SYS_exit 1 */ GO(SYS_exit, "1s 0m"); SY(SYS_exit, x0); FAIL; diff --git a/memcheck/tests/freebsd/scalar.stderr.exp b/memcheck/tests/freebsd/scalar.stderr.exp index ed5f0a9b1..4a57e002a 100644 --- a/memcheck/tests/freebsd/scalar.stderr.exp +++ b/memcheck/tests/freebsd/scalar.stderr.exp @@ -5710,6 +5710,40 @@ Syscall param timerfd_settime(old_value) points to unaddressable byte(s) ... Address 0x........ is not stack'd, malloc'd or (recently) free'd +--------------------------------------------------------- +588: SYS_kcmp 5s 0m +--------------------------------------------------------- +Syscall param kcmp(pid1) contains uninitialised byte(s) + ... + +Syscall param kcmp(pid2) contains uninitialised byte(s) + ... + +Syscall param kcmp(type) contains uninitialised byte(s) + ... + +Syscall param kcmp(idx1) contains uninitialised byte(s) + ... + +Syscall param kcmp(idx2) contains uninitialised byte(s) + ... + +--------------------------------------------------------- +589: SYS_getrlimitusage 3s, 1m +--------------------------------------------------------- +Syscall param getrlimitusage(which) contains uninitialised byte(s) + ... + +Syscall param getrlimitusage(flags) contains uninitialised byte(s) + ... + +Syscall param getrlimitusage(res) contains uninitialised byte(s) + ... + +Syscall param getrlimitusage(res) points to unaddressable byte(s) + ... + Address 0x........ is not stack'd, malloc'd or (recently) free'd + --------------------------------------------------------- 1: SYS_exit 1s 0m ---------------------------------------------------------