strace/filter_qualify.c

470 lines
11 KiB
C
Raw Normal View History

/*
* Copyright (c) 2016 Dmitry V. Levin <ldv@altlinux.org>
* Copyright (c) 2016-2018 The strace developers.
* All rights reserved.
*
* SPDX-License-Identifier: LGPL-2.1-or-later
*/
#include "defs.h"
#include "nsig.h"
#include "number_set.h"
#include "filter.h"
#include "delay.h"
#include "retval.h"
struct number_set *read_set;
struct number_set *write_set;
struct number_set *signal_set;
static struct number_set *abbrev_set;
static struct number_set *inject_set;
static struct number_set *raw_set;
static struct number_set *trace_set;
static struct number_set *verbose_set;
Rewrite remaining qual_* parsers using bit sets * defs.h (struct fault_opts): Replace forward declaration with a definition. (qualbits_t, qualify_read, qualify_write, qualify_signals): Remove. (qual_flags): New function prototype. (nsyscall_vec, sysent_vec, fault_vec): New variable prototypes. * qualify.c (abbrev_set, fault_set, raw_set, trace_set, verbose_set): New variables. (qualify_read, qualify_write, qualify_signals): Add static qualifier. (find_errno_by_name, lookup_class, parse_fault_expression, parse_fault_token, qual_flags, qualify, qualify_abbrev, qualify_fault, qualify_raw, qualify_syscall, qualify_syscall_class, qualify_syscall_name, qualify_syscall_number, qualify_syscall_tokens, qualify_trace, qualify_verbose, strip_prefix): New functions. * syscall.c (nsyscall_vec, nsysent_vec): Remove static qualifier. (MAX_NSYSCALLS1, MAX_NSYSCALLS2, MAX_NSYSCALLS, qual_vec, qual_flags, qual_fault, qual_syscall, qual_options, fault_opts, qualify_one, qualify_scno, lookup_class, qualify_syscall_class, qualify_syscall_name, qual_syscall_ex, qual_syscall, strip_prefix, find_errno_by_name, parse_fault_token, parse_fault_expression, qual_fault, qualify): Remove. (decode_socket_subcall, decode_ipc_subcall, decode_mips_subcall, get_scno): Update use of qual_flags. (inject_syscall_fault_entering): Update per-personality allocation of tcp->fault_vec. * tests/fault_injection-exit_group.test: Check parsing of inversed fault sets. * tests/fault_injection.test: Check parsing of -efault=none. * tests/options-syntax.test: Check parsing of invalid syscall numbers.
2016-12-04 17:39:48 +03:00
/* Only syscall numbers are personality-specific so far. */
struct inject_personality_data {
uint16_t scno;
};
static int
sigstr_to_uint(const char *s)
{
if (*s >= '0' && *s <= '9')
return string_to_uint_upto(s, 255);
if (strncasecmp(s, "SIG", 3) == 0)
s += 3;
for (int i = 1; i <= 255; ++i) {
const char *name = signame(i);
if (!name)
continue;
if (strncasecmp(name, "SIG", 3) != 0)
continue;
name += 3;
if (strcasecmp(name, s) != 0)
continue;
return i;
}
return -1;
}
Rewrite remaining qual_* parsers using bit sets * defs.h (struct fault_opts): Replace forward declaration with a definition. (qualbits_t, qualify_read, qualify_write, qualify_signals): Remove. (qual_flags): New function prototype. (nsyscall_vec, sysent_vec, fault_vec): New variable prototypes. * qualify.c (abbrev_set, fault_set, raw_set, trace_set, verbose_set): New variables. (qualify_read, qualify_write, qualify_signals): Add static qualifier. (find_errno_by_name, lookup_class, parse_fault_expression, parse_fault_token, qual_flags, qualify, qualify_abbrev, qualify_fault, qualify_raw, qualify_syscall, qualify_syscall_class, qualify_syscall_name, qualify_syscall_number, qualify_syscall_tokens, qualify_trace, qualify_verbose, strip_prefix): New functions. * syscall.c (nsyscall_vec, nsysent_vec): Remove static qualifier. (MAX_NSYSCALLS1, MAX_NSYSCALLS2, MAX_NSYSCALLS, qual_vec, qual_flags, qual_fault, qual_syscall, qual_options, fault_opts, qualify_one, qualify_scno, lookup_class, qualify_syscall_class, qualify_syscall_name, qual_syscall_ex, qual_syscall, strip_prefix, find_errno_by_name, parse_fault_token, parse_fault_expression, qual_fault, qualify): Remove. (decode_socket_subcall, decode_ipc_subcall, decode_mips_subcall, get_scno): Update use of qual_flags. (inject_syscall_fault_entering): Update per-personality allocation of tcp->fault_vec. * tests/fault_injection-exit_group.test: Check parsing of inversed fault sets. * tests/fault_injection.test: Check parsing of -efault=none. * tests/options-syntax.test: Check parsing of invalid syscall numbers.
2016-12-04 17:39:48 +03:00
static int
find_errno_by_name(const char *name)
{
for (unsigned int i = 1; i < nerrnos; ++i) {
if (errnoent[i] && (strcasecmp(name, errnoent[i]) == 0))
Rewrite remaining qual_* parsers using bit sets * defs.h (struct fault_opts): Replace forward declaration with a definition. (qualbits_t, qualify_read, qualify_write, qualify_signals): Remove. (qual_flags): New function prototype. (nsyscall_vec, sysent_vec, fault_vec): New variable prototypes. * qualify.c (abbrev_set, fault_set, raw_set, trace_set, verbose_set): New variables. (qualify_read, qualify_write, qualify_signals): Add static qualifier. (find_errno_by_name, lookup_class, parse_fault_expression, parse_fault_token, qual_flags, qualify, qualify_abbrev, qualify_fault, qualify_raw, qualify_syscall, qualify_syscall_class, qualify_syscall_name, qualify_syscall_number, qualify_syscall_tokens, qualify_trace, qualify_verbose, strip_prefix): New functions. * syscall.c (nsyscall_vec, nsysent_vec): Remove static qualifier. (MAX_NSYSCALLS1, MAX_NSYSCALLS2, MAX_NSYSCALLS, qual_vec, qual_flags, qual_fault, qual_syscall, qual_options, fault_opts, qualify_one, qualify_scno, lookup_class, qualify_syscall_class, qualify_syscall_name, qual_syscall_ex, qual_syscall, strip_prefix, find_errno_by_name, parse_fault_token, parse_fault_expression, qual_fault, qualify): Remove. (decode_socket_subcall, decode_ipc_subcall, decode_mips_subcall, get_scno): Update use of qual_flags. (inject_syscall_fault_entering): Update per-personality allocation of tcp->fault_vec. * tests/fault_injection-exit_group.test: Check parsing of inversed fault sets. * tests/fault_injection.test: Check parsing of -efault=none. * tests/options-syntax.test: Check parsing of invalid syscall numbers.
2016-12-04 17:39:48 +03:00
return i;
}
return -1;
}
Implement delay injection Add -e inject=SET:delay_enter= and -e inject=SET:delay_exit= options. * configure.ac (AC_SEARCH_LIBS): Check for timer_create -lrt. * delay.c: New file. * Makefile.am (strace_SOURCES): Add it. (strace_LDADD): Add $(timer_LIBS). * defs.h (INJECT_F_DELAY_ENTER, INJECT_F_DELAY_EXIT, TCB_INJECT_DELAY_EXIT, TCB_DELAYED, inject_delay_exit, syscall_delayed): New macros. (alloc_delay_data, fill_delay_data, is_delay_timer_created, arm_delay_timer, delay_tcb): New prototypes. (struct inject_data): Replace reserved field with delay_idx. (struct tcb): Add delay_expiration_time field. * filter_qualify.c (parse_delay_token): New function. (parse_inject_token): Use it. (qualify_inject_common): Initialize struct inject_opts.data.delay_idx. * strace.c: Include <setjmp.h> (timer_jmp_buf, timer_set): New static variables. (timer_sighandler, restart_delayed_tcb, restart_delayed_tcbs): New functions. (init): Block SIGALRM, set SIGALRM handler. (dispatch_event): Do not restart delayed syscalls. (next_event): Unblock SIGALRM during wait4 invocation. * syscall.c (tamper_with_syscall_entering): Arm delay timer if INJECT_F_DELAY_ENTER injection flag is set, set TCB_INJECT_DELAY_EXIT flag if INJECT_F_DELAY_EXIT injection flag is set. tamper_with_syscall_exiting): Arm delay timer if inject_delay_exit. (syscall_exiting_trace): Call tamper_with_syscall_exiting in case of inject_delay_exit. (syscall_exiting_finish): Clear TCB_INJECT_DELAY_EXIT flag. * strace.1.in: Document delay injection. * NEWS: Mention this improvement. Co-Authored-by: Dmitry V. Levin <ldv@altlinux.org>
2018-02-18 23:21:48 +03:00
static bool
parse_delay_token(const char *input, struct inject_opts *fopts, bool isenter)
{
unsigned flag = isenter ? INJECT_F_DELAY_ENTER : INJECT_F_DELAY_EXIT;
if (fopts->data.flags & flag) /* duplicate */
return false;
long long intval = string_to_ulonglong(input);
if (intval < 0) /* couldn't parse */
return false;
if (fopts->data.delay_idx == (uint16_t) -1)
fopts->data.delay_idx = alloc_delay_data();
/* populate .ts_enter or .ts_exit */
fill_delay_data(fopts->data.delay_idx, intval, isenter);
fopts->data.flags |= flag;
return true;
}
Rewrite remaining qual_* parsers using bit sets * defs.h (struct fault_opts): Replace forward declaration with a definition. (qualbits_t, qualify_read, qualify_write, qualify_signals): Remove. (qual_flags): New function prototype. (nsyscall_vec, sysent_vec, fault_vec): New variable prototypes. * qualify.c (abbrev_set, fault_set, raw_set, trace_set, verbose_set): New variables. (qualify_read, qualify_write, qualify_signals): Add static qualifier. (find_errno_by_name, lookup_class, parse_fault_expression, parse_fault_token, qual_flags, qualify, qualify_abbrev, qualify_fault, qualify_raw, qualify_syscall, qualify_syscall_class, qualify_syscall_name, qualify_syscall_number, qualify_syscall_tokens, qualify_trace, qualify_verbose, strip_prefix): New functions. * syscall.c (nsyscall_vec, nsysent_vec): Remove static qualifier. (MAX_NSYSCALLS1, MAX_NSYSCALLS2, MAX_NSYSCALLS, qual_vec, qual_flags, qual_fault, qual_syscall, qual_options, fault_opts, qualify_one, qualify_scno, lookup_class, qualify_syscall_class, qualify_syscall_name, qual_syscall_ex, qual_syscall, strip_prefix, find_errno_by_name, parse_fault_token, parse_fault_expression, qual_fault, qualify): Remove. (decode_socket_subcall, decode_ipc_subcall, decode_mips_subcall, get_scno): Update use of qual_flags. (inject_syscall_fault_entering): Update per-personality allocation of tcp->fault_vec. * tests/fault_injection-exit_group.test: Check parsing of inversed fault sets. * tests/fault_injection.test: Check parsing of -efault=none. * tests/options-syntax.test: Check parsing of invalid syscall numbers.
2016-12-04 17:39:48 +03:00
static bool
parse_inject_token(const char *const token, struct inject_opts *const fopts,
struct inject_personality_data *const pdata,
const bool fault_tokens_only)
Rewrite remaining qual_* parsers using bit sets * defs.h (struct fault_opts): Replace forward declaration with a definition. (qualbits_t, qualify_read, qualify_write, qualify_signals): Remove. (qual_flags): New function prototype. (nsyscall_vec, sysent_vec, fault_vec): New variable prototypes. * qualify.c (abbrev_set, fault_set, raw_set, trace_set, verbose_set): New variables. (qualify_read, qualify_write, qualify_signals): Add static qualifier. (find_errno_by_name, lookup_class, parse_fault_expression, parse_fault_token, qual_flags, qualify, qualify_abbrev, qualify_fault, qualify_raw, qualify_syscall, qualify_syscall_class, qualify_syscall_name, qualify_syscall_number, qualify_syscall_tokens, qualify_trace, qualify_verbose, strip_prefix): New functions. * syscall.c (nsyscall_vec, nsysent_vec): Remove static qualifier. (MAX_NSYSCALLS1, MAX_NSYSCALLS2, MAX_NSYSCALLS, qual_vec, qual_flags, qual_fault, qual_syscall, qual_options, fault_opts, qualify_one, qualify_scno, lookup_class, qualify_syscall_class, qualify_syscall_name, qual_syscall_ex, qual_syscall, strip_prefix, find_errno_by_name, parse_fault_token, parse_fault_expression, qual_fault, qualify): Remove. (decode_socket_subcall, decode_ipc_subcall, decode_mips_subcall, get_scno): Update use of qual_flags. (inject_syscall_fault_entering): Update per-personality allocation of tcp->fault_vec. * tests/fault_injection-exit_group.test: Check parsing of inversed fault sets. * tests/fault_injection.test: Check parsing of -efault=none. * tests/options-syntax.test: Check parsing of invalid syscall numbers.
2016-12-04 17:39:48 +03:00
{
const char *val;
int intval;
Rewrite remaining qual_* parsers using bit sets * defs.h (struct fault_opts): Replace forward declaration with a definition. (qualbits_t, qualify_read, qualify_write, qualify_signals): Remove. (qual_flags): New function prototype. (nsyscall_vec, sysent_vec, fault_vec): New variable prototypes. * qualify.c (abbrev_set, fault_set, raw_set, trace_set, verbose_set): New variables. (qualify_read, qualify_write, qualify_signals): Add static qualifier. (find_errno_by_name, lookup_class, parse_fault_expression, parse_fault_token, qual_flags, qualify, qualify_abbrev, qualify_fault, qualify_raw, qualify_syscall, qualify_syscall_class, qualify_syscall_name, qualify_syscall_number, qualify_syscall_tokens, qualify_trace, qualify_verbose, strip_prefix): New functions. * syscall.c (nsyscall_vec, nsysent_vec): Remove static qualifier. (MAX_NSYSCALLS1, MAX_NSYSCALLS2, MAX_NSYSCALLS, qual_vec, qual_flags, qual_fault, qual_syscall, qual_options, fault_opts, qualify_one, qualify_scno, lookup_class, qualify_syscall_class, qualify_syscall_name, qual_syscall_ex, qual_syscall, strip_prefix, find_errno_by_name, parse_fault_token, parse_fault_expression, qual_fault, qualify): Remove. (decode_socket_subcall, decode_ipc_subcall, decode_mips_subcall, get_scno): Update use of qual_flags. (inject_syscall_fault_entering): Update per-personality allocation of tcp->fault_vec. * tests/fault_injection-exit_group.test: Check parsing of inversed fault sets. * tests/fault_injection.test: Check parsing of -efault=none. * tests/options-syntax.test: Check parsing of invalid syscall numbers.
2016-12-04 17:39:48 +03:00
if ((val = STR_STRIP_PREFIX(token, "when=")) != token) {
Rewrite remaining qual_* parsers using bit sets * defs.h (struct fault_opts): Replace forward declaration with a definition. (qualbits_t, qualify_read, qualify_write, qualify_signals): Remove. (qual_flags): New function prototype. (nsyscall_vec, sysent_vec, fault_vec): New variable prototypes. * qualify.c (abbrev_set, fault_set, raw_set, trace_set, verbose_set): New variables. (qualify_read, qualify_write, qualify_signals): Add static qualifier. (find_errno_by_name, lookup_class, parse_fault_expression, parse_fault_token, qual_flags, qualify, qualify_abbrev, qualify_fault, qualify_raw, qualify_syscall, qualify_syscall_class, qualify_syscall_name, qualify_syscall_number, qualify_syscall_tokens, qualify_trace, qualify_verbose, strip_prefix): New functions. * syscall.c (nsyscall_vec, nsysent_vec): Remove static qualifier. (MAX_NSYSCALLS1, MAX_NSYSCALLS2, MAX_NSYSCALLS, qual_vec, qual_flags, qual_fault, qual_syscall, qual_options, fault_opts, qualify_one, qualify_scno, lookup_class, qualify_syscall_class, qualify_syscall_name, qual_syscall_ex, qual_syscall, strip_prefix, find_errno_by_name, parse_fault_token, parse_fault_expression, qual_fault, qualify): Remove. (decode_socket_subcall, decode_ipc_subcall, decode_mips_subcall, get_scno): Update use of qual_flags. (inject_syscall_fault_entering): Update per-personality allocation of tcp->fault_vec. * tests/fault_injection-exit_group.test: Check parsing of inversed fault sets. * tests/fault_injection.test: Check parsing of -efault=none. * tests/options-syntax.test: Check parsing of invalid syscall numbers.
2016-12-04 17:39:48 +03:00
/*
* == 1+1
Rewrite remaining qual_* parsers using bit sets * defs.h (struct fault_opts): Replace forward declaration with a definition. (qualbits_t, qualify_read, qualify_write, qualify_signals): Remove. (qual_flags): New function prototype. (nsyscall_vec, sysent_vec, fault_vec): New variable prototypes. * qualify.c (abbrev_set, fault_set, raw_set, trace_set, verbose_set): New variables. (qualify_read, qualify_write, qualify_signals): Add static qualifier. (find_errno_by_name, lookup_class, parse_fault_expression, parse_fault_token, qual_flags, qualify, qualify_abbrev, qualify_fault, qualify_raw, qualify_syscall, qualify_syscall_class, qualify_syscall_name, qualify_syscall_number, qualify_syscall_tokens, qualify_trace, qualify_verbose, strip_prefix): New functions. * syscall.c (nsyscall_vec, nsysent_vec): Remove static qualifier. (MAX_NSYSCALLS1, MAX_NSYSCALLS2, MAX_NSYSCALLS, qual_vec, qual_flags, qual_fault, qual_syscall, qual_options, fault_opts, qualify_one, qualify_scno, lookup_class, qualify_syscall_class, qualify_syscall_name, qual_syscall_ex, qual_syscall, strip_prefix, find_errno_by_name, parse_fault_token, parse_fault_expression, qual_fault, qualify): Remove. (decode_socket_subcall, decode_ipc_subcall, decode_mips_subcall, get_scno): Update use of qual_flags. (inject_syscall_fault_entering): Update per-personality allocation of tcp->fault_vec. * tests/fault_injection-exit_group.test: Check parsing of inversed fault sets. * tests/fault_injection.test: Check parsing of -efault=none. * tests/options-syntax.test: Check parsing of invalid syscall numbers.
2016-12-04 17:39:48 +03:00
* F == F+0
* F+ == F+1
* F+S
*/
char *end;
intval = string_to_uint_ex(val, &end, 0xffff, "+");
if (intval < 1)
return false;
fopts->first = intval;
if (*end) {
val = end + 1;
if (*val) {
/* F+S */
intval = string_to_uint_upto(val, 0xffff);
if (intval < 1)
return false;
fopts->step = intval;
} else {
/* F+ == F+1 */
fopts->step = 1;
}
} else {
/* F == F+0 */
fopts->step = 0;
}
} else if ((val = STR_STRIP_PREFIX(token, "syscall=")) != token) {
if (fopts->data.flags & INJECT_F_SYSCALL)
return false;
for (unsigned int p = 0; p < SUPPORTED_PERSONALITIES; ++p) {
kernel_long_t scno = scno_by_name(val, p, 0);
if (scno < 0)
return false;
/*
* We want to inject only pure system calls with no side
* effects.
*/
if (!(sysent_vec[p][scno].sys_flags & TRACE_PURE))
return false;
pdata[p].scno = scno;
}
fopts->data.flags |= INJECT_F_SYSCALL;
} else if ((val = STR_STRIP_PREFIX(token, "error=")) != token) {
if (fopts->data.flags & (INJECT_F_ERROR | INJECT_F_RETVAL))
Implement success injection This extends fault injection syntax with :retval= option. When :retval=VALUE is specified, the syscall number is replaced by -1 and a bogus success VALUE is returned to the callee. * defs.h (fault_opts): Remove err field, add rval field. (MAX_ERRNO_VALUE, FAULT_OPTS_RVAL_DEFAULT, FAULT_OPTS_RVAL_DISABLE): New macros. * qualify.c (parse_fault_token): Handle retval= token. (qualify_fault): Update fault_opts initialization after the move from struct fault_opts.err to struct fault_opts.rval. * syscall.c (arch_set_success): New prototype. (inject_syscall_fault_entering): Check opts->rval instead of opts->err. (update_syscall_fault_exiting): Implement retval injection. * strace.1: Update the section on fault injection. * NEWS: Mention retval= option. * linux/aarch64/set_error.c (arch_set_success): New function. * linux/alpha/set_error.c: Likewise. * linux/arc/set_error.c: Likewise. * linux/arm/set_error.c: Likewise. * linux/avr32/set_error.c: Likewise. * linux/bfin/set_error.c: Likewise. * linux/crisv10/set_error.c: Likewise. * linux/hppa/set_error.c: Likewise. * linux/i386/set_error.c: Likewise. * linux/ia64/set_error.c: Likewise. * linux/m68k/set_error.c: Likewise. * linux/metag/set_error.c: Likewise. * linux/microblaze/set_error.c: Likewise. * linux/mips/set_error.c: Likewise. * linux/nios2/set_error.c: Likewise. * linux/or1k/set_error.c: Likewise. * linux/powerpc/set_error.c: Likewise. * linux/riscv/set_error.c: Likewise. * linux/s390/set_error.c: Likewise. * linux/sh/set_error.c: Likewise. * linux/sh64/set_error.c: Likewise. * linux/sparc/set_error.c: Likewise. * linux/sparc64/set_error.c: Likewise. * linux/tile/set_error.c: Likewise. * linux/x86_64/set_error.c: Likewise. * linux/xtensa/set_error.c: Likewise. Closes: https://github.com/strace/strace/issues/3
2017-01-25 02:59:16 +03:00
return false;
intval = string_to_uint_upto(val, MAX_ERRNO_VALUE);
Rewrite remaining qual_* parsers using bit sets * defs.h (struct fault_opts): Replace forward declaration with a definition. (qualbits_t, qualify_read, qualify_write, qualify_signals): Remove. (qual_flags): New function prototype. (nsyscall_vec, sysent_vec, fault_vec): New variable prototypes. * qualify.c (abbrev_set, fault_set, raw_set, trace_set, verbose_set): New variables. (qualify_read, qualify_write, qualify_signals): Add static qualifier. (find_errno_by_name, lookup_class, parse_fault_expression, parse_fault_token, qual_flags, qualify, qualify_abbrev, qualify_fault, qualify_raw, qualify_syscall, qualify_syscall_class, qualify_syscall_name, qualify_syscall_number, qualify_syscall_tokens, qualify_trace, qualify_verbose, strip_prefix): New functions. * syscall.c (nsyscall_vec, nsysent_vec): Remove static qualifier. (MAX_NSYSCALLS1, MAX_NSYSCALLS2, MAX_NSYSCALLS, qual_vec, qual_flags, qual_fault, qual_syscall, qual_options, fault_opts, qualify_one, qualify_scno, lookup_class, qualify_syscall_class, qualify_syscall_name, qual_syscall_ex, qual_syscall, strip_prefix, find_errno_by_name, parse_fault_token, parse_fault_expression, qual_fault, qualify): Remove. (decode_socket_subcall, decode_ipc_subcall, decode_mips_subcall, get_scno): Update use of qual_flags. (inject_syscall_fault_entering): Update per-personality allocation of tcp->fault_vec. * tests/fault_injection-exit_group.test: Check parsing of inversed fault sets. * tests/fault_injection.test: Check parsing of -efault=none. * tests/options-syntax.test: Check parsing of invalid syscall numbers.
2016-12-04 17:39:48 +03:00
if (intval < 0)
intval = find_errno_by_name(val);
if (intval < 1)
return false;
fopts->data.rval_idx = retval_new(intval);
fopts->data.flags |= INJECT_F_ERROR;
} else if (!fault_tokens_only
&& (val = STR_STRIP_PREFIX(token, "retval=")) != token) {
if (fopts->data.flags & (INJECT_F_ERROR | INJECT_F_RETVAL))
Implement success injection This extends fault injection syntax with :retval= option. When :retval=VALUE is specified, the syscall number is replaced by -1 and a bogus success VALUE is returned to the callee. * defs.h (fault_opts): Remove err field, add rval field. (MAX_ERRNO_VALUE, FAULT_OPTS_RVAL_DEFAULT, FAULT_OPTS_RVAL_DISABLE): New macros. * qualify.c (parse_fault_token): Handle retval= token. (qualify_fault): Update fault_opts initialization after the move from struct fault_opts.err to struct fault_opts.rval. * syscall.c (arch_set_success): New prototype. (inject_syscall_fault_entering): Check opts->rval instead of opts->err. (update_syscall_fault_exiting): Implement retval injection. * strace.1: Update the section on fault injection. * NEWS: Mention retval= option. * linux/aarch64/set_error.c (arch_set_success): New function. * linux/alpha/set_error.c: Likewise. * linux/arc/set_error.c: Likewise. * linux/arm/set_error.c: Likewise. * linux/avr32/set_error.c: Likewise. * linux/bfin/set_error.c: Likewise. * linux/crisv10/set_error.c: Likewise. * linux/hppa/set_error.c: Likewise. * linux/i386/set_error.c: Likewise. * linux/ia64/set_error.c: Likewise. * linux/m68k/set_error.c: Likewise. * linux/metag/set_error.c: Likewise. * linux/microblaze/set_error.c: Likewise. * linux/mips/set_error.c: Likewise. * linux/nios2/set_error.c: Likewise. * linux/or1k/set_error.c: Likewise. * linux/powerpc/set_error.c: Likewise. * linux/riscv/set_error.c: Likewise. * linux/s390/set_error.c: Likewise. * linux/sh/set_error.c: Likewise. * linux/sh64/set_error.c: Likewise. * linux/sparc/set_error.c: Likewise. * linux/sparc64/set_error.c: Likewise. * linux/tile/set_error.c: Likewise. * linux/x86_64/set_error.c: Likewise. * linux/xtensa/set_error.c: Likewise. Closes: https://github.com/strace/strace/issues/3
2017-01-25 02:59:16 +03:00
return false;
errno = 0;
char *endp;
unsigned long long ullval = strtoull(val, &endp, 0);
if (endp == val || *endp || (kernel_ulong_t) ullval != ullval
|| ((ullval == 0 || ullval == ULLONG_MAX) && errno))
Implement success injection This extends fault injection syntax with :retval= option. When :retval=VALUE is specified, the syscall number is replaced by -1 and a bogus success VALUE is returned to the callee. * defs.h (fault_opts): Remove err field, add rval field. (MAX_ERRNO_VALUE, FAULT_OPTS_RVAL_DEFAULT, FAULT_OPTS_RVAL_DISABLE): New macros. * qualify.c (parse_fault_token): Handle retval= token. (qualify_fault): Update fault_opts initialization after the move from struct fault_opts.err to struct fault_opts.rval. * syscall.c (arch_set_success): New prototype. (inject_syscall_fault_entering): Check opts->rval instead of opts->err. (update_syscall_fault_exiting): Implement retval injection. * strace.1: Update the section on fault injection. * NEWS: Mention retval= option. * linux/aarch64/set_error.c (arch_set_success): New function. * linux/alpha/set_error.c: Likewise. * linux/arc/set_error.c: Likewise. * linux/arm/set_error.c: Likewise. * linux/avr32/set_error.c: Likewise. * linux/bfin/set_error.c: Likewise. * linux/crisv10/set_error.c: Likewise. * linux/hppa/set_error.c: Likewise. * linux/i386/set_error.c: Likewise. * linux/ia64/set_error.c: Likewise. * linux/m68k/set_error.c: Likewise. * linux/metag/set_error.c: Likewise. * linux/microblaze/set_error.c: Likewise. * linux/mips/set_error.c: Likewise. * linux/nios2/set_error.c: Likewise. * linux/or1k/set_error.c: Likewise. * linux/powerpc/set_error.c: Likewise. * linux/riscv/set_error.c: Likewise. * linux/s390/set_error.c: Likewise. * linux/sh/set_error.c: Likewise. * linux/sh64/set_error.c: Likewise. * linux/sparc/set_error.c: Likewise. * linux/sparc64/set_error.c: Likewise. * linux/tile/set_error.c: Likewise. * linux/x86_64/set_error.c: Likewise. * linux/xtensa/set_error.c: Likewise. Closes: https://github.com/strace/strace/issues/3
2017-01-25 02:59:16 +03:00
return false;
#if ANY_WORDSIZE_LESS_THAN_KERNEL_LONG
bool inadvertent_fault_injection = false;
#endif
#if !HAVE_ARCH_DEDICATED_ERR_REG
if ((kernel_long_t) ullval < 0
&& (kernel_long_t) ullval >= -MAX_ERRNO_VALUE) {
# if ANY_WORDSIZE_LESS_THAN_KERNEL_LONG
inadvertent_fault_injection = true;
# endif
error_msg("Inadvertent injection of error %" PRI_kld
" is possible for retval=%llu",
-(kernel_long_t) ullval, ullval);
}
# if ANY_WORDSIZE_LESS_THAN_KERNEL_LONG
else if ((int) ullval < 0 && (int) ullval >= -MAX_ERRNO_VALUE) {
inadvertent_fault_injection = true;
error_msg("Inadvertent injection of error %d is"
" possible in compat personality for"
" retval=%llu",
-(int) ullval, ullval);
}
# endif
#endif
#if ANY_WORDSIZE_LESS_THAN_KERNEL_LONG
if (!inadvertent_fault_injection
&& (unsigned int) ullval != ullval) {
error_msg("Injected return value %llu will be"
" clipped to %u in compat personality",
ullval, (unsigned int) ullval);
}
#endif
fopts->data.rval_idx = retval_new(ullval);
fopts->data.flags |= INJECT_F_RETVAL;
} else if (!fault_tokens_only
&& (val = STR_STRIP_PREFIX(token, "signal=")) != token) {
if (fopts->data.flags & INJECT_F_SIGNAL)
return false;
intval = sigstr_to_uint(val);
if (intval < 1 || intval > NSIG_BYTES * 8)
return false;
fopts->data.signo = intval;
fopts->data.flags |= INJECT_F_SIGNAL;
Implement delay injection Add -e inject=SET:delay_enter= and -e inject=SET:delay_exit= options. * configure.ac (AC_SEARCH_LIBS): Check for timer_create -lrt. * delay.c: New file. * Makefile.am (strace_SOURCES): Add it. (strace_LDADD): Add $(timer_LIBS). * defs.h (INJECT_F_DELAY_ENTER, INJECT_F_DELAY_EXIT, TCB_INJECT_DELAY_EXIT, TCB_DELAYED, inject_delay_exit, syscall_delayed): New macros. (alloc_delay_data, fill_delay_data, is_delay_timer_created, arm_delay_timer, delay_tcb): New prototypes. (struct inject_data): Replace reserved field with delay_idx. (struct tcb): Add delay_expiration_time field. * filter_qualify.c (parse_delay_token): New function. (parse_inject_token): Use it. (qualify_inject_common): Initialize struct inject_opts.data.delay_idx. * strace.c: Include <setjmp.h> (timer_jmp_buf, timer_set): New static variables. (timer_sighandler, restart_delayed_tcb, restart_delayed_tcbs): New functions. (init): Block SIGALRM, set SIGALRM handler. (dispatch_event): Do not restart delayed syscalls. (next_event): Unblock SIGALRM during wait4 invocation. * syscall.c (tamper_with_syscall_entering): Arm delay timer if INJECT_F_DELAY_ENTER injection flag is set, set TCB_INJECT_DELAY_EXIT flag if INJECT_F_DELAY_EXIT injection flag is set. tamper_with_syscall_exiting): Arm delay timer if inject_delay_exit. (syscall_exiting_trace): Call tamper_with_syscall_exiting in case of inject_delay_exit. (syscall_exiting_finish): Clear TCB_INJECT_DELAY_EXIT flag. * strace.1.in: Document delay injection. * NEWS: Mention this improvement. Co-Authored-by: Dmitry V. Levin <ldv@altlinux.org>
2018-02-18 23:21:48 +03:00
} else if (!fault_tokens_only
&& (val = STR_STRIP_PREFIX(token, "delay_enter=")) != token) {
if (!parse_delay_token(val, fopts, true))
return false;
} else if (!fault_tokens_only
&& (val = STR_STRIP_PREFIX(token, "delay_exit=")) != token) {
if (!parse_delay_token(val, fopts, false))
return false;
Rewrite remaining qual_* parsers using bit sets * defs.h (struct fault_opts): Replace forward declaration with a definition. (qualbits_t, qualify_read, qualify_write, qualify_signals): Remove. (qual_flags): New function prototype. (nsyscall_vec, sysent_vec, fault_vec): New variable prototypes. * qualify.c (abbrev_set, fault_set, raw_set, trace_set, verbose_set): New variables. (qualify_read, qualify_write, qualify_signals): Add static qualifier. (find_errno_by_name, lookup_class, parse_fault_expression, parse_fault_token, qual_flags, qualify, qualify_abbrev, qualify_fault, qualify_raw, qualify_syscall, qualify_syscall_class, qualify_syscall_name, qualify_syscall_number, qualify_syscall_tokens, qualify_trace, qualify_verbose, strip_prefix): New functions. * syscall.c (nsyscall_vec, nsysent_vec): Remove static qualifier. (MAX_NSYSCALLS1, MAX_NSYSCALLS2, MAX_NSYSCALLS, qual_vec, qual_flags, qual_fault, qual_syscall, qual_options, fault_opts, qualify_one, qualify_scno, lookup_class, qualify_syscall_class, qualify_syscall_name, qual_syscall_ex, qual_syscall, strip_prefix, find_errno_by_name, parse_fault_token, parse_fault_expression, qual_fault, qualify): Remove. (decode_socket_subcall, decode_ipc_subcall, decode_mips_subcall, get_scno): Update use of qual_flags. (inject_syscall_fault_entering): Update per-personality allocation of tcp->fault_vec. * tests/fault_injection-exit_group.test: Check parsing of inversed fault sets. * tests/fault_injection.test: Check parsing of -efault=none. * tests/options-syntax.test: Check parsing of invalid syscall numbers.
2016-12-04 17:39:48 +03:00
} else {
return false;
}
return true;
}
static const char *
parse_inject_expression(char *const str,
struct inject_opts *const fopts,
struct inject_personality_data *const pdata,
const bool fault_tokens_only)
Rewrite remaining qual_* parsers using bit sets * defs.h (struct fault_opts): Replace forward declaration with a definition. (qualbits_t, qualify_read, qualify_write, qualify_signals): Remove. (qual_flags): New function prototype. (nsyscall_vec, sysent_vec, fault_vec): New variable prototypes. * qualify.c (abbrev_set, fault_set, raw_set, trace_set, verbose_set): New variables. (qualify_read, qualify_write, qualify_signals): Add static qualifier. (find_errno_by_name, lookup_class, parse_fault_expression, parse_fault_token, qual_flags, qualify, qualify_abbrev, qualify_fault, qualify_raw, qualify_syscall, qualify_syscall_class, qualify_syscall_name, qualify_syscall_number, qualify_syscall_tokens, qualify_trace, qualify_verbose, strip_prefix): New functions. * syscall.c (nsyscall_vec, nsysent_vec): Remove static qualifier. (MAX_NSYSCALLS1, MAX_NSYSCALLS2, MAX_NSYSCALLS, qual_vec, qual_flags, qual_fault, qual_syscall, qual_options, fault_opts, qualify_one, qualify_scno, lookup_class, qualify_syscall_class, qualify_syscall_name, qual_syscall_ex, qual_syscall, strip_prefix, find_errno_by_name, parse_fault_token, parse_fault_expression, qual_fault, qualify): Remove. (decode_socket_subcall, decode_ipc_subcall, decode_mips_subcall, get_scno): Update use of qual_flags. (inject_syscall_fault_entering): Update per-personality allocation of tcp->fault_vec. * tests/fault_injection-exit_group.test: Check parsing of inversed fault sets. * tests/fault_injection.test: Check parsing of -efault=none. * tests/options-syntax.test: Check parsing of invalid syscall numbers.
2016-12-04 17:39:48 +03:00
{
if (str[0] == '\0' || str[0] == ':')
return "";
Rewrite remaining qual_* parsers using bit sets * defs.h (struct fault_opts): Replace forward declaration with a definition. (qualbits_t, qualify_read, qualify_write, qualify_signals): Remove. (qual_flags): New function prototype. (nsyscall_vec, sysent_vec, fault_vec): New variable prototypes. * qualify.c (abbrev_set, fault_set, raw_set, trace_set, verbose_set): New variables. (qualify_read, qualify_write, qualify_signals): Add static qualifier. (find_errno_by_name, lookup_class, parse_fault_expression, parse_fault_token, qual_flags, qualify, qualify_abbrev, qualify_fault, qualify_raw, qualify_syscall, qualify_syscall_class, qualify_syscall_name, qualify_syscall_number, qualify_syscall_tokens, qualify_trace, qualify_verbose, strip_prefix): New functions. * syscall.c (nsyscall_vec, nsysent_vec): Remove static qualifier. (MAX_NSYSCALLS1, MAX_NSYSCALLS2, MAX_NSYSCALLS, qual_vec, qual_flags, qual_fault, qual_syscall, qual_options, fault_opts, qualify_one, qualify_scno, lookup_class, qualify_syscall_class, qualify_syscall_name, qual_syscall_ex, qual_syscall, strip_prefix, find_errno_by_name, parse_fault_token, parse_fault_expression, qual_fault, qualify): Remove. (decode_socket_subcall, decode_ipc_subcall, decode_mips_subcall, get_scno): Update use of qual_flags. (inject_syscall_fault_entering): Update per-personality allocation of tcp->fault_vec. * tests/fault_injection-exit_group.test: Check parsing of inversed fault sets. * tests/fault_injection.test: Check parsing of -efault=none. * tests/options-syntax.test: Check parsing of invalid syscall numbers.
2016-12-04 17:39:48 +03:00
char *saveptr = NULL;
const char *name = strtok_r(str, ":", &saveptr);
Rewrite remaining qual_* parsers using bit sets * defs.h (struct fault_opts): Replace forward declaration with a definition. (qualbits_t, qualify_read, qualify_write, qualify_signals): Remove. (qual_flags): New function prototype. (nsyscall_vec, sysent_vec, fault_vec): New variable prototypes. * qualify.c (abbrev_set, fault_set, raw_set, trace_set, verbose_set): New variables. (qualify_read, qualify_write, qualify_signals): Add static qualifier. (find_errno_by_name, lookup_class, parse_fault_expression, parse_fault_token, qual_flags, qualify, qualify_abbrev, qualify_fault, qualify_raw, qualify_syscall, qualify_syscall_class, qualify_syscall_name, qualify_syscall_number, qualify_syscall_tokens, qualify_trace, qualify_verbose, strip_prefix): New functions. * syscall.c (nsyscall_vec, nsysent_vec): Remove static qualifier. (MAX_NSYSCALLS1, MAX_NSYSCALLS2, MAX_NSYSCALLS, qual_vec, qual_flags, qual_fault, qual_syscall, qual_options, fault_opts, qualify_one, qualify_scno, lookup_class, qualify_syscall_class, qualify_syscall_name, qual_syscall_ex, qual_syscall, strip_prefix, find_errno_by_name, parse_fault_token, parse_fault_expression, qual_fault, qualify): Remove. (decode_socket_subcall, decode_ipc_subcall, decode_mips_subcall, get_scno): Update use of qual_flags. (inject_syscall_fault_entering): Update per-personality allocation of tcp->fault_vec. * tests/fault_injection-exit_group.test: Check parsing of inversed fault sets. * tests/fault_injection.test: Check parsing of -efault=none. * tests/options-syntax.test: Check parsing of invalid syscall numbers.
2016-12-04 17:39:48 +03:00
char *token;
while ((token = strtok_r(NULL, ":", &saveptr))) {
if (!parse_inject_token(token, fopts, pdata, fault_tokens_only))
return NULL;
Rewrite remaining qual_* parsers using bit sets * defs.h (struct fault_opts): Replace forward declaration with a definition. (qualbits_t, qualify_read, qualify_write, qualify_signals): Remove. (qual_flags): New function prototype. (nsyscall_vec, sysent_vec, fault_vec): New variable prototypes. * qualify.c (abbrev_set, fault_set, raw_set, trace_set, verbose_set): New variables. (qualify_read, qualify_write, qualify_signals): Add static qualifier. (find_errno_by_name, lookup_class, parse_fault_expression, parse_fault_token, qual_flags, qualify, qualify_abbrev, qualify_fault, qualify_raw, qualify_syscall, qualify_syscall_class, qualify_syscall_name, qualify_syscall_number, qualify_syscall_tokens, qualify_trace, qualify_verbose, strip_prefix): New functions. * syscall.c (nsyscall_vec, nsysent_vec): Remove static qualifier. (MAX_NSYSCALLS1, MAX_NSYSCALLS2, MAX_NSYSCALLS, qual_vec, qual_flags, qual_fault, qual_syscall, qual_options, fault_opts, qualify_one, qualify_scno, lookup_class, qualify_syscall_class, qualify_syscall_name, qual_syscall_ex, qual_syscall, strip_prefix, find_errno_by_name, parse_fault_token, parse_fault_expression, qual_fault, qualify): Remove. (decode_socket_subcall, decode_ipc_subcall, decode_mips_subcall, get_scno): Update use of qual_flags. (inject_syscall_fault_entering): Update per-personality allocation of tcp->fault_vec. * tests/fault_injection-exit_group.test: Check parsing of inversed fault sets. * tests/fault_injection.test: Check parsing of -efault=none. * tests/options-syntax.test: Check parsing of invalid syscall numbers.
2016-12-04 17:39:48 +03:00
}
return name;
Rewrite remaining qual_* parsers using bit sets * defs.h (struct fault_opts): Replace forward declaration with a definition. (qualbits_t, qualify_read, qualify_write, qualify_signals): Remove. (qual_flags): New function prototype. (nsyscall_vec, sysent_vec, fault_vec): New variable prototypes. * qualify.c (abbrev_set, fault_set, raw_set, trace_set, verbose_set): New variables. (qualify_read, qualify_write, qualify_signals): Add static qualifier. (find_errno_by_name, lookup_class, parse_fault_expression, parse_fault_token, qual_flags, qualify, qualify_abbrev, qualify_fault, qualify_raw, qualify_syscall, qualify_syscall_class, qualify_syscall_name, qualify_syscall_number, qualify_syscall_tokens, qualify_trace, qualify_verbose, strip_prefix): New functions. * syscall.c (nsyscall_vec, nsysent_vec): Remove static qualifier. (MAX_NSYSCALLS1, MAX_NSYSCALLS2, MAX_NSYSCALLS, qual_vec, qual_flags, qual_fault, qual_syscall, qual_options, fault_opts, qualify_one, qualify_scno, lookup_class, qualify_syscall_class, qualify_syscall_name, qual_syscall_ex, qual_syscall, strip_prefix, find_errno_by_name, parse_fault_token, parse_fault_expression, qual_fault, qualify): Remove. (decode_socket_subcall, decode_ipc_subcall, decode_mips_subcall, get_scno): Update use of qual_flags. (inject_syscall_fault_entering): Update per-personality allocation of tcp->fault_vec. * tests/fault_injection-exit_group.test: Check parsing of inversed fault sets. * tests/fault_injection.test: Check parsing of -efault=none. * tests/options-syntax.test: Check parsing of invalid syscall numbers.
2016-12-04 17:39:48 +03:00
}
static void
qualify_read(const char *const str)
{
if (!read_set)
read_set = alloc_number_set_array(1);
qualify_tokens(str, read_set, string_to_uint, "descriptor");
Rewrite remaining qual_* parsers using bit sets * defs.h (struct fault_opts): Replace forward declaration with a definition. (qualbits_t, qualify_read, qualify_write, qualify_signals): Remove. (qual_flags): New function prototype. (nsyscall_vec, sysent_vec, fault_vec): New variable prototypes. * qualify.c (abbrev_set, fault_set, raw_set, trace_set, verbose_set): New variables. (qualify_read, qualify_write, qualify_signals): Add static qualifier. (find_errno_by_name, lookup_class, parse_fault_expression, parse_fault_token, qual_flags, qualify, qualify_abbrev, qualify_fault, qualify_raw, qualify_syscall, qualify_syscall_class, qualify_syscall_name, qualify_syscall_number, qualify_syscall_tokens, qualify_trace, qualify_verbose, strip_prefix): New functions. * syscall.c (nsyscall_vec, nsysent_vec): Remove static qualifier. (MAX_NSYSCALLS1, MAX_NSYSCALLS2, MAX_NSYSCALLS, qual_vec, qual_flags, qual_fault, qual_syscall, qual_options, fault_opts, qualify_one, qualify_scno, lookup_class, qualify_syscall_class, qualify_syscall_name, qual_syscall_ex, qual_syscall, strip_prefix, find_errno_by_name, parse_fault_token, parse_fault_expression, qual_fault, qualify): Remove. (decode_socket_subcall, decode_ipc_subcall, decode_mips_subcall, get_scno): Update use of qual_flags. (inject_syscall_fault_entering): Update per-personality allocation of tcp->fault_vec. * tests/fault_injection-exit_group.test: Check parsing of inversed fault sets. * tests/fault_injection.test: Check parsing of -efault=none. * tests/options-syntax.test: Check parsing of invalid syscall numbers.
2016-12-04 17:39:48 +03:00
}
static void
qualify_write(const char *const str)
{
if (!write_set)
write_set = alloc_number_set_array(1);
qualify_tokens(str, write_set, string_to_uint, "descriptor");
Rewrite remaining qual_* parsers using bit sets * defs.h (struct fault_opts): Replace forward declaration with a definition. (qualbits_t, qualify_read, qualify_write, qualify_signals): Remove. (qual_flags): New function prototype. (nsyscall_vec, sysent_vec, fault_vec): New variable prototypes. * qualify.c (abbrev_set, fault_set, raw_set, trace_set, verbose_set): New variables. (qualify_read, qualify_write, qualify_signals): Add static qualifier. (find_errno_by_name, lookup_class, parse_fault_expression, parse_fault_token, qual_flags, qualify, qualify_abbrev, qualify_fault, qualify_raw, qualify_syscall, qualify_syscall_class, qualify_syscall_name, qualify_syscall_number, qualify_syscall_tokens, qualify_trace, qualify_verbose, strip_prefix): New functions. * syscall.c (nsyscall_vec, nsysent_vec): Remove static qualifier. (MAX_NSYSCALLS1, MAX_NSYSCALLS2, MAX_NSYSCALLS, qual_vec, qual_flags, qual_fault, qual_syscall, qual_options, fault_opts, qualify_one, qualify_scno, lookup_class, qualify_syscall_class, qualify_syscall_name, qual_syscall_ex, qual_syscall, strip_prefix, find_errno_by_name, parse_fault_token, parse_fault_expression, qual_fault, qualify): Remove. (decode_socket_subcall, decode_ipc_subcall, decode_mips_subcall, get_scno): Update use of qual_flags. (inject_syscall_fault_entering): Update per-personality allocation of tcp->fault_vec. * tests/fault_injection-exit_group.test: Check parsing of inversed fault sets. * tests/fault_injection.test: Check parsing of -efault=none. * tests/options-syntax.test: Check parsing of invalid syscall numbers.
2016-12-04 17:39:48 +03:00
}
static void
qualify_signals(const char *const str)
{
if (!signal_set)
signal_set = alloc_number_set_array(1);
qualify_tokens(str, signal_set, sigstr_to_uint, "signal");
}
Rewrite remaining qual_* parsers using bit sets * defs.h (struct fault_opts): Replace forward declaration with a definition. (qualbits_t, qualify_read, qualify_write, qualify_signals): Remove. (qual_flags): New function prototype. (nsyscall_vec, sysent_vec, fault_vec): New variable prototypes. * qualify.c (abbrev_set, fault_set, raw_set, trace_set, verbose_set): New variables. (qualify_read, qualify_write, qualify_signals): Add static qualifier. (find_errno_by_name, lookup_class, parse_fault_expression, parse_fault_token, qual_flags, qualify, qualify_abbrev, qualify_fault, qualify_raw, qualify_syscall, qualify_syscall_class, qualify_syscall_name, qualify_syscall_number, qualify_syscall_tokens, qualify_trace, qualify_verbose, strip_prefix): New functions. * syscall.c (nsyscall_vec, nsysent_vec): Remove static qualifier. (MAX_NSYSCALLS1, MAX_NSYSCALLS2, MAX_NSYSCALLS, qual_vec, qual_flags, qual_fault, qual_syscall, qual_options, fault_opts, qualify_one, qualify_scno, lookup_class, qualify_syscall_class, qualify_syscall_name, qual_syscall_ex, qual_syscall, strip_prefix, find_errno_by_name, parse_fault_token, parse_fault_expression, qual_fault, qualify): Remove. (decode_socket_subcall, decode_ipc_subcall, decode_mips_subcall, get_scno): Update use of qual_flags. (inject_syscall_fault_entering): Update per-personality allocation of tcp->fault_vec. * tests/fault_injection-exit_group.test: Check parsing of inversed fault sets. * tests/fault_injection.test: Check parsing of -efault=none. * tests/options-syntax.test: Check parsing of invalid syscall numbers.
2016-12-04 17:39:48 +03:00
static void
qualify_trace(const char *const str)
{
if (!trace_set)
trace_set = alloc_number_set_array(SUPPORTED_PERSONALITIES);
qualify_syscall_tokens(str, trace_set);
Rewrite remaining qual_* parsers using bit sets * defs.h (struct fault_opts): Replace forward declaration with a definition. (qualbits_t, qualify_read, qualify_write, qualify_signals): Remove. (qual_flags): New function prototype. (nsyscall_vec, sysent_vec, fault_vec): New variable prototypes. * qualify.c (abbrev_set, fault_set, raw_set, trace_set, verbose_set): New variables. (qualify_read, qualify_write, qualify_signals): Add static qualifier. (find_errno_by_name, lookup_class, parse_fault_expression, parse_fault_token, qual_flags, qualify, qualify_abbrev, qualify_fault, qualify_raw, qualify_syscall, qualify_syscall_class, qualify_syscall_name, qualify_syscall_number, qualify_syscall_tokens, qualify_trace, qualify_verbose, strip_prefix): New functions. * syscall.c (nsyscall_vec, nsysent_vec): Remove static qualifier. (MAX_NSYSCALLS1, MAX_NSYSCALLS2, MAX_NSYSCALLS, qual_vec, qual_flags, qual_fault, qual_syscall, qual_options, fault_opts, qualify_one, qualify_scno, lookup_class, qualify_syscall_class, qualify_syscall_name, qual_syscall_ex, qual_syscall, strip_prefix, find_errno_by_name, parse_fault_token, parse_fault_expression, qual_fault, qualify): Remove. (decode_socket_subcall, decode_ipc_subcall, decode_mips_subcall, get_scno): Update use of qual_flags. (inject_syscall_fault_entering): Update per-personality allocation of tcp->fault_vec. * tests/fault_injection-exit_group.test: Check parsing of inversed fault sets. * tests/fault_injection.test: Check parsing of -efault=none. * tests/options-syntax.test: Check parsing of invalid syscall numbers.
2016-12-04 17:39:48 +03:00
}
static void
qualify_abbrev(const char *const str)
{
if (!abbrev_set)
abbrev_set = alloc_number_set_array(SUPPORTED_PERSONALITIES);
qualify_syscall_tokens(str, abbrev_set);
Rewrite remaining qual_* parsers using bit sets * defs.h (struct fault_opts): Replace forward declaration with a definition. (qualbits_t, qualify_read, qualify_write, qualify_signals): Remove. (qual_flags): New function prototype. (nsyscall_vec, sysent_vec, fault_vec): New variable prototypes. * qualify.c (abbrev_set, fault_set, raw_set, trace_set, verbose_set): New variables. (qualify_read, qualify_write, qualify_signals): Add static qualifier. (find_errno_by_name, lookup_class, parse_fault_expression, parse_fault_token, qual_flags, qualify, qualify_abbrev, qualify_fault, qualify_raw, qualify_syscall, qualify_syscall_class, qualify_syscall_name, qualify_syscall_number, qualify_syscall_tokens, qualify_trace, qualify_verbose, strip_prefix): New functions. * syscall.c (nsyscall_vec, nsysent_vec): Remove static qualifier. (MAX_NSYSCALLS1, MAX_NSYSCALLS2, MAX_NSYSCALLS, qual_vec, qual_flags, qual_fault, qual_syscall, qual_options, fault_opts, qualify_one, qualify_scno, lookup_class, qualify_syscall_class, qualify_syscall_name, qual_syscall_ex, qual_syscall, strip_prefix, find_errno_by_name, parse_fault_token, parse_fault_expression, qual_fault, qualify): Remove. (decode_socket_subcall, decode_ipc_subcall, decode_mips_subcall, get_scno): Update use of qual_flags. (inject_syscall_fault_entering): Update per-personality allocation of tcp->fault_vec. * tests/fault_injection-exit_group.test: Check parsing of inversed fault sets. * tests/fault_injection.test: Check parsing of -efault=none. * tests/options-syntax.test: Check parsing of invalid syscall numbers.
2016-12-04 17:39:48 +03:00
}
static void
qualify_verbose(const char *const str)
{
if (!verbose_set)
verbose_set = alloc_number_set_array(SUPPORTED_PERSONALITIES);
qualify_syscall_tokens(str, verbose_set);
Rewrite remaining qual_* parsers using bit sets * defs.h (struct fault_opts): Replace forward declaration with a definition. (qualbits_t, qualify_read, qualify_write, qualify_signals): Remove. (qual_flags): New function prototype. (nsyscall_vec, sysent_vec, fault_vec): New variable prototypes. * qualify.c (abbrev_set, fault_set, raw_set, trace_set, verbose_set): New variables. (qualify_read, qualify_write, qualify_signals): Add static qualifier. (find_errno_by_name, lookup_class, parse_fault_expression, parse_fault_token, qual_flags, qualify, qualify_abbrev, qualify_fault, qualify_raw, qualify_syscall, qualify_syscall_class, qualify_syscall_name, qualify_syscall_number, qualify_syscall_tokens, qualify_trace, qualify_verbose, strip_prefix): New functions. * syscall.c (nsyscall_vec, nsysent_vec): Remove static qualifier. (MAX_NSYSCALLS1, MAX_NSYSCALLS2, MAX_NSYSCALLS, qual_vec, qual_flags, qual_fault, qual_syscall, qual_options, fault_opts, qualify_one, qualify_scno, lookup_class, qualify_syscall_class, qualify_syscall_name, qual_syscall_ex, qual_syscall, strip_prefix, find_errno_by_name, parse_fault_token, parse_fault_expression, qual_fault, qualify): Remove. (decode_socket_subcall, decode_ipc_subcall, decode_mips_subcall, get_scno): Update use of qual_flags. (inject_syscall_fault_entering): Update per-personality allocation of tcp->fault_vec. * tests/fault_injection-exit_group.test: Check parsing of inversed fault sets. * tests/fault_injection.test: Check parsing of -efault=none. * tests/options-syntax.test: Check parsing of invalid syscall numbers.
2016-12-04 17:39:48 +03:00
}
static void
qualify_raw(const char *const str)
{
if (!raw_set)
raw_set = alloc_number_set_array(SUPPORTED_PERSONALITIES);
qualify_syscall_tokens(str, raw_set);
Rewrite remaining qual_* parsers using bit sets * defs.h (struct fault_opts): Replace forward declaration with a definition. (qualbits_t, qualify_read, qualify_write, qualify_signals): Remove. (qual_flags): New function prototype. (nsyscall_vec, sysent_vec, fault_vec): New variable prototypes. * qualify.c (abbrev_set, fault_set, raw_set, trace_set, verbose_set): New variables. (qualify_read, qualify_write, qualify_signals): Add static qualifier. (find_errno_by_name, lookup_class, parse_fault_expression, parse_fault_token, qual_flags, qualify, qualify_abbrev, qualify_fault, qualify_raw, qualify_syscall, qualify_syscall_class, qualify_syscall_name, qualify_syscall_number, qualify_syscall_tokens, qualify_trace, qualify_verbose, strip_prefix): New functions. * syscall.c (nsyscall_vec, nsysent_vec): Remove static qualifier. (MAX_NSYSCALLS1, MAX_NSYSCALLS2, MAX_NSYSCALLS, qual_vec, qual_flags, qual_fault, qual_syscall, qual_options, fault_opts, qualify_one, qualify_scno, lookup_class, qualify_syscall_class, qualify_syscall_name, qual_syscall_ex, qual_syscall, strip_prefix, find_errno_by_name, parse_fault_token, parse_fault_expression, qual_fault, qualify): Remove. (decode_socket_subcall, decode_ipc_subcall, decode_mips_subcall, get_scno): Update use of qual_flags. (inject_syscall_fault_entering): Update per-personality allocation of tcp->fault_vec. * tests/fault_injection-exit_group.test: Check parsing of inversed fault sets. * tests/fault_injection.test: Check parsing of -efault=none. * tests/options-syntax.test: Check parsing of invalid syscall numbers.
2016-12-04 17:39:48 +03:00
}
static void
qualify_inject_common(const char *const str,
const bool fault_tokens_only,
const char *const description)
Rewrite remaining qual_* parsers using bit sets * defs.h (struct fault_opts): Replace forward declaration with a definition. (qualbits_t, qualify_read, qualify_write, qualify_signals): Remove. (qual_flags): New function prototype. (nsyscall_vec, sysent_vec, fault_vec): New variable prototypes. * qualify.c (abbrev_set, fault_set, raw_set, trace_set, verbose_set): New variables. (qualify_read, qualify_write, qualify_signals): Add static qualifier. (find_errno_by_name, lookup_class, parse_fault_expression, parse_fault_token, qual_flags, qualify, qualify_abbrev, qualify_fault, qualify_raw, qualify_syscall, qualify_syscall_class, qualify_syscall_name, qualify_syscall_number, qualify_syscall_tokens, qualify_trace, qualify_verbose, strip_prefix): New functions. * syscall.c (nsyscall_vec, nsysent_vec): Remove static qualifier. (MAX_NSYSCALLS1, MAX_NSYSCALLS2, MAX_NSYSCALLS, qual_vec, qual_flags, qual_fault, qual_syscall, qual_options, fault_opts, qualify_one, qualify_scno, lookup_class, qualify_syscall_class, qualify_syscall_name, qual_syscall_ex, qual_syscall, strip_prefix, find_errno_by_name, parse_fault_token, parse_fault_expression, qual_fault, qualify): Remove. (decode_socket_subcall, decode_ipc_subcall, decode_mips_subcall, get_scno): Update use of qual_flags. (inject_syscall_fault_entering): Update per-personality allocation of tcp->fault_vec. * tests/fault_injection-exit_group.test: Check parsing of inversed fault sets. * tests/fault_injection.test: Check parsing of -efault=none. * tests/options-syntax.test: Check parsing of invalid syscall numbers.
2016-12-04 17:39:48 +03:00
{
struct inject_opts opts = {
Rewrite remaining qual_* parsers using bit sets * defs.h (struct fault_opts): Replace forward declaration with a definition. (qualbits_t, qualify_read, qualify_write, qualify_signals): Remove. (qual_flags): New function prototype. (nsyscall_vec, sysent_vec, fault_vec): New variable prototypes. * qualify.c (abbrev_set, fault_set, raw_set, trace_set, verbose_set): New variables. (qualify_read, qualify_write, qualify_signals): Add static qualifier. (find_errno_by_name, lookup_class, parse_fault_expression, parse_fault_token, qual_flags, qualify, qualify_abbrev, qualify_fault, qualify_raw, qualify_syscall, qualify_syscall_class, qualify_syscall_name, qualify_syscall_number, qualify_syscall_tokens, qualify_trace, qualify_verbose, strip_prefix): New functions. * syscall.c (nsyscall_vec, nsysent_vec): Remove static qualifier. (MAX_NSYSCALLS1, MAX_NSYSCALLS2, MAX_NSYSCALLS, qual_vec, qual_flags, qual_fault, qual_syscall, qual_options, fault_opts, qualify_one, qualify_scno, lookup_class, qualify_syscall_class, qualify_syscall_name, qual_syscall_ex, qual_syscall, strip_prefix, find_errno_by_name, parse_fault_token, parse_fault_expression, qual_fault, qualify): Remove. (decode_socket_subcall, decode_ipc_subcall, decode_mips_subcall, get_scno): Update use of qual_flags. (inject_syscall_fault_entering): Update per-personality allocation of tcp->fault_vec. * tests/fault_injection-exit_group.test: Check parsing of inversed fault sets. * tests/fault_injection.test: Check parsing of -efault=none. * tests/options-syntax.test: Check parsing of invalid syscall numbers.
2016-12-04 17:39:48 +03:00
.first = 1,
Implement delay injection Add -e inject=SET:delay_enter= and -e inject=SET:delay_exit= options. * configure.ac (AC_SEARCH_LIBS): Check for timer_create -lrt. * delay.c: New file. * Makefile.am (strace_SOURCES): Add it. (strace_LDADD): Add $(timer_LIBS). * defs.h (INJECT_F_DELAY_ENTER, INJECT_F_DELAY_EXIT, TCB_INJECT_DELAY_EXIT, TCB_DELAYED, inject_delay_exit, syscall_delayed): New macros. (alloc_delay_data, fill_delay_data, is_delay_timer_created, arm_delay_timer, delay_tcb): New prototypes. (struct inject_data): Replace reserved field with delay_idx. (struct tcb): Add delay_expiration_time field. * filter_qualify.c (parse_delay_token): New function. (parse_inject_token): Use it. (qualify_inject_common): Initialize struct inject_opts.data.delay_idx. * strace.c: Include <setjmp.h> (timer_jmp_buf, timer_set): New static variables. (timer_sighandler, restart_delayed_tcb, restart_delayed_tcbs): New functions. (init): Block SIGALRM, set SIGALRM handler. (dispatch_event): Do not restart delayed syscalls. (next_event): Unblock SIGALRM during wait4 invocation. * syscall.c (tamper_with_syscall_entering): Arm delay timer if INJECT_F_DELAY_ENTER injection flag is set, set TCB_INJECT_DELAY_EXIT flag if INJECT_F_DELAY_EXIT injection flag is set. tamper_with_syscall_exiting): Arm delay timer if inject_delay_exit. (syscall_exiting_trace): Call tamper_with_syscall_exiting in case of inject_delay_exit. (syscall_exiting_finish): Clear TCB_INJECT_DELAY_EXIT flag. * strace.1.in: Document delay injection. * NEWS: Mention this improvement. Co-Authored-by: Dmitry V. Levin <ldv@altlinux.org>
2018-02-18 23:21:48 +03:00
.step = 1,
.data = {
.delay_idx = -1
}
Rewrite remaining qual_* parsers using bit sets * defs.h (struct fault_opts): Replace forward declaration with a definition. (qualbits_t, qualify_read, qualify_write, qualify_signals): Remove. (qual_flags): New function prototype. (nsyscall_vec, sysent_vec, fault_vec): New variable prototypes. * qualify.c (abbrev_set, fault_set, raw_set, trace_set, verbose_set): New variables. (qualify_read, qualify_write, qualify_signals): Add static qualifier. (find_errno_by_name, lookup_class, parse_fault_expression, parse_fault_token, qual_flags, qualify, qualify_abbrev, qualify_fault, qualify_raw, qualify_syscall, qualify_syscall_class, qualify_syscall_name, qualify_syscall_number, qualify_syscall_tokens, qualify_trace, qualify_verbose, strip_prefix): New functions. * syscall.c (nsyscall_vec, nsysent_vec): Remove static qualifier. (MAX_NSYSCALLS1, MAX_NSYSCALLS2, MAX_NSYSCALLS, qual_vec, qual_flags, qual_fault, qual_syscall, qual_options, fault_opts, qualify_one, qualify_scno, lookup_class, qualify_syscall_class, qualify_syscall_name, qual_syscall_ex, qual_syscall, strip_prefix, find_errno_by_name, parse_fault_token, parse_fault_expression, qual_fault, qualify): Remove. (decode_socket_subcall, decode_ipc_subcall, decode_mips_subcall, get_scno): Update use of qual_flags. (inject_syscall_fault_entering): Update per-personality allocation of tcp->fault_vec. * tests/fault_injection-exit_group.test: Check parsing of inversed fault sets. * tests/fault_injection.test: Check parsing of -efault=none. * tests/options-syntax.test: Check parsing of invalid syscall numbers.
2016-12-04 17:39:48 +03:00
};
struct inject_personality_data pdata[SUPPORTED_PERSONALITIES] = { { 0 } };
char *copy = xstrdup(str);
const char *name =
parse_inject_expression(copy, &opts, pdata, fault_tokens_only);
if (!name)
error_msg_and_die("invalid %s '%s'", description, str);
Rewrite remaining qual_* parsers using bit sets * defs.h (struct fault_opts): Replace forward declaration with a definition. (qualbits_t, qualify_read, qualify_write, qualify_signals): Remove. (qual_flags): New function prototype. (nsyscall_vec, sysent_vec, fault_vec): New variable prototypes. * qualify.c (abbrev_set, fault_set, raw_set, trace_set, verbose_set): New variables. (qualify_read, qualify_write, qualify_signals): Add static qualifier. (find_errno_by_name, lookup_class, parse_fault_expression, parse_fault_token, qual_flags, qualify, qualify_abbrev, qualify_fault, qualify_raw, qualify_syscall, qualify_syscall_class, qualify_syscall_name, qualify_syscall_number, qualify_syscall_tokens, qualify_trace, qualify_verbose, strip_prefix): New functions. * syscall.c (nsyscall_vec, nsysent_vec): Remove static qualifier. (MAX_NSYSCALLS1, MAX_NSYSCALLS2, MAX_NSYSCALLS, qual_vec, qual_flags, qual_fault, qual_syscall, qual_options, fault_opts, qualify_one, qualify_scno, lookup_class, qualify_syscall_class, qualify_syscall_name, qual_syscall_ex, qual_syscall, strip_prefix, find_errno_by_name, parse_fault_token, parse_fault_expression, qual_fault, qualify): Remove. (decode_socket_subcall, decode_ipc_subcall, decode_mips_subcall, get_scno): Update use of qual_flags. (inject_syscall_fault_entering): Update per-personality allocation of tcp->fault_vec. * tests/fault_injection-exit_group.test: Check parsing of inversed fault sets. * tests/fault_injection.test: Check parsing of -efault=none. * tests/options-syntax.test: Check parsing of invalid syscall numbers.
2016-12-04 17:39:48 +03:00
struct number_set *tmp_set =
alloc_number_set_array(SUPPORTED_PERSONALITIES);
qualify_syscall_tokens(name, tmp_set);
free(copy);
Implement delay injection Add -e inject=SET:delay_enter= and -e inject=SET:delay_exit= options. * configure.ac (AC_SEARCH_LIBS): Check for timer_create -lrt. * delay.c: New file. * Makefile.am (strace_SOURCES): Add it. (strace_LDADD): Add $(timer_LIBS). * defs.h (INJECT_F_DELAY_ENTER, INJECT_F_DELAY_EXIT, TCB_INJECT_DELAY_EXIT, TCB_DELAYED, inject_delay_exit, syscall_delayed): New macros. (alloc_delay_data, fill_delay_data, is_delay_timer_created, arm_delay_timer, delay_tcb): New prototypes. (struct inject_data): Replace reserved field with delay_idx. (struct tcb): Add delay_expiration_time field. * filter_qualify.c (parse_delay_token): New function. (parse_inject_token): Use it. (qualify_inject_common): Initialize struct inject_opts.data.delay_idx. * strace.c: Include <setjmp.h> (timer_jmp_buf, timer_set): New static variables. (timer_sighandler, restart_delayed_tcb, restart_delayed_tcbs): New functions. (init): Block SIGALRM, set SIGALRM handler. (dispatch_event): Do not restart delayed syscalls. (next_event): Unblock SIGALRM during wait4 invocation. * syscall.c (tamper_with_syscall_entering): Arm delay timer if INJECT_F_DELAY_ENTER injection flag is set, set TCB_INJECT_DELAY_EXIT flag if INJECT_F_DELAY_EXIT injection flag is set. tamper_with_syscall_exiting): Arm delay timer if inject_delay_exit. (syscall_exiting_trace): Call tamper_with_syscall_exiting in case of inject_delay_exit. (syscall_exiting_finish): Clear TCB_INJECT_DELAY_EXIT flag. * strace.1.in: Document delay injection. * NEWS: Mention this improvement. Co-Authored-by: Dmitry V. Levin <ldv@altlinux.org>
2018-02-18 23:21:48 +03:00
/* If neither of retval, error, signal or delay is specified, then ... */
if (!(opts.data.flags & INJECT_ACTION_FLAGS)) {
if (fault_tokens_only) {
/* in fault= syntax the default error code is ENOSYS. */
opts.data.rval_idx = retval_new(ENOSYS);
opts.data.flags |= INJECT_F_ERROR;
} else {
/* in inject= syntax this is not allowed. */
error_msg_and_die("invalid %s '%s'", description, str);
}
Implement success injection This extends fault injection syntax with :retval= option. When :retval=VALUE is specified, the syscall number is replaced by -1 and a bogus success VALUE is returned to the callee. * defs.h (fault_opts): Remove err field, add rval field. (MAX_ERRNO_VALUE, FAULT_OPTS_RVAL_DEFAULT, FAULT_OPTS_RVAL_DISABLE): New macros. * qualify.c (parse_fault_token): Handle retval= token. (qualify_fault): Update fault_opts initialization after the move from struct fault_opts.err to struct fault_opts.rval. * syscall.c (arch_set_success): New prototype. (inject_syscall_fault_entering): Check opts->rval instead of opts->err. (update_syscall_fault_exiting): Implement retval injection. * strace.1: Update the section on fault injection. * NEWS: Mention retval= option. * linux/aarch64/set_error.c (arch_set_success): New function. * linux/alpha/set_error.c: Likewise. * linux/arc/set_error.c: Likewise. * linux/arm/set_error.c: Likewise. * linux/avr32/set_error.c: Likewise. * linux/bfin/set_error.c: Likewise. * linux/crisv10/set_error.c: Likewise. * linux/hppa/set_error.c: Likewise. * linux/i386/set_error.c: Likewise. * linux/ia64/set_error.c: Likewise. * linux/m68k/set_error.c: Likewise. * linux/metag/set_error.c: Likewise. * linux/microblaze/set_error.c: Likewise. * linux/mips/set_error.c: Likewise. * linux/nios2/set_error.c: Likewise. * linux/or1k/set_error.c: Likewise. * linux/powerpc/set_error.c: Likewise. * linux/riscv/set_error.c: Likewise. * linux/s390/set_error.c: Likewise. * linux/sh/set_error.c: Likewise. * linux/sh64/set_error.c: Likewise. * linux/sparc/set_error.c: Likewise. * linux/sparc64/set_error.c: Likewise. * linux/tile/set_error.c: Likewise. * linux/x86_64/set_error.c: Likewise. * linux/xtensa/set_error.c: Likewise. Closes: https://github.com/strace/strace/issues/3
2017-01-25 02:59:16 +03:00
}
Rewrite remaining qual_* parsers using bit sets * defs.h (struct fault_opts): Replace forward declaration with a definition. (qualbits_t, qualify_read, qualify_write, qualify_signals): Remove. (qual_flags): New function prototype. (nsyscall_vec, sysent_vec, fault_vec): New variable prototypes. * qualify.c (abbrev_set, fault_set, raw_set, trace_set, verbose_set): New variables. (qualify_read, qualify_write, qualify_signals): Add static qualifier. (find_errno_by_name, lookup_class, parse_fault_expression, parse_fault_token, qual_flags, qualify, qualify_abbrev, qualify_fault, qualify_raw, qualify_syscall, qualify_syscall_class, qualify_syscall_name, qualify_syscall_number, qualify_syscall_tokens, qualify_trace, qualify_verbose, strip_prefix): New functions. * syscall.c (nsyscall_vec, nsysent_vec): Remove static qualifier. (MAX_NSYSCALLS1, MAX_NSYSCALLS2, MAX_NSYSCALLS, qual_vec, qual_flags, qual_fault, qual_syscall, qual_options, fault_opts, qualify_one, qualify_scno, lookup_class, qualify_syscall_class, qualify_syscall_name, qual_syscall_ex, qual_syscall, strip_prefix, find_errno_by_name, parse_fault_token, parse_fault_expression, qual_fault, qualify): Remove. (decode_socket_subcall, decode_ipc_subcall, decode_mips_subcall, get_scno): Update use of qual_flags. (inject_syscall_fault_entering): Update per-personality allocation of tcp->fault_vec. * tests/fault_injection-exit_group.test: Check parsing of inversed fault sets. * tests/fault_injection.test: Check parsing of -efault=none. * tests/options-syntax.test: Check parsing of invalid syscall numbers.
2016-12-04 17:39:48 +03:00
/*
* Initialize inject_vec according to tmp_set.
* Merge tmp_set into inject_set.
Rewrite remaining qual_* parsers using bit sets * defs.h (struct fault_opts): Replace forward declaration with a definition. (qualbits_t, qualify_read, qualify_write, qualify_signals): Remove. (qual_flags): New function prototype. (nsyscall_vec, sysent_vec, fault_vec): New variable prototypes. * qualify.c (abbrev_set, fault_set, raw_set, trace_set, verbose_set): New variables. (qualify_read, qualify_write, qualify_signals): Add static qualifier. (find_errno_by_name, lookup_class, parse_fault_expression, parse_fault_token, qual_flags, qualify, qualify_abbrev, qualify_fault, qualify_raw, qualify_syscall, qualify_syscall_class, qualify_syscall_name, qualify_syscall_number, qualify_syscall_tokens, qualify_trace, qualify_verbose, strip_prefix): New functions. * syscall.c (nsyscall_vec, nsysent_vec): Remove static qualifier. (MAX_NSYSCALLS1, MAX_NSYSCALLS2, MAX_NSYSCALLS, qual_vec, qual_flags, qual_fault, qual_syscall, qual_options, fault_opts, qualify_one, qualify_scno, lookup_class, qualify_syscall_class, qualify_syscall_name, qual_syscall_ex, qual_syscall, strip_prefix, find_errno_by_name, parse_fault_token, parse_fault_expression, qual_fault, qualify): Remove. (decode_socket_subcall, decode_ipc_subcall, decode_mips_subcall, get_scno): Update use of qual_flags. (inject_syscall_fault_entering): Update per-personality allocation of tcp->fault_vec. * tests/fault_injection-exit_group.test: Check parsing of inversed fault sets. * tests/fault_injection.test: Check parsing of -efault=none. * tests/options-syntax.test: Check parsing of invalid syscall numbers.
2016-12-04 17:39:48 +03:00
*/
for (unsigned int p = 0; p < SUPPORTED_PERSONALITIES; ++p) {
if (number_set_array_is_empty(tmp_set, p))
Rewrite remaining qual_* parsers using bit sets * defs.h (struct fault_opts): Replace forward declaration with a definition. (qualbits_t, qualify_read, qualify_write, qualify_signals): Remove. (qual_flags): New function prototype. (nsyscall_vec, sysent_vec, fault_vec): New variable prototypes. * qualify.c (abbrev_set, fault_set, raw_set, trace_set, verbose_set): New variables. (qualify_read, qualify_write, qualify_signals): Add static qualifier. (find_errno_by_name, lookup_class, parse_fault_expression, parse_fault_token, qual_flags, qualify, qualify_abbrev, qualify_fault, qualify_raw, qualify_syscall, qualify_syscall_class, qualify_syscall_name, qualify_syscall_number, qualify_syscall_tokens, qualify_trace, qualify_verbose, strip_prefix): New functions. * syscall.c (nsyscall_vec, nsysent_vec): Remove static qualifier. (MAX_NSYSCALLS1, MAX_NSYSCALLS2, MAX_NSYSCALLS, qual_vec, qual_flags, qual_fault, qual_syscall, qual_options, fault_opts, qualify_one, qualify_scno, lookup_class, qualify_syscall_class, qualify_syscall_name, qual_syscall_ex, qual_syscall, strip_prefix, find_errno_by_name, parse_fault_token, parse_fault_expression, qual_fault, qualify): Remove. (decode_socket_subcall, decode_ipc_subcall, decode_mips_subcall, get_scno): Update use of qual_flags. (inject_syscall_fault_entering): Update per-personality allocation of tcp->fault_vec. * tests/fault_injection-exit_group.test: Check parsing of inversed fault sets. * tests/fault_injection.test: Check parsing of -efault=none. * tests/options-syntax.test: Check parsing of invalid syscall numbers.
2016-12-04 17:39:48 +03:00
continue;
if (!inject_set) {
inject_set =
alloc_number_set_array(SUPPORTED_PERSONALITIES);
}
if (!inject_vec[p]) {
inject_vec[p] = xcalloc(nsyscall_vec[p],
sizeof(*inject_vec[p]));
Rewrite remaining qual_* parsers using bit sets * defs.h (struct fault_opts): Replace forward declaration with a definition. (qualbits_t, qualify_read, qualify_write, qualify_signals): Remove. (qual_flags): New function prototype. (nsyscall_vec, sysent_vec, fault_vec): New variable prototypes. * qualify.c (abbrev_set, fault_set, raw_set, trace_set, verbose_set): New variables. (qualify_read, qualify_write, qualify_signals): Add static qualifier. (find_errno_by_name, lookup_class, parse_fault_expression, parse_fault_token, qual_flags, qualify, qualify_abbrev, qualify_fault, qualify_raw, qualify_syscall, qualify_syscall_class, qualify_syscall_name, qualify_syscall_number, qualify_syscall_tokens, qualify_trace, qualify_verbose, strip_prefix): New functions. * syscall.c (nsyscall_vec, nsysent_vec): Remove static qualifier. (MAX_NSYSCALLS1, MAX_NSYSCALLS2, MAX_NSYSCALLS, qual_vec, qual_flags, qual_fault, qual_syscall, qual_options, fault_opts, qualify_one, qualify_scno, lookup_class, qualify_syscall_class, qualify_syscall_name, qual_syscall_ex, qual_syscall, strip_prefix, find_errno_by_name, parse_fault_token, parse_fault_expression, qual_fault, qualify): Remove. (decode_socket_subcall, decode_ipc_subcall, decode_mips_subcall, get_scno): Update use of qual_flags. (inject_syscall_fault_entering): Update per-personality allocation of tcp->fault_vec. * tests/fault_injection-exit_group.test: Check parsing of inversed fault sets. * tests/fault_injection.test: Check parsing of -efault=none. * tests/options-syntax.test: Check parsing of invalid syscall numbers.
2016-12-04 17:39:48 +03:00
}
for (unsigned int i = 0; i < nsyscall_vec[p]; ++i) {
if (is_number_in_set_array(i, tmp_set, p)) {
add_number_to_set_array(i, inject_set, p);
inject_vec[p][i] = opts;
/* Copy per-personality data. */
inject_vec[p][i].data.scno =
pdata[p].scno;
Rewrite remaining qual_* parsers using bit sets * defs.h (struct fault_opts): Replace forward declaration with a definition. (qualbits_t, qualify_read, qualify_write, qualify_signals): Remove. (qual_flags): New function prototype. (nsyscall_vec, sysent_vec, fault_vec): New variable prototypes. * qualify.c (abbrev_set, fault_set, raw_set, trace_set, verbose_set): New variables. (qualify_read, qualify_write, qualify_signals): Add static qualifier. (find_errno_by_name, lookup_class, parse_fault_expression, parse_fault_token, qual_flags, qualify, qualify_abbrev, qualify_fault, qualify_raw, qualify_syscall, qualify_syscall_class, qualify_syscall_name, qualify_syscall_number, qualify_syscall_tokens, qualify_trace, qualify_verbose, strip_prefix): New functions. * syscall.c (nsyscall_vec, nsysent_vec): Remove static qualifier. (MAX_NSYSCALLS1, MAX_NSYSCALLS2, MAX_NSYSCALLS, qual_vec, qual_flags, qual_fault, qual_syscall, qual_options, fault_opts, qualify_one, qualify_scno, lookup_class, qualify_syscall_class, qualify_syscall_name, qual_syscall_ex, qual_syscall, strip_prefix, find_errno_by_name, parse_fault_token, parse_fault_expression, qual_fault, qualify): Remove. (decode_socket_subcall, decode_ipc_subcall, decode_mips_subcall, get_scno): Update use of qual_flags. (inject_syscall_fault_entering): Update per-personality allocation of tcp->fault_vec. * tests/fault_injection-exit_group.test: Check parsing of inversed fault sets. * tests/fault_injection.test: Check parsing of -efault=none. * tests/options-syntax.test: Check parsing of invalid syscall numbers.
2016-12-04 17:39:48 +03:00
}
}
}
free_number_set_array(tmp_set, SUPPORTED_PERSONALITIES);
Rewrite remaining qual_* parsers using bit sets * defs.h (struct fault_opts): Replace forward declaration with a definition. (qualbits_t, qualify_read, qualify_write, qualify_signals): Remove. (qual_flags): New function prototype. (nsyscall_vec, sysent_vec, fault_vec): New variable prototypes. * qualify.c (abbrev_set, fault_set, raw_set, trace_set, verbose_set): New variables. (qualify_read, qualify_write, qualify_signals): Add static qualifier. (find_errno_by_name, lookup_class, parse_fault_expression, parse_fault_token, qual_flags, qualify, qualify_abbrev, qualify_fault, qualify_raw, qualify_syscall, qualify_syscall_class, qualify_syscall_name, qualify_syscall_number, qualify_syscall_tokens, qualify_trace, qualify_verbose, strip_prefix): New functions. * syscall.c (nsyscall_vec, nsysent_vec): Remove static qualifier. (MAX_NSYSCALLS1, MAX_NSYSCALLS2, MAX_NSYSCALLS, qual_vec, qual_flags, qual_fault, qual_syscall, qual_options, fault_opts, qualify_one, qualify_scno, lookup_class, qualify_syscall_class, qualify_syscall_name, qual_syscall_ex, qual_syscall, strip_prefix, find_errno_by_name, parse_fault_token, parse_fault_expression, qual_fault, qualify): Remove. (decode_socket_subcall, decode_ipc_subcall, decode_mips_subcall, get_scno): Update use of qual_flags. (inject_syscall_fault_entering): Update per-personality allocation of tcp->fault_vec. * tests/fault_injection-exit_group.test: Check parsing of inversed fault sets. * tests/fault_injection.test: Check parsing of -efault=none. * tests/options-syntax.test: Check parsing of invalid syscall numbers.
2016-12-04 17:39:48 +03:00
}
static void
qualify_fault(const char *const str)
{
qualify_inject_common(str, true, "fault argument");
}
static void
qualify_inject(const char *const str)
{
qualify_inject_common(str, false, "inject argument");
}
kvm: attach the exit reason of vcpu as auxstr to KVM_RUN output In KVM, a virtual machine implementation like Qemu can access a vcpu via ioctl. KVM_RUN is an ioctl command to enter vcpu. The command returns control for various reasons: needs of device emulation or consuming time slices are the typical ones. The vmi takes a different action for the reason. We, strace users, want to know the reason to understand kvm. This change prints the reason as auxstr if "-e kvm=vcpu" option is given, and if strace runs on Linux 4.16.0 or higher, which includes commit e46b469278a59781f9b25ff608af84892963821b, "kvm: embed vcpu id to dentry of vcpu anon inode." The way to get the reason is a bit complicated because the ioctl does not return it to the userspace directly. Instead, the vmi and kvm communicate via an area of the process virtual memory where the fd of vcpu is mmap'ed. strace must peek the area to know the reason. The change does three things: (1) recording the area for the given vcpu when the target calls VCPU_CREATE to vcpu_info_list per tcb data field, (2) verifying the data recorded in vcpu_info_list before doing (3), and (3) decoding the exit reason field of the area. The change is complicated because there is a case that strace does not have a chance to do (1) if -p option is used. In this case, vcpu_info data created in the step (2). The area has more fields than "exit reason", dumping them may be implemented in the future. * defs.h (struct tcb) [HAVE_LINUX_KVM_H]: Add vcpu_info_list field. [HAVE_LINUX_KVM_H]: (kvm_run_structure_decoder_init, kvm_vcpu_info_free): New declarations. * strace.c (usage): Add "kvm" as a new expression for -e option. (droptcb): Call kvm_vcpu_info_free. * filter_qualify.c (qualify_kvm): New function calling kvm_run_structure_decoder_init to enable for attaching the exit reason to auxstr. (qual_options): Add "kvm" as an entry. * xlat/kvm_exit_reason.in: New file. * kvm.c: Include xmalloc.h and mmap_cache.h. (dump_kvm_run_structure): New static variable. (kvm_run_structure_decoder_init): New function. (vcpu_info): New struct definition representing the 3-tuple: vcpu file descriptor, id of the vcpu, and mmap'ed entry. (vcpu_find, vcpu_alloc, vcpu_register, vcpu_getinfo, kvm_vcpu_info_free): New functions to access tcb's vcpu_info_list field and vcpu_info data type. (is_map_for_file, map_len): New helper functions. (kvm_ioclt_run_attach_auxstr, kvm_ioctl_decode_run): New functions decoding vcpu exit reason and attaching the decoded data to auxstr field of tcb. (kvm_ioctl_create_vcpu): Call vcpu_register to make an entry mapping a file descriptor and the vcpu id associated with the fd. (kvm_ioctl): Call kvm_ioctl_decode_run. Signed-off-by: Masatake YAMATO <yamato@redhat.com> Co-Authored-by: Dmitry V. Levin <ldv@altlinux.org>
2018-07-07 10:49:11 +03:00
static void
qualify_kvm(const char *const str)
{
if (strcmp(str, "vcpu") == 0) {
#ifdef HAVE_LINUX_KVM_H
kvm: attach the exit reason of vcpu as auxstr to KVM_RUN output In KVM, a virtual machine implementation like Qemu can access a vcpu via ioctl. KVM_RUN is an ioctl command to enter vcpu. The command returns control for various reasons: needs of device emulation or consuming time slices are the typical ones. The vmi takes a different action for the reason. We, strace users, want to know the reason to understand kvm. This change prints the reason as auxstr if "-e kvm=vcpu" option is given, and if strace runs on Linux 4.16.0 or higher, which includes commit e46b469278a59781f9b25ff608af84892963821b, "kvm: embed vcpu id to dentry of vcpu anon inode." The way to get the reason is a bit complicated because the ioctl does not return it to the userspace directly. Instead, the vmi and kvm communicate via an area of the process virtual memory where the fd of vcpu is mmap'ed. strace must peek the area to know the reason. The change does three things: (1) recording the area for the given vcpu when the target calls VCPU_CREATE to vcpu_info_list per tcb data field, (2) verifying the data recorded in vcpu_info_list before doing (3), and (3) decoding the exit reason field of the area. The change is complicated because there is a case that strace does not have a chance to do (1) if -p option is used. In this case, vcpu_info data created in the step (2). The area has more fields than "exit reason", dumping them may be implemented in the future. * defs.h (struct tcb) [HAVE_LINUX_KVM_H]: Add vcpu_info_list field. [HAVE_LINUX_KVM_H]: (kvm_run_structure_decoder_init, kvm_vcpu_info_free): New declarations. * strace.c (usage): Add "kvm" as a new expression for -e option. (droptcb): Call kvm_vcpu_info_free. * filter_qualify.c (qualify_kvm): New function calling kvm_run_structure_decoder_init to enable for attaching the exit reason to auxstr. (qual_options): Add "kvm" as an entry. * xlat/kvm_exit_reason.in: New file. * kvm.c: Include xmalloc.h and mmap_cache.h. (dump_kvm_run_structure): New static variable. (kvm_run_structure_decoder_init): New function. (vcpu_info): New struct definition representing the 3-tuple: vcpu file descriptor, id of the vcpu, and mmap'ed entry. (vcpu_find, vcpu_alloc, vcpu_register, vcpu_getinfo, kvm_vcpu_info_free): New functions to access tcb's vcpu_info_list field and vcpu_info data type. (is_map_for_file, map_len): New helper functions. (kvm_ioclt_run_attach_auxstr, kvm_ioctl_decode_run): New functions decoding vcpu exit reason and attaching the decoded data to auxstr field of tcb. (kvm_ioctl_create_vcpu): Call vcpu_register to make an entry mapping a file descriptor and the vcpu id associated with the fd. (kvm_ioctl): Call kvm_ioctl_decode_run. Signed-off-by: Masatake YAMATO <yamato@redhat.com> Co-Authored-by: Dmitry V. Levin <ldv@altlinux.org>
2018-07-07 10:49:11 +03:00
if (os_release >= KERNEL_VERSION(4, 16, 0))
kvm_run_structure_decoder_init();
else
error_msg("-e kvm=vcpu option needs"
" Linux 4.16.0 or higher");
#else
error_msg("-e kvm=vcpu option is not implemented"
" for this architecture");
#endif
kvm: attach the exit reason of vcpu as auxstr to KVM_RUN output In KVM, a virtual machine implementation like Qemu can access a vcpu via ioctl. KVM_RUN is an ioctl command to enter vcpu. The command returns control for various reasons: needs of device emulation or consuming time slices are the typical ones. The vmi takes a different action for the reason. We, strace users, want to know the reason to understand kvm. This change prints the reason as auxstr if "-e kvm=vcpu" option is given, and if strace runs on Linux 4.16.0 or higher, which includes commit e46b469278a59781f9b25ff608af84892963821b, "kvm: embed vcpu id to dentry of vcpu anon inode." The way to get the reason is a bit complicated because the ioctl does not return it to the userspace directly. Instead, the vmi and kvm communicate via an area of the process virtual memory where the fd of vcpu is mmap'ed. strace must peek the area to know the reason. The change does three things: (1) recording the area for the given vcpu when the target calls VCPU_CREATE to vcpu_info_list per tcb data field, (2) verifying the data recorded in vcpu_info_list before doing (3), and (3) decoding the exit reason field of the area. The change is complicated because there is a case that strace does not have a chance to do (1) if -p option is used. In this case, vcpu_info data created in the step (2). The area has more fields than "exit reason", dumping them may be implemented in the future. * defs.h (struct tcb) [HAVE_LINUX_KVM_H]: Add vcpu_info_list field. [HAVE_LINUX_KVM_H]: (kvm_run_structure_decoder_init, kvm_vcpu_info_free): New declarations. * strace.c (usage): Add "kvm" as a new expression for -e option. (droptcb): Call kvm_vcpu_info_free. * filter_qualify.c (qualify_kvm): New function calling kvm_run_structure_decoder_init to enable for attaching the exit reason to auxstr. (qual_options): Add "kvm" as an entry. * xlat/kvm_exit_reason.in: New file. * kvm.c: Include xmalloc.h and mmap_cache.h. (dump_kvm_run_structure): New static variable. (kvm_run_structure_decoder_init): New function. (vcpu_info): New struct definition representing the 3-tuple: vcpu file descriptor, id of the vcpu, and mmap'ed entry. (vcpu_find, vcpu_alloc, vcpu_register, vcpu_getinfo, kvm_vcpu_info_free): New functions to access tcb's vcpu_info_list field and vcpu_info data type. (is_map_for_file, map_len): New helper functions. (kvm_ioclt_run_attach_auxstr, kvm_ioctl_decode_run): New functions decoding vcpu exit reason and attaching the decoded data to auxstr field of tcb. (kvm_ioctl_create_vcpu): Call vcpu_register to make an entry mapping a file descriptor and the vcpu id associated with the fd. (kvm_ioctl): Call kvm_ioctl_decode_run. Signed-off-by: Masatake YAMATO <yamato@redhat.com> Co-Authored-by: Dmitry V. Levin <ldv@altlinux.org>
2018-07-07 10:49:11 +03:00
} else {
error_msg_and_die("invalid -e kvm= argument: '%s'", str);
kvm: attach the exit reason of vcpu as auxstr to KVM_RUN output In KVM, a virtual machine implementation like Qemu can access a vcpu via ioctl. KVM_RUN is an ioctl command to enter vcpu. The command returns control for various reasons: needs of device emulation or consuming time slices are the typical ones. The vmi takes a different action for the reason. We, strace users, want to know the reason to understand kvm. This change prints the reason as auxstr if "-e kvm=vcpu" option is given, and if strace runs on Linux 4.16.0 or higher, which includes commit e46b469278a59781f9b25ff608af84892963821b, "kvm: embed vcpu id to dentry of vcpu anon inode." The way to get the reason is a bit complicated because the ioctl does not return it to the userspace directly. Instead, the vmi and kvm communicate via an area of the process virtual memory where the fd of vcpu is mmap'ed. strace must peek the area to know the reason. The change does three things: (1) recording the area for the given vcpu when the target calls VCPU_CREATE to vcpu_info_list per tcb data field, (2) verifying the data recorded in vcpu_info_list before doing (3), and (3) decoding the exit reason field of the area. The change is complicated because there is a case that strace does not have a chance to do (1) if -p option is used. In this case, vcpu_info data created in the step (2). The area has more fields than "exit reason", dumping them may be implemented in the future. * defs.h (struct tcb) [HAVE_LINUX_KVM_H]: Add vcpu_info_list field. [HAVE_LINUX_KVM_H]: (kvm_run_structure_decoder_init, kvm_vcpu_info_free): New declarations. * strace.c (usage): Add "kvm" as a new expression for -e option. (droptcb): Call kvm_vcpu_info_free. * filter_qualify.c (qualify_kvm): New function calling kvm_run_structure_decoder_init to enable for attaching the exit reason to auxstr. (qual_options): Add "kvm" as an entry. * xlat/kvm_exit_reason.in: New file. * kvm.c: Include xmalloc.h and mmap_cache.h. (dump_kvm_run_structure): New static variable. (kvm_run_structure_decoder_init): New function. (vcpu_info): New struct definition representing the 3-tuple: vcpu file descriptor, id of the vcpu, and mmap'ed entry. (vcpu_find, vcpu_alloc, vcpu_register, vcpu_getinfo, kvm_vcpu_info_free): New functions to access tcb's vcpu_info_list field and vcpu_info data type. (is_map_for_file, map_len): New helper functions. (kvm_ioclt_run_attach_auxstr, kvm_ioctl_decode_run): New functions decoding vcpu exit reason and attaching the decoded data to auxstr field of tcb. (kvm_ioctl_create_vcpu): Call vcpu_register to make an entry mapping a file descriptor and the vcpu id associated with the fd. (kvm_ioctl): Call kvm_ioctl_decode_run. Signed-off-by: Masatake YAMATO <yamato@redhat.com> Co-Authored-by: Dmitry V. Levin <ldv@altlinux.org>
2018-07-07 10:49:11 +03:00
}
}
Rewrite remaining qual_* parsers using bit sets * defs.h (struct fault_opts): Replace forward declaration with a definition. (qualbits_t, qualify_read, qualify_write, qualify_signals): Remove. (qual_flags): New function prototype. (nsyscall_vec, sysent_vec, fault_vec): New variable prototypes. * qualify.c (abbrev_set, fault_set, raw_set, trace_set, verbose_set): New variables. (qualify_read, qualify_write, qualify_signals): Add static qualifier. (find_errno_by_name, lookup_class, parse_fault_expression, parse_fault_token, qual_flags, qualify, qualify_abbrev, qualify_fault, qualify_raw, qualify_syscall, qualify_syscall_class, qualify_syscall_name, qualify_syscall_number, qualify_syscall_tokens, qualify_trace, qualify_verbose, strip_prefix): New functions. * syscall.c (nsyscall_vec, nsysent_vec): Remove static qualifier. (MAX_NSYSCALLS1, MAX_NSYSCALLS2, MAX_NSYSCALLS, qual_vec, qual_flags, qual_fault, qual_syscall, qual_options, fault_opts, qualify_one, qualify_scno, lookup_class, qualify_syscall_class, qualify_syscall_name, qual_syscall_ex, qual_syscall, strip_prefix, find_errno_by_name, parse_fault_token, parse_fault_expression, qual_fault, qualify): Remove. (decode_socket_subcall, decode_ipc_subcall, decode_mips_subcall, get_scno): Update use of qual_flags. (inject_syscall_fault_entering): Update per-personality allocation of tcp->fault_vec. * tests/fault_injection-exit_group.test: Check parsing of inversed fault sets. * tests/fault_injection.test: Check parsing of -efault=none. * tests/options-syntax.test: Check parsing of invalid syscall numbers.
2016-12-04 17:39:48 +03:00
static const struct qual_options {
const char *name;
void (*qualify)(const char *);
} qual_options[] = {
{ "trace", qualify_trace },
{ "t", qualify_trace },
{ "abbrev", qualify_abbrev },
{ "a", qualify_abbrev },
{ "verbose", qualify_verbose },
{ "v", qualify_verbose },
{ "raw", qualify_raw },
{ "x", qualify_raw },
{ "signal", qualify_signals },
{ "signals", qualify_signals },
{ "s", qualify_signals },
{ "read", qualify_read },
{ "reads", qualify_read },
{ "r", qualify_read },
{ "write", qualify_write },
{ "writes", qualify_write },
{ "w", qualify_write },
{ "fault", qualify_fault },
{ "inject", qualify_inject },
kvm: attach the exit reason of vcpu as auxstr to KVM_RUN output In KVM, a virtual machine implementation like Qemu can access a vcpu via ioctl. KVM_RUN is an ioctl command to enter vcpu. The command returns control for various reasons: needs of device emulation or consuming time slices are the typical ones. The vmi takes a different action for the reason. We, strace users, want to know the reason to understand kvm. This change prints the reason as auxstr if "-e kvm=vcpu" option is given, and if strace runs on Linux 4.16.0 or higher, which includes commit e46b469278a59781f9b25ff608af84892963821b, "kvm: embed vcpu id to dentry of vcpu anon inode." The way to get the reason is a bit complicated because the ioctl does not return it to the userspace directly. Instead, the vmi and kvm communicate via an area of the process virtual memory where the fd of vcpu is mmap'ed. strace must peek the area to know the reason. The change does three things: (1) recording the area for the given vcpu when the target calls VCPU_CREATE to vcpu_info_list per tcb data field, (2) verifying the data recorded in vcpu_info_list before doing (3), and (3) decoding the exit reason field of the area. The change is complicated because there is a case that strace does not have a chance to do (1) if -p option is used. In this case, vcpu_info data created in the step (2). The area has more fields than "exit reason", dumping them may be implemented in the future. * defs.h (struct tcb) [HAVE_LINUX_KVM_H]: Add vcpu_info_list field. [HAVE_LINUX_KVM_H]: (kvm_run_structure_decoder_init, kvm_vcpu_info_free): New declarations. * strace.c (usage): Add "kvm" as a new expression for -e option. (droptcb): Call kvm_vcpu_info_free. * filter_qualify.c (qualify_kvm): New function calling kvm_run_structure_decoder_init to enable for attaching the exit reason to auxstr. (qual_options): Add "kvm" as an entry. * xlat/kvm_exit_reason.in: New file. * kvm.c: Include xmalloc.h and mmap_cache.h. (dump_kvm_run_structure): New static variable. (kvm_run_structure_decoder_init): New function. (vcpu_info): New struct definition representing the 3-tuple: vcpu file descriptor, id of the vcpu, and mmap'ed entry. (vcpu_find, vcpu_alloc, vcpu_register, vcpu_getinfo, kvm_vcpu_info_free): New functions to access tcb's vcpu_info_list field and vcpu_info data type. (is_map_for_file, map_len): New helper functions. (kvm_ioclt_run_attach_auxstr, kvm_ioctl_decode_run): New functions decoding vcpu exit reason and attaching the decoded data to auxstr field of tcb. (kvm_ioctl_create_vcpu): Call vcpu_register to make an entry mapping a file descriptor and the vcpu id associated with the fd. (kvm_ioctl): Call kvm_ioctl_decode_run. Signed-off-by: Masatake YAMATO <yamato@redhat.com> Co-Authored-by: Dmitry V. Levin <ldv@altlinux.org>
2018-07-07 10:49:11 +03:00
{ "kvm", qualify_kvm },
Rewrite remaining qual_* parsers using bit sets * defs.h (struct fault_opts): Replace forward declaration with a definition. (qualbits_t, qualify_read, qualify_write, qualify_signals): Remove. (qual_flags): New function prototype. (nsyscall_vec, sysent_vec, fault_vec): New variable prototypes. * qualify.c (abbrev_set, fault_set, raw_set, trace_set, verbose_set): New variables. (qualify_read, qualify_write, qualify_signals): Add static qualifier. (find_errno_by_name, lookup_class, parse_fault_expression, parse_fault_token, qual_flags, qualify, qualify_abbrev, qualify_fault, qualify_raw, qualify_syscall, qualify_syscall_class, qualify_syscall_name, qualify_syscall_number, qualify_syscall_tokens, qualify_trace, qualify_verbose, strip_prefix): New functions. * syscall.c (nsyscall_vec, nsysent_vec): Remove static qualifier. (MAX_NSYSCALLS1, MAX_NSYSCALLS2, MAX_NSYSCALLS, qual_vec, qual_flags, qual_fault, qual_syscall, qual_options, fault_opts, qualify_one, qualify_scno, lookup_class, qualify_syscall_class, qualify_syscall_name, qual_syscall_ex, qual_syscall, strip_prefix, find_errno_by_name, parse_fault_token, parse_fault_expression, qual_fault, qualify): Remove. (decode_socket_subcall, decode_ipc_subcall, decode_mips_subcall, get_scno): Update use of qual_flags. (inject_syscall_fault_entering): Update per-personality allocation of tcp->fault_vec. * tests/fault_injection-exit_group.test: Check parsing of inversed fault sets. * tests/fault_injection.test: Check parsing of -efault=none. * tests/options-syntax.test: Check parsing of invalid syscall numbers.
2016-12-04 17:39:48 +03:00
};
void
qualify(const char *str)
{
const struct qual_options *opt = qual_options;
for (unsigned int i = 0; i < ARRAY_SIZE(qual_options); ++i) {
const char *name = qual_options[i].name;
const size_t len = strlen(name);
const char *val = str_strip_prefix_len(str, name, len);
Rewrite remaining qual_* parsers using bit sets * defs.h (struct fault_opts): Replace forward declaration with a definition. (qualbits_t, qualify_read, qualify_write, qualify_signals): Remove. (qual_flags): New function prototype. (nsyscall_vec, sysent_vec, fault_vec): New variable prototypes. * qualify.c (abbrev_set, fault_set, raw_set, trace_set, verbose_set): New variables. (qualify_read, qualify_write, qualify_signals): Add static qualifier. (find_errno_by_name, lookup_class, parse_fault_expression, parse_fault_token, qual_flags, qualify, qualify_abbrev, qualify_fault, qualify_raw, qualify_syscall, qualify_syscall_class, qualify_syscall_name, qualify_syscall_number, qualify_syscall_tokens, qualify_trace, qualify_verbose, strip_prefix): New functions. * syscall.c (nsyscall_vec, nsysent_vec): Remove static qualifier. (MAX_NSYSCALLS1, MAX_NSYSCALLS2, MAX_NSYSCALLS, qual_vec, qual_flags, qual_fault, qual_syscall, qual_options, fault_opts, qualify_one, qualify_scno, lookup_class, qualify_syscall_class, qualify_syscall_name, qual_syscall_ex, qual_syscall, strip_prefix, find_errno_by_name, parse_fault_token, parse_fault_expression, qual_fault, qualify): Remove. (decode_socket_subcall, decode_ipc_subcall, decode_mips_subcall, get_scno): Update use of qual_flags. (inject_syscall_fault_entering): Update per-personality allocation of tcp->fault_vec. * tests/fault_injection-exit_group.test: Check parsing of inversed fault sets. * tests/fault_injection.test: Check parsing of -efault=none. * tests/options-syntax.test: Check parsing of invalid syscall numbers.
2016-12-04 17:39:48 +03:00
if (val == str || *val != '=')
Rewrite remaining qual_* parsers using bit sets * defs.h (struct fault_opts): Replace forward declaration with a definition. (qualbits_t, qualify_read, qualify_write, qualify_signals): Remove. (qual_flags): New function prototype. (nsyscall_vec, sysent_vec, fault_vec): New variable prototypes. * qualify.c (abbrev_set, fault_set, raw_set, trace_set, verbose_set): New variables. (qualify_read, qualify_write, qualify_signals): Add static qualifier. (find_errno_by_name, lookup_class, parse_fault_expression, parse_fault_token, qual_flags, qualify, qualify_abbrev, qualify_fault, qualify_raw, qualify_syscall, qualify_syscall_class, qualify_syscall_name, qualify_syscall_number, qualify_syscall_tokens, qualify_trace, qualify_verbose, strip_prefix): New functions. * syscall.c (nsyscall_vec, nsysent_vec): Remove static qualifier. (MAX_NSYSCALLS1, MAX_NSYSCALLS2, MAX_NSYSCALLS, qual_vec, qual_flags, qual_fault, qual_syscall, qual_options, fault_opts, qualify_one, qualify_scno, lookup_class, qualify_syscall_class, qualify_syscall_name, qual_syscall_ex, qual_syscall, strip_prefix, find_errno_by_name, parse_fault_token, parse_fault_expression, qual_fault, qualify): Remove. (decode_socket_subcall, decode_ipc_subcall, decode_mips_subcall, get_scno): Update use of qual_flags. (inject_syscall_fault_entering): Update per-personality allocation of tcp->fault_vec. * tests/fault_injection-exit_group.test: Check parsing of inversed fault sets. * tests/fault_injection.test: Check parsing of -efault=none. * tests/options-syntax.test: Check parsing of invalid syscall numbers.
2016-12-04 17:39:48 +03:00
continue;
str = val + 1;
Rewrite remaining qual_* parsers using bit sets * defs.h (struct fault_opts): Replace forward declaration with a definition. (qualbits_t, qualify_read, qualify_write, qualify_signals): Remove. (qual_flags): New function prototype. (nsyscall_vec, sysent_vec, fault_vec): New variable prototypes. * qualify.c (abbrev_set, fault_set, raw_set, trace_set, verbose_set): New variables. (qualify_read, qualify_write, qualify_signals): Add static qualifier. (find_errno_by_name, lookup_class, parse_fault_expression, parse_fault_token, qual_flags, qualify, qualify_abbrev, qualify_fault, qualify_raw, qualify_syscall, qualify_syscall_class, qualify_syscall_name, qualify_syscall_number, qualify_syscall_tokens, qualify_trace, qualify_verbose, strip_prefix): New functions. * syscall.c (nsyscall_vec, nsysent_vec): Remove static qualifier. (MAX_NSYSCALLS1, MAX_NSYSCALLS2, MAX_NSYSCALLS, qual_vec, qual_flags, qual_fault, qual_syscall, qual_options, fault_opts, qualify_one, qualify_scno, lookup_class, qualify_syscall_class, qualify_syscall_name, qual_syscall_ex, qual_syscall, strip_prefix, find_errno_by_name, parse_fault_token, parse_fault_expression, qual_fault, qualify): Remove. (decode_socket_subcall, decode_ipc_subcall, decode_mips_subcall, get_scno): Update use of qual_flags. (inject_syscall_fault_entering): Update per-personality allocation of tcp->fault_vec. * tests/fault_injection-exit_group.test: Check parsing of inversed fault sets. * tests/fault_injection.test: Check parsing of -efault=none. * tests/options-syntax.test: Check parsing of invalid syscall numbers.
2016-12-04 17:39:48 +03:00
opt = &qual_options[i];
break;
}
opt->qualify(str);
}
unsigned int
qual_flags(const unsigned int scno)
{
return (is_number_in_set_array(scno, trace_set, current_personality)
Rewrite remaining qual_* parsers using bit sets * defs.h (struct fault_opts): Replace forward declaration with a definition. (qualbits_t, qualify_read, qualify_write, qualify_signals): Remove. (qual_flags): New function prototype. (nsyscall_vec, sysent_vec, fault_vec): New variable prototypes. * qualify.c (abbrev_set, fault_set, raw_set, trace_set, verbose_set): New variables. (qualify_read, qualify_write, qualify_signals): Add static qualifier. (find_errno_by_name, lookup_class, parse_fault_expression, parse_fault_token, qual_flags, qualify, qualify_abbrev, qualify_fault, qualify_raw, qualify_syscall, qualify_syscall_class, qualify_syscall_name, qualify_syscall_number, qualify_syscall_tokens, qualify_trace, qualify_verbose, strip_prefix): New functions. * syscall.c (nsyscall_vec, nsysent_vec): Remove static qualifier. (MAX_NSYSCALLS1, MAX_NSYSCALLS2, MAX_NSYSCALLS, qual_vec, qual_flags, qual_fault, qual_syscall, qual_options, fault_opts, qualify_one, qualify_scno, lookup_class, qualify_syscall_class, qualify_syscall_name, qual_syscall_ex, qual_syscall, strip_prefix, find_errno_by_name, parse_fault_token, parse_fault_expression, qual_fault, qualify): Remove. (decode_socket_subcall, decode_ipc_subcall, decode_mips_subcall, get_scno): Update use of qual_flags. (inject_syscall_fault_entering): Update per-personality allocation of tcp->fault_vec. * tests/fault_injection-exit_group.test: Check parsing of inversed fault sets. * tests/fault_injection.test: Check parsing of -efault=none. * tests/options-syntax.test: Check parsing of invalid syscall numbers.
2016-12-04 17:39:48 +03:00
? QUAL_TRACE : 0)
| (is_number_in_set_array(scno, abbrev_set, current_personality)
Rewrite remaining qual_* parsers using bit sets * defs.h (struct fault_opts): Replace forward declaration with a definition. (qualbits_t, qualify_read, qualify_write, qualify_signals): Remove. (qual_flags): New function prototype. (nsyscall_vec, sysent_vec, fault_vec): New variable prototypes. * qualify.c (abbrev_set, fault_set, raw_set, trace_set, verbose_set): New variables. (qualify_read, qualify_write, qualify_signals): Add static qualifier. (find_errno_by_name, lookup_class, parse_fault_expression, parse_fault_token, qual_flags, qualify, qualify_abbrev, qualify_fault, qualify_raw, qualify_syscall, qualify_syscall_class, qualify_syscall_name, qualify_syscall_number, qualify_syscall_tokens, qualify_trace, qualify_verbose, strip_prefix): New functions. * syscall.c (nsyscall_vec, nsysent_vec): Remove static qualifier. (MAX_NSYSCALLS1, MAX_NSYSCALLS2, MAX_NSYSCALLS, qual_vec, qual_flags, qual_fault, qual_syscall, qual_options, fault_opts, qualify_one, qualify_scno, lookup_class, qualify_syscall_class, qualify_syscall_name, qual_syscall_ex, qual_syscall, strip_prefix, find_errno_by_name, parse_fault_token, parse_fault_expression, qual_fault, qualify): Remove. (decode_socket_subcall, decode_ipc_subcall, decode_mips_subcall, get_scno): Update use of qual_flags. (inject_syscall_fault_entering): Update per-personality allocation of tcp->fault_vec. * tests/fault_injection-exit_group.test: Check parsing of inversed fault sets. * tests/fault_injection.test: Check parsing of -efault=none. * tests/options-syntax.test: Check parsing of invalid syscall numbers.
2016-12-04 17:39:48 +03:00
? QUAL_ABBREV : 0)
| (is_number_in_set_array(scno, verbose_set, current_personality)
Rewrite remaining qual_* parsers using bit sets * defs.h (struct fault_opts): Replace forward declaration with a definition. (qualbits_t, qualify_read, qualify_write, qualify_signals): Remove. (qual_flags): New function prototype. (nsyscall_vec, sysent_vec, fault_vec): New variable prototypes. * qualify.c (abbrev_set, fault_set, raw_set, trace_set, verbose_set): New variables. (qualify_read, qualify_write, qualify_signals): Add static qualifier. (find_errno_by_name, lookup_class, parse_fault_expression, parse_fault_token, qual_flags, qualify, qualify_abbrev, qualify_fault, qualify_raw, qualify_syscall, qualify_syscall_class, qualify_syscall_name, qualify_syscall_number, qualify_syscall_tokens, qualify_trace, qualify_verbose, strip_prefix): New functions. * syscall.c (nsyscall_vec, nsysent_vec): Remove static qualifier. (MAX_NSYSCALLS1, MAX_NSYSCALLS2, MAX_NSYSCALLS, qual_vec, qual_flags, qual_fault, qual_syscall, qual_options, fault_opts, qualify_one, qualify_scno, lookup_class, qualify_syscall_class, qualify_syscall_name, qual_syscall_ex, qual_syscall, strip_prefix, find_errno_by_name, parse_fault_token, parse_fault_expression, qual_fault, qualify): Remove. (decode_socket_subcall, decode_ipc_subcall, decode_mips_subcall, get_scno): Update use of qual_flags. (inject_syscall_fault_entering): Update per-personality allocation of tcp->fault_vec. * tests/fault_injection-exit_group.test: Check parsing of inversed fault sets. * tests/fault_injection.test: Check parsing of -efault=none. * tests/options-syntax.test: Check parsing of invalid syscall numbers.
2016-12-04 17:39:48 +03:00
? QUAL_VERBOSE : 0)
| (is_number_in_set_array(scno, raw_set, current_personality)
Rewrite remaining qual_* parsers using bit sets * defs.h (struct fault_opts): Replace forward declaration with a definition. (qualbits_t, qualify_read, qualify_write, qualify_signals): Remove. (qual_flags): New function prototype. (nsyscall_vec, sysent_vec, fault_vec): New variable prototypes. * qualify.c (abbrev_set, fault_set, raw_set, trace_set, verbose_set): New variables. (qualify_read, qualify_write, qualify_signals): Add static qualifier. (find_errno_by_name, lookup_class, parse_fault_expression, parse_fault_token, qual_flags, qualify, qualify_abbrev, qualify_fault, qualify_raw, qualify_syscall, qualify_syscall_class, qualify_syscall_name, qualify_syscall_number, qualify_syscall_tokens, qualify_trace, qualify_verbose, strip_prefix): New functions. * syscall.c (nsyscall_vec, nsysent_vec): Remove static qualifier. (MAX_NSYSCALLS1, MAX_NSYSCALLS2, MAX_NSYSCALLS, qual_vec, qual_flags, qual_fault, qual_syscall, qual_options, fault_opts, qualify_one, qualify_scno, lookup_class, qualify_syscall_class, qualify_syscall_name, qual_syscall_ex, qual_syscall, strip_prefix, find_errno_by_name, parse_fault_token, parse_fault_expression, qual_fault, qualify): Remove. (decode_socket_subcall, decode_ipc_subcall, decode_mips_subcall, get_scno): Update use of qual_flags. (inject_syscall_fault_entering): Update per-personality allocation of tcp->fault_vec. * tests/fault_injection-exit_group.test: Check parsing of inversed fault sets. * tests/fault_injection.test: Check parsing of -efault=none. * tests/options-syntax.test: Check parsing of invalid syscall numbers.
2016-12-04 17:39:48 +03:00
? QUAL_RAW : 0)
| (is_number_in_set_array(scno, inject_set, current_personality)
? QUAL_INJECT : 0);
Rewrite remaining qual_* parsers using bit sets * defs.h (struct fault_opts): Replace forward declaration with a definition. (qualbits_t, qualify_read, qualify_write, qualify_signals): Remove. (qual_flags): New function prototype. (nsyscall_vec, sysent_vec, fault_vec): New variable prototypes. * qualify.c (abbrev_set, fault_set, raw_set, trace_set, verbose_set): New variables. (qualify_read, qualify_write, qualify_signals): Add static qualifier. (find_errno_by_name, lookup_class, parse_fault_expression, parse_fault_token, qual_flags, qualify, qualify_abbrev, qualify_fault, qualify_raw, qualify_syscall, qualify_syscall_class, qualify_syscall_name, qualify_syscall_number, qualify_syscall_tokens, qualify_trace, qualify_verbose, strip_prefix): New functions. * syscall.c (nsyscall_vec, nsysent_vec): Remove static qualifier. (MAX_NSYSCALLS1, MAX_NSYSCALLS2, MAX_NSYSCALLS, qual_vec, qual_flags, qual_fault, qual_syscall, qual_options, fault_opts, qualify_one, qualify_scno, lookup_class, qualify_syscall_class, qualify_syscall_name, qual_syscall_ex, qual_syscall, strip_prefix, find_errno_by_name, parse_fault_token, parse_fault_expression, qual_fault, qualify): Remove. (decode_socket_subcall, decode_ipc_subcall, decode_mips_subcall, get_scno): Update use of qual_flags. (inject_syscall_fault_entering): Update per-personality allocation of tcp->fault_vec. * tests/fault_injection-exit_group.test: Check parsing of inversed fault sets. * tests/fault_injection.test: Check parsing of -efault=none. * tests/options-syntax.test: Check parsing of invalid syscall numbers.
2016-12-04 17:39:48 +03:00
}