On 04/17/2014 12:22 PM, Markos Chandras wrote:
> On 04/16/2014 09:55 PM, Paul Moore wrote:
>> Signed-off-by: Paul Moore <[email protected]>
>> ---
>>    tools/Makefile          |   16 ++++--
>>    tools/scmp_bpf_disasm.c |   43 +++++++++++++--
>>    tools/scmp_bpf_sim.c    |  118 +++++++----------------------------------
>>    tools/util.c            |  134 
>> +++++++++++++++++++++++++++++++++++++++++++++++
>>    tools/util.h            |   37 +++++++++++++
>>    5 files changed, 237 insertions(+), 111 deletions(-)
>>    create mode 100644 tools/util.c
>>    create mode 100644 tools/util.h
>>
>> diff --git a/tools/Makefile b/tools/Makefile
>> index 24dbd78..adb7e43 100644
>> --- a/tools/Makefile
>> +++ b/tools/Makefile
>> @@ -32,7 +32,9 @@ include ../macros.mk
>>    include $(TOPDIR)/configure.mk
>>    include $(TOPDIR)/install.mk
>>
>> -LIBFLAGS := ../src/libseccomp.a
>> +OBJS = util.o
>> +
>> +LIBFLAGS := ../src/libseccomp.a $(OBJS)
>>
>>    TOOLS = scmp_bpf_disasm \
>>      scmp_bpf_sim \
>> @@ -41,7 +43,8 @@ TOOLS = scmp_bpf_disasm \
>>
>>    TOOLS_INSTALL = scmp_sys_resolver
>>
>> -DEPS = $(TOOLS:%=%.d)
>> +DEPS_OBJS = $(OBJS:%.o=%.d)
>> +DEPS_TOOLS = $(TOOLS:%=%.d)
>>
>>    #
>>    # targets
>> @@ -49,12 +52,13 @@ DEPS = $(TOOLS:%=%.d)
>>
>>    .PHONY: install clean
>>
>> -all: $(TOOLS)
>> +all: $(TOOLS) $(OBJS)
>>
>> --include $(DEPS)
>> +-include $(DEPS_TOOLS) $(DEPS_OBJS)
>>
>> -$(DEPS):
>> +$(DEPS_TOOLS):
>>      $(MAKEDEP_EXEC)
>> +    $(ADDDEP) $@ $(OBJS)
>>
>>    $(TOOLS):
>>      $(COMPILE_EXEC)
>> @@ -63,4 +67,4 @@ install: $(TOOLS_INSTALL)
>>      $(INSTALL_BIN_MACRO)
>>
>>    clean:
>> -    $(RM) $(DEPS) $(TOOLS)
>> +    $(RM) $(DEPS_TOOLS) $(DEPS_OBJS) $(TOOLS)
>> diff --git a/tools/scmp_bpf_disasm.c b/tools/scmp_bpf_disasm.c
>> index 8474eb1..d7babbe 100644
>> --- a/tools/scmp_bpf_disasm.c
>> +++ b/tools/scmp_bpf_disasm.c
>> @@ -27,10 +27,12 @@
>>    #include <stdio.h>
>>    #include <string.h>
>>    #include <unistd.h>
>> +#include <linux/audit.h>
>>    #include <sys/types.h>
>>    #include <sys/stat.h>
>>
>>    #include "bpf.h"
>> +#include "util.h"
>>
>>    #define _OP_FMT                   "%-3s"
>>
>> @@ -274,9 +276,15 @@ static int bpf_decode(FILE *file)
>>      printf("=================================\n");
>>
>>      while ((len = fread(&bpf, sizeof(bpf), 1, file))) {
>> +            /* convert the bpf statement */
>> +            bpf.code = ttoh16(arch, bpf.code);
>> +            bpf.k = ttoh32(arch, bpf.k);
>> +
>> +            /* display a hex dump */
>>              printf(" %.4u: 0x%.2x 0x%.2x 0x%.2x 0x%.8x",
>>                     line, bpf.code, bpf.jt, bpf.jf, bpf.k);
>>
>> +            /* display the assembler statements */
>>              printf("   ");
>>              bpf_decode_op(&bpf);
>>              printf(" ");
>> @@ -297,18 +305,40 @@ static int bpf_decode(FILE *file)
>>    int main(int argc, char *argv[])
>>    {
>>      int rc;
>> +    int opt;
>>      FILE *file;
>>
>> -    if (argc > 2) {
>> -            fprintf(stderr, "usage: %s [<bpf_file>]\n", argv[0]);
>> -            return EINVAL;
>> +    /* parse the command line */
>> +    while ((opt = getopt(argc, argv, "a:h")) > 0) {
>> +            switch (opt) {
>> +            case 'a':
>> +                    if (strcmp(optarg, "x86") == 0)
>> +                            arch = AUDIT_ARCH_I386;
>> +                    else if (strcmp(optarg, "x86_64") == 0)
>> +                            arch = AUDIT_ARCH_X86_64;
>> +                    else if (strcmp(optarg, "x32") == 0)
>> +                            arch = AUDIT_ARCH_X86_64;
>> +                    else if (strcmp(optarg, "arm") == 0)
>> +                            arch = AUDIT_ARCH_ARM;
>> +                    else if (strcmp(optarg, "mips") == 0)
>> +                            arch = AUDIT_ARCH_MIPS;
>> +                    else if (strcmp(optarg, "mipsel") == 0)
>> +                            arch = AUDIT_ARCH_MIPSEL;
>> +                    else
>> +                            exit_usage(argv[0]);
>> +                    break;
>> +            default:
>> +                    /* usage information */
>> +                    exit_usage(argv[0]);
>> +            }
>>      }
>>
>> -    if (argc == 2) {
>> -            file = fopen(argv[1], "r");
>> +    if ((optind > 1) && (optind < argc)) {
>> +            int opt_file = optind - 1 ;
>> +            file = fopen(argv[opt_file], "r");
>>              if (file == NULL) {
>>                      fprintf(stderr, "error: unable to open \"%s\" (%s)\n",
>> -                            argv[1], strerror(errno));
>> +                            argv[opt_file], strerror(errno));
>>                      return errno;
>>              }
>>      } else
>> @@ -319,4 +349,3 @@ int main(int argc, char *argv[])
>>
>>      return rc;
>>    }
>> -
>> diff --git a/tools/scmp_bpf_sim.c b/tools/scmp_bpf_sim.c
>> index 87846c4..e910c64 100644
>> --- a/tools/scmp_bpf_sim.c
>> +++ b/tools/scmp_bpf_sim.c
>> @@ -31,30 +31,8 @@
>>    #include <sys/types.h>
>>    #include <sys/stat.h>
>>
>> -#ifndef _BSD_SOURCE
>> -#define _BSD_SOURCE
>> -#endif
>> -#include <endian.h>
>> -
>>    #include "bpf.h"
>> -
>> -#if __i386__
>> -#define ARCH_NATIVE         AUDIT_ARCH_X86
>> -#elif __x86_64__
>> -#ifdef __ILP32__
>> -#define ARCH_NATIVE         AUDIT_ARCH_X86_64
>> -#else
>> -#define ARCH_NATIVE         AUDIT_ARCH_X86_64
>> -#endif /* __ILP32__ */
>> -#elif __arm__
>> -#define ARCH_NATIVE         AUDIT_ARCH_ARM
>> -#elif __MIPSEB__
>> -#define ARCH_NATIVE         AUDIT_ARCH_MIPS
>> -#elif __MIPSEL__
>> -#define ARCH_NATIVE         AUDIT_ARCH_MIPSEL
>> -#else
>> -#error the simulator code needs to know about your machine type
>> -#endif /* machine type guess */
>> +#include "util.h"
>>
>>    #define BPF_PRG_MAX_LEN           4096
>>
>> @@ -74,70 +52,6 @@ struct bpf_program {
>>    static unsigned int opt_verbose = 0;
>>
>>    /**
>> - * Convert a 16-bit target integer into the host's endianess
>> - * @param arch the architecture token
>> - * @param val the 16-bit integer
>> - *
>> - * Convert the endianess of the supplied value and return it to the caller.
>> - *
>> - */
>> -uint16_t _ttoh16(uint32_t arch, uint16_t val)
>> -{
>> -    if (arch & __AUDIT_ARCH_LE)
>> -            return le16toh(val);
>> -    else
>> -            return be16toh(val);
>> -}
>> -
>> -/**
>> - * Convert a 32-bit target integer into the host's endianess
>> - * @param arch the architecture token
>> - * @param val the 32-bit integer
>> - *
>> - * Convert the endianess of the supplied value and return it to the caller.
>> - *
>> - */
>> -uint32_t _ttoh32(uint32_t arch, uint32_t val)
>> -{
>> -    if (arch & __AUDIT_ARCH_LE)
>> -            return le32toh(val);
>> -    else
>> -            return be32toh(val);
>> -}
>> -
>> -/**
>> - * Convert a 32-bit host integer into the target's endianess
>> - * @param arch the architecture token
>> - * @param val the 32-bit integer
>> - *
>> - * Convert the endianess of the supplied value and return it to the caller.
>> - *
>> - */
>> -uint32_t _htot32(uint32_t arch, uint32_t val)
>> -{
>> -    if (arch & __AUDIT_ARCH_LE)
>> -            return htole32(val);
>> -    else
>> -            return htobe32(val);
>> -}
>> -
>> -/**
>> - * Print the usage information to stderr and exit
>> - * @param program the name of the current program being invoked
>> - *
>> - * Print the usage information and exit with EINVAL.
>> - *
>> - */
>> -static void exit_usage(const char *program)
>> -{
>> -    fprintf(stderr,
>> -            "usage: %s -f <bpf_file> [-v]"
>> -            " -a <arch> -s <syscall_num> [-0 <a0>] ... [-5 <a5>]\n",
>> -            program);
>> -    exit(EINVAL);
>> -}
>> -
>> -/**
>>     * Handle a simulator fault
>>     * @param rc the error or return code
>>     *
>> @@ -238,16 +152,16 @@ static void bpf_execute(const struct bpf_program *prg,
>>              ip_c = ip;
>>              bpf = &prg->i[ip++];
>>
>> -            code = _ttoh16(sys_data->arch, bpf->code);
>> +            code = ttoh16(arch, bpf->code);
>>              jt = bpf->jt;
>>              jf = bpf->jf;
>> -            k = _ttoh32(sys_data->arch, bpf->k);
>> +            k = ttoh32(arch, bpf->k);
>>
>>              switch (code) {
>>              case BPF_LD+BPF_W+BPF_ABS:
>> -                    if (bpf->k < BPF_SYSCALL_MAX) {
>> +                    if (k < BPF_SYSCALL_MAX) {
>>                              uint32_t val = *((uint32_t *)&sys_data_b[k]);
>> -                            state.acc = _htot32(sys_data->arch, val);
>> +                            state.acc = ttoh32(arch, val);
>>                      } else
>>                              exit_error(ERANGE, ip_c);
>>                      break;
>> @@ -299,6 +213,7 @@ static void bpf_execute(const struct bpf_program *prg,
>>    int main(int argc, char *argv[])
>>    {
>>      int opt;
>> +    int iter;
>>      char *opt_file = NULL;
>>      FILE *file;
>>      size_t file_read_len;
>> @@ -307,24 +222,23 @@ int main(int argc, char *argv[])
>>
>>      /* initialize the syscall record */
>>      memset(&sys_data, 0, sizeof(sys_data));
>> -    sys_data.arch = ARCH_NATIVE;
>>
>>      /* parse the command line */
>>      while ((opt = getopt(argc, argv, "a:f:h:s:v0:1:2:3:4:5:")) > 0) {
>>              switch (opt) {
>>              case 'a':
>>                      if (strcmp(optarg, "x86") == 0)
>> -                            sys_data.arch = AUDIT_ARCH_I386;
>> +                            arch = AUDIT_ARCH_I386;
>>                      else if (strcmp(optarg, "x86_64") == 0)
>> -                            sys_data.arch = AUDIT_ARCH_X86_64;
>> +                            arch = AUDIT_ARCH_X86_64;
>>                      else if (strcmp(optarg, "x32") == 0)
>> -                            sys_data.arch = AUDIT_ARCH_X86_64;
>> +                            arch = AUDIT_ARCH_X86_64;
>>                      else if (strcmp(optarg, "arm") == 0)
>> -                            sys_data.arch = AUDIT_ARCH_ARM;
>> +                            arch = AUDIT_ARCH_ARM;
>>                      else if (strcmp(optarg, "mips") == 0)
>> -                            sys_data.arch = AUDIT_ARCH_MIPS;
>> +                            arch = AUDIT_ARCH_MIPS;
>>                      else if (strcmp(optarg, "mipsel") == 0)
>> -                            sys_data.arch = AUDIT_ARCH_MIPSEL;
>> +                            arch = AUDIT_ARCH_MIPSEL;
>>                      else
>>                              exit_fault(EINVAL);
>>                      break;
>> @@ -364,6 +278,14 @@ int main(int argc, char *argv[])
>>              }
>>      }
>>
>> +    /* adjust the endianess of sys_data to match the target */
>> +    sys_data.nr = htot32(arch, sys_data.nr);
>> +    sys_data.arch = htot32(arch, arch);
>> +    sys_data.instruction_pointer = htot64(arch,
>> +                                          sys_data.instruction_pointer);
>> +    for (iter = 0; iter < BPF_SYS_ARG_MAX; iter++)
>> +            sys_data.args[iter] = htot64(arch, sys_data.args[iter]);
>> +
>>      /* allocate space for the bpf program */
>>      /* XXX - we should make this dynamic */
>>      bpf_prg.i_cnt = 0;
>> diff --git a/tools/util.c b/tools/util.c
>> new file mode 100644
>> index 0000000..0d6932c
>> --- /dev/null
>> +++ b/tools/util.c
>> @@ -0,0 +1,134 @@
>> +/**
>> + * Tool utility functions
>> + *
>> + * Copyright (c) 2014 Red Hat <[email protected]>
>> + * Author: Paul Moore <[email protected]>
>> + */
>> +
>> +/*
>> + * This library is free software; you can redistribute it and/or modify it
>> + * under the terms of version 2.1 of the GNU Lesser General Public License 
>> as
>> + * published by the Free Software Foundation.
>> + *
>> + * This library is distributed in the hope that it will be useful, but 
>> WITHOUT
>> + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
>> + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public 
>> License
>> + * for more details.
>> + *
>> + * You should have received a copy of the GNU Lesser General Public License
>> + * along with this library; if not, see <http://www.gnu.org/licenses>.
>> + */
>> +
>> +#include <errno.h>
>> +#include <stdlib.h>
>> +#include <stdio.h>
>> +#include <linux/audit.h>
>> +
>> +#ifndef _BSD_SOURCE
>> +#define _BSD_SOURCE
>> +#endif
>> +#include <endian.h>
>> +
>> +#include "util.h"
>> +
>> +/* determine the native architecture */
>> +#if __i386__
>> +#define ARCH_NATIVE         AUDIT_ARCH_X86
>> +#elif __x86_64__
>> +#ifdef __ILP32__
>> +#define ARCH_NATIVE         AUDIT_ARCH_X86_64
>> +#else
>> +#define ARCH_NATIVE         AUDIT_ARCH_X86_64
>> +#endif /* __ILP32__ */
>> +#elif __arm__
>> +#define ARCH_NATIVE         AUDIT_ARCH_ARM
>> +#elif __MIPSEB__
>> +#define ARCH_NATIVE         AUDIT_ARCH_MIPS
>> +#elif __MIPSEL__
>> +#define ARCH_NATIVE         AUDIT_ARCH_MIPSEL
>> +#else
>> +#error the simulator code needs to know about your machine type
>> +#endif
>> +
>> +/* default to the native arch */
>> +uint32_t arch = ARCH_NATIVE;
>> +
>> +/**
>> + * Print the usage information to stderr and exit
>> + * @param program the name of the current program being invoked
>> + *
>> + * Print the usage information and exit with EINVAL.
>> + *
>> + */
>> +void exit_usage(const char *program)
>> +{
>> +    fprintf(stderr,
>> +            "usage: %s -f <bpf_file> [-v]"
>> +            " -a <arch> -s <syscall_num> [-0 <a0>] ... [-5 <a5>]\n",
>> +            program);
>> +    exit(EINVAL);
>> +}
>> +
>> +/**
>> + * Convert a 16-bit target integer into the host's endianess
>> + * @param arch the architecture token
>> + * @param val the 16-bit integer
>> + *
>> + * Convert the endianess of the supplied value and return it to the caller.
>> + *
>> + */
>> +uint16_t ttoh16(uint32_t arch, uint16_t val)
>> +{
>> +    if (arch & __AUDIT_ARCH_LE)
>> +            return le16toh(val);
>> +    else
>> +            return be16toh(val);
>> +}
>> +
>> +/**
>> + * Convert a 32-bit target integer into the host's endianess
>> + * @param arch the architecture token
>> + * @param val the 32-bit integer
>> + *
>> + * Convert the endianess of the supplied value and return it to the caller.
>> + *
>> + */
>> +uint32_t ttoh32(uint32_t arch, uint32_t val)
>> +{
>> +    if (arch & __AUDIT_ARCH_LE)
>> +            return le32toh(val);
>> +    else
>> +            return be32toh(val);
>> +}
>> +
>> +/**
>> + * Convert a 32-bit host integer into the target's endianess
>> + * @param arch the architecture token
>> + * @param val the 32-bit integer
>> + *
>> + * Convert the endianess of the supplied value and return it to the caller.
>> + *
>> + */
>> +uint32_t htot32(uint32_t arch, uint32_t val)
>> +{
>> +    if (arch & __AUDIT_ARCH_LE)
>> +            return htole32(val);
>> +    else
>> +            return htobe32(val);
>> +}
>> +
>> +/**
>> + * Convert a 64-bit host integer into the target's endianess
>> + * @param arch the architecture token
>> + * @param val the 64-bit integer
>> + *
>> + * Convert the endianess of the supplied value and return it to the caller.
>> + *
>> + */
>> +uint64_t htot64(uint32_t arch, uint64_t val)
>> +{
>> +    if (arch & __AUDIT_ARCH_LE)
>> +            return htole64(val);
>> +    else
>> +            return htobe64(val);
>> +}
>> diff --git a/tools/util.h b/tools/util.h
>> new file mode 100644
>> index 0000000..72c4cce
>> --- /dev/null
>> +++ b/tools/util.h
>> @@ -0,0 +1,37 @@
>> +/**
>> + * Tool utility functions
>> + *
>> + * Copyright (c) 2014 Red Hat <[email protected]>
>> + * Author: Paul Moore <[email protected]>
>> + */
>> +
>> +/*
>> + * This library is free software; you can redistribute it and/or modify it
>> + * under the terms of version 2.1 of the GNU Lesser General Public License 
>> as
>> + * published by the Free Software Foundation.
>> + *
>> + * This library is distributed in the hope that it will be useful, but 
>> WITHOUT
>> + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
>> + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public 
>> License
>> + * for more details.
>> + *
>> + * You should have received a copy of the GNU Lesser General Public License
>> + * along with this library; if not, see <http://www.gnu.org/licenses>.
>> + */
>> +
>> +#ifndef _UTIL_H
>> +#define _UTIL_H
>> +
>> +#include <inttypes.h>
>> +
>> +extern uint32_t arch;
>> +
>> +void exit_usage(const char *program);
>> +
>> +uint16_t ttoh16(uint32_t arch, uint16_t val);
>> +uint32_t ttoh32(uint32_t arch, uint32_t val);
>> +
>> +uint32_t htot32(uint32_t arch, uint32_t val);
>> +uint64_t htot64(uint32_t arch, uint64_t val);
>> +
>> +#endif
>>
>>
>> ------------------------------------------------------------------------------
>> Learn Graph Databases - Download FREE O'Reilly Book
>> "Graph Databases" is the definitive new guide to graph databases and their
>> applications. Written by three acclaimed leaders in the field,
>> this first edition is now available. Download your free book today!
>> http://p.sf.net/sfu/NeoTech
>> _______________________________________________
>> libseccomp-discuss mailing list
>> [email protected]
>> https://lists.sourceforge.net/lists/listinfo/libseccomp-discuss
>>
>
> Hi Paul,
>
> I have no luck with these changes. The new 23-sim-arch_all_basic test
> for MIPS big-endian (based on the original 23 test but only for all_be
> architectures and only add on arch in the 'c' file (MIPS)) fails with
> 'exit_fault(EOPNOTSUPP)" in bpf_execute. The same test passes on little
> endian. It seems it's a problem with all the byte swapping functions in
> tools/util.c. I will keep looking... It should be easy to reproduce it
> yourself but I can send you the new test if you want to.
>

I think I found the problem. The failure is in the fuzz test and more 
specifically in the run_test_bpf_sim_fuzz() function. This function, 
calls the simulator without the '-a' argument, so it defaults to the 
native architecture and it does no byte swapping when executing the 
filter. Obviously, the following hack fixes it.

diff --git a/tests/regression b/tests/regression
index b83e8a2..b45d261 100755
--- a/tests/regression
+++ b/tests/regression
@@ -288,7 +288,7 @@ function run_test_bpf_sim_fuzz() {
                  # simulate the fuzzed syscall data against the BPF 
filter, we
                  # don't verify the resulting action since we're just 
testing for
                  # stability
-                allow=$($GLBL_SYS_SIM -f $tmpfile -s $sys \
+                allow=$($GLBL_SYS_SIM -a mips -f $tmpfile -s $sys \
                          ${arg[0]} ${arg[1]} ${arg[2]} ${arg[3]} 
${arg[4]} \
                          ${arg[5]})
                  rc=$?


I think it's necessary to modify this function to pass a little or big 
endian architecture based on the value of 'Arch' value in the .tests 
file. Any little or big endian architecture value will do the trick 
since the test is not actually verify the action but rather the 
stability of the filter.

-- 
markos

------------------------------------------------------------------------------
Learn Graph Databases - Download FREE O'Reilly Book
"Graph Databases" is the definitive new guide to graph databases and their
applications. Written by three acclaimed leaders in the field,
this first edition is now available. Download your free book today!
http://p.sf.net/sfu/NeoTech
_______________________________________________
libseccomp-discuss mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/libseccomp-discuss

Reply via email to