[DTrace-devel] [PATCH 2/6] dtprobed: stop malloc making syscalls in the DOF parser child

Kris Van Hees kris.van.hees at oracle.com
Thu May 25 19:04:04 UTC 2023


On Mon, May 22, 2023 at 09:20:13PM +0100, Nick Alcock via DTrace-devel wrote:
> If dtprobed receives DOF larger than the glibc mmap threshold (64KiB by
> default), it will make an mmap() to allocate space for it in the parser
> child.  Since it's in a seccomp jail, this is denied and the child is
> killed.  Whoops.
> 
> Rejigging the entire parser child to avoid allocations is possible, but
> needless: we can just ask glibc to never call mmap and keep enough space
> free at the top of the heap for plausible allocations, make a big
> allocation right before nailing ourselves into the jail, and keep
> going. We have a (fairly small) maximum size for a given piece of DOF,
> and there is no risk of heap fragmentation because we free everything
> on every message received, so a fixed size (with respect to that
> maximum) should always be enough.
> 
> (There is a slight extra cocmplexity here: we have to hide the malloc()
> and free() for the big allocation in another translation unit (and turn
> LTO off for that translation unit), or GCC will recognise that the
> malloc/free are do-nothing, and optimize them away.)
> 
> (If glibc ever stops respecting M_MMAP_MAX or M_TRIM_THRESHOLD we'll be
> in bigger trouble and might need our own simpleminded allocator, but
> this doesn't seem at all likely in the near future at least.)
> 
> Signed-off-by: Nick Alcock <nick.alcock at oracle.com>

Reviewed-by: Kris Van Hees <kris.van.hees at oracle.com>

> ---
>  dtprobed/Build                |  3 ++-
>  dtprobed/dtprobed.c           | 18 +++++++++++++++---
>  dtprobed/seccomp-assistance.c | 18 ++++++++++++++++++
>  dtprobed/seccomp-assistance.h | 15 +++++++++++++++
>  4 files changed, 50 insertions(+), 4 deletions(-)
>  create mode 100644 dtprobed/seccomp-assistance.c
>  create mode 100644 dtprobed/seccomp-assistance.h
> 
> diff --git a/dtprobed/Build b/dtprobed/Build
> index 7e3113fdd0b6f..fcaea2d324a1e 100644
> --- a/dtprobed/Build
> +++ b/dtprobed/Build
> @@ -26,7 +26,7 @@ dtprobed_CPPFLAGS := -I. -Idtprobed -Ilibproc -Ilibcommon -Ilibport
>  dtprobed_CFLAGS := $(shell pkg-config --cflags $(LIBFUSE))
>  dtprobed_LIBS := -lcommon -lproc -lcommon -lport -lelf $(shell pkg-config --libs $(LIBFUSE))
>  dtprobed_DEPS := libproc.a libcommon.a libport.a
> -dtprobed_SOURCES := dtprobed.c
> +dtprobed_SOURCES := dtprobed.c seccomp-assistance.c
>  dtprobed_LIBSOURCES := libproc libcommon
>  
>  ifdef HAVE_LIBSYSTEMD
> @@ -39,6 +39,7 @@ dtprobed_SOURCES += rpl_fuse_log.c
>  endif
>  
>  dtprobed.c_CFLAGS := -Wno-pedantic
> +seccomp-assistance.c_CFLAGS := -fno-lto
>  endif
>  
>  install::
> diff --git a/dtprobed/dtprobed.c b/dtprobed/dtprobed.c
> index 3725dba2fe1c6..9eadf8cffc15d 100644
> --- a/dtprobed/dtprobed.c
> +++ b/dtprobed/dtprobed.c
> @@ -9,6 +9,7 @@
>  #include <sys/wait.h>
>  #include <errno.h>
>  #include <fcntl.h>
> +#include <malloc.h>
>  #include <poll.h>
>  #include <stdarg.h>
>  #include <stdio.h>
> @@ -52,6 +53,8 @@
>  #include "dof_parser.h"
>  #include "uprobes.h"
>  
> +#include "seccomp-assistance.h"
> +
>  #define DOF_MAXSZ 512 * 1024 * 1024
>  
>  static struct fuse_session *cuse_session;
> @@ -250,12 +253,21 @@ dof_parser_start(int sync_fd)
>  		 * closed all pipes that we might use to report it.  Just exit 1
>  		 * and rely on the admin using strace :(
>  		 *
> -		 * Don't do any of this if debugging (but still run in a child
> -		 * process).
> +		 * Take additional measures to ensure that we can still do
> +		 * sufficiently-large mallocs in the child without needing to
> +		 * make any syscalls.
> +		 *
> +		 * Don't lock the process in jail if debugging (but still run in
> +		 * a child process).
>  		 */
> -		if (!_dtrace_debug)
> +		mallopt(M_MMAP_MAX, 0);
> +		mallopt(M_TRIM_THRESHOLD, -1);
> +		seccomp_fill_memory_really_free(seccomp_fill_memory_really_malloc(DOF_MAXSZ * 2));
> +
> +		if (!_dtrace_debug) {
>  			if (syscall(SYS_seccomp, SECCOMP_SET_MODE_STRICT, 0, NULL) < 0)
>  				_exit(1);
> +		}
>  
>  		while (parse_dof(parser_in_pipe[0], parser_out_pipe[1]))
>  			;
> diff --git a/dtprobed/seccomp-assistance.c b/dtprobed/seccomp-assistance.c
> new file mode 100644
> index 0000000000000..02f36e1cc6aff
> --- /dev/null
> +++ b/dtprobed/seccomp-assistance.c
> @@ -0,0 +1,18 @@
> +/*
> + * Oracle Linux DTrace; assist seccomp, fool the compiler
> + * Copyright (c) 2023, Oracle and/or its affiliates. All rights reserved.
> + * Licensed under the Universal Permissive License v 1.0 as shown at
> + * http://oss.oracle.com/licenses/upl.
> + */
> +
> +#include <stdlib.h>
> +
> +void *seccomp_fill_memory_really_malloc(size_t size)
> +{
> +	return malloc(size);
> +}
> +
> +void seccomp_fill_memory_really_free(void *ptr)
> +{
> +	free(ptr);
> +}
> diff --git a/dtprobed/seccomp-assistance.h b/dtprobed/seccomp-assistance.h
> new file mode 100644
> index 0000000000000..8a82a0f60b82c
> --- /dev/null
> +++ b/dtprobed/seccomp-assistance.h
> @@ -0,0 +1,15 @@
> +/*
> + * Oracle Linux DTrace; assist seccomp, fool the compiler
> + * Copyright (c) 2023, Oracle and/or its affiliates. All rights reserved.
> + * Licensed under the Universal Permissive License v 1.0 as shown at
> + * http://oss.oracle.com/licenses/upl.
> + */
> +
> +#ifndef	_SECCOMP_ASSISTANCE_H
> +#define	_SECCOMP__ASSISTANCE_H
> +
> +void *seccomp_fill_memory_really_malloc(size_t size);
> +void seccomp_fill_memory_really_free(void *ptr);
> +
> +#endif
> +
> -- 
> 2.39.1.268.g9de2f9a303
> 
> 
> _______________________________________________
> DTrace-devel mailing list
> DTrace-devel at oss.oracle.com
> https://oss.oracle.com/mailman/listinfo/dtrace-devel



More information about the DTrace-devel mailing list