[PATCH 3/4] Introduce syscall fault injection feature

Dmitry V. Levin ldv at altlinux.org
Fri Jul 29 01:04:02 UTC 2016


On Wed, Jul 27, 2016 at 08:41:16PM +0200, Nahim El Atmani wrote:
> From: Nahim El Atmani <naam at lse.epita.fr>
> 
> From: Nahim El Atmani <nahim+dev at naam.me>
> 
> * defs.h: Add new qualifier and struct fault_opts
> * linux/x86_64/fault.h: New file.
>   (fault_set_sc_err): New function.
>   (fault_discard_sc): Likewise.
> * Makefile.am: Add it.
> * syscall.c (reallocate_fault): New function.
>   (qualify_one): Also extend the size of faults_vec.
>   (qual_fault): New function.
>   (qual_signal): Also reallocate faults_vec.
>   (fault_syscall_enter): New function.
>   (fault_syscall_exit): Likewise.
>   (trace_syscall_entering): Discard syscall if needed.
>   (trace_syscall_exiting): Set syscall's return error value, print when syscall
>   has been discarded.
> 
> Signed-off-by: Nahim El Atmani <nahim+dev at naam.me>
> Reviewed-By: Gabriel Laskar <gabriel at lse.epita.fr>
> ---
> * The fault injection is currently only available for i386 & x86_64, hence a

Why the fault injection is limited to i386 and x86_64?
The mechanism of setting syscall number and error code is similar on all
architectures.

>   new configure flag have been created (--enable-fault-injection) to keep the
>   build clean on other architectures.

Please don't make this option configurable.  It complicates the code
(== causes mistakes) and gives very little in return.

> * Concerning the struct qual_options, the name 'fault' and short name 'f' are
>   not fixed, feel free to comment if something better comes to your mind.
> * Regarding the error number checks in qual_fault(), they're light on purpose
>   to allow one to return any kind of return value.

Even if they are light, they should be correct.

> * There is still one TODO left which is supporting the fuzzy approach using
>   percentage as an occurrence. It should comes soon since all the option
>   parsing is done. On that note fuzzing means we want to be able to reproduce,
>   so we have to keep the seed somewhere and take it as an input. I my opinion
>   using the environment for this kind of things is better than adding a new
>   option, what do you think?

Using environment is OK.

> --- a/Makefile.am
> +++ b/Makefile.am
> @@ -659,6 +659,11 @@ EXTRA_DIST =				\
>  	xlat/gen.sh			\
>  	xlate.el
>  
> +if ENABLE_FAULT_INJECTION
> +EXTRA_DIST += linux/x86_64/fault.h \
> +	      linux/i386/fault.h
> +endif
> +

When configured without --enable-fault-injection, this would create
tarball without these fault.h files; such tarball won't support
--enable-fault-injection because of missing files.

> @@ -767,7 +788,6 @@ if test "x$use_libunwind" = xyes; then
>  	AC_SUBST(libunwind_CPPFLAGS)
>  fi
>  AM_CONDITIONAL([USE_LIBUNWIND], [test "x$use_libunwind" = xyes])
> -AC_MSG_RESULT([$use_libunwind])

What was wrong with the message?

>  if test "$arch" = mips && test "$no_create" != yes; then
>  	mkdir -p linux/mips
> diff --git a/defs.h b/defs.h
> index 2edf943..d4b0dde 100644
> --- a/defs.h
> +++ b/defs.h
> @@ -363,6 +363,9 @@ struct tcb {
>  #define QUAL_SIGNAL	0x010	/* report events with this signal */
>  #define QUAL_READ	0x020	/* dump data read on this file descriptor */
>  #define QUAL_WRITE	0x040	/* dump data written to this file descriptor */
> +#if ENABLE_FAULT_INJECTION
> +#define QUAL_FAULT	0x080	/* this system call fail on purpose */
> +#endif

Why this new macro is ifdef'ed?

>  typedef uint8_t qualbits_t;
>  
>  #define DEFAULT_QUAL_FLAGS (QUAL_TRACE | QUAL_ABBREV | QUAL_VERBOSE)
> @@ -458,6 +461,28 @@ enum iov_decode {
>  	IOV_DECODE_NETLINK
>  };
>  
> +#if ENABLE_FAULT_INJECTION
> +/* Fault injection qualifiers concerning syscalls:
> + * FAULT_ENTER: already discarded, but error is not yet propagated
> + * FAULT_DONE: already discarded and we were using FAULT_AT (prevent overflow)
> + * FAULT_AT: discard syscall at the nth time
> + * FAULT_EVERY: discard syscall every nth time
> + * FAULT_FUZZY: discard syscall on a random basis every nth percent of the time
> + */
> +#define FAULT_ENTER 1
> +#define FAULT_EVERY (1 << 2)
> +#define FAULT_FUZZY (1 << 3)
> +#define FAULT_AT (1 << 4)
> +#define FAULT_DONE (1 << 5)

I prefer enums in new code.  BTW, (1 << 1) is missing.

> +static inline long
> +fault_set_sc_err(struct tcb *tcp, int error)
> +{
> +	return ptrace(PTRACE_POKEUSER, tcp->pid,
> +		      offsetof(struct user, regs.eax),
> +		      (unsigned long long int)error);
> +}

I'd rather call this function set_error or arch_set_error, opposite to
get_error, and placed it into $arch/get_error.c

It might be a good idea to omit the second argument and just set
the error register from tcp->u_error.

> +static inline long
> +fault_discard_sc(struct tcb *tcp)
> +{
> +	return ptrace(PTRACE_POKEUSER, tcp->pid,
> +		      offsetof(struct user, regs.orig_eax),
> +		      (unsigned long long int)-1);
> +}

Likewise, arch_set_scno and $arch/get_scno.c

get_error.c and get_scno.c could be renamed if necessary.

> --- a/syscall.c
> +++ b/syscall.c
> @@ -266,6 +266,14 @@ enum {
>  	MIN_QUALS = MAX_NSYSCALLS > 255 ? MAX_NSYSCALLS : 255
>  };
>  
> +#if ENABLE_FAULT_INJECTION
> +#include "fault.h"
> +struct fault_opts *faults_vec[SUPPORTED_PERSONALITIES];
> +#define syscall_failed(tcp)					\
> +	(((tcp)->qual_flg & QUAL_FAULT) &&			\
> +	 (faults_vec[current_personality][(tcp)->scno].flag & FAULT_ENTER))
> +#endif

This is wrong: faults_vec[current_personality][(tcp)->scno].flag
is a global flag, it cannot be used as a state of syscall parsing
for a tracee.

Use tcp->flags to store this information.

> +	opts.occ = strtol(ss, &end, 10);

Result of strtol is assigned to int.

> +	if (end == ss || (*end != '\0' && *end != '%' && *end != '.')
> +	    || errno == ERANGE || errno == EINVAL || opts.occ < 1

errno is not cleared before the call.


-- 
ldv
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 819 bytes
Desc: not available
URL: <http://lists.strace.io/pipermail/strace-devel/attachments/20160729/ad5bd0cf/attachment.bin>


More information about the Strace-devel mailing list