/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
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
sem_timedwait \
sem_clockwait_np \
fdatasync \
- getrandom
+ getrandom \
+ getrlimitusage
])
# AC_CHECK_LIB adds any library found to the variable LIBS, and links these
[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 \
# 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
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
/*--------------------------------------------------------------------*/
# 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 )
{
// __FreeBSD_version 1400507 and 1500012
DECL_TEMPLATE(freebsd, sys_kcmp) // 588
+DECL_TEMPLATE(freebsd, sys_getrlimitusage) // 589
DECL_TEMPLATE(freebsd, sys_fake_sigreturn)
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);
}
}
+// 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
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
/* 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
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);
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
#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;
// __FreeBSD_version 1400507 and 1500012
#define __NR_kcmp 588
+#define __NR_getrlimitusage 589
+
#define __NR_fake_sigreturn 1000
#endif /* VKI_UNISTD_FREEBSD_H */
getfsstat.stderr.exp \
getfsstat.supp \
getfsstat.stderr.exp-x86 \
+ getrlimitusage.vgtest getrlimitusage.stderr.exp \
kqueue.vgtest \
kqueue.stderr.exp \
kqueue.stdout.exp \
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
--- /dev/null
+/*-
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Copyright (c) 2024 The FreeBSD Foundation
+ *
+ * This software was developed by Konstantin Belousov <kib@FreeBSD.org>
+ * 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 <sys/param.h>
+#define _RLIMIT_IDENT
+#include <err.h>
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/resource.h>
+#include <unistd.h>
+
+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);
+}
--- /dev/null
+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
--- /dev/null
+prereq: test -e ./getrlimitusage
+prog: getrlimitusage
+vgopts: -q
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;
...
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
---------------------------------------------------------