diff options
43 files changed, 1027 insertions, 194 deletions
@@ -2,6 +2,21 @@ libseccomp: Releases =============================================================================== https://github.com/seccomp/libseccomp +* Version 2.2.3 - July 8, 2015 +- Fix a problem with 'make check' on 32-bit ARM systems + +* Version 2.2.2 - July 6, 2015 +- Fix a problem with the masked equality operator +- Fix a problem on x86_64/x32 involving invalid architectures +- Fix a problem with the ARM specific syscalls +- Fix a build problem when the source and build directories differ + +* Version 2.2.1 - May 13, 2015 +- Fix a problem with syscall argument filtering on 64-bit systems +- Fix some problems with the 32-bit ARM syscall table +- Fix build problems on very old systems +- Update the README file with the GitHub and Google Groups information + * Version 2.2.0 - February 12, 2015 - Migrated the build system to autotools - Added support for the aarch64 architecture @@ -12,12 +27,12 @@ https://github.com/seccomp/libseccomp - Added Python bindings - Updated the internal syscall tables to Linux v3.19 - Added documentation to help contributors wishing to submit patches -- Migrated to Github for git hosting and Google Groups for the mailing list +- Migrated to GitHub for git hosting and Google Groups for the mailing list - Numerous minor bug fixes * Version 2.1.1 - October 31, 2013 - Build system improvements -- Automated test improvments, including a "check" target for use by +- Automated test improvements, including a "check" target for use by packagers to verify the build - Numerous bug fixes related to the filter's internal rule database which affect those creating rules with syscall arguments @@ -34,8 +49,8 @@ https://github.com/seccomp/libseccomp * Version 2.0.0 - January 28, 2013 - Fixes for the x86 multiplexed syscalls -- Additions to the API to better support non-native architecures -- Additions to the API to support multiple architecures in one filter +- Additions to the API to better support non-native architectures +- Additions to the API to support multiple architectures in one filter - Additions to the API to resolve syscall name/number mappings - Assorted minor bug fixes - Improved build messages regardless of build verbosity @@ -2,8 +2,10 @@ libseccomp: Contributors =============================================================================== https://github.com/seccomp/libseccomp +Andrew Jones <drjones@redhat.com> Andy Lutomirski <luto@amacapital.net> Ashley Lai <adlai@us.ibm.com> +Colin Walters <walters@verbum.org> Corey Bryant <coreyb@linux.vnet.ibm.com> Eduardo Otubo <otubo@linux.vnet.ibm.com> Eric Paris <eparis@redhat.com> @@ -14,7 +16,9 @@ Kees Cook <keescook@chromium.org> Marcin Juszkiewicz <mjuszkiewicz@redhat.com> Marcus Meissner <meissner@suse.de> Markos Chandras <markos.chandras@imgtec.com> +Mathias Krause <minipli@googlemail.com> Michael Forney <mforney@mforney.org> +Mike Strosaker <strosake@linux.vnet.ibm.com> Paul Moore <pmoore@redhat.com> Serge Hallyn <serge.hallyn@ubuntu.com> Thiago Marcos P. Santos <thiago.santos@intel.com> @@ -8,6 +8,18 @@ designed to abstract away the underlying BPF based syscall filter language and present a more conventional function-call based filtering interface that should be familiar to, and easily adopted by, application developers. +* Online Resources + +The library source repository currently lives on GitHub at the following URL: + + -> https://github.com/seccomp/libseccomp + +The project mailing list is currently hosted on Google Groups at the URL below, +please note that a Google account is not required to subscribe to the mailing +list. + + -> https://groups.google.com/d/forum/libseccomp + * Documentation The "doc/" directory contains all of the currently available documentation, @@ -20,14 +32,17 @@ read the SUBMITTING_PATCHES in the top level directory. * Building and Installing the Library -In order to build the library you should follow the familiar three step -process used by most autotools based applications: +If you are building the libseccomp library from an official release tarball, +you should follow the familiar three step process used by most autotools based +applications: # ./configure # make [V=0|1] # make install -As usual, running "./configure -h" will display a list of build-time +However, if you are building the library from sources retrieved from the source +repository you may need to run the autogen.sh script before running configure. +In both cases, running "./configure -h" will display a list of build-time configuration options. * Testing the Library diff --git a/include/seccomp.h.in b/include/seccomp.h.in index 3af4c2b..d100dc8 100644 --- a/include/seccomp.h.in +++ b/include/seccomp.h.in @@ -121,10 +121,13 @@ struct scmp_arg_cmp { * The ARM architecture tokens */ #define SCMP_ARCH_ARM AUDIT_ARCH_ARM -#ifndef AUDIT_ARCH_AARCH64 /* AArch64 support for audit was merged in 3.17-rc1 */ +#ifndef AUDIT_ARCH_AARCH64 +#ifndef EM_AARCH64 +#define EM_AARCH64 183 +#endif /* EM_AARCH64 */ #define AUDIT_ARCH_AARCH64 (EM_AARCH64|__AUDIT_ARCH_64BIT|__AUDIT_ARCH_LE) -#endif +#endif /* AUDIT_ARCH_AARCH64 */ #define SCMP_ARCH_AARCH64 AUDIT_ARCH_AARCH64 /** @@ -133,21 +136,30 @@ struct scmp_arg_cmp { #ifndef __AUDIT_ARCH_CONVENTION_MIPS64_N32 #define __AUDIT_ARCH_CONVENTION_MIPS64_N32 0x20000000 #endif -#define SCMP_ARCH_MIPS AUDIT_ARCH_MIPS -#define SCMP_ARCH_MIPS64 AUDIT_ARCH_MIPS64 -#ifndef AUDIT_ARCH_MIPS64N32 +#ifndef EM_MIPS +#define EM_MIPS 8 +#endif +#ifndef AUDIT_ARCH_MIPS +#define AUDIT_ARCH_MIPS (EM_MIPS) +#endif +#ifndef AUDIT_ARCH_MIPS64 +#define AUDIT_ARCH_MIPS64 (EM_MIPS|__AUDIT_ARCH_64BIT) +#endif /* MIPS64N32 support was merged in 3.15 */ +#ifndef AUDIT_ARCH_MIPS64N32 #define AUDIT_ARCH_MIPS64N32 (EM_MIPS|__AUDIT_ARCH_64BIT|\ __AUDIT_ARCH_CONVENTION_MIPS64_N32) #endif -#define SCMP_ARCH_MIPS64N32 AUDIT_ARCH_MIPS64N32 -#define SCMP_ARCH_MIPSEL AUDIT_ARCH_MIPSEL -#define SCMP_ARCH_MIPSEL64 AUDIT_ARCH_MIPSEL64 -#ifndef AUDIT_ARCH_MIPSEL64N32 /* MIPSEL64N32 support was merged in 3.15 */ +#ifndef AUDIT_ARCH_MIPSEL64N32 #define AUDIT_ARCH_MIPSEL64N32 (EM_MIPS|__AUDIT_ARCH_64BIT|__AUDIT_ARCH_LE|\ __AUDIT_ARCH_CONVENTION_MIPS64_N32) #endif +#define SCMP_ARCH_MIPS AUDIT_ARCH_MIPS +#define SCMP_ARCH_MIPS64 AUDIT_ARCH_MIPS64 +#define SCMP_ARCH_MIPS64N32 AUDIT_ARCH_MIPS64N32 +#define SCMP_ARCH_MIPSEL AUDIT_ARCH_MIPSEL +#define SCMP_ARCH_MIPSEL64 AUDIT_ARCH_MIPSEL64 #define SCMP_ARCH_MIPSEL64N32 AUDIT_ARCH_MIPSEL64N32 /** @@ -1225,9 +1237,11 @@ int seccomp_export_bpf(const scmp_filter_ctx ctx, int fd); #endif /* __NR_cachectl */ #define __PNR_cacheflush -10104 -#ifndef __NR_cacheflush +#ifdef __ARM_NR_cacheflush +#define __NR_cacheflush __ARM_NR_cacheflush +#else #define __NR_cacheflush __PNR_cacheflush -#endif /* __NR_cacheflush */ +#endif /* __ARM_NR_cacheflush */ #define __PNR_sysmips -10106 #ifndef __NR_sysmips @@ -1434,37 +1448,75 @@ int seccomp_export_bpf(const scmp_filter_ctx ctx, int fd); #define __NR_utimes __PNR_utimes #endif /* __NR_utimes */ -#define __PNR_multiplexer -10180 +#define __PNR_getrlimit -10180 +#ifndef __NR_getrlimit +#define __NR_getrlimit __PNR_getrlimit +#endif /* __NR_utimes */ + +#define __PNR_mmap -10181 +#ifndef __NR_mmap +#define __NR_mmap __PNR_mmap +#endif /* __NR_utimes */ + +#define __PNR_breakpoint -10182 +#ifdef __ARM_NR_breakpoint +#define __NR_breakpoint __ARM_NR_breakpoint +#else +#define __NR_breakpoint __PNR_breakpoint +#endif /* __ARM_NR_breakpoint */ + +#define __PNR_set_tls -10183 +#ifdef __ARM_NR_set_tls +#define __NR_set_tls __ARM_NR_set_tls +#else +#define __NR_set_tls __PNR_set_tls +#endif /* __ARM_NR_set_tls */ + +#define __PNR_usr26 -10184 +#ifdef __ARM_NR_usr26 +#define __NR_usr26 __ARM_NR_usr26 +#else +#define __NR_usr26 __PNR_usr26 +#endif /* __ARM_NR_usr26 */ + +#define __PNR_usr32 -10185 +#ifdef __ARM_NR_usr32 +#define __NR_usr32 __ARM_NR_usr32 +#else +#define __NR_usr32 __PNR_usr32 +#endif /* __ARM_NR_usr32 */ + +#define __PNR_multiplexer -10186 #ifndef __NR_multiplexer #define __NR_multiplexer __PNR_multiplexer #endif /* __NR_multiplexer */ -#define __PNR_rtas -10181 +#define __PNR_rtas -10187 #ifndef __NR_rtas #define __NR_rtas __PNR_rtas #endif /* __NR_rtas */ -#define __PNR_spu_create -10182 +#define __PNR_spu_create -10188 #ifndef __NR_spu_create #define __NR_spu_create __PNR_spu_create #endif /* __NR_spu_create */ -#define __PNR_spu_run -10183 +#define __PNR_spu_run -10189 #ifndef __NR_spu_run #define __NR_spu_run __PNR_spu_run #endif /* __NR_spu_run */ -#define __PNR_subpage_prot -10184 +#define __PNR_subpage_prot -10189 #ifndef __NR_subpage_prot #define __NR_subpage_prot __PNR_subpage_prot #endif /* __NR_subpage_prot */ -#define __PNR_swapcontext -10185 +#define __PNR_swapcontext -10190 #ifndef __NR_swapcontext #define __NR_swapcontext __PNR_swapcontext #endif /* __NR_swapcontext */ -#define __PNR_sys_debug_setcontext -10186 +#define __PNR_sys_debug_setcontext -10191 #ifndef __NR_sys_debug_setcontext #define __NR_sys_debug_setcontext __PNR_sys_debug_setcontext #endif /* __NR_sys_debug_setcontext */ diff --git a/src/Makefile.am b/src/Makefile.am index 54f8478..23d9a91 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -53,6 +53,7 @@ arch_syscall_dump_SOURCES = arch-syscall-dump.c ${SOURCES_ARCH} arch_syscall_check_SOURCES = arch-syscall-check.c ${SOURCES_ARCH} libseccomp_la_SOURCES = ${SOURCES_GEN} ${SOURCES_ARCH} +libseccomp_la_CPPFLAGS = ${AM_CPPFLAGS} -I$(top_builddir)/include libseccomp_la_CFLAGS = ${AM_CFLAGS} ${CFLAGS} -fPIC -DPIC -fvisibility=hidden libseccomp_la_LDFLAGS = ${AM_LDFLAGS} ${LDFLAGS} \ -version-number ${VERSION_MAJOR}:${VERSION_MINOR}:${VERSION_MICRO} @@ -380,7 +380,7 @@ syscall_priority_failure: * @param action the filter action * @param syscall the syscall number * @param arg_cnt the number of argument filters in the argument filter chain - * @param arg_list the argument filter chain, (uint, enum scmp_compare, ulong) + * @param arg_array the argument filter chain, (uint, enum scmp_compare, ulong) * * This function adds a new argument/comparison/value to the seccomp filter for * a syscall; multiple arguments can be specified and they will be chained diff --git a/src/arch-aarch64-syscalls.c b/src/arch-aarch64-syscalls.c index c76dae7..315be10 100644 --- a/src/arch-aarch64-syscalls.c +++ b/src/arch-aarch64-syscalls.c @@ -46,6 +46,7 @@ const struct arch_syscall_def aarch64_syscall_table[] = { \ { "bind", 200 }, { "bpf", 280 }, { "break", __PNR_break }, + { "breakpoint", __PNR_breakpoint }, { "brk", 214 }, { "cachectl", __PNR_cachectl }, { "cacheflush", __PNR_cacheflush }, @@ -324,6 +325,7 @@ const struct arch_syscall_def aarch64_syscall_table[] = { \ { "set_robust_list", 99 }, { "set_thread_area", __PNR_set_thread_area }, { "set_tid_address", 96 }, + { "set_tls", __PNR_set_tls }, { "setdomainname", 162 }, { "setfsgid", 152 }, { "setfsgid32", __PNR_setfsgid32 }, @@ -424,6 +426,8 @@ const struct arch_syscall_def aarch64_syscall_table[] = { \ { "unlinkat", 35 }, { "unshare", 97 }, { "uselib", __PNR_uselib }, + { "usr26", __PNR_usr26 }, + { "usr32", __PNR_usr32 }, { "ustat", __PNR_ustat }, { "utime", __PNR_utime }, { "utimensat", 88 }, diff --git a/src/arch-arm-syscalls.c b/src/arch-arm-syscalls.c index b9400a3..3d75062 100644 --- a/src/arch-arm-syscalls.c +++ b/src/arch-arm-syscalls.c @@ -27,6 +27,7 @@ #include "arch-arm.h" #define __NR_OABI_SYSCALL_BASE 0x900000 +#define __ARM_NR_BASE 0x0f0000 /* NOTE: we currently only support the ARM EABI, more info at the URL below: * -> http://wiki.embeddedarm.com/wiki/EABI_vs_OABI */ @@ -49,7 +50,7 @@ const struct arch_syscall_def arm_syscall_table[] = { \ { "add_key", (__NR_SYSCALL_BASE + 309) }, { "adjtimex", (__NR_SYSCALL_BASE + 124) }, { "afs_syscall", __PNR_afs_syscall }, - { "alarm", (__NR_SYSCALL_BASE + 27) }, + { "alarm", __PNR_alarm }, { "arm_fadvise64_64", (__NR_SYSCALL_BASE + 270) }, { "arm_sync_file_range", (__NR_SYSCALL_BASE + 341) }, { "arch_prctl", __PNR_arch_prctl }, @@ -57,9 +58,10 @@ const struct arch_syscall_def arm_syscall_table[] = { \ { "bind", (__NR_SYSCALL_BASE + 282) }, { "bpf", (__NR_SYSCALL_BASE + 386) }, { "break", __PNR_break }, + { "breakpoint", (__NR_SYSCALL_BASE + (__ARM_NR_BASE + 1)) }, { "brk", (__NR_SYSCALL_BASE + 45) }, { "cachectl", __PNR_cachectl }, - { "cacheflush", __PNR_cacheflush }, + { "cacheflush", (__NR_SYSCALL_BASE + (__ARM_NR_BASE + 2)) }, { "capget", (__NR_SYSCALL_BASE + 184) }, { "capset", (__NR_SYSCALL_BASE + 185) }, { "chdir", (__NR_SYSCALL_BASE + 12) }, @@ -156,7 +158,7 @@ const struct arch_syscall_def arm_syscall_table[] = { \ { "getresgid32", (__NR_SYSCALL_BASE + 211) }, { "getresuid", (__NR_SYSCALL_BASE + 165) }, { "getresuid32", (__NR_SYSCALL_BASE + 209) }, - { "getrlimit", (__NR_SYSCALL_BASE + 76) }, + { "getrlimit", __PNR_getrlimit }, { "getrusage", (__NR_SYSCALL_BASE + 77) }, { "getsid", (__NR_SYSCALL_BASE + 147) }, { "getsockname", (__NR_SYSCALL_BASE + 286) }, @@ -183,7 +185,7 @@ const struct arch_syscall_def arm_syscall_table[] = { \ { "iopl", __PNR_iopl }, { "ioprio_get", (__NR_SYSCALL_BASE + 315) }, { "ioprio_set", (__NR_SYSCALL_BASE + 314) }, - { "ipc", (__NR_SYSCALL_BASE + 117) }, + { "ipc", __PNR_ipc }, { "kcmp", (__NR_SYSCALL_BASE + 378) }, { "kexec_file_load", __PNR_kexec_file_load }, { "kexec_load", (__NR_SYSCALL_BASE + 347) }, @@ -215,7 +217,7 @@ const struct arch_syscall_def arm_syscall_table[] = { \ { "mknodat", (__NR_SYSCALL_BASE + 324) }, { "mlock", (__NR_SYSCALL_BASE + 150) }, { "mlockall", (__NR_SYSCALL_BASE + 152) }, - { "mmap", (__NR_SYSCALL_BASE + 90) }, + { "mmap", __PNR_mmap }, { "mmap2", (__NR_SYSCALL_BASE + 192) }, { "modify_ldt", __PNR_modify_ldt }, { "mount", (__NR_SYSCALL_BASE + 21) }, @@ -280,7 +282,7 @@ const struct arch_syscall_def arm_syscall_table[] = { \ { "quotactl", (__NR_SYSCALL_BASE + 131) }, { "read", (__NR_SYSCALL_BASE + 3) }, { "readahead", (__NR_SYSCALL_BASE + 225) }, - { "readdir", (__NR_SYSCALL_BASE + 89) }, + { "readdir", __PNR_readdir }, { "readlink", (__NR_SYSCALL_BASE + 85) }, { "readlinkat", (__NR_SYSCALL_BASE + 332) }, { "readv", (__NR_SYSCALL_BASE + 145) }, @@ -320,7 +322,7 @@ const struct arch_syscall_def arm_syscall_table[] = { \ { "sched_yield", (__NR_SYSCALL_BASE + 158) }, { "seccomp", (__NR_SYSCALL_BASE + 383) }, { "security", __PNR_security }, - { "select", (__NR_SYSCALL_BASE + 82) }, + { "select", __PNR_select }, { "semctl", (__NR_SYSCALL_BASE + 300) }, { "semget", (__NR_SYSCALL_BASE + 299) }, { "semop", (__NR_SYSCALL_BASE + 298) }, @@ -335,6 +337,7 @@ const struct arch_syscall_def arm_syscall_table[] = { \ { "set_robust_list", (__NR_SYSCALL_BASE + 338) }, { "set_thread_area", __PNR_set_thread_area }, { "set_tid_address", (__NR_SYSCALL_BASE + 256) }, + { "set_tls", (__NR_SYSCALL_BASE + (__ARM_NR_BASE + 5)) }, { "setdomainname", (__NR_SYSCALL_BASE + 121) }, { "setfsgid", (__NR_SYSCALL_BASE + 139) }, { "setfsgid32", (__NR_SYSCALL_BASE + 216) }, @@ -380,7 +383,7 @@ const struct arch_syscall_def arm_syscall_table[] = { \ { "sigreturn", (__NR_SYSCALL_BASE + 119) }, { "sigsuspend", (__NR_SYSCALL_BASE + 72) }, { "socket", (__NR_SYSCALL_BASE + 281) }, - { "socketcall", (__NR_SYSCALL_BASE + 102) }, + { "socketcall", __PNR_socketcall }, { "socketpair", (__NR_SYSCALL_BASE + 288) }, { "splice", (__NR_SYSCALL_BASE + 340) }, { "spu_create", __PNR_spu_create }, @@ -390,7 +393,7 @@ const struct arch_syscall_def arm_syscall_table[] = { \ { "stat64", (__NR_SYSCALL_BASE + 195) }, { "statfs", (__NR_SYSCALL_BASE + 99) }, { "statfs64", (__NR_SYSCALL_BASE + 266) }, - { "stime", (__NR_SYSCALL_BASE + 25) }, + { "stime", __PNR_stime }, { "stty", __PNR_stty }, { "subpage_prot", __PNR_subpage_prot }, { "swapcontext", __PNR_swapcontext }, @@ -410,7 +413,7 @@ const struct arch_syscall_def arm_syscall_table[] = { \ { "sysmips", __PNR_sysmips }, { "tee", (__NR_SYSCALL_BASE + 342) }, { "tgkill", (__NR_SYSCALL_BASE + 268) }, - { "time", (__NR_SYSCALL_BASE + 13) }, + { "time", __PNR_time }, { "timer_create", (__NR_SYSCALL_BASE + 257) }, { "timer_delete", (__NR_SYSCALL_BASE + 261) }, { "timer_getoverrun", (__NR_SYSCALL_BASE + 260) }, @@ -428,15 +431,17 @@ const struct arch_syscall_def arm_syscall_table[] = { \ { "ugetrlimit", (__NR_SYSCALL_BASE + 191) }, { "ulimit", __PNR_ulimit }, { "umask", (__NR_SYSCALL_BASE + 60) }, - { "umount", (__NR_SYSCALL_BASE + 22) }, + { "umount", __PNR_umount }, { "umount2", (__NR_SYSCALL_BASE + 52) }, { "uname", (__NR_SYSCALL_BASE + 122) }, { "unlink", (__NR_SYSCALL_BASE + 10) }, { "unlinkat", (__NR_SYSCALL_BASE + 328) }, { "unshare", (__NR_SYSCALL_BASE + 337) }, { "uselib", (__NR_SYSCALL_BASE + 86) }, + { "usr26", (__NR_SYSCALL_BASE + (__ARM_NR_BASE + 3)) }, + { "usr32", (__NR_SYSCALL_BASE + (__ARM_NR_BASE + 4)) }, { "ustat", (__NR_SYSCALL_BASE + 62) }, - { "utime", (__NR_SYSCALL_BASE + 30) }, + { "utime", __PNR_utime }, { "utimensat", (__NR_SYSCALL_BASE + 348) }, { "utimes", (__NR_SYSCALL_BASE + 269) }, { "vfork", (__NR_SYSCALL_BASE + 190) }, diff --git a/src/arch-mips-syscalls.c b/src/arch-mips-syscalls.c index c318aa0..f02988e 100644 --- a/src/arch-mips-syscalls.c +++ b/src/arch-mips-syscalls.c @@ -50,6 +50,7 @@ const struct arch_syscall_def mips_syscall_table[] = { \ { "bind", (__NR_SYSCALL_BASE + 169) }, { "bpf", (__NR_SYSCALL_BASE + 355) }, { "break", __NR_SYSCALL_BASE + 17 }, + { "breakpoint", __PNR_breakpoint }, { "brk", (__NR_SYSCALL_BASE + 45) }, { "cachectl", (__NR_SYSCALL_BASE + 148) }, { "cacheflush", (__NR_SYSCALL_BASE + 147) }, @@ -328,6 +329,7 @@ const struct arch_syscall_def mips_syscall_table[] = { \ { "set_robust_list", (__NR_SYSCALL_BASE + 309) }, { "set_thread_area", (__NR_SYSCALL_BASE + 283) }, { "set_tid_address", (__NR_SYSCALL_BASE + 252) }, + { "set_tls", __PNR_set_tls }, { "setdomainname", (__NR_SYSCALL_BASE + 121) }, { "setfsgid", (__NR_SYSCALL_BASE + 139) }, { "setfsgid32", __PNR_setfsgid32 }, @@ -428,6 +430,8 @@ const struct arch_syscall_def mips_syscall_table[] = { \ { "unlinkat", (__NR_SYSCALL_BASE + 294) }, { "unshare", (__NR_SYSCALL_BASE + 303) }, { "uselib", (__NR_SYSCALL_BASE + 86) }, + { "usr26", __PNR_usr26 }, + { "usr32", __PNR_usr32 }, { "ustat", (__NR_SYSCALL_BASE + 62) }, { "utime", (__NR_SYSCALL_BASE + 30) }, { "utimensat", (__NR_SYSCALL_BASE + 316) }, diff --git a/src/arch-mips64-syscalls.c b/src/arch-mips64-syscalls.c index 007a472..7faea23 100644 --- a/src/arch-mips64-syscalls.c +++ b/src/arch-mips64-syscalls.c @@ -50,6 +50,7 @@ const struct arch_syscall_def mips64_syscall_table[] = { \ { "bind", (__NR_SYSCALL_BASE + 48) }, { "bpf", (__NR_SYSCALL_BASE + 315) }, { "break", __PNR_break }, + { "breakpoint", __PNR_breakpoint }, { "brk", (__NR_SYSCALL_BASE + 12) }, { "cachectl", (__NR_SYSCALL_BASE + 198) }, { "cacheflush", (__NR_SYSCALL_BASE + 197) }, @@ -328,6 +329,7 @@ const struct arch_syscall_def mips64_syscall_table[] = { \ { "set_robust_list", (__NR_SYSCALL_BASE + 268) }, { "set_thread_area", (__NR_SYSCALL_BASE + 242) }, { "set_tid_address", (__NR_SYSCALL_BASE + 212) }, + { "set_tls", __PNR_set_tls }, { "setdomainname", (__NR_SYSCALL_BASE + 166) }, { "setfsgid", (__NR_SYSCALL_BASE + 121) }, { "setfsgid32", __PNR_setfsgid32 }, @@ -428,6 +430,8 @@ const struct arch_syscall_def mips64_syscall_table[] = { \ { "unlinkat", (__NR_SYSCALL_BASE + 253) }, { "unshare", (__NR_SYSCALL_BASE + 262) }, { "uselib", __PNR_uselib }, + { "usr26", __PNR_usr26 }, + { "usr32", __PNR_usr32 }, { "ustat", (__NR_SYSCALL_BASE + 133) }, { "utime", (__NR_SYSCALL_BASE + 130) }, { "utimensat", (__NR_SYSCALL_BASE + 275) }, diff --git a/src/arch-mips64n32-syscalls.c b/src/arch-mips64n32-syscalls.c index ae1c9b8..18ee476 100644 --- a/src/arch-mips64n32-syscalls.c +++ b/src/arch-mips64n32-syscalls.c @@ -50,6 +50,7 @@ const struct arch_syscall_def mips64n32_syscall_table[] = { \ { "bind", (__NR_SYSCALL_BASE + 48) }, { "bpf", (__NR_SYSCALL_BASE + 319) }, { "break", __PNR_break }, + { "breakpoint", __PNR_breakpoint }, { "brk", (__NR_SYSCALL_BASE + 12) }, { "cachectl", (__NR_SYSCALL_BASE + 198) }, { "cacheflush", (__NR_SYSCALL_BASE + 197) }, @@ -328,6 +329,7 @@ const struct arch_syscall_def mips64n32_syscall_table[] = { \ { "set_robust_list", (__NR_SYSCALL_BASE + 272) }, { "set_thread_area", (__NR_SYSCALL_BASE + 246) }, { "set_tid_address", (__NR_SYSCALL_BASE + 213) }, + { "set_tls", __PNR_set_tls }, { "setdomainname", (__NR_SYSCALL_BASE + 166) }, { "setfsgid", (__NR_SYSCALL_BASE + 121) }, { "setfsgid32", __PNR_setfsgid32 }, @@ -428,6 +430,8 @@ const struct arch_syscall_def mips64n32_syscall_table[] = { \ { "unlinkat", (__NR_SYSCALL_BASE + 257) }, { "unshare", (__NR_SYSCALL_BASE + 266) }, { "uselib", __PNR_uselib }, + { "usr26", __PNR_usr26 }, + { "usr32", __PNR_usr32 }, { "ustat", (__NR_SYSCALL_BASE + 133) }, { "utime", (__NR_SYSCALL_BASE + 130) }, { "utimensat", (__NR_SYSCALL_BASE + 279) }, diff --git a/src/arch-syscall-validate b/src/arch-syscall-validate index 595dfef..ba5cd89 100755 --- a/src/arch-syscall-validate +++ b/src/arch-syscall-validate @@ -63,6 +63,8 @@ libseccomp syscall validation script optional arguments: -h show this help message and exit -a architecture + -l output the library's syscall definitions + -s output the system's syscall definitions EOF } @@ -75,7 +77,7 @@ EOF # Dump the architecture's syscall table to stdout. # function dump_sys_x86() { - cat $1/arch/x86/syscalls/syscall_32.tbl | \ + cat $1/arch/x86/entry/syscalls/syscall_32.tbl | \ grep -v "^#" | awk '{ print $3"\t"$1 }' | sed '/^[ \t]*$/d' | \ sort } @@ -98,7 +100,7 @@ function dump_lib_x86() { # Dump the architecture's syscall table to stdout. # function dump_sys_x86_64() { - cat $1/arch/x86/syscalls/syscall_64.tbl | \ + cat $1/arch/x86/entry/syscalls/syscall_64.tbl | \ grep -v "^#" | awk '{ print $2,$3,$1 }' | sed -e '/^x32/d' | \ awk '{ print $2"\t"$3 }' | sed '/^[ \t]*$/d' | sort } @@ -121,7 +123,7 @@ function dump_lib_x86_64() { # Dump the architecture's syscall table to stdout. # function dump_sys_x32() { - cat $1/arch/x86/syscalls/syscall_64.tbl | \ + cat $1/arch/x86/entry/syscalls/syscall_64.tbl | \ grep -v "^#" | awk '{ print $2,$3,$1 }' | sed -e '/^64/d' | \ awk '{ print $2"\t"$3 }' | sed '/^[ \t]*$/d' | sort } @@ -146,12 +148,22 @@ function dump_lib_x32() { # function dump_sys_arm() { # NOTE: arm_sync_file_range() and sync_file_range2() share values - cat $1/arch/arm/include/uapi/asm/unistd.h | \ - grep "^#define __NR_" | sort | \ + gcc -E -dM -D__ARM_EABI__ $1/arch/arm/include/uapi/asm/unistd.h | \ + grep "^#define __\(ARM_\)*NR_" | \ grep -v "^#define __NR_OABI_SYSCALL_BASE" | \ grep -v "^#define __NR_SYSCALL_BASE" | \ - sed -e 's/#define[ \t]\+__NR_\([^ \t]\+\)[ \t]\+(__NR_SYSCALL_BASE[ \t]*+[ \t]*\([0-9]\+\)).*/\1\t\2/' | \ - sed -e '/#define __NR_sync_file_range2[ \t]\+__NR_arm_sync_file_range/d' + grep -v "^#define __ARM_NR_BASE" | \ + sed -e 's/#define[ \t]\+__NR_\([^ \t]\+\)[ \t]\+(__NR_SYSCALL_BASE[ \t]*+[ \t]*\([0-9]\+\)).*/\1\t\2/;s/#define[ \t]\+__ARM_NR_\([^ \t]\+\)[ \t]\+(__ARM_NR_BASE[ \t]*+[ \t]*\([0-9]\+\)).*/\1\t983040 + \2/' | \ + while read line; do \ + if echo "$line" | grep -q "+"; then \ + echo "$line" | awk '{ print $1"\t"$2+$4 }'; \ + else \ + echo "$line"; \ + fi; \ + done | \ + cat - | \ + sed -e '/#define __NR_sync_file_range2[ \t]\+__NR_arm_sync_file_range/d' | \ + sort } # @@ -175,7 +187,7 @@ function dump_lib_arm() { # function dump_sys_aarch64() { gcc -E -dM -I$1/include/uapi -D__BITS_PER_LONG=64 $1/include/uapi/asm-generic/unistd.h | \ - grep "^#define __NR_" | sort | \ + grep "^#define __NR_" | \ sed -e '/__NR_syscalls/d' | \ sed -e '/__NR_arch_specific_syscall/d' | \ sed -e 's/#define[ \t]\+__NR_\([^ \t]\+\)[ \t]\+\(.*\)/\1\t\2/' | \ @@ -191,7 +203,8 @@ function dump_sys_aarch64() { sed -e 's/__NR3264_mmap/222/' | \ sed -e 's/__NR3264_fstat/80/' | \ sed -e 's/__NR3264_lstat/1039/' | \ - sed -e 's/__NR3264_stat/1038/' + sed -e 's/__NR3264_stat/1038/' | \ + sort } # @@ -217,14 +230,15 @@ function dump_sys_mips() { # _MIPS_SIM_NABI32 == 2 # _MIPS_SIM_ABI64 == 3 gcc -E -dM -I$1/arch/mips/include/uapi -D_MIPS_SIM=1 $1/arch/mips/include/uapi/asm/unistd.h | \ - grep "^#define __NR_" | sort | \ + grep "^#define __NR_" | \ grep -v "^#define __NR_O32_" | \ grep -v "^#define __NR_N32_" | \ grep -v "^#define __NR_64_" | \ grep -v "^#define __NR_Linux" | \ grep -v "^#define __NR_unused" | \ grep -v "^#define __NR_reserved" | \ - sed -e 's/#define[ \t]\+__NR_\([^ \t]\+\)[ \t]\+(__NR_Linux[ \t]*+[ \t]*\([0-9]\+\)).*/\1\t\2/' + sed -e 's/#define[ \t]\+__NR_\([^ \t]\+\)[ \t]\+(__NR_Linux[ \t]*+[ \t]*\([0-9]\+\)).*/\1\t\2/' | \ + sort } # @@ -250,14 +264,15 @@ function dump_sys_mips64() { # _MIPS_SIM_NABI32 == 2 # _MIPS_SIM_ABI64 == 3 gcc -E -dM -I$1/arch/mips/include/uapi -D_MIPS_SIM=3 $1/arch/mips/include/uapi/asm/unistd.h | \ - grep "^#define __NR_" | sort | \ + grep "^#define __NR_" | \ grep -v "^#define __NR_O32_" | \ grep -v "^#define __NR_N32_" | \ grep -v "^#define __NR_64_" | \ grep -v "^#define __NR_Linux" | \ grep -v "^#define __NR_unused" | \ grep -v "^#define __NR_reserved" | \ - sed -e 's/#define[ \t]\+__NR_\([^ \t]\+\)[ \t]\+(__NR_Linux[ \t]*+[ \t]*\([0-9]\+\)).*/\1\t\2/' + sed -e 's/#define[ \t]\+__NR_\([^ \t]\+\)[ \t]\+(__NR_Linux[ \t]*+[ \t]*\([0-9]\+\)).*/\1\t\2/' | \ + sort } # @@ -283,14 +298,15 @@ function dump_sys_mips64n32() { # _MIPS_SIM_NABI32 == 2 # _MIPS_SIM_ABI64 == 3 gcc -E -dM -I$1/arch/mips/include/uapi -D_MIPS_SIM=2 $1/arch/mips/include/uapi/asm/unistd.h | \ - grep "^#define __NR_" | sort | \ + grep "^#define __NR_" | \ grep -v "^#define __NR_O32_" | \ grep -v "^#define __NR_N32_" | \ grep -v "^#define __NR_64_" | \ grep -v "^#define __NR_Linux" | \ grep -v "^#define __NR_unused" | \ grep -v "^#define __NR_reserved" | \ - sed -e 's/#define[ \t]\+__NR_\([^ \t]\+\)[ \t]\+(__NR_Linux[ \t]*+[ \t]*\([0-9]\+\)).*/\1\t\2/' + sed -e 's/#define[ \t]\+__NR_\([^ \t]\+\)[ \t]\+(__NR_Linux[ \t]*+[ \t]*\([0-9]\+\)).*/\1\t\2/' | \ + sort } # @@ -406,28 +422,28 @@ function dump_sys() { function dump_lib() { case $1 in x86) - dump_lib_x86 "$2" + dump_lib_x86 ;; x86_64) - dump_lib_x86_64 "$2" + dump_lib_x86_64 ;; x32) - dump_lib_x32 "$2" + dump_lib_x32 ;; arm) - dump_lib_arm "$2" + dump_lib_arm ;; aarch64) - dump_lib_aarch64 "$2" + dump_lib_aarch64 ;; mips) - dump_lib_mips "$2" + dump_lib_mips ;; mips64) - dump_lib_mips64 "$2" + dump_lib_mips64 ;; mips64n32) - dump_lib_mips64n32 "$2" + dump_lib_mips64n32 ;; ppc64) dump_lib_ppc64 "$2" @@ -454,12 +470,22 @@ if [[ ! -x $LIB_SYS_DUMP ]]; then exit 1 fi -arches="" +opt_arches="" +opt_sys="" +opt_lib="" -while getopts "a:h" opt; do +while getopts "a:slh" opt; do case $opt in a) - arches+="$OPTARG " + opt_arches+="$OPTARG " + ;; + s) + opt_sys=1 + opt_lib=0 + ;; + l) + opt_sys=0 + opt_lib=1 ;; h|*) usage @@ -470,8 +496,8 @@ done shift $(($OPTIND - 1)) # defaults -if [[ $arches == "" ]]; then - arches="x86 x86_64 x32 arm aarch64 mips mips64 mips64n32 ppc64 ppc" +if [[ $opt_arches == "" ]]; then + opt_arches="x86 x86_64 x32 arm aarch64 mips mips64 mips64n32 ppc pcc64" fi # sanity checks @@ -486,20 +512,27 @@ if [[ ! -d $kernel_dir ]]; then fi # generate some temp files -tmp_orig=$(mktemp -t syscall_validate_XXXXXX) -tmp_new=$(mktemp -t syscall_validate_XXXXXX) +tmp_lib=$(mktemp -t syscall_validate_XXXXXX) +tmp_sys=$(mktemp -t syscall_validate_XXXXXX) -# loop through the architectures -for i in $arches; do +# loop through the architectures and compare +for i in $opt_arches; do # dump the syscall tables - dump_lib $i > $tmp_orig - dump_sys $i "$kernel_dir" > $tmp_new - - # do the comparison - diff -u --label="$i [library]" $tmp_orig --label "$i [system]" $tmp_new + dump_lib $i > $tmp_lib + dump_sys $i "$kernel_dir" > $tmp_sys + + if [[ $opt_lib -eq 1 ]]; then + cat $tmp_lib + elif [[ $opt_sys -eq 1 ]]; then + cat $tmp_sys + else + # compare the lib and sys output + diff -u --label="$i [library]" $tmp_lib \ + --label "$i [system]" $tmp_sys + fi done # cleanup and exit -rm -f $tmp_orig $tmp_new +rm -f $tmp_lib $tmp_sys exit 0 diff --git a/src/arch-x32-syscalls.c b/src/arch-x32-syscalls.c index 578d534..a0b4247 100644 --- a/src/arch-x32-syscalls.c +++ b/src/arch-x32-syscalls.c @@ -46,6 +46,7 @@ const struct arch_syscall_def x32_syscall_table[] = { \ { "bind", (X32_SYSCALL_BIT + 49) }, { "bpf", (X32_SYSCALL_BIT + 321) }, { "break", __PNR_break }, + { "breakpoint", __PNR_breakpoint }, { "brk", (X32_SYSCALL_BIT + 12) }, { "cachectl", __PNR_cachectl }, { "cacheflush", __PNR_cacheflush }, @@ -324,6 +325,7 @@ const struct arch_syscall_def x32_syscall_table[] = { \ { "set_robust_list", (X32_SYSCALL_BIT + 530) }, { "set_thread_area", __PNR_set_thread_area }, { "set_tid_address", (X32_SYSCALL_BIT + 218) }, + { "set_tls", __PNR_set_tls }, { "setdomainname", (X32_SYSCALL_BIT + 171) }, { "setfsgid", (X32_SYSCALL_BIT + 123) }, { "setfsgid32", __PNR_setfsgid32 }, @@ -424,6 +426,8 @@ const struct arch_syscall_def x32_syscall_table[] = { \ { "unlinkat", (X32_SYSCALL_BIT + 263) }, { "unshare", (X32_SYSCALL_BIT + 272) }, { "uselib", __PNR_uselib }, + { "usr26", __PNR_usr26 }, + { "usr32", __PNR_usr32 }, { "ustat", (X32_SYSCALL_BIT + 136) }, { "utime", (X32_SYSCALL_BIT + 132) }, { "utimensat", (X32_SYSCALL_BIT + 280) }, diff --git a/src/arch-x86-syscalls.c b/src/arch-x86-syscalls.c index 92343f0..d27a4d1 100644 --- a/src/arch-x86-syscalls.c +++ b/src/arch-x86-syscalls.c @@ -46,6 +46,7 @@ const struct arch_syscall_def x86_syscall_table[] = { \ { "bind", __PNR_bind }, { "bpf", 357 }, { "break", 17 }, + { "breakpoint", __PNR_breakpoint }, { "brk", 45 }, { "cachectl", __PNR_cachectl }, { "cacheflush", __PNR_cacheflush }, @@ -324,6 +325,7 @@ const struct arch_syscall_def x86_syscall_table[] = { \ { "set_robust_list", 311 }, { "set_thread_area", 243 }, { "set_tid_address", 258 }, + { "set_tls", __PNR_set_tls }, { "setdomainname", 121 }, { "setfsgid", 139 }, { "setfsgid32", 216 }, @@ -424,6 +426,8 @@ const struct arch_syscall_def x86_syscall_table[] = { \ { "unlinkat", 301 }, { "unshare", 310 }, { "uselib", 86 }, + { "usr26", __PNR_usr26 }, + { "usr32", __PNR_usr32 }, { "ustat", 62 }, { "utime", 30 }, { "utimensat", 320 }, diff --git a/src/arch-x86_64-syscalls.c b/src/arch-x86_64-syscalls.c index d0d4241..cd9eb6d 100644 --- a/src/arch-x86_64-syscalls.c +++ b/src/arch-x86_64-syscalls.c @@ -46,6 +46,7 @@ const struct arch_syscall_def x86_64_syscall_table[] = { \ { "bind", 49 }, { "bpf", 321 }, { "break", __PNR_break }, + { "breakpoint", __PNR_breakpoint }, { "brk", 12 }, { "cachectl", __PNR_cachectl }, { "cacheflush", __PNR_cacheflush }, @@ -324,6 +325,7 @@ const struct arch_syscall_def x86_64_syscall_table[] = { \ { "set_robust_list", 273 }, { "set_thread_area", 205 }, { "set_tid_address", 218 }, + { "set_tls", __PNR_set_tls }, { "setdomainname", 171 }, { "setfsgid", 123 }, { "setfsgid32", __PNR_setfsgid32 }, @@ -424,6 +426,8 @@ const struct arch_syscall_def x86_64_syscall_table[] = { \ { "unlinkat", 263 }, { "unshare", 272 }, { "uselib", 134 }, + { "usr26", __PNR_usr26 }, + { "usr32", __PNR_usr32 }, { "ustat", 136 }, { "utime", 132 }, { "utimensat", 280 }, @@ -145,7 +145,7 @@ const struct arch_def *arch_def_lookup(uint32_t token) /** * Lookup the architecture definition by name - * @param arch the architecure name + * @param arch_name the architecure name * * Return the matching architecture definition, returns NULL on failure. * @@ -72,10 +72,9 @@ static unsigned int __db_tree_free(struct db_arg_chain_tree *tree) /** * Free a syscall filter argument chain tree - * @param list the argument chain list + * @param tree the argument chain list * - * This function frees a syscall argument chain list and returns the number of - * nodes freed. + * This function frees a tree and returns the number of nodes freed. * */ static unsigned int _db_tree_free(struct db_arg_chain_tree *tree) @@ -576,7 +575,7 @@ int db_col_attr_get(const struct db_filter_col *col, /** * Set a filter attribute - * @param db the seccomp filter collection + * @param col the seccomp filter collection * @param attr the filter attribute * @param value the filter attribute value * @@ -699,7 +698,6 @@ int db_col_db_remove(struct db_filter_col *col, uint32_t arch_token) /** * Free and reset the seccomp filter DB * @param db the seccomp filter DB - * @param def_action the default filter action * * This function frees any existing filters and resets the filter DB to a * default state; only the DB architecture is preserved. @@ -827,20 +825,47 @@ int db_syscall_priority(struct db_filter *db, } /** + * Test if the argument filter can be skipped because it's a tautology + * @param arg argument filter + * + * If this argument filter applied to the lower 32 bit can be skipped this + * function returns false. + * + */ +static bool _db_arg_cmp_need_lo(const struct db_api_arg *arg) +{ + if (arg->op == SCMP_CMP_MASKED_EQ && D64_LO(arg->mask) == 0) + return false; + + return true; +} + +/** + * Test if the argument filter can be skipped because it's a tautology + * @param arg argument filter + * + * If this argument filter applied to the upper 32 bit can be skipped this + * function returns false. + * + */ +static bool _db_arg_cmp_need_hi(const struct db_api_arg *arg) +{ + if (arg->op == SCMP_CMP_MASKED_EQ && D64_HI(arg->mask) == 0) + return false; + + return true; +} + +/** * Fixup the node based on the op/mask * @param node the chain node * - * Apply some simplifications based on the comparison op and mask value. + * Ensure the datum is masked as well. * */ static void _db_node_mask_fixup(struct db_arg_chain_tree *node) { - if (node->op == SCMP_CMP_MASKED_EQ && node->mask == 0) { - node->op = SCMP_CMP_EQ; - node->mask = ARG_MASK_MAX; - node->datum = 0; - } else - node->datum &= node->mask; + node->datum &= node->mask; } /** @@ -880,6 +905,13 @@ static struct db_sys_list *_db_rule_gen_64(const struct arch_def *arch, if (chain[iter].valid == 0) continue; + /* TODO: handle the case were either hi or lo isn't needed */ + + /* skip generating instruction which are no-ops */ + if (!_db_arg_cmp_need_hi(&chain[iter]) && + !_db_arg_cmp_need_lo(&chain[iter])) + continue; + c_iter_hi = malloc(sizeof(*c_iter_hi)); if (c_iter_hi == NULL) goto gen_64_failure; @@ -1012,6 +1044,10 @@ static struct db_sys_list *_db_rule_gen_32(const struct arch_def *arch, if (chain[iter].valid == 0) continue; + /* skip generating instructions which are no-ops */ + if (!_db_arg_cmp_need_lo(&chain[iter])) + continue; + c_iter = malloc(sizeof(*c_iter)); if (c_iter == NULL) goto gen_32_failure; @@ -1020,6 +1056,7 @@ static struct db_sys_list *_db_rule_gen_32(const struct arch_def *arch, c_iter->arg = chain[iter].arg; c_iter->arg_offset = arch_arg_offset(arch, c_iter->arg); c_iter->op = chain[iter].op; + /* implicitly strips off the upper 32 bit */ c_iter->mask = chain[iter].mask; c_iter->datum = chain[iter].datum; @@ -33,7 +33,7 @@ struct db_api_arg { unsigned int arg; - unsigned int op; + enum scmp_compare op; scmp_datum_t mask; scmp_datum_t datum; diff --git a/src/gen_bpf.c b/src/gen_bpf.c index 8f3ea41..8d1b1b5 100644 --- a/src/gen_bpf.c +++ b/src/gen_bpf.c @@ -48,6 +48,14 @@ struct acc_state { int32_t offset; uint32_t mask; }; +#define _ACC_STATE(x,y) \ + (struct acc_state){ .offset = (x), .mask = (y) } +#define _ACC_STATE_OFFSET(x) \ + _ACC_STATE(x,ARG_MASK_MAX) +#define _ACC_STATE_UNDEF \ + _ACC_STATE_OFFSET(-1) +#define _ACC_CMP_EQ(x,y) \ + ((x).offset == (y).offset && (x).mask == (y).mask) enum bpf_jump_type { TGT_NONE = 0, @@ -97,12 +105,19 @@ struct bpf_instr { }; #define _BPF_OFFSET_SYSCALL (offsetof(struct seccomp_data, nr)) #define _BPF_SYSCALL(a) _BPF_K(a,_BPF_OFFSET_SYSCALL) +#define _BPF_OFFSET_ARCH (offsetof(struct seccomp_data, arch)) +#define _BPF_ARCH(a) _BPF_K(a,_BPF_OFFSET_ARCH) struct bpf_blk { + /* bpf instructions */ struct bpf_instr *blks; unsigned int blk_cnt; unsigned int blk_alloc; + /* accumulator state */ + struct acc_state acc_start; + struct acc_state acc_end; + /* priority - higher is better */ unsigned int priority; @@ -119,7 +134,6 @@ struct bpf_blk { struct bpf_blk *hash_nxt; struct bpf_blk *prev, *next; struct bpf_blk *lvl_prv, *lvl_nxt; - struct acc_state acc_state; }; #define _BLK_MSZE(x) \ ((x)->blk_cnt * sizeof(*((x)->blks))) @@ -139,6 +153,8 @@ struct bpf_state { /* filter attributes */ const struct db_filter_attr *attr; + /* bad arch action */ + uint64_t bad_arch_hsh; /* default action */ uint64_t def_hsh; @@ -288,12 +304,70 @@ static void _blk_free(struct bpf_state *state, struct bpf_blk *blk) } /** + * Allocate and initialize a new instruction block + * + * Allocate a new BPF instruction block and perform some very basic + * initialization. Returns a pointer to the block on success, NULL on failure. + * + */ +static struct bpf_blk *_blk_alloc(void) +{ + struct bpf_blk *blk; + + blk = malloc(sizeof(*blk)); + if (blk == NULL) + return NULL; + + memset(blk, 0, sizeof(*blk)); + blk->flag_unique = true; + blk->acc_start = _ACC_STATE_UNDEF; + blk->acc_end = _ACC_STATE_UNDEF; + + return blk; +} + +/** + * Resize an instruction block + * @param state the BPF state + * @param blk the existing instruction block, or NULL + * @param size_add the minimum amount of instructions to add + * + * Resize the given instruction block such that it is at least as large as the + * current size plus @size_add. Returns a pointer to the block on success, + * NULL on failure. + * + */ +static struct bpf_blk *_blk_resize(struct bpf_state *state, + struct bpf_blk *blk, + unsigned int size_add) +{ + unsigned int size_adj = (AINC_BLK > size_add ? AINC_BLK : size_add); + struct bpf_instr *new; + + if (blk == NULL) + return NULL; + + if ((blk->blk_cnt + size_adj) <= blk->blk_alloc) + return blk; + + blk->blk_alloc += size_adj; + new = realloc(blk->blks, blk->blk_alloc * sizeof(*(blk->blks))); + if (new == NULL) { + _blk_free(state, blk); + return NULL; + } + blk->blks = new; + + return blk; +} + +/** * Append a new BPF instruction to an instruction block * @param state the BPF state * @param blk the existing instruction block, or NULL * @param instr the new instruction * - * Add the new BPF instruction to the end of the give instruction block. If + * Add the new BPF instruction to the end of the given instruction block. If * the given instruction block is NULL, a new block will be allocated. Returns * a pointer to the block on success, NULL on failure, and in the case of * failure the instruction block is free'd. @@ -303,30 +377,48 @@ static struct bpf_blk *_blk_append(struct bpf_state *state, struct bpf_blk *blk, const struct bpf_instr *instr) { - struct bpf_instr *new; - if (blk == NULL) { - blk = malloc(sizeof(*blk)); + blk = _blk_alloc(); if (blk == NULL) return NULL; - memset(blk, 0, sizeof(*blk)); - blk->flag_unique = true; - } - if ((blk->blk_cnt + 1) > blk->blk_alloc) { - blk->blk_alloc += AINC_BLK; - new = realloc(blk->blks, blk->blk_alloc * sizeof(*(blk->blks))); - if (new == NULL) { - _blk_free(state, blk); - return NULL; - } - blk->blks = new; } + + if (_blk_resize(state, blk, 1) == NULL) + return NULL; memcpy(&blk->blks[blk->blk_cnt++], instr, sizeof(*instr)); return blk; } /** + * Prepend a new BPF instruction to an instruction block + * @param state the BPF state + * @param blk the existing instruction block, or NULL + * @param instr the new instruction + * + * Add the new BPF instruction to the start of the given instruction block. + * If the given instruction block is NULL, a new block will be allocated. + * Returns a pointer to the block on success, NULL on failure, and in the case + * of failure the instruction block is free'd. + * + */ +static struct bpf_blk *_blk_prepend(struct bpf_state *state, + struct bpf_blk *blk, + const struct bpf_instr *instr) +{ + /* empty - we can treat this like a normal append operation */ + if (blk == NULL || blk->blk_cnt == 0) + return _blk_append(state, blk, instr); + + if (_blk_resize(state, blk, 1) == NULL) + return NULL; + memmove(&blk->blks[1], &blk->blks[0], blk->blk_cnt++ * sizeof(*instr)); + memcpy(&blk->blks[0], instr, sizeof(*instr)); + + return blk; +} + +/** * Append a block of BPF instructions to the final BPF program * @param prg the BPF program * @param blk the BPF instruction block @@ -426,7 +518,7 @@ static void _program_free(struct bpf_program *prg) /** * Free the BPF state - * @param the BPF state + * @param state the BPF state * * Free all of the BPF state, including the BPF program if present. * @@ -715,9 +807,13 @@ static struct bpf_blk *_gen_bpf_node(struct bpf_state *state, int32_t acc_offset; uint32_t acc_mask; uint64_t act_t_hash = 0, act_f_hash = 0; - struct bpf_blk *blk = NULL, *b_act; + struct bpf_blk *blk, *b_act; struct bpf_instr instr; - struct acc_state a_state_orig = *a_state; + + blk = _blk_alloc(); + if (blk == NULL) + return NULL; + blk->acc_start = *a_state; /* generate the action blocks */ if (node->act_t_flg) { @@ -749,6 +845,8 @@ static struct bpf_blk *_gen_bpf_node(struct bpf_state *state, blk = _blk_append(state, blk, &instr); if (blk == NULL) goto node_failure; + /* we're not dependent on the accumulator anymore */ + blk->acc_start = _ACC_STATE_UNDEF; } if (acc_mask != a_state->mask) { /* apply the bitmask */ @@ -806,7 +904,7 @@ static struct bpf_blk *_gen_bpf_node(struct bpf_state *state, goto node_failure; blk->node = node; - blk->acc_state = a_state_orig; + blk->acc_end = *a_state; return blk; node_failure: @@ -861,7 +959,7 @@ static struct bpf_blk *_gen_bpf_chain_lvl_res(struct bpf_state *state, case TGT_PTR_DB: node = (struct db_arg_chain_tree *)i_iter->jt.tgt.db; b_new = _gen_bpf_chain(state, sys, node, - nxt_jump, &blk->acc_state); + nxt_jump, &blk->acc_start); if (b_new == NULL) return NULL; i_iter->jt = _BPF_JMP_HSH(b_new->hash); @@ -887,7 +985,7 @@ static struct bpf_blk *_gen_bpf_chain_lvl_res(struct bpf_state *state, case TGT_PTR_DB: node = (struct db_arg_chain_tree *)i_iter->jf.tgt.db; b_new = _gen_bpf_chain(state, sys, node, - nxt_jump, &blk->acc_state); + nxt_jump, &blk->acc_start); if (b_new == NULL) return NULL; i_iter->jf = _BPF_JMP_HSH(b_new->hash); @@ -940,6 +1038,7 @@ static struct bpf_blk *_gen_bpf_chain(struct bpf_state *state, const struct db_arg_chain_tree *c_iter; unsigned int iter; struct bpf_jump nxt_jump_tmp; + struct acc_state acc = *a_state; if (chain == NULL) { b_head = _gen_bpf_action(state, NULL, sys->action); @@ -954,7 +1053,7 @@ static struct bpf_blk *_gen_bpf_chain(struct bpf_state *state, /* build all of the blocks for this level */ do { - b_iter = _gen_bpf_node(state, c_iter, a_state); + b_iter = _gen_bpf_node(state, c_iter, &acc); if (b_iter == NULL) goto chain_failure; if (b_head != NULL) { @@ -1058,7 +1157,7 @@ static struct bpf_blk *_gen_bpf_syscall(struct bpf_state *state, { int rc; struct bpf_instr instr; - struct bpf_blk *blk_c, *blk_s = NULL; + struct bpf_blk *blk_c, *blk_s; struct bpf_jump def_jump; struct acc_state a_state; @@ -1066,20 +1165,27 @@ static struct bpf_blk *_gen_bpf_syscall(struct bpf_state *state, memset(&def_jump, 0, sizeof(def_jump)); def_jump = _BPF_JMP_HSH(state->def_hsh); + blk_s = _blk_alloc(); + if (blk_s == NULL) + return NULL; + /* setup the accumulator state */ if (acc_reset) { _BPF_INSTR(instr, _BPF_OP(state->arch, BPF_LD + BPF_ABS), _BPF_JMP_NO, _BPF_JMP_NO, _BPF_SYSCALL(state->arch)); - blk_s = _blk_append(state, NULL, &instr); + blk_s = _blk_append(state, blk_s, &instr); if (blk_s == NULL) return NULL; - a_state.offset = _BPF_OFFSET_SYSCALL; - a_state.mask = ARG_MASK_MAX; + /* we've loaded the syscall ourselves */ + a_state = _ACC_STATE_OFFSET(_BPF_OFFSET_SYSCALL); + blk_s->acc_start = _ACC_STATE_UNDEF; + blk_s->acc_end = _ACC_STATE_OFFSET(_BPF_OFFSET_SYSCALL); } else { - /* set the accumulator state to an unknown value */ - a_state.offset = -1; - a_state.mask = ARG_MASK_MAX; + /* we rely on someone else to load the syscall */ + a_state = _ACC_STATE_UNDEF; + blk_s->acc_start = _ACC_STATE_OFFSET(_BPF_OFFSET_SYSCALL); + blk_s->acc_end = _ACC_STATE_OFFSET(_BPF_OFFSET_SYSCALL); } /* generate the argument chains */ @@ -1243,26 +1349,31 @@ static struct bpf_blk *_gen_bpf_arch(struct bpf_state *state, b_new = _blk_append(state, NULL, &instr); if (b_new == NULL) goto arch_failure; + b_new->acc_end = _ACC_STATE_OFFSET(_BPF_OFFSET_SYSCALL); if (state->arch->token == SCMP_ARCH_X86_64) { /* filter out x32 */ _BPF_INSTR(instr, _BPF_OP(state->arch, BPF_JMP + BPF_JGE), - _BPF_JMP_NXT(blk_cnt++), _BPF_JMP_NO, + _BPF_JMP_HSH(state->bad_arch_hsh), + _BPF_JMP_NO, _BPF_K(state->arch, X32_SYSCALL_BIT)); if (b_head != NULL) instr.jf = _BPF_JMP_HSH(b_head->hash); else instr.jf = _BPF_JMP_HSH(state->def_hsh); + blk_cnt++; } else if (state->arch->token == SCMP_ARCH_X32) { /* filter out x86_64 */ _BPF_INSTR(instr, _BPF_OP(state->arch, BPF_JMP + BPF_JGE), - _BPF_JMP_NO, _BPF_JMP_NXT(blk_cnt++), + _BPF_JMP_NO, + _BPF_JMP_HSH(state->bad_arch_hsh), _BPF_K(state->arch, X32_SYSCALL_BIT)); if (b_head != NULL) instr.jt = _BPF_JMP_HSH(b_head->hash); else instr.jt = _BPF_JMP_HSH(state->def_hsh); + blk_cnt++; } else /* we should never get here */ goto arch_failure; @@ -1531,6 +1642,7 @@ static int _gen_bpf_build_bpf(struct bpf_state *state, rc = _hsh_add(state, &b_badarch, 1); if (rc < 0) return rc; + state->bad_arch_hsh = b_badarch->hash; /* generate the default action */ b_default = _gen_bpf_action(state, NULL, state->attr->act_default); @@ -1543,11 +1655,11 @@ static int _gen_bpf_build_bpf(struct bpf_state *state, /* load the architecture token/number */ _BPF_INSTR(instr, _BPF_OP(state->arch, BPF_LD + BPF_ABS), - _BPF_JMP_NO, _BPF_JMP_NO, - _BPF_K(state->arch, offsetof(struct seccomp_data, arch))); + _BPF_JMP_NO, _BPF_JMP_NO, _BPF_ARCH(state->arch)); b_head = _blk_append(state, NULL, &instr); if (b_head == NULL) return -ENOMEM; + b_head->acc_end = _ACC_STATE_OFFSET(_BPF_OFFSET_ARCH); rc = _hsh_add(state, &b_head, 1); if (rc < 0) return rc; @@ -1638,6 +1750,37 @@ static int _gen_bpf_build_bpf(struct bpf_state *state, b_jmp = _hsh_find_once(state, i_iter->k.tgt.hash); if (b_jmp != NULL) { + /* do we need to reload the accumulator? */ + if ((b_jmp->acc_start.offset != -1) && + !_ACC_CMP_EQ(b_iter->acc_end, + b_jmp->acc_start)) { + if (b_jmp->acc_start.mask != ARG_MASK_MAX) { + _BPF_INSTR(instr, + _BPF_OP(state->arch, + BPF_ALU + BPF_AND), + _BPF_JMP_NO, + _BPF_JMP_NO, + _BPF_K(state->arch, + b_jmp->acc_start.mask)); + b_jmp = _blk_prepend(state, + b_jmp, + &instr); + if (b_jmp == NULL) + return -EFAULT; + } + _BPF_INSTR(instr, + _BPF_OP(state->arch, + BPF_LD + BPF_ABS), + _BPF_JMP_NO, _BPF_JMP_NO, + _BPF_K(state->arch, + b_jmp->acc_start.offset)); + b_jmp = _blk_prepend(state, + b_jmp, &instr); + if (b_jmp == NULL) + return -EFAULT; + /* not reliant on the accumulator */ + b_jmp->acc_start = _ACC_STATE_UNDEF; + } /* insert the new block after this block */ b_jmp->prev = b_iter; b_jmp->next = b_iter->next; @@ -1654,6 +1797,7 @@ static int _gen_bpf_build_bpf(struct bpf_state *state, b_iter = b_iter->prev; } while (b_iter != NULL); + /* NOTE - from here to the end of the function we need to fail via the * the build_bpf_free_blks label, not just return an error; see * the _gen_bpf_build_jmp() function for details */ @@ -1806,7 +1950,7 @@ bpf_generate_end: /** * Free memory associated with a BPF representation - * @param fprog the BPF representation + * @param program the BPF representation * * Free the memory associated with a BPF representation generated by the * gen_bpf_generate() function. diff --git a/src/gen_pfc.c b/src/gen_pfc.c index 3484dab..4f2ee4f 100644 --- a/src/gen_pfc.c +++ b/src/gen_pfc.c @@ -177,6 +177,9 @@ static void _gen_pfc_chain(const struct arch_def *arch, case SCMP_CMP_MASKED_EQ: fprintf(fds, " & 0x%.8x == ", c_iter->mask); break; + case SCMP_CMP_NE: + case SCMP_CMP_LT: + case SCMP_CMP_LE: default: fprintf(fds, " ??? "); } @@ -247,7 +250,7 @@ static void _gen_pfc_syscall(const struct arch_def *arch, static int _gen_pfc_arch(const struct db_filter_col *col, const struct db_filter *db, FILE *fds) { - int rc; + int rc = 0; struct db_sys_list *s_iter; struct pfc_sys_list *p_iter = NULL, *p_new, *p_head = NULL, *p_prev; @@ -189,7 +189,7 @@ static uint32_t jhash_word(const uint32_t *k, size_t length, uint32_t initval) /** * Hash a variable-length key into a 32-bit value - * @param k the key (the unaligned variable-length array of bytes) + * @param key the key (the unaligned variable-length array of bytes) * @param length the length of the key, counting by bytes * @param initval can be any 4-byte value * @@ -456,7 +456,7 @@ static uint32_t jhash_le(const void *key, size_t length, uint32_t initval) /** * Hash a variable-length key into a 32-bit value - * @param k the key (the unaligned variable-length array of bytes) + * @param key the key (the unaligned variable-length array of bytes) * @param length the length of the key, counting by bytes * @param initval can be any 4-byte value * @@ -655,7 +655,7 @@ static uint32_t jhash_be( const void *key, size_t length, uint32_t initval) /** * Hash a variable-length key into a 32-bit value - * @param k the key (the unaligned variable-length array of bytes) + * @param key the key (the unaligned variable-length array of bytes) * @param length the length of the key, counting by bytes * @param initval can be any 4-byte value * diff --git a/src/python/seccomp.pyx b/src/python/seccomp.pyx index 2da8c66..18360a7 100644 --- a/src/python/seccomp.pyx +++ b/src/python/seccomp.pyx @@ -420,7 +420,7 @@ cdef class SyscallFilter: Lookup the given attribute in the filter and return the attribute's value to the caller. """ - value = 0 + cdef uint32_t value = 0 rc = libseccomp.seccomp_attr_get(self._ctx, attr, <uint32_t *>&value) if rc == -errno.EINVAL: diff --git a/tests/.gitignore b/tests/.gitignore index 6c2440b..d47ea65 100644 --- a/tests/.gitignore +++ b/tests/.gitignore @@ -1,6 +1,7 @@ *.bpf *.bpfd *.pfc +miniseq util.pyc 00-test.c 00-test @@ -30,3 +31,6 @@ util.pyc 24-live-arg_allow 25-sim-multilevel_chains_adv 26-sim-arch_all_be_basic +27-sim-bpf_blk_state +28-sim-arch_x86 + diff --git a/tests/02-sim-basic.py b/tests/02-sim-basic.py index 868664f..60ad321 100755 --- a/tests/02-sim-basic.py +++ b/tests/02-sim-basic.py @@ -30,10 +30,10 @@ from seccomp import * def test(args): f = SyscallFilter(KILL) - f.add_rule_exactly(ALLOW, "read"); - f.add_rule_exactly(ALLOW, "write"); - f.add_rule_exactly(ALLOW, "close"); - f.add_rule_exactly(ALLOW, "rt_sigreturn"); + f.add_rule_exactly(ALLOW, "read") + f.add_rule_exactly(ALLOW, "write") + f.add_rule_exactly(ALLOW, "close") + f.add_rule_exactly(ALLOW, "rt_sigreturn") return f args = util.get_opt() diff --git a/tests/03-sim-basic_chains.py b/tests/03-sim-basic_chains.py index 324170d..81eac1a 100755 --- a/tests/03-sim-basic_chains.py +++ b/tests/03-sim-basic_chains.py @@ -30,11 +30,11 @@ from seccomp import * def test(args): f = SyscallFilter(KILL) - f.add_rule_exactly(ALLOW, "read", Arg(0, EQ, sys.stdin.fileno())); - f.add_rule_exactly(ALLOW, "write", Arg(0, EQ, sys.stdout.fileno())); - f.add_rule_exactly(ALLOW, "write", Arg(0, EQ, sys.stderr.fileno())); - f.add_rule_exactly(ALLOW, "close"); - f.add_rule_exactly(ALLOW, "rt_sigreturn"); + f.add_rule_exactly(ALLOW, "read", Arg(0, EQ, sys.stdin.fileno())) + f.add_rule_exactly(ALLOW, "write", Arg(0, EQ, sys.stdout.fileno())) + f.add_rule_exactly(ALLOW, "write", Arg(0, EQ, sys.stderr.fileno())) + f.add_rule_exactly(ALLOW, "close") + f.add_rule_exactly(ALLOW, "rt_sigreturn") return f args = util.get_opt() diff --git a/tests/04-sim-multilevel_chains.py b/tests/04-sim-multilevel_chains.py index 73a6921..3878636 100755 --- a/tests/04-sim-multilevel_chains.py +++ b/tests/04-sim-multilevel_chains.py @@ -30,22 +30,22 @@ from seccomp import * def test(args): f = SyscallFilter(KILL) - f.add_rule(ALLOW, "open"); - f.add_rule(ALLOW, "close"); + f.add_rule(ALLOW, "open") + f.add_rule(ALLOW, "close") f.add_rule(ALLOW, "read", Arg(0, EQ, sys.stdin.fileno()), Arg(1, NE, 0), - Arg(2, LT, sys.maxsize)); + Arg(2, LT, sys.maxsize)) f.add_rule(ALLOW, "write", Arg(0, EQ, sys.stdout.fileno()), Arg(1, NE, 0), - Arg(2, LT, sys.maxsize)); + Arg(2, LT, sys.maxsize)) f.add_rule(ALLOW, "write", Arg(0, EQ, sys.stderr.fileno()), Arg(1, NE, 0), - Arg(2, LT, sys.maxsize)); - f.add_rule(ALLOW, "close"); - f.add_rule(ALLOW, "rt_sigreturn"); + Arg(2, LT, sys.maxsize)) + f.add_rule(ALLOW, "close") + f.add_rule(ALLOW, "rt_sigreturn") return f args = util.get_opt() diff --git a/tests/12-sim-basic_masked_ops.tests b/tests/12-sim-basic_masked_ops.tests index 20e0f6d..5f1327f 100644 --- a/tests/12-sim-basic_masked_ops.tests +++ b/tests/12-sim-basic_masked_ops.tests @@ -30,6 +30,12 @@ test type: bpf-sim 12-sim-basic_masked_ops all 1000 0 0x400 2 N N N KILL 12-sim-basic_masked_ops all 1000 0 0x402-0x4FF 2 N N N KILL 12-sim-basic_masked_ops all 1000 0 0x10300-0x103FF 2 N N N ALLOW +12-sim-basic_masked_ops all 1000 0 0x00000000F00003E8 2 N N N ALLOW +12-sim-basic_masked_ops all 1000 0 0x00000000800003E8 2 N N N ALLOW +12-sim-basic_masked_ops all 1000 0 0x00000001800003E8 2 N N N ALLOW +12-sim-basic_masked_ops all 1000 0 0x00000001000003E8 2 N N N ALLOW +12-sim-basic_masked_ops all 1000 0 0x0000000F000003E8 2 N N N ALLOW +12-sim-basic_masked_ops all 1000 0 0xFFFFFFFFFFFF03E8 2 N N N ALLOW test type: bpf-sim-fuzz diff --git a/tests/15-basic-resolver.c b/tests/15-basic-resolver.c index a8988fd..0bd0cf8 100644 --- a/tests/15-basic-resolver.c +++ b/tests/15-basic-resolver.c @@ -21,40 +21,51 @@ #include <errno.h> #include <string.h> +#include <stdlib.h> #include <seccomp.h> int main(int argc, char *argv[]) { - char *name; + char *name = NULL; if (seccomp_syscall_resolve_name("open") != __NR_open) - return 1; + goto fail; if (seccomp_syscall_resolve_name("socket") != __NR_socket) - return 1; + goto fail; if (seccomp_syscall_resolve_name("INVALID") != __NR_SCMP_ERROR) - return 1; + goto fail; if (seccomp_syscall_resolve_name_arch(SCMP_ARCH_NATIVE, "open") != __NR_open) - return 1; + goto fail; if (seccomp_syscall_resolve_name_arch(SCMP_ARCH_NATIVE, "socket") != __NR_socket) - return 1; + goto fail; if (seccomp_syscall_resolve_name_arch(SCMP_ARCH_NATIVE, "INVALID") != __NR_SCMP_ERROR) - return 1; + goto fail; name = seccomp_syscall_resolve_num_arch(SCMP_ARCH_NATIVE, __NR_open); if (name == NULL || strcmp(name, "open") != 0) - return 1; + goto fail; + free(name); + name = seccomp_syscall_resolve_num_arch(SCMP_ARCH_NATIVE, __NR_socket); if (name == NULL || strcmp(name, "socket") != 0) - return 1; + goto fail; + free(name); + name = seccomp_syscall_resolve_num_arch(SCMP_ARCH_NATIVE, __NR_SCMP_ERROR); if (name != NULL) - return 1; + goto fail; + free(name); return 0; + +fail: + if (name != NULL) + free(name); + return 1; } diff --git a/tests/18-sim-basic_whitelist.py b/tests/18-sim-basic_whitelist.py index a7b9cb7..95ae7c1 100755 --- a/tests/18-sim-basic_whitelist.py +++ b/tests/18-sim-basic_whitelist.py @@ -30,11 +30,11 @@ from seccomp import * def test(args): f = SyscallFilter(ALLOW) - f.add_rule_exactly(KILL, "read", Arg(0, EQ, sys.stdin.fileno())); - f.add_rule_exactly(KILL, "write", Arg(0, EQ, sys.stdout.fileno())); - f.add_rule_exactly(KILL, "write", Arg(0, EQ, sys.stderr.fileno())); - f.add_rule_exactly(KILL, "close"); - f.add_rule_exactly(KILL, "rt_sigreturn"); + f.add_rule_exactly(KILL, "read", Arg(0, EQ, sys.stdin.fileno())) + f.add_rule_exactly(KILL, "write", Arg(0, EQ, sys.stdout.fileno())) + f.add_rule_exactly(KILL, "write", Arg(0, EQ, sys.stderr.fileno())) + f.add_rule_exactly(KILL, "close") + f.add_rule_exactly(KILL, "rt_sigreturn") return f args = util.get_opt() diff --git a/tests/22-sim-basic_chains_array.py b/tests/22-sim-basic_chains_array.py index dfc3a58..c228661 100755 --- a/tests/22-sim-basic_chains_array.py +++ b/tests/22-sim-basic_chains_array.py @@ -33,11 +33,11 @@ from seccomp import * def test(args): f = SyscallFilter(KILL) - f.add_rule_exactly(ALLOW, "read", Arg(0, EQ, sys.stdin.fileno())); - f.add_rule_exactly(ALLOW, "write", Arg(0, EQ, sys.stdout.fileno())); - f.add_rule_exactly(ALLOW, "write", Arg(0, EQ, sys.stderr.fileno())); - f.add_rule_exactly(ALLOW, "close"); - f.add_rule_exactly(ALLOW, "rt_sigreturn"); + f.add_rule_exactly(ALLOW, "read", Arg(0, EQ, sys.stdin.fileno())) + f.add_rule_exactly(ALLOW, "write", Arg(0, EQ, sys.stdout.fileno())) + f.add_rule_exactly(ALLOW, "write", Arg(0, EQ, sys.stderr.fileno())) + f.add_rule_exactly(ALLOW, "close") + f.add_rule_exactly(ALLOW, "rt_sigreturn") return f args = util.get_opt() diff --git a/tests/25-sim-multilevel_chains_adv.py b/tests/25-sim-multilevel_chains_adv.py index 95a673c..0dd85de 100755 --- a/tests/25-sim-multilevel_chains_adv.py +++ b/tests/25-sim-multilevel_chains_adv.py @@ -32,11 +32,11 @@ def test(args): f = SyscallFilter(KILL) f.add_rule_exactly(ALLOW, 10, Arg(0, EQ, 11), - Arg(1, NE, 12)); + Arg(1, NE, 12)) f.add_rule_exactly(ALLOW, 20, Arg(0, EQ, 21), Arg(1, NE, 22), - Arg(2, EQ, 23)); + Arg(2, EQ, 23)) return f args = util.get_opt() diff --git a/tests/27-sim-bpf_blk_state.c b/tests/27-sim-bpf_blk_state.c new file mode 100644 index 0000000..fd69044 --- /dev/null +++ b/tests/27-sim-bpf_blk_state.c @@ -0,0 +1,103 @@ +/** + * Seccomp Library test program + * + * Copyright (c) 2015 Red Hat <pmoore@redhat.com> + * Author: Paul Moore <pmoore@redhat.com> + */ + +/* + * 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 <unistd.h> + +#include <seccomp.h> + +#include "util.h" + +int main(int argc, char *argv[]) +{ + int rc; + struct util_options opts; + scmp_filter_ctx ctx = NULL; + + rc = util_getopt(argc, argv, &opts); + if (rc < 0) + goto out; + + ctx = seccomp_init(SCMP_ACT_ALLOW); + if (ctx == NULL) + return ENOMEM; + + rc = seccomp_rule_add_exact(ctx, SCMP_ACT_KILL, 1000, 1, + SCMP_A0(SCMP_CMP_EQ, 3)); + if (rc != 0) + goto out; + rc = seccomp_rule_add_exact(ctx, SCMP_ACT_KILL, 1000, 1, + SCMP_A0(SCMP_CMP_EQ, 4)); + if (rc != 0) + goto out; + rc = seccomp_rule_add_exact(ctx, SCMP_ACT_KILL, 1000, 1, + SCMP_A0(SCMP_CMP_EQ, 5)); + if (rc != 0) + goto out; + rc = seccomp_rule_add_exact(ctx, SCMP_ACT_KILL, 1000, 1, + SCMP_A0(SCMP_CMP_EQ, 6)); + if (rc != 0) + goto out; + rc = seccomp_rule_add_exact(ctx, SCMP_ACT_KILL, 1000, 1, + SCMP_A0(SCMP_CMP_EQ, 7)); + if (rc != 0) + goto out; + rc = seccomp_rule_add_exact(ctx, SCMP_ACT_KILL, 1000, 1, + SCMP_A0(SCMP_CMP_EQ, 8)); + if (rc != 0) + goto out; + rc = seccomp_rule_add_exact(ctx, SCMP_ACT_KILL, 1000, 1, + SCMP_A0(SCMP_CMP_EQ, 9)); + if (rc != 0) + goto out; + rc = seccomp_rule_add_exact(ctx, SCMP_ACT_KILL, 1000, 1, + SCMP_A0(SCMP_CMP_EQ, 11)); + if (rc != 0) + goto out; + rc = seccomp_rule_add_exact(ctx, SCMP_ACT_KILL, 1000, 1, + SCMP_A0(SCMP_CMP_EQ, 12)); + if (rc != 0) + goto out; + rc = seccomp_rule_add_exact(ctx, SCMP_ACT_KILL, 1000, 1, + SCMP_A0(SCMP_CMP_EQ, 13)); + if (rc != 0) + goto out; + rc = seccomp_rule_add_exact(ctx, SCMP_ACT_KILL, 1000, 1, + SCMP_A0(SCMP_CMP_EQ, 14)); + if (rc != 0) + goto out; + rc = seccomp_rule_add_exact(ctx, SCMP_ACT_KILL, 1000, 1, + SCMP_A0(SCMP_CMP_EQ, 15)); + if (rc != 0) + goto out; + rc = seccomp_rule_add_exact(ctx, SCMP_ACT_KILL, 1000, 1, + SCMP_A0(SCMP_CMP_GE, 16)); + if (rc != 0) + goto out; + + rc = util_filter_output(&opts, ctx); + if (rc) + goto out; + +out: + seccomp_release(ctx); + return (rc < 0 ? -rc : rc); +} diff --git a/tests/27-sim-bpf_blk_state.py b/tests/27-sim-bpf_blk_state.py new file mode 100755 index 0000000..ff53ac9 --- /dev/null +++ b/tests/27-sim-bpf_blk_state.py @@ -0,0 +1,53 @@ +#!/usr/bin/env python + +# +# Seccomp Library test program +# +# Copyright (c) 2015 Red Hat <pmoore@redhat.com> +# Author: Paul Moore <pmoore@redhat.com> +# + +# +# 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>. +# + +import argparse +import sys + +import util + +from seccomp import * + +def test(args): + f = SyscallFilter(ALLOW) + f.add_rule_exactly(KILL, 1000, Arg(0, EQ, 3)) + f.add_rule_exactly(KILL, 1000, Arg(0, EQ, 4)) + f.add_rule_exactly(KILL, 1000, Arg(0, EQ, 5)) + f.add_rule_exactly(KILL, 1000, Arg(0, EQ, 6)) + f.add_rule_exactly(KILL, 1000, Arg(0, EQ, 7)) + f.add_rule_exactly(KILL, 1000, Arg(0, EQ, 8)) + f.add_rule_exactly(KILL, 1000, Arg(0, EQ, 9)) + f.add_rule_exactly(KILL, 1000, Arg(0, EQ, 11)) + f.add_rule_exactly(KILL, 1000, Arg(0, EQ, 12)) + f.add_rule_exactly(KILL, 1000, Arg(0, EQ, 13)) + f.add_rule_exactly(KILL, 1000, Arg(0, EQ, 14)) + f.add_rule_exactly(KILL, 1000, Arg(0, EQ, 15)) + f.add_rule_exactly(KILL, 1000, Arg(0, GE, 16)) + return f + +args = util.get_opt() +ctx = test(args) +util.filter_output(args, ctx) + +# kate: syntax python; +# kate: indent-mode python; space-indent on; indent-width 4; mixedindent off; diff --git a/tests/27-sim-bpf_blk_state.tests b/tests/27-sim-bpf_blk_state.tests new file mode 100644 index 0000000..a4a8ae1 --- /dev/null +++ b/tests/27-sim-bpf_blk_state.tests @@ -0,0 +1,24 @@ +# +# libseccomp regression test automation data +# +# Copyright (c) 2015 Red Hat <pmoore@redhat.com> +# Author: Paul Moore <pmoore@redhat.com +# + +test type: bpf-sim + +# Testname Arch Syscall Arg0 Arg1 Arg2 Arg3 Arg4 Arg5 Result +27-sim-bpf_blk_state all 1000 0-2 N N N N N ALLOW +27-sim-bpf_blk_state all 1000 3-9 N N N N N KILL +27-sim-bpf_blk_state all 1000 10 N N N N N ALLOW +27-sim-bpf_blk_state all 1000 11-32 N N N N N KILL + +test type: bpf-sim-fuzz + +# Testname StressCount +27-sim-bpf_blk_state 50 + +test type: bpf-valgrind + +# Testname +27-sim-bpf_blk_state diff --git a/tests/28-sim-arch_x86.c b/tests/28-sim-arch_x86.c new file mode 100644 index 0000000..fa6302f --- /dev/null +++ b/tests/28-sim-arch_x86.c @@ -0,0 +1,71 @@ +/** + * Seccomp Library test program + * + * This test triggered a bug in libseccomp erroneously allowing the close() + * syscall on x32 instead of 'KILL'ing it, as it should do for unsupported + * architectures. + * + * Copyright (c) 2012 Red Hat <pmoore@redhat.com> + * Authors: Paul Moore <pmoore@redhat.com> + * Mathias Krause <minipli@googlemail.com> + */ + +/* + * 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 <unistd.h> + +#include <seccomp.h> + +#include "util.h" + +int main(int argc, char *argv[]) +{ + int rc; + struct util_options opts; + scmp_filter_ctx ctx = NULL; + + rc = util_getopt(argc, argv, &opts); + if (rc < 0) + goto out; + + ctx = seccomp_init(SCMP_ACT_ALLOW); + if (ctx == NULL) + return ENOMEM; + + rc = seccomp_arch_remove(ctx, SCMP_ARCH_NATIVE); + if (rc != 0) + goto out; + + /* add x86-64 and x86 (in that order!) but explicitly leave out x32 */ + rc = seccomp_arch_add(ctx, SCMP_ARCH_X86_64); + if (rc != 0) + goto out; + rc = seccomp_arch_add(ctx, SCMP_ARCH_X86); + if (rc != 0) + goto out; + + rc = seccomp_rule_add(ctx, SCMP_ACT_ERRNO(1), SCMP_SYS(close), 0); + if (rc != 0) + goto out; + + rc = util_filter_output(&opts, ctx); + if (rc) + goto out; + +out: + seccomp_release(ctx); + return (rc < 0 ? -rc : rc); +} diff --git a/tests/28-sim-arch_x86.py b/tests/28-sim-arch_x86.py new file mode 100644 index 0000000..3ef7b77 --- /dev/null +++ b/tests/28-sim-arch_x86.py @@ -0,0 +1,47 @@ +#!/usr/bin/env python + +# +# Seccomp Library test program +# +# Copyright (c) 2015 Red Hat <pmoore@redhat.com> +# Author: Paul Moore <pmoore@redhat.com> +# +# Adapted from 29-sim-arch_x86.c by Mathias Krause <minipli@googlemail.com> +# + +# +# 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>. +# + +import argparse +import sys + +import util + +from seccomp import * + +def test(args): + f = SyscallFilter(ALLOW) + f.remove_arch(Arch()) + # add x86-64 and x86 (in that order!) but explicitly leave out x32 + f.add_arch(Arch("x86_64")) + f.add_arch(Arch("x86")) + f.add_rule(ERRNO(1), "close") + return f + +args = util.get_opt() +ctx = test(args) +util.filter_output(args, ctx) + +# kate: syntax python; +# kate: indent-mode python; space-indent on; indent-width 4; mixedindent off; diff --git a/tests/28-sim-arch_x86.tests b/tests/28-sim-arch_x86.tests new file mode 100644 index 0000000..45978aa --- /dev/null +++ b/tests/28-sim-arch_x86.tests @@ -0,0 +1,27 @@ +# +# libseccomp regression test automation data +# +# This test triggered a bug in libseccomp erroneously allowing the close() +# syscall on x32 instead of 'KILL'ing it, as it should do for unsupported +# architectures. +# +# Author: Mathias Krause <minipli@googlemail.com> +# + +test type: bpf-sim + +# Testname Arch Syscall Arg0 Arg1 Arg2 Arg3 Arg4 Arg5 Result +28-sim-arch_x86 +x86,+x86_64 read N N N N N N ALLOW +28-sim-arch_x86 +x86,+x86_64 close N N N N N N ERRNO(1) +28-sim-arch_x86 +arm,+x32 read N N N N N N KILL +28-sim-arch_x86 +arm,+x32 close N N N N N N KILL + +test type: bpf-sim-fuzz + +# Testname StressCount +28-sim-arch_x86 50 + +test type: bpf-valgrind + +# Testname +28-sim-arch_x86 diff --git a/tests/Makefile.am b/tests/Makefile.am index edb50a3..ba670c6 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -23,9 +23,12 @@ check_LTLIBRARIES = util.la util_la_SOURCES = util.c util.h util_la_LDFLAGS = -module +miniseq_LDADD = + TESTS = regression check_PROGRAMS = \ + miniseq \ 01-sim-allow \ 02-sim-basic \ 03-sim-basic_chains \ @@ -51,7 +54,9 @@ check_PROGRAMS = \ 23-sim-arch_all_le_basic \ 24-live-arg_allow \ 25-sim-multilevel_chains_adv \ - 26-sim-arch_all_be_basic + 26-sim-arch_all_be_basic \ + 27-sim-bpf_blk_state \ + 28-sim-arch_x86 EXTRA_DIST_TESTPYTHON = \ util.py \ @@ -80,7 +85,9 @@ EXTRA_DIST_TESTPYTHON = \ 23-sim-arch_all_le_basic.py \ 24-live-arg_allow.py \ 25-sim-multilevel_chains_adv.py \ - 26-sim-arch_all_be_basic.py + 26-sim-arch_all_be_basic.py \ + 27-sim-bpf_blk_state.py \ + 28-sim-arch_x86.py EXTRA_DIST_TESTCFGS = \ 01-sim-allow.tests \ @@ -108,7 +115,9 @@ EXTRA_DIST_TESTCFGS = \ 23-sim-arch_all_le_basic.tests \ 24-live-arg_allow.tests \ 25-sim-multilevel_chains_adv.tests \ - 26-sim-arch_all_be_basic.tests + 26-sim-arch_all_be_basic.tests \ + 27-sim-bpf_blk_state.tests \ + 28-sim-arch_x86.tests EXTRA_DIST_TESTSCRIPTS = regression testdiff testgen diff --git a/tests/miniseq.c b/tests/miniseq.c new file mode 100644 index 0000000..7addc70 --- /dev/null +++ b/tests/miniseq.c @@ -0,0 +1,57 @@ +/** + * Seccomp Library test support program + * + * Copyright (c) 2015 Mathias Krause <minipli@googlemail.com> + */ + +/* + * 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 <inttypes.h> +#include <stdlib.h> +#include <stdint.h> +#include <stdio.h> +#include <errno.h> + +static int get_number(char *str, uint64_t *res) +{ + char *end = str; + + errno = 0; + *res = strtoull(str, &end, 0); + if (errno || *end != '\0') { + fprintf(stderr, "error: failed to convert '%s'\n", str); + return -1; + } + + return 0; +} + +int main(int argc, char *argv[]) +{ + uint64_t first, last, cur; + + if (argc != 3) { + fprintf(stderr, "usage: %s FIRST LAST\n", argv[0]); + return 1; + } + + if (get_number(argv[1], &first) || get_number(argv[2], &last)) + return 1; + + for (cur = first; cur <= last; cur++) + printf("%" PRIu64 "\n", cur); + + return 0; +} diff --git a/tests/regression b/tests/regression index 9f0c17e..2aba23b 100755 --- a/tests/regression +++ b/tests/regression @@ -170,6 +170,23 @@ function get_range() { } # +# Get the number sequence for a given range with increments of 1, i.e. +# implement a specialized seq(1). +# +# We use our own implementation based on miniseq in favour to the standard seq +# tool as, at least, seq of coreutils v8.23 and v8.24 has problems on 32 bit +# ARM for large numbers (see the mailing thread at +# https://groups.google.com/forum/#!topic/libseccomp/VtrClkXxLGA). +# +# Arguments: +# 1 starting value +# 2 last value +# +function get_seq() { + ${basedir}/miniseq "$1" "$2" +} + +# # Run the specified test command (with valgrind if requested) # # Arguments: @@ -251,7 +268,7 @@ function run_test_bpf_sim_fuzz() { local testname=${line[0]} local stress_count=${line[1]} - for i in $(seq 1 $stress_count); do + for i in $(get_seq 1 $stress_count); do local sys=$(generate_random_data) local -a arg=($(generate_random_data) $(generate_random_data) \ $(generate_random_data) $(generate_random_data) \ @@ -468,13 +485,13 @@ function run_test_bpf_sim() { # and arg ranges and generate/run every combination of requested # tests; if no ranges were specifed, then the single test is # run - for sys in $(seq -f "%1.0f" $low_syscall $high_syscall); do - for arg0 in $(seq -f "%1.0f" ${low_arg[0]} ${high_arg[0]}); do - for arg1 in $(seq -f "%1.0f" ${low_arg[1]} ${high_arg[1]}); do - for arg2 in $(seq -f "%1.0f" ${low_arg[2]} ${high_arg[2]}); do - for arg3 in $(seq -f "%1.0f" ${low_arg[3]} ${high_arg[3]}); do - for arg4 in $(seq -f "%1.0f" ${low_arg[4]} ${high_arg[4]}); do - for arg5 in $(seq -f "%1.0f" ${low_arg[5]} ${high_arg[5]}); do + for sys in $(get_seq $low_syscall $high_syscall); do + for arg0 in $(get_seq ${low_arg[0]} ${high_arg[0]}); do + for arg1 in $(get_seq ${low_arg[1]} ${high_arg[1]}); do + for arg2 in $(get_seq ${low_arg[2]} ${high_arg[2]}); do + for arg3 in $(get_seq ${low_arg[3]} ${high_arg[3]}); do + for arg4 in $(get_seq ${low_arg[4]} ${high_arg[4]}); do + for arg5 in $(get_seq ${low_arg[5]} ${high_arg[5]}); do local -a arg=($arg0 $arg1 $arg2 $arg3 $arg4 $arg5) # Get the generated sub-test num string @@ -833,7 +850,6 @@ function run_tests() { verify_deps head verify_deps sed verify_deps awk -verify_deps seq verify_deps tr # global variables diff --git a/tools/Makefile.am b/tools/Makefile.am index 422b35d..b18dc9b 100644 --- a/tools/Makefile.am +++ b/tools/Makefile.am @@ -16,6 +16,8 @@ # along with this library; if not, see <http://www.gnu.org/licenses>. # +AM_CPPFLAGS = -I$(top_builddir)/include + noinst_LTLIBRARIES = util.la util_la_SOURCES = util.c util.h bpf.h util_la_LDFLAGS = -module diff --git a/tools/check-syntax b/tools/check-syntax index aebdf50..1ef5faf 100755 --- a/tools/check-syntax +++ b/tools/check-syntax @@ -3,7 +3,7 @@ # # libseccomp code syntax checking tool # -# Copyright (c) 2013 Red Hat <pmoore@redhat.com> +# Copyright (c) 2013,2015 Red Hat <pmoore@redhat.com> # Author: Paul Moore <pmoore@redhat.com> # @@ -54,18 +54,17 @@ usage: check-syntax [-h] libseccomp code syntax checking tool optional arguments: -h show this help message and exit + -f fix the file formatting EOF } # -# Check the formatting on a C source/header file +# Generate a properly formatted C source/header file # # Arguments: -# 1 File to check +# 1 Source file # function tool_c_style() { - [[ -z "$1" || ! -r "$1" ]] && return - astyle --options=none --lineend=linux --mode=c \ --style=linux \ --indent=force-tab=8 \ @@ -77,8 +76,33 @@ function tool_c_style() { --align-pointer=name \ --align-reference=name \ --max-code-length=80 \ - --break-after-logical < "$1" \ - | diff -pu --label="$1.orig" "$1" --label="$1" - + --break-after-logical < "$1" +} + +# +# Check the formatting on a C source/header file +# +# Arguments: +# 1 File to check +# +function tool_c_style_check() { + [[ -z "$1" || ! -r "$1" ]] && return + + tool_c_style "$1" | diff -pu --label="$1.orig" "$1" --label="$1" - +} + +# +# Fix the formatting on a C source/header file +# +# Arguments: +# 1 File to fix +# +function tool_c_style_fix() { + [[ -z "$1" || ! -r "$1" ]] && return + + tmp="$(mktemp --tmpdir=$(dirname "$1"))" + tool_c_style "$1" > "$tmp" + mv "$tmp" "$1" } # @@ -88,7 +112,18 @@ function check_c() { for i in $CHK_C_LIST; do echo "$CHK_C_EXCLUDE" | grep -q "$i" && continue echo "Differences for $i" - tool_c_style "$i" + tool_c_style_check "$i" + done +} + +# +# Perform all known syntax fixess for the configured C sources/headers +# +function fix_c() { + for i in $CHK_C_LIST; do + echo "$CHK_C_EXCLUDE" | grep -q "$i" && continue + echo "Fixing $i" + tool_c_style_fix "$i" done } @@ -97,8 +132,13 @@ function check_c() { verify_deps astyle -while getopts "h" opt; do +opt_fix=0 + +while getopts "fh" opt; do case $opt in + f) + opt_fix=1 + ;; h|*) usage exit 1 @@ -109,7 +149,11 @@ done # display the results echo "=============== $(date) ===============" echo "Code Syntax Check Results (\"check-syntax $*\")" -check_c +if [[ $opt_fix -eq 1 ]]; then + fix_c +else + check_c +fi echo "============================================================" # exit diff --git a/tools/util.h b/tools/util.h index 806f78a..2fed617 100644 --- a/tools/util.h +++ b/tools/util.h @@ -22,21 +22,43 @@ #ifndef _UTIL_H #define _UTIL_H +#include <elf.h> #include <inttypes.h> #include <linux/audit.h> +/** + * The ARM architecture tokens + */ +/* AArch64 support for audit was merged in 3.17-rc1 */ +#ifndef AUDIT_ARCH_AARCH64 +#ifndef EM_AARCH64 +#define EM_AARCH64 183 +#endif /* EM_AARCH64 */ +#define AUDIT_ARCH_AARCH64 (EM_AARCH64|__AUDIT_ARCH_64BIT|__AUDIT_ARCH_LE) +#endif /* AUDIT_ARCH_AARCH64 */ + +/** + * The MIPS architecture tokens + */ #ifndef __AUDIT_ARCH_CONVENTION_MIPS64_N32 #define __AUDIT_ARCH_CONVENTION_MIPS64_N32 0x20000000 #endif - -#ifndef AUDIT_ARCH_MIPS64N32 +#ifndef EM_MIPS +#define EM_MIPS 8 +#endif +#ifndef AUDIT_ARCH_MIPS +#define AUDIT_ARCH_MIPS (EM_MIPS) +#endif +#ifndef AUDIT_ARCH_MIPS64 +#define AUDIT_ARCH_MIPS64 (EM_MIPS|__AUDIT_ARCH_64BIT) +#endif /* MIPS64N32 support was merged in 3.15 */ +#ifndef AUDIT_ARCH_MIPS64N32 #define AUDIT_ARCH_MIPS64N32 (EM_MIPS|__AUDIT_ARCH_64BIT|\ __AUDIT_ARCH_CONVENTION_MIPS64_N32) #endif - -#ifndef AUDIT_ARCH_MIPSEL64N32 /* MIPSEL64N32 support was merged in 3.15 */ +#ifndef AUDIT_ARCH_MIPSEL64N32 #define AUDIT_ARCH_MIPSEL64N32 (EM_MIPS|__AUDIT_ARCH_64BIT|__AUDIT_ARCH_LE|\ __AUDIT_ARCH_CONVENTION_MIPS64_N32) #endif |