]> granicus.if.org Git - strace/commitdiff
Turn struct inject_data.rval into an index
authorDmitry V. Levin <ldv@altlinux.org>
Wed, 28 Mar 2018 04:29:22 +0000 (04:29 +0000)
committerDmitry V. Levin <ldv@altlinux.org>
Wed, 28 Mar 2018 04:29:22 +0000 (04:29 +0000)
Add one level of indirection to decrease the size of struct inject_data
as hundreds of these structures are created for each process when
injection mechanism is activated.

* retval.h: New file.
* retval.c: Likewise.
* Makefile.am (strace_SOURCES): Add them.
* defs.h (struct inject_data): Replace rval field with rval_idx.
* filter_qualify.c: Include "retval.h".
(parse_inject_token, qualify_inject_common): Initialize
struct inject_data.rval_idx using retval_new.
* syscall.c: Include "retval.h".
(tamper_with_syscall_exiting): Obtain the value that has to be injected
using retval_get.

Makefile.am
defs.h
filter_qualify.c
retval.c [new file with mode: 0644]
retval.h [new file with mode: 0644]
syscall.c

index d43b03c4e58b870d4faff51969adee4cd5802ec1..efd5b351287ea35a6427abbd983d865708fc4e64 100644 (file)
@@ -260,6 +260,8 @@ strace_SOURCES =    \
        regs.h          \
        renameat.c      \
        resource.c      \
+       retval.c        \
+       retval.h        \
        riscv.c         \
        rt_sigframe.c   \
        rt_sigreturn.c  \
diff --git a/defs.h b/defs.h
index 95fc254426b59a204096b941f5bcedc1e8ae7287..a173579a32f379d9c4a223ba1efd8b79650f95c0 100644 (file)
--- a/defs.h
+++ b/defs.h
@@ -179,8 +179,8 @@ typedef struct ioctlent {
 struct inject_data {
        uint8_t flags;          /* only 4 of 8 flags are used so far */
        uint8_t signo;          /* NSIG <= 128 */
+       uint16_t rval_idx;      /* index in retval_vec */
        uint16_t delay_idx;     /* index in delay_data_vec */
-       kernel_long_t rval;
 };
 
 struct inject_opts {
index f4a405cccb8232cbd4f0bc501f2885f4583b310f..ebe28f5c5010aff7e80e01cedd965282beafb734 100644 (file)
@@ -30,6 +30,7 @@
 #include "nsig.h"
 #include "number_set.h"
 #include "filter.h"
+#include "retval.h"
 
 struct number_set *read_set;
 struct number_set *write_set;
@@ -143,7 +144,7 @@ parse_inject_token(const char *const token, struct inject_opts *const fopts,
                        intval = find_errno_by_name(val);
                if (intval < 1)
                        return false;
-               fopts->data.rval = -intval;
+               fopts->data.rval_idx = retval_new(-intval);
                fopts->data.flags |= INJECT_F_RETVAL;
        } else if (!fault_tokens_only
                   && (val = STR_STRIP_PREFIX(token, "retval=")) != token) {
@@ -166,7 +167,7 @@ parse_inject_token(const char *const token, struct inject_opts *const fopts,
                                  -(int) intval, intval);
 #endif
 
-               fopts->data.rval = intval;
+               fopts->data.rval_idx = retval_new(intval);
                fopts->data.flags |= INJECT_F_RETVAL;
        } else if (!fault_tokens_only
                   && (val = STR_STRIP_PREFIX(token, "signal=")) != token) {
@@ -296,7 +297,7 @@ qualify_inject_common(const char *const str,
        if (!opts.data.flags) {
                if (fault_tokens_only) {
                        /* in fault= syntax the default error code is ENOSYS. */
-                       opts.data.rval = -ENOSYS;
+                       opts.data.rval_idx = retval_new(-ENOSYS);
                        opts.data.flags |= INJECT_F_RETVAL;
                } else {
                        /* in inject= syntax this is not allowed. */
diff --git a/retval.c b/retval.c
new file mode 100644 (file)
index 0000000..b8916d0
--- /dev/null
+++ b/retval.c
@@ -0,0 +1,70 @@
+/*
+ * 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"
+#include "retval.h"
+
+static kernel_long_t *retval_vec;
+static size_t retval_vec_capacity; /* size of the arena */
+static size_t retval_vec_size;     /* size of the used arena */
+
+static void
+expand_retval_vec(void)
+{
+       const size_t old_capacity = retval_vec_capacity;
+       retval_vec = xgrowarray(retval_vec, &retval_vec_capacity,
+                               sizeof(*retval_vec));
+       memset(retval_vec + old_capacity, 0,
+              (retval_vec_capacity - old_capacity)
+              * sizeof(*retval_vec));
+}
+
+uint16_t
+retval_new(const kernel_long_t rval)
+{
+       const uint16_t idx = retval_vec_size;
+
+       if (idx < retval_vec_size)
+               error_func_msg_and_die("retval index overflow");
+
+       if (retval_vec_size == retval_vec_capacity)
+               expand_retval_vec();
+
+       retval_vec[idx] = rval;
+       ++retval_vec_size;
+
+       return idx;
+}
+
+kernel_long_t
+retval_get(const uint16_t rval_idx)
+{
+       if (rval_idx >= retval_vec_size)
+               error_func_msg_and_die("rval_idx >= retval_vec_size");
+
+       return retval_vec[rval_idx];
+}
diff --git a/retval.h b/retval.h
new file mode 100644 (file)
index 0000000..0de38c5
--- /dev/null
+++ b/retval.h
@@ -0,0 +1,8 @@
+/* retval to index and visa versa.  */
+#ifndef STRACE_RETVAL_H
+#define STRACE_RETVAL_H
+
+uint16_t retval_new(kernel_long_t rval);
+kernel_long_t retval_get(uint16_t rval_idx);
+
+#endif /* !STRACE_RETVAL_H */
index 9f1f864252cba3e812920fe4d2048eceb0babf55..989aecfe52ef5cefa933b34eb90cd5a3ad507135 100644 (file)
--- a/syscall.c
+++ b/syscall.c
@@ -38,6 +38,7 @@
 #include "ptrace.h"
 #include "nsig.h"
 #include "number_set.h"
+#include "retval.h"
 #include <limits.h>
 
 /* for struct iovec */
@@ -576,10 +577,11 @@ tamper_with_syscall_exiting(struct tcb *tcp)
 
        bool update_tcb = false;
 
-       if (opts->data.rval >= 0) {
+       const kernel_long_t inject_rval = retval_get(opts->data.rval_idx);
+       if (inject_rval >= 0) {
                kernel_long_t u_rval = tcp->u_rval;
 
-               tcp->u_rval = opts->data.rval;
+               tcp->u_rval = inject_rval;
                if (arch_set_success(tcp)) {
                        tcp->u_rval = u_rval;
                } else {
@@ -587,7 +589,7 @@ tamper_with_syscall_exiting(struct tcb *tcp)
                        tcp->u_error = 0;
                }
        } else {
-               unsigned long new_error = -opts->data.rval;
+               unsigned long new_error = -inject_rval;
 
                if (new_error != tcp->u_error && new_error <= MAX_ERRNO_VALUE) {
                        unsigned long u_error = tcp->u_error;