From f03d67cfd9aefc2d2c62b623c6f37b24854c5c4a Mon Sep 17 00:00:00 2001 From: "Dmitry V. Levin" Date: Sun, 21 Jan 2018 23:23:31 +0000 Subject: [PATCH] Transform fetch_old_mmap_args into fetch_indirect_syscall_args As there are more than one old style syscall that take their arguments via array, generalize fetch_old_mmap_args into a function that could fetch variable number of arguments. * mem.c (fetch_old_mmap_args): Transform into ... * fetch_indirect_syscall_args.c: ... fetch_indirect_syscall_args in this new file. * Makefile.am (libstrace_a_SOURCES): Add it. * defs.h [HAVE_ARCH_OLD_MMAP] (fetch_old_mmap_args): Remove. (fetch_indirect_syscall_args): New prototype. * pathtrace.c (pathtrace_match_set) [HAVE_ARCH_OLD_MMAP]: Use fetch_indirect_syscall_args instead of fetch_old_mmap_args. --- Makefile.am | 1 + defs.h | 5 ++-- fetch_indirect_syscall_args.c | 55 +++++++++++++++++++++++++++++++++++ mem.c | 29 +++--------------- pathtrace.c | 3 +- 5 files changed, 64 insertions(+), 29 deletions(-) create mode 100644 fetch_indirect_syscall_args.c diff --git a/Makefile.am b/Makefile.am index db822c5c..43795fe1 100644 --- a/Makefile.am +++ b/Makefile.am @@ -70,6 +70,7 @@ noinst_LIBRARIES = libstrace.a libstrace_a_CPPFLAGS = $(strace_CPPFLAGS) libstrace_a_CFLAGS = $(strace_CFLAGS) libstrace_a_SOURCES = \ + fetch_indirect_syscall_args.c \ fstatfs.c \ fstatfs64.c \ getpagesize.c \ diff --git a/defs.h b/defs.h index 6f4c5e85..dddf8a69 100644 --- a/defs.h +++ b/defs.h @@ -554,9 +554,8 @@ extern void print_numeric_long_umask(unsigned long); extern void print_dev_t(unsigned long long dev); extern void print_abnormal_hi(kernel_ulong_t); -#if HAVE_ARCH_OLD_MMAP -extern kernel_ulong_t *fetch_old_mmap_args(struct tcb *tcp); -#endif +extern kernel_ulong_t * +fetch_indirect_syscall_args(struct tcb *, kernel_ulong_t addr, unsigned int n_args); extern void dumpiov_in_msghdr(struct tcb *, kernel_ulong_t addr, kernel_ulong_t data_size); diff --git a/fetch_indirect_syscall_args.c b/fetch_indirect_syscall_args.c new file mode 100644 index 00000000..72ee7c75 --- /dev/null +++ b/fetch_indirect_syscall_args.c @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2018 The strace developers. + * All rights reserved. + * + * 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. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 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 "defs.h" + +/* + * Fetch indirect syscall arguments that are provided as an array. + * Return a pointer to a static array of kernel_ulong_t elements, + * or NULL in case of fetch failure. + */ +kernel_ulong_t * +fetch_indirect_syscall_args(struct tcb *const tcp, + const kernel_ulong_t addr, + const unsigned int n_args) +{ + static kernel_ulong_t u_arg[MAX_ARGS]; + + if (current_wordsize == sizeof(*u_arg)) { + if (umoven(tcp, addr, sizeof(*u_arg) * n_args, u_arg)) + return NULL; + } else { + uint32_t narrow_arg[ARRAY_SIZE(u_arg)]; + + if (umoven(tcp, addr, sizeof(*narrow_arg) * n_args, narrow_arg)) + return NULL; + for (unsigned int i = 0; i < n_args; ++i) + u_arg[i] = narrow_arg[i]; + } + + return u_arg; +} diff --git a/mem.c b/mem.c index f5657332..535ce255 100644 --- a/mem.c +++ b/mem.c @@ -108,33 +108,11 @@ print_mmap(struct tcb *tcp, kernel_ulong_t *u_arg, unsigned long long offset) */ #if HAVE_ARCH_OLD_MMAP -/** - * Fetch old_mmap/old_mmap_pgoff arguments that are provided as a 6-element - * array. Return pointer to a static array or NULL in case of fetch failure. - */ -kernel_ulong_t * -fetch_old_mmap_args(struct tcb *tcp) -{ - static kernel_ulong_t u_arg[6]; - - if (current_wordsize == 4) { - unsigned int narrow_arg[6]; - if (umove(tcp, tcp->u_arg[0], &narrow_arg)) - return NULL; - for (unsigned int i = 0; i < 6; i++) - u_arg[i] = narrow_arg[i]; - } else { - if (umove(tcp, tcp->u_arg[0], &u_arg)) - return NULL; - } - - return u_arg; -} - /* Params are pointed to by u_arg[0], offset is in bytes */ SYS_FUNC(old_mmap) { - kernel_ulong_t *args = fetch_old_mmap_args(tcp); + kernel_ulong_t *args = + fetch_indirect_syscall_args(tcp, tcp->u_arg[0], 6); if (args) print_mmap(tcp, args, args[5]); @@ -148,7 +126,8 @@ SYS_FUNC(old_mmap) /* Params are pointed to by u_arg[0], offset is in pages */ SYS_FUNC(old_mmap_pgoff) { - kernel_ulong_t *args = fetch_old_mmap_args(tcp); + kernel_ulong_t *args = + fetch_indirect_syscall_args(tcp, tcp->u_arg[0], 6); if (args) { unsigned long long offset; diff --git a/pathtrace.c b/pathtrace.c index 14cba6f1..b8799b39 100644 --- a/pathtrace.c +++ b/pathtrace.c @@ -220,7 +220,8 @@ pathtrace_match_set(struct tcb *tcp, struct path_set *set) case SEN_old_mmap_pgoff: # endif { - kernel_ulong_t *args = fetch_old_mmap_args(tcp); + kernel_ulong_t *args = + fetch_indirect_syscall_args(tcp, tcp->u_arg[0], 6); return args && fdmatch(tcp, args[4], set); } -- 2.40.0