From 8af9ba443ff1c678b3f5037ca936f11edc697ae7 Mon Sep 17 00:00:00 2001 From: Andy Lutomirski Date: Fri, 4 Oct 2013 08:14:30 -0400 Subject: python: Improve MASKED_EQ docs It wasn't clear before which datum was the mask and which was the value. Signed-off-by: Andy Lutomirski Signed-off-by: Paul Moore --- src/python/seccomp.pyx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/python/seccomp.pyx b/src/python/seccomp.pyx index a87e1a4..0108a6a 100644 --- a/src/python/seccomp.pyx +++ b/src/python/seccomp.pyx @@ -45,7 +45,7 @@ Argument comparison values: EQ - argument equal the value GT - argument greater than the value GE - argument greater than, or equal to, the value - MASKED_EQ - masked argument is equal to the value + MASKED_EQ - (arg & datum_b) == datum_a Example: -- cgit v1.2.1 From 70c894341f0b397730c8f3aef56b95c037c7a6e6 Mon Sep 17 00:00:00 2001 From: Paul Moore Date: Fri, 4 Oct 2013 08:19:25 -0400 Subject: python: improve the argument comparison documentation Expand on the comments made by Andy Lutomirski. Signed-off-by: Paul Moore --- src/python/seccomp.pyx | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/python/seccomp.pyx b/src/python/seccomp.pyx index 0108a6a..4d58a80 100644 --- a/src/python/seccomp.pyx +++ b/src/python/seccomp.pyx @@ -37,14 +37,14 @@ Filter action values: tracing process via PTRACE_EVENT_SECCOMP and the PTRACE_GETEVENTMSG option -Argument comparison values: - - NE - argument not equal the value - LT - argument less than the value - LE - argument less than, or equal to, the value - EQ - argument equal the value - GT - argument greater than the value - GE - argument greater than, or equal to, the value +Argument comparison values (see the Arg class): + + NE - arg != datum_a + LT - arg < datum_a + LE - arg <= datum_a + EQ - arg == datum_a + GT - arg > datum_a + GE - arg >= datum_a MASKED_EQ - (arg & datum_b) == datum_a -- cgit v1.2.1 From cb528e0ed26eb6cf1f308e5f4db784b96610b562 Mon Sep 17 00:00:00 2001 From: Joe MacDonald Date: Fri, 4 Oct 2013 08:25:21 -0400 Subject: build: remove quotes in the INSTALL_BIN_MACRO macro The double-quotes around $^ in INSTALL_BIN_MACRO prevented it from being used to install more than a single binary to INSTALL_BIN_DIR at a time. Signed-off-by: Joe MacDonald Signed-off-by: Paul Moore --- macros.mk | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/macros.mk b/macros.mk index 9c62fa7..15529f6 100644 --- a/macros.mk +++ b/macros.mk @@ -181,7 +181,7 @@ INSTALL_BIN_MACRO += \ $(INSTALL) -o $(INSTALL_OWNER) -g $(INSTALL_GROUP) \ -d "$(INSTALL_BIN_DIR)"; \ $(INSTALL) -o $(INSTALL_OWNER) -g $(INSTALL_GROUP) -m 0755 \ - "$^" "$(INSTALL_BIN_DIR)"; + $^ "$(INSTALL_BIN_DIR)"; ifeq ($(V),0) INSTALL_PC_MACRO = \ -- cgit v1.2.1 From 4021195b83f6d7fd50c382928cb522feadaea842 Mon Sep 17 00:00:00 2001 From: Andy Lutomirski Date: Tue, 8 Oct 2013 15:36:13 -0400 Subject: python: Add a docstring for the SyscallFilter constructor Cython doesn't support docstrings for __cinit__. This change will (very slightly) slow down construction, but it makes ipython happer. Signed-off-by: Andy Lutomirski Signed-off-by: Paul Moore --- src/python/seccomp.pyx | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/python/seccomp.pyx b/src/python/seccomp.pyx index 4d58a80..ed7c1bb 100644 --- a/src/python/seccomp.pyx +++ b/src/python/seccomp.pyx @@ -191,6 +191,12 @@ cdef class SyscallFilter: cdef libseccomp.scmp_filter_ctx _ctx def __cinit__(self, int defaction): + self._ctx = libseccomp.seccomp_init(defaction) + if self._ctx == NULL: + raise RuntimeError("Library error") + _defaction = defaction + + def __init__(self, defaction): """ Initialize the filter state Arguments: @@ -199,10 +205,6 @@ cdef class SyscallFilter: Description: Initializes the seccomp filter state to the defaults. """ - self._ctx = libseccomp.seccomp_init(defaction) - if self._ctx == NULL: - raise RuntimeError("Library error") - _defaction = defaction def __dealloc__(self): """ Destroys the filter state and releases any resources. -- cgit v1.2.1 From 3b6b69184196189d3b53ae695c0d130b9cf70784 Mon Sep 17 00:00:00 2001 From: Paul Moore Date: Thu, 12 Sep 2013 10:23:17 -0400 Subject: build: correct some build dependencies Signed-off-by: Paul Moore --- Makefile | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Makefile b/Makefile index 4fd50c6..6fcae19 100644 --- a/Makefile +++ b/Makefile @@ -78,15 +78,15 @@ include: $(VERSION_HDR) $(CONFIGS) @$(ECHO_INFO) "building in directory $@/ ..." @$(MAKE) -C $@ -src: $(VERSION_HDR) $(CONFIGS) +src: $(VERSION_HDR) $(CONFIGS) include @$(ECHO_INFO) "building in directory $@/ ..." @$(MAKE) -C $@ -tests: src +tests: src include @$(ECHO_INFO) "building in directory $@/ ..." @$(MAKE) -C $@ -tools: src +tools: src include @$(ECHO_INFO) "building in directory $@/ ..." @$(MAKE) -C $@ -- cgit v1.2.1 From 15752e8cf4eb95e463e496de44e005a8b6b24ca8 Mon Sep 17 00:00:00 2001 From: Paul Moore Date: Tue, 3 Sep 2013 18:24:37 -0400 Subject: tests: return a useful error code from the test harness With this patch the test harness returns 0 if there were no errors or failures detected, positive values if a error or failure was detected. Signed-off-by: Paul Moore --- tests/regression | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/tests/regression b/tests/regression index 6e3d6d1..c1d7303 100755 --- a/tests/regression +++ b/tests/regression @@ -825,4 +825,8 @@ echo "============================================================" >&$logfd # cleanup and exit rm -f $tmpfile -exit 0 +rc=0 +[[ $stats_failure -gt 0 ]] && rc=$(($rc + 2)) +[[ $stats_error -gt 0 ]] && rc=$(($rc + 4)) + +exit $rc -- cgit v1.2.1 From b411c57b0e05ed569a8d6fb4ee5e53a51d696a0f Mon Sep 17 00:00:00 2001 From: Paul Moore Date: Mon, 7 Oct 2013 15:54:25 -0400 Subject: build: fixup the "clean" portions of the build process Reported-by: Kees Cook Signed-off-by: Paul Moore --- Makefile | 2 +- src/Makefile | 4 ++-- tests/Makefile | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Makefile b/Makefile index 6fcae19..71a2133 100644 --- a/Makefile +++ b/Makefile @@ -49,7 +49,7 @@ $(CONFIGS): version_info @$(ECHO_INFO) "automatically generating configuration ..." @./configure -tarball: clean +tarball: dist-clean @ver=$(VERSION_RELEASE); \ tarball=libseccomp-$$ver.tar.gz; \ $(ECHO_INFO) "creating the tarball ../$$tarball"; \ diff --git a/src/Makefile b/src/Makefile index ae50f86..7b980ab 100644 --- a/src/Makefile +++ b/src/Makefile @@ -85,8 +85,8 @@ install: $(LIB_SHARED) done clean: - $(RM) $(DEPS) $(OBJS) $(LIB_STATIC) $(LIB_SHARED) - @for dir in $(BINDINGS); do \ + $(RM) $(DEPS) $(OBJS) $(LIB_STATIC) libseccomp.so.* + @for dir in python; do \ $(MAKE) -C $$dir clean; \ done diff --git a/tests/Makefile b/tests/Makefile index adb5820..1bc8d65 100644 --- a/tests/Makefile +++ b/tests/Makefile @@ -89,4 +89,4 @@ $(TEST_PRIVATE): 00-test.c $(OBJS) ../src/libseccomp.a $(COMPILE_EXEC) clean: - $(RM) $(DEPS_TESTS) $(DEPS_OBJS) $(TESTS) $(TEST_PRIVATE) $(OBJS) + $(RM) $(DEPS_TESTS) $(DEPS_OBJS) $(TESTS) $(TEST_PRIVATE) $(OBJS) *.pyc -- cgit v1.2.1 From 58950121c48693dc086f2856a1ff30fdd0512996 Mon Sep 17 00:00:00 2001 From: Paul Moore Date: Mon, 9 Sep 2013 11:29:24 -0400 Subject: tests: correct some architecture problems with 25-sim-multilevel_chains_adv The current tests are not safe for non-native architectures. Signed-off-by: Paul Moore --- tests/25-sim-multilevel_chains_adv.tests | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/tests/25-sim-multilevel_chains_adv.tests b/tests/25-sim-multilevel_chains_adv.tests index d47a23b..33d3c65 100644 --- a/tests/25-sim-multilevel_chains_adv.tests +++ b/tests/25-sim-multilevel_chains_adv.tests @@ -8,16 +8,16 @@ test type: bpf-sim # Testname Arch Syscall Arg0 Arg1 Arg2 Arg3 Arg4 Arg5 Result -25-sim-multilevel_chains_adv +x86_64 0-9 N N N N N N KILL -25-sim-multilevel_chains_adv +x86_64 10 0x0000000b 0x00000000 N N N N ALLOW -25-sim-multilevel_chains_adv +x86_64 10 0x10000000b 0x00000000 N N N N KILL -25-sim-multilevel_chains_adv +x86_64 10 0x0000000b 0x10000000c N N N N ALLOW -25-sim-multilevel_chains_adv +x86_64 11-19 N N N N N N KILL -25-sim-multilevel_chains_adv +x86_64 20 0x00000015 0x00000000 0x00000017 N N N ALLOW -25-sim-multilevel_chains_adv +x86_64 20 0x00000015 0x00000016 0x00000017 N N N KILL -25-sim-multilevel_chains_adv +x86_64 20 0x100000015 0x00000000 0x00000017 N N N KILL -25-sim-multilevel_chains_adv +x86_64 20 0x00000015 0x00000000 0x100000017 N N N KILL -25-sim-multilevel_chains_adv +x86_64 21-30 N N N N N N KILL +25-sim-multilevel_chains_adv all 0-9 N N N N N N KILL +25-sim-multilevel_chains_adv all 10 0x0000000b 0x00000000 N N N N ALLOW +25-sim-multilevel_chains_adv x86_64 10 0x10000000b 0x00000000 N N N N KILL +25-sim-multilevel_chains_adv x86_64 10 0x0000000b 0x10000000c N N N N ALLOW +25-sim-multilevel_chains_adv all 11-19 N N N N N N KILL +25-sim-multilevel_chains_adv all 20 0x00000015 0x00000000 0x00000017 N N N ALLOW +25-sim-multilevel_chains_adv all 20 0x00000015 0x00000016 0x00000017 N N N KILL +25-sim-multilevel_chains_adv x86_64 20 0x100000015 0x00000000 0x00000017 N N N KILL +25-sim-multilevel_chains_adv x86_64 20 0x00000015 0x00000000 0x100000017 N N N KILL +25-sim-multilevel_chains_adv all 21-30 N N N N N N KILL test type: bpf-sim-fuzz -- cgit v1.2.1 From b3fede4d549f0e92a4f4cda0b4c0c12762ae58d1 Mon Sep 17 00:00:00 2001 From: Paul Moore Date: Fri, 18 Oct 2013 09:15:26 -0400 Subject: tests: make the regression test valgrind mode more useful We don't really need to run valgrind multiple times for each test case, just once should be enough. Signed-off-by: Paul Moore --- tests/01-sim-allow.tests | 5 ++ tests/02-sim-basic.tests | 5 ++ tests/03-sim-basic_chains.tests | 5 ++ tests/04-sim-multilevel_chains.tests | 5 ++ tests/05-sim-long_jumps.tests | 5 ++ tests/06-sim-actions.tests | 5 ++ tests/07-sim-db_bug_looping.tests | 5 ++ tests/08-sim-subtree_checks.tests | 6 ++ tests/09-sim-syscall_priority_pre.tests | 5 ++ tests/10-sim-syscall_priority_post.tests | 5 ++ tests/12-sim-basic_masked_ops.tests | 5 ++ tests/14-sim-reset.tests | 5 ++ tests/16-sim-arch_basic.tests | 5 ++ tests/17-sim-arch_merge.tests | 5 ++ tests/18-sim-basic_whitelist.tests | 5 ++ tests/19-sim-missing_syscalls.tests | 5 ++ tests/22-sim-basic_chains_array.tests | 5 ++ tests/23-sim-arch_all_basic.tests | 5 ++ tests/25-sim-multilevel_chains_adv.tests | 5 ++ tests/regression | 129 +++++++++++++++++++++---------- 20 files changed, 184 insertions(+), 41 deletions(-) diff --git a/tests/01-sim-allow.tests b/tests/01-sim-allow.tests index e3da13c..9630276 100644 --- a/tests/01-sim-allow.tests +++ b/tests/01-sim-allow.tests @@ -14,3 +14,8 @@ test type: bpf-sim-fuzz # Testname StressCount 01-sim-allow 50 + +test type: bpf-valgrind + +# Testname +01-sim-allow diff --git a/tests/02-sim-basic.tests b/tests/02-sim-basic.tests index 2121d37..07004a4 100644 --- a/tests/02-sim-basic.tests +++ b/tests/02-sim-basic.tests @@ -23,3 +23,8 @@ test type: bpf-sim-fuzz # Testname StressCount 02-sim-basic 50 + +test type: bpf-valgrind + +# Testname +02-sim-basic diff --git a/tests/03-sim-basic_chains.tests b/tests/03-sim-basic_chains.tests index 6692640..ef4353a 100644 --- a/tests/03-sim-basic_chains.tests +++ b/tests/03-sim-basic_chains.tests @@ -25,3 +25,8 @@ test type: bpf-sim-fuzz # Testname StressCount 03-sim-basic_chains 50 + +test type: bpf-valgrind + +# Testname +03-sim-basic_chains diff --git a/tests/04-sim-multilevel_chains.tests b/tests/04-sim-multilevel_chains.tests index 6f50562..cefbc4f 100644 --- a/tests/04-sim-multilevel_chains.tests +++ b/tests/04-sim-multilevel_chains.tests @@ -35,3 +35,8 @@ test type: bpf-sim-fuzz # Testname StressCount 04-sim-multilevel_chains 50 + +test type: bpf-valgrind + +# Testname +04-sim-multilevel_chains diff --git a/tests/05-sim-long_jumps.tests b/tests/05-sim-long_jumps.tests index bbdeaa1..03eb6d9 100644 --- a/tests/05-sim-long_jumps.tests +++ b/tests/05-sim-long_jumps.tests @@ -30,3 +30,8 @@ test type: bpf-sim-fuzz # Testname StressCount 05-sim-long_jumps 50 + +test type: bpf-valgrind + +# Testname +05-sim-long_jumps diff --git a/tests/06-sim-actions.tests b/tests/06-sim-actions.tests index 99d1071..f09f0a0 100644 --- a/tests/06-sim-actions.tests +++ b/tests/06-sim-actions.tests @@ -20,3 +20,8 @@ test type: bpf-sim-fuzz # Testname StressCount 06-sim-actions 50 + +test type: bpf-valgrind + +# Testname +06-sim-actions diff --git a/tests/07-sim-db_bug_looping.tests b/tests/07-sim-db_bug_looping.tests index f2b1b84..a7ec72b 100644 --- a/tests/07-sim-db_bug_looping.tests +++ b/tests/07-sim-db_bug_looping.tests @@ -16,3 +16,8 @@ test type: bpf-sim-fuzz # Testname StressCount 07-sim-db_bug_looping 50 + +test type: bpf-valgrind + +# Testname +07-sim-db_bug_looping diff --git a/tests/08-sim-subtree_checks.tests b/tests/08-sim-subtree_checks.tests index d4511bd..ed3ec42 100644 --- a/tests/08-sim-subtree_checks.tests +++ b/tests/08-sim-subtree_checks.tests @@ -39,3 +39,9 @@ test type: bpf-sim-fuzz # Testname StressCount 08-sim-subtree_checks 50 + + +test type: bpf-valgrind + +# Testname +08-sim-subtree_checks diff --git a/tests/09-sim-syscall_priority_pre.tests b/tests/09-sim-syscall_priority_pre.tests index 3e17bc4..7b7d53f 100644 --- a/tests/09-sim-syscall_priority_pre.tests +++ b/tests/09-sim-syscall_priority_pre.tests @@ -19,3 +19,8 @@ test type: bpf-sim-fuzz # Testname StressCount 09-sim-syscall_priority_pre 50 + +test type: bpf-valgrind + +# Testname +09-sim-syscall_priority_pre diff --git a/tests/10-sim-syscall_priority_post.tests b/tests/10-sim-syscall_priority_post.tests index 6624d2d..aa0389f 100644 --- a/tests/10-sim-syscall_priority_post.tests +++ b/tests/10-sim-syscall_priority_post.tests @@ -19,3 +19,8 @@ test type: bpf-sim-fuzz # Testname StressCount 10-sim-syscall_priority_post 50 + +test type: bpf-valgrind + +# Testname +10-sim-syscall_priority_post diff --git a/tests/12-sim-basic_masked_ops.tests b/tests/12-sim-basic_masked_ops.tests index 23eada2..20e0f6d 100644 --- a/tests/12-sim-basic_masked_ops.tests +++ b/tests/12-sim-basic_masked_ops.tests @@ -35,3 +35,8 @@ test type: bpf-sim-fuzz # Testname StressCount 12-sim-basic_masked_ops 50 + +test type: bpf-valgrind + +# Testname +12-sim-basic_masked_ops diff --git a/tests/14-sim-reset.tests b/tests/14-sim-reset.tests index 4c42e3f..da52b2d 100644 --- a/tests/14-sim-reset.tests +++ b/tests/14-sim-reset.tests @@ -22,3 +22,8 @@ test type: bpf-sim-fuzz # Testname StressCount 14-sim-reset 50 + +test type: bpf-valgrind + +# Testname +14-sim-reset diff --git a/tests/16-sim-arch_basic.tests b/tests/16-sim-arch_basic.tests index 80bd705..39917b5 100644 --- a/tests/16-sim-arch_basic.tests +++ b/tests/16-sim-arch_basic.tests @@ -25,3 +25,8 @@ test type: bpf-sim-fuzz # Testname StressCount 16-sim-arch_basic 50 + +test type: bpf-valgrind + +# Testname +16-sim-arch_basic diff --git a/tests/17-sim-arch_merge.tests b/tests/17-sim-arch_merge.tests index c32f5fe..0f27ca9 100644 --- a/tests/17-sim-arch_merge.tests +++ b/tests/17-sim-arch_merge.tests @@ -22,3 +22,8 @@ test type: bpf-sim-fuzz # Testname StressCount 17-sim-arch_merge 50 + +test type: bpf-valgrind + +# Testname +17-sim-arch_merge diff --git a/tests/18-sim-basic_whitelist.tests b/tests/18-sim-basic_whitelist.tests index 2669ec4..d88d0d2 100644 --- a/tests/18-sim-basic_whitelist.tests +++ b/tests/18-sim-basic_whitelist.tests @@ -25,3 +25,8 @@ test type: bpf-sim-fuzz # Testname StressCount 18-sim-basic_whitelist 50 + +test type: bpf-valgrind + +# Testname +18-sim-basic_whitelist diff --git a/tests/19-sim-missing_syscalls.tests b/tests/19-sim-missing_syscalls.tests index 113fc66..5a1f244 100644 --- a/tests/19-sim-missing_syscalls.tests +++ b/tests/19-sim-missing_syscalls.tests @@ -14,3 +14,8 @@ test type: bpf-sim-fuzz # Testname StressCount 19-sim-missing_syscalls 50 + +test type: bpf-valgrind + +# Testname +19-sim-missing_syscalls diff --git a/tests/22-sim-basic_chains_array.tests b/tests/22-sim-basic_chains_array.tests index 6785152..b8867b7 100644 --- a/tests/22-sim-basic_chains_array.tests +++ b/tests/22-sim-basic_chains_array.tests @@ -24,3 +24,8 @@ test type: bpf-sim-fuzz # Testname StressCount 22-sim-basic_chains_array 50 + +test type: bpf-valgrind + +# Testname +22-sim-basic_chains_array diff --git a/tests/23-sim-arch_all_basic.tests b/tests/23-sim-arch_all_basic.tests index 02b3a79..980268f 100644 --- a/tests/23-sim-arch_all_basic.tests +++ b/tests/23-sim-arch_all_basic.tests @@ -21,3 +21,8 @@ test type: bpf-sim-fuzz # Testname StressCount 23-sim-arch_all_basic 50 + +test type: bpf-valgrind + +# Testname +23-sim-arch_all_basic diff --git a/tests/25-sim-multilevel_chains_adv.tests b/tests/25-sim-multilevel_chains_adv.tests index 33d3c65..1bdfa40 100644 --- a/tests/25-sim-multilevel_chains_adv.tests +++ b/tests/25-sim-multilevel_chains_adv.tests @@ -23,3 +23,8 @@ test type: bpf-sim-fuzz # Testname StressCount 25-sim-multilevel_chains_adv 50 + +test type: bpf-valgrind + +# Testname +25-sim-multilevel_chains_adv diff --git a/tests/regression b/tests/regression index c1d7303..bb1c33d 100755 --- a/tests/regression +++ b/tests/regression @@ -30,6 +30,18 @@ GLBL_SYS_SIM="../tools/scmp_bpf_sim" #### # functions +# +# Dependency check +# +# Arguments: +# 1 Dependency to check for +# +function check_deps() { + [[ -z "$1" ]] && return + which "$1" >& /dev/null + return $? +} + # # Dependency verification # @@ -38,7 +50,7 @@ GLBL_SYS_SIM="../tools/scmp_bpf_sim" # function verify_deps() { [[ -z "$1" ]] && return - if ! which "$1" >& /dev/null; then + if ! check_deps "$1"; then echo "error: install \"$1\" and include it in your \$PATH" exit 1 fi @@ -49,8 +61,8 @@ function verify_deps() { # function usage() { cat << EOF -usage: regression [-h] [-m MODE] [-a] [-b BATCH_NAME] [-g] [-l ] - [-s SINGLE_TEST] [-t ] [-T ] [-v] +usage: regression [-h] [-v] [-m MODE] [-a] [-b BATCH_NAME] [-l ] + [-s SINGLE_TEST] [-t ] [-T ] libseccomp regression test automation script optional arguments: @@ -58,7 +70,6 @@ optional arguments: -m MODE specified the test mode [c (default), python] -a specifies all tests are to be run -b BATCH_NAME specifies batch of tests to be run - -g specifies that tests are to be run with valgrind -l [LOG] specifies log file to write test results to -s SINGLE_TEST specifies individual test number to be run -t [TEMP_DIR] specifies directory to create temporary files in @@ -97,7 +108,7 @@ function generate_test_num() { # 2 string containing line of test data # function print_data() { - if $verbose; then + if [[ -n $verbose ]]; then printf "Test %s data: %s\n" "$1" "$2" >&$logfd fi } @@ -111,7 +122,7 @@ function print_data() { # 3 string containing addition details # function print_result() { - if [[ $2 == "INFO" ]] && ! $verbose; then + if [[ $2 == "INFO" && -z $verbose ]]; then return fi if [[ $3 == "" ]]; then @@ -128,8 +139,8 @@ function print_result() { # 1 string containing generated test number # function print_valgrind() { - if $verbose; then - printf "Test %s valgrind results:\n" "$1" >&$logfd + if [[ -n $verbose ]]; then + printf "Test %s valgrind output\n" "$1" >&$logfd fi } @@ -164,26 +175,12 @@ function get_range() { function run_test_command() { local cmd - if $use_valgrind && $verbose; then - print_valgrind $1 - if [[ $logfd -eq 3 ]]; then - cmd="/usr/bin/valgrind --log-fd=$logfd ./$2 $3" - else - cmd="/usr/bin/valgrind ./$2 $3" - fi - elif $use_valgrind; then - # with -q, valgrind will only print error messages - if [[ $logfd -eq 3 ]]; then - cmd="/usr/bin/valgrind -q --log-fd=$logfd ./$2 $3" - else - cmd="/usr/bin/valgrind -q ./$2 $3" - fi - elif [[ $mode == "python" ]]; then + if [[ $mode == "python" ]]; then cmd="PYTHONPATH=$PYTHONPATH" cmd="$cmd:$(cd $(pwd)/../src/python/build/lib.*; pwd)" - cmd="$cmd /usr/bin/env python ./$2.py $3" + cmd="$cmd /usr/bin/env python $2.py $3" else - cmd="./$2 $3" + cmd="$2 $3" fi # setup the stdout/stderr redirects @@ -278,7 +275,7 @@ function run_test_bpf_sim_fuzz() { # run the test command and put the BPF filter in a temp file exec 4>$tmpfile - run_test_command "$testnumstr" "$testname" "-b" 4 "" "" + run_test_command "$testnumstr" "./$testname" "-b" 4 "" rc=$? exec 4>&- if [[ $rc -ne 0 ]]; then @@ -464,7 +461,7 @@ function run_test_bpf_sim() { # run the test command and put the BPF in a temp file exec 4>$tmpfile - run_test_command "$testnumstr" "$testname" "-b" 4 "" + run_test_command "$testnumstr" "./$testname" "-b" 4 "" rc=$? exec 4>&- if [[ $rc -ne 0 ]]; then @@ -523,8 +520,56 @@ function run_test_basic() { print_data "$1" "$2" # run the command - run_test_command "$1" "$2" "" "" "" + run_test_command "$1" "./$2" "" "" "" + rc=$? + if [[ $rc -ne 0 ]]; then + print_result $1 "FAILURE" "$2 rc=$rc" + stats_failure=$(($stats_failure+1)) + else + print_result $1 "SUCCESS" "" + stats_success=$(($stats_success+1)) + fi + stats_all=$(($stats_all+1)) +} + +# +# Run the specified "bpf-valgrind" test +# +# Tests that belong to the "bpf-valgrind" test type generate a BPF filter +# while running under valgrind to detect any memory errors. +# +# Arguments: +# 1 value of test number from batch file +# 2 string containing line of test data from batch file +# +function run_test_bpf_valgrind() { + local rc + local testcmd + + # print out the input test data to the log file + print_data "$1" "$2" + + # build the command + testcmd="$2" + testvalgrind="valgrind \ + --tool=memcheck \ + --error-exitcode=1 \ + --leak-check=full \ + --read-var-info=yes \ + --track-origins=yes" + if [[ -n $logfile ]]; then + testvalgrind+=" --log-fd=$logfd" + fi + if [[ -z $verbose ]]; then + testvalgrind+=" --quiet --log-fd=4" + fi + + # run the command + exec 4>/dev/null + print_valgrind "$1" + run_test_command "$1" "$testvalgrind --" "./$testcmd -b" 4 2 rc=$? + exec 4>&- if [[ $rc -ne 0 ]]; then print_result $1 "FAILURE" "$2 rc=$rc" stats_failure=$(($stats_failure+1)) @@ -560,7 +605,7 @@ function run_test_live() { # run the command exec 4>/dev/null - run_test_command "$1" "$line_cmd" "$line_act" "" 4 + run_test_command "$1" "./$line_cmd" "$line_act" "" 4 rc=$? exec 4>&- @@ -603,7 +648,7 @@ function run_test_live() { # function run_test() { # generate the test number string for the line of batch test data - local testnumstr=$(generate_test_num "$1" $2 0) + local testnumstr=$(generate_test_num "$1" $2 1) # ensure we only run tests which match the specified type [[ -n $type && "$4" != "$type" ]] && return @@ -615,6 +660,13 @@ function run_test() { run_test_bpf_sim "$1" $2 "$3" elif [[ "$4" == "bpf-sim-fuzz" ]]; then run_test_bpf_sim_fuzz "$1" $2 "$3" + elif [[ "$4" == "bpf-valgrind" ]]; then + # only run this test if valgrind is installed + if check_deps valgrind; then + run_test_bpf_valgrind "$testnumstr" "$3" + else + stats_skipped=$(($stats_skipped+1)) + fi elif [[ "$4" == "live" ]]; then # only run this test if explicitly requested if [[ -n $type ]]; then @@ -712,13 +764,12 @@ batch_count=0 logfile= logfd= mode_list="" -runall=false +runall= singlecount=0 tmpfile="" tmpdir="" type= -use_valgrind=false -verbose=false +verbose= stats_all=0 stats_skipped=0 stats_success=0 @@ -728,16 +779,12 @@ stats_error=0 while getopts "ab:gl:m:s:t:T:vh" opt; do case $opt in a) - runall=true + runall=1 ;; b) batch_list[batch_count]="$OPTARG" batch_count=$(($batch_count+1)) ;; - g) - verify_deps valgrind - use_valgrind=true - ;; l) logfile="$OPTARG" ;; @@ -766,7 +813,7 @@ while getopts "ab:gl:m:s:t:T:vh" opt; do type="$OPTARG" ;; v) - verbose=true + verbose=1 ;; h|*) usage @@ -782,11 +829,11 @@ fi # default to all tests if batch or single tests not requested if [[ -z $batch_list ]] && [[ -z $single_list ]]; then - runall=true + runall=1 fi # drop any requested batch and single tests if all tests were requested -if $runall; then +if [[ -n $runall ]]; then batch_list=() single_list=() fi -- cgit v1.2.1 From cad1fefb4689713b18bd29f82c8825150070ca1e Mon Sep 17 00:00:00 2001 From: Paul Moore Date: Mon, 9 Sep 2013 15:05:44 -0400 Subject: tests: add some scripts to compare test output from different test runs Signed-off-by: Paul Moore --- tests/.gitignore | 1 + tests/testdiff | 126 ++++++++++++++++++++++++++++++++++ tests/testgen | 206 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 333 insertions(+) create mode 100755 tests/testdiff create mode 100755 tests/testgen diff --git a/tests/.gitignore b/tests/.gitignore index b393021..9b5a1b2 100644 --- a/tests/.gitignore +++ b/tests/.gitignore @@ -1,4 +1,5 @@ *.bpf +*.bpfd *.pfc util.pyc 00-test.c diff --git a/tests/testdiff b/tests/testdiff new file mode 100755 index 0000000..4bc5dd5 --- /dev/null +++ b/tests/testdiff @@ -0,0 +1,126 @@ +#!/bin/bash + +# +# libseccomp test diff generator +# +# Copyright (c) 2013 Red Hat +# Author: Paul Moore +# + +# +# 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 . +# + +#### +# functions + +# +# Print out script usage details +# +function usage() { +cat << EOF +usage: regression [-h] LABEL_1 LABEL_2 + +libseccomp test diff generator script +optional arguments: + -h show this help message and exit +EOF +} + +# +# Print the test header +# +# Arguments: +# 1 string containing generated test number +# +function print_test() { + printf "Test %s comparison:\n" "$1" +} + +# +# Compare the tests +# +# Arguments: +# 1 string containing first test label +# 2 string containing second test label +# +function diff_tests() { + local batch_name + local label_a + local label_b + local file_a + local file_b + + if [[ -n $1 ]]; then + label_a=".$1" + else + label_a="" + fi + + if [[ -n $2 ]]; then + label_b=".$2" + else + label_b="" + fi + + for file in *-sim-*.tests; do + # extract the batch name from the file name + batch_name=$(basename $file .tests) + + print_test "$batch_name" + + file_a="${batch_name}${label_a}" + file_b="${batch_name}${label_b}" + + if [[ -r "$file_a.pfc" && -r "$file_b.pfc" ]]; then + diff -pu "$file_a.pfc" "$file_b.pfc" + fi + + if [[ -r "$file_a.bpf" && -r "$file_b.bpf" ]]; then + diff -pu "$file_a.bpf" "$file_b.bpf" + fi + + if [[ -r "$file_a.bpfd" && -r "$file_b.bpfd" ]]; then + diff -pu "$file_a.bpfd" "$file_b.bpfd" + fi + done + + return +} + +#### +# main + +opt_label= +opt_disasm=0 + +while getopts "h" opt; do + case $opt in + h|*) + usage + exit 1 + ;; + esac +done + +stats_all=0 +stats_failure=0 + +# display the test output and run the requested tests +echo "=============== $(date) ===============" +echo "Comparing Test Output (\"testgen $*\")" +diff_tests "$1" "$2" +echo "============================================================" + +# exit +exit 0 diff --git a/tests/testgen b/tests/testgen new file mode 100755 index 0000000..0da599d --- /dev/null +++ b/tests/testgen @@ -0,0 +1,206 @@ +#!/bin/bash + +# +# libseccomp test output generator +# +# Copyright (c) 2013 Red Hat +# Author: Paul Moore +# + +# +# 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 . +# + +#### +# functions + +# +# Dependency verification +# +# Arguments: +# 1 Dependency to check for +# +function verify_deps() { + [[ -z "$1" ]] && return + if ! which "$1" >& /dev/null; then + echo "error: install \"$1\" and include it in your \$PATH" + exit 1 + fi +} + +# +# Print out script usage details +# +function usage() { +cat << EOF +usage: regression [-h] [-d] [-l LABEL] + +libseccomp test output generator script +optional arguments: + -h show this help message and exit + -b generate BPF output + -d generate disassembled BPF output + -p generate PFC output + -v perform valgrind checks + -l [LABEL] specifies label for the test output +EOF +} + +# +# Print the test result +# +# Arguments: +# 1 string containing generated test number +# 2 string containing the test result +# +function print_result() { + printf "Test %s result: %s\n" "$1" "$2" +} + +# +# Run the tests +# +# Arguments: +# 1 string containing output label +# +function run_tests() { + local batch_name + local label + local rc + + if [[ -n $1 ]]; then + label=".$1" + else + label="" + fi + + for file in *-sim-*.tests; do + # extract the batch name from the file name + batch_name=$(basename $file .tests) + + if [[ -x "$batch_name" ]]; then + if [[ $opt_pfc -eq 1 ]]; then + ./$batch_name > ${batch_name}${label}.pfc + rc=$? + stats_all=$(($stats_all + 1)) + if [[ $rc -eq 0 ]]; then + print_result "$batch_name [pfc]" "SUCCESS" + else + stats_failure=$(($stats_failure + 1)) + print_result "$batch_name [pfc]" "FAILURE" + fi + fi + + if [[ $opt_bpf -eq 1 ]]; then + ./$batch_name -b > ${batch_name}${label}.bpf + rc=$? + stats_all=$(($stats_all + 1)) + if [[ $rc -eq 0 ]]; then + print_result "$batch_name [bpf]" "SUCCESS" + else + stats_failure=$(($stats_failure + 1)) + print_result "$batch_name [bpf]" "FAILURE" + fi + fi + + if [[ $opt_disasm -eq 1 ]]; then + ./$batch_name -b | \ + ../tools/scmp_bpf_disasm > ${batch_name}${label}.bpfd + rc=$? + stats_all=$(($stats_all + 1)) + if [[ $rc -eq 0 ]]; then + print_result "$batch_name [bpfd]" "SUCCESS" + else + stats_failure=$(($stats_failure + 1)) + print_result "$batch_name [bpfd]" "FAILURE" + fi + fi + + if [[ $opt_valgrind -eq 1 ]]; then + valgrind --tool=memcheck \ + --quiet --error-exitcode=1 \ + --leak-check=full \ + --read-var-info=yes \ + --track-origins=yes \ + -- ./$batch_name -b > /dev/null + rc=$? + stats_all=$(($stats_all + 1)) + if [[ $rc -eq 0 ]]; then + print_result "$batch_name [valgrind]" "SUCCESS" + else + stats_failure=$(($stats_failure + 1)) + print_result "$batch_name [valgrind]" "FAILURE" + fi + fi + else + stats_failure=$(($stats_failure + 1)) + print_result "$batch_name" "FAILURE" + fi + done + + return +} + +#### +# main + +opt_label= +opt_bpf=0 +opt_disasm=0 +opt_pfc=0 +opt_valgrind=0 + +while getopts "bphdl:v" opt; do + case $opt in + b) + opt_bpf=1 + ;; + d) + opt_disasm=1 + ;; + l) + opt_label="$OPTARG" + ;; + p) + opt_pfc=1 + ;; + v) + opt_valgrind=1 + ;; + h|*) + usage + exit 1 + ;; + esac +done + +# verify valgrind +[[ $opt_valgrind -eq 1 ]] && verify_deps valgrind + +stats_all=0 +stats_failure=0 + +# display the test output and run the requested tests +echo "=============== $(date) ===============" +echo "Collecting Test Output (\"testgen $*\")" +run_tests "$opt_label" +echo "Test Summary" +echo " tests run: $stats_all" +echo " tests failed: $stats_failure" +echo "============================================================" + +# cleanup and exit +rc=0 +[[ $stats_failure -gt 0 ]] && rc=$(($rc + 2)) + +exit $rc -- cgit v1.2.1 From c2355b09b281111f6197002ade193fd760c3b0a9 Mon Sep 17 00:00:00 2001 From: Paul Moore Date: Mon, 9 Sep 2013 14:57:51 -0400 Subject: build: enable "make check" to run the regression tests Signed-off-by: Paul Moore --- Makefile | 6 +++++- tests/Makefile | 5 ++++- 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/Makefile b/Makefile index 71a2133..932fb6c 100644 --- a/Makefile +++ b/Makefile @@ -41,7 +41,7 @@ CONFIGS = configure.mk configure.h version_info.mk libseccomp.pc SUBDIRS_BUILD = include src tests tools SUBDIRS_INSTALL = include src tools doc -.PHONY: tarball install ctags cstags clean dist-clean $(SUBDIRS_BUILD) +.PHONY: tarball install check ctags cstags clean dist-clean $(SUBDIRS_BUILD) all: $(SUBDIRS_BUILD) @@ -98,6 +98,10 @@ install: $(SUBDIRS_BUILD) $(MAKE) -C $$dir install; \ done +check: tools tests + @$(ECHO_INFO) "checking in directory tests/ ..." + @$(MAKE) -C tests check + ctags: @$(ECHO_INFO) "generating ctags for the project ..." @ctags -R * diff --git a/tests/Makefile b/tests/Makefile index 1bc8d65..5fdbca7 100644 --- a/tests/Makefile +++ b/tests/Makefile @@ -71,7 +71,7 @@ DEPS_TESTS = $(TESTS:%=%.d) # targets # -.PHONY: clean +.PHONY: check clean all: $(TESTS) $(OBJS) @@ -88,5 +88,8 @@ $(TESTS): $(TEST_PRIVATE): 00-test.c $(OBJS) ../src/libseccomp.a $(COMPILE_EXEC) +check: $(TESTS) + ./regression + clean: $(RM) $(DEPS_TESTS) $(DEPS_OBJS) $(TESTS) $(TEST_PRIVATE) $(OBJS) *.pyc -- cgit v1.2.1 From fee3e3f7fc1a5a081a8b7b62b2a904d73dcb0628 Mon Sep 17 00:00:00 2001 From: Paul Moore Date: Fri, 6 Sep 2013 16:39:19 -0400 Subject: db: perform sub-tree "pruning" correctly The existing sub-tree pruning was bad, so very bad. It was obviously broken on 32-bit platforms (our own tests were failing), and somewhat less obviously broken on 64-bit platforms. Reported-by: Kees Cook Signed-off-by: Paul Moore --- src/db.c | 272 +++++++++++++++++++++++++++++++++++++++++---------------------- src/db.h | 7 +- 2 files changed, 182 insertions(+), 97 deletions(-) diff --git a/src/db.c b/src/db.c index 29d94c8..ff73741 100644 --- a/src/db.c +++ b/src/db.c @@ -42,6 +42,13 @@ #define _DB_PRI_MASK_USER 0x00FF0000 #define _DB_PRI_USER(x) (((x) << 16) & _DB_PRI_MASK_USER) +/* private structure for tracking the state of the sub-tree "pruning" */ +struct db_prune_state { + bool prefix_exist; + bool prefix_new; + bool matched; +}; + static unsigned int _db_tree_free(struct db_arg_chain_tree *tree); /** @@ -91,8 +98,7 @@ static unsigned int _db_tree_free(struct db_arg_chain_tree *tree) * @param node the node to remove * * This function searches the tree looking for the node and removes it once - * found. The function also removes any other nodes that are no longer needed - * as a result of removing the given node. Returns the number of nodes freed. + * found. Returns the number of nodes freed. * */ static unsigned int _db_tree_remove(struct db_arg_chain_tree **tree, @@ -109,7 +115,7 @@ static unsigned int _db_tree_remove(struct db_arg_chain_tree **tree, c_iter = c_iter->lvl_prv; do { - if (c_iter == node) { + if (c_iter == node || db_chain_zombie(c_iter)) { /* remove from the tree */ if (c_iter == *tree) { if (c_iter->lvl_prv != NULL) @@ -181,71 +187,162 @@ static int _db_tree_act_check(struct db_arg_chain_tree *tree, uint32_t action) } /** - * Checks for a sub-tree match in an existing tree and prunes the leaves - * @param tree_head the head of the existing tree - * @param tree_start the starting point into the existing tree - * @param new_p pointer to the new tree - * @param remove_flg removal flag, only valid on return if return >= 0 + * Checks for a sub-tree match in an existing tree and prunes the tree + * @param prev the head of the existing tree or sub-tree + * @param existing the starting point into the existing tree + * @param new pointer to the new tree + * @param state pointer to the pruning state * - * This function searches the existing tree for an occurance of the new tree - * and removes as much of it as possible. Returns the number of nodes removed - * from the tree on success, and negative values on failure. + * This function searches the existing and new trees trying to prune each to + * eliminate redundancy. Returns the number of nodes removed from the tree on + * success, zero if no changes were made, and negative values if the new tree + * should be discarded. * */ -static int _db_tree_sub_prune(struct db_arg_chain_tree **tree_head, - struct db_arg_chain_tree *tree_start, - struct db_arg_chain_tree *new, - bool *remove_flg) +static int _db_tree_sub_prune(struct db_arg_chain_tree **prev, + struct db_arg_chain_tree *existing, + struct db_arg_chain_tree *new, + struct db_prune_state *state) { int rc = 0; - struct db_arg_chain_tree *c_iter = tree_start; - - *remove_flg = false; + int rc_tmp; + struct db_arg_chain_tree *ec_iter; + struct db_arg_chain_tree *ec_iter_tmp; + struct db_arg_chain_tree *c_iter; + struct db_prune_state state_new; - if (new == NULL || c_iter == NULL) + if (!state || !existing || !new) return 0; - while (c_iter->lvl_prv != NULL) - c_iter = c_iter->lvl_prv; + ec_iter = existing; + c_iter = new; do { - if (db_chain_eq(c_iter, new)) { - if (new->act_t_flg) { - rc += _db_tree_remove(tree_head, c_iter->nxt_t); - c_iter->act_t = new->act_t; - c_iter->act_t_flg = true; - } else if (new->nxt_t != NULL) - rc += _db_tree_sub_prune(tree_head, - c_iter->nxt_t, - new->nxt_t, - remove_flg); - if (new->act_f_flg) { - rc += _db_tree_remove(tree_head, c_iter->nxt_f); - c_iter->act_f = new->act_f; - c_iter->act_f_flg = true; - } else if (new->nxt_f != NULL) - rc += _db_tree_sub_prune(tree_head, - c_iter->nxt_f, - new->nxt_f, - remove_flg); - } else if (db_chain_lt(c_iter, new)) { - if (c_iter->nxt_t != NULL) - rc += _db_tree_sub_prune(tree_head, - c_iter->nxt_t, new, - remove_flg); - if (c_iter->nxt_f != NULL) - rc += _db_tree_sub_prune(tree_head, - c_iter->nxt_f, new, - remove_flg); - - } else if (db_chain_gt(c_iter, new)) - goto sub_prune_return; + if (db_chain_eq(ec_iter, c_iter)) { + /* equal */ + + if (db_chain_leaf(c_iter)) { + /* leaf */ + if (db_chain_eq_result(ec_iter, c_iter)) { + /* identical results */ + if (prev != NULL) + return _db_tree_remove(prev, + ec_iter); + else + return -1; + } + if (c_iter->act_t_flg && ec_iter->nxt_t) { + /* new is shorter (true) */ + if (prev == NULL) + return -1; + rc += _db_tree_remove(&(ec_iter->nxt_t), + ec_iter->nxt_t); + ec_iter->act_t = c_iter->act_t; + ec_iter->act_t_flg = true; + } + if (c_iter->act_f_flg && ec_iter->nxt_f) { + /* new is shorter (false) */ + if (prev == NULL) + return -1; + rc += _db_tree_remove(&(ec_iter->nxt_f), + ec_iter->nxt_f); + ec_iter->act_f = c_iter->act_f; + ec_iter->act_f_flg = true; + } - c_iter = c_iter->lvl_nxt; - } while (c_iter != NULL); + return rc; + } + + if (c_iter->nxt_t && ec_iter->act_t_flg) + /* existing is shorter (true) */ + return -1; + if (c_iter->nxt_f && ec_iter->act_f_flg) + /* existing is shorter (false) */ + return -1; + + if (c_iter->nxt_t) { + state_new = *state; + state_new.matched = true; + rc_tmp = _db_tree_sub_prune((prev ? + &ec_iter : NULL), + ec_iter->nxt_t, + c_iter->nxt_t, + &state_new); + rc += (rc_tmp > 0 ? rc_tmp : 0); + if (state->prefix_new && rc_tmp < 0) + return (rc > 0 ? rc : rc_tmp); + } + if (c_iter->nxt_f) { + state_new = *state; + state_new.matched = true; + rc_tmp = _db_tree_sub_prune((prev ? + &ec_iter : NULL), + ec_iter->nxt_f, + c_iter->nxt_f, + &state_new); + rc += (rc_tmp > 0 ? rc_tmp : 0); + if (state->prefix_new && rc_tmp < 0) + return (rc > 0 ? rc : rc_tmp); + } + } else if (db_chain_lt(ec_iter, c_iter)) { + /* less than */ + if (state->matched || state->prefix_new) + goto next; + state_new = *state; + state_new.prefix_exist = true; + + if (ec_iter->nxt_t) { + rc_tmp = _db_tree_sub_prune((prev ? + &ec_iter : NULL), + ec_iter->nxt_t, + c_iter, + &state_new); + rc += (rc_tmp > 0 ? rc_tmp : 0); + } + if (ec_iter->nxt_f) { + rc_tmp = _db_tree_sub_prune((prev ? + &ec_iter : NULL), + ec_iter->nxt_f, + c_iter, + &state_new); + rc += (rc_tmp > 0 ? rc_tmp : 0); + } + } else if (db_chain_gt(ec_iter, c_iter)) { + /* greater than */ + if (state->matched || state->prefix_exist) + goto next; + state_new = *state; + state_new.prefix_new = true; + + if (c_iter->nxt_t) { + rc_tmp = _db_tree_sub_prune(NULL, + ec_iter, + c_iter->nxt_t, + &state_new); + rc += (rc_tmp > 0 ? rc_tmp : 0); + if (rc_tmp < 0) + return (rc > 0 ? rc : rc_tmp); + } + if (c_iter->nxt_f) { + rc_tmp = _db_tree_sub_prune(NULL, + ec_iter, + c_iter->nxt_f, + &state_new); + rc += (rc_tmp > 0 ? rc_tmp : 0); + if (rc_tmp < 0) + return (rc > 0 ? rc : rc_tmp); + } + } + +next: + /* re-check current node and advance to the next node */ + if (db_chain_zombie(ec_iter)) { + ec_iter_tmp = ec_iter->lvl_nxt; + rc += _db_tree_remove(prev, ec_iter); + ec_iter = ec_iter_tmp; + } else + ec_iter = ec_iter->lvl_nxt; + } while (ec_iter); -sub_prune_return: - if (rc > 0) - *remove_flg = true; return rc; } @@ -960,7 +1057,8 @@ int db_rule_add(struct db_filter *db, uint32_t action, unsigned int syscall, int rc = -ENOMEM; struct db_sys_list *s_new, *s_iter, *s_prev = NULL; struct db_arg_chain_tree *c_iter = NULL, *c_prev = NULL; - struct db_arg_chain_tree *ec_iter, *ec_iter_b; + struct db_arg_chain_tree *ec_iter; + struct db_prune_state state; bool rm_flag = false; unsigned int new_chain_cnt = 0; unsigned int n_cnt; @@ -1037,41 +1135,26 @@ add_reset: s_iter->action = action; goto add_free_ok; } + + /* check for sub-tree matches */ + memset(&state, 0, sizeof(state)); + rc = _db_tree_sub_prune(&(s_iter->chains), ec_iter, c_iter, &state); + if (rc > 0) { + rm_flag = true; + s_iter->node_cnt -= rc; + goto add_reset; + } else if (rc < 0) + goto add_free_ok; + /* syscall exists and has at least one existing chain - start at the * top and walk the two chains */ do { - /* check for sub-tree matches in the existing tree */ - rc = _db_tree_sub_prune(&(s_iter->chains), ec_iter, c_iter, - &rm_flag); - if (rc > 0) { - s_iter->node_cnt -= rc; - goto add_reset; - } else if (rc < 0) - goto add_free; - - /* check for sub-tree matches in the new tree */ - ec_iter_b = ec_iter; - while (ec_iter_b->lvl_prv != NULL) - ec_iter_b = ec_iter_b->lvl_prv; - do { - rc = _db_tree_sub_prune(&(s_new->chains), - c_iter, ec_iter_b, &rm_flag); - ec_iter_b = ec_iter_b->lvl_nxt; - } while (rc == 0 && ec_iter_b != NULL); - if (rc > 0) { - s_new->node_cnt -= rc; - if (s_new->node_cnt > 0) - goto add_reset; - rc = 0; - goto add_free; - } else if (rc < 0) - goto add_free; - /* insert the new rule into the existing tree */ if (db_chain_eq(c_iter, ec_iter)) { /* found a matching node on this chain level */ - if (db_chain_leaf(c_iter) && db_chain_leaf(ec_iter)) { - /* both are leaf nodes */ + if (db_chain_action(c_iter) && + db_chain_action(ec_iter)) { + /* both are "action" nodes */ if (c_iter->act_t_flg && ec_iter->act_t_flg) { if (ec_iter->act_t != action) goto add_free_exist; @@ -1092,9 +1175,9 @@ add_reset: &(s_iter->chains), ec_iter); s_iter->node_cnt -= n_cnt; + goto add_free_ok; } - goto add_free_ok; - } else if (db_chain_leaf(c_iter)) { + } else if (db_chain_action(c_iter)) { /* new is shorter */ if (c_iter->act_t_flg) { rc = _db_tree_act_check(ec_iter->nxt_t, @@ -1116,8 +1199,8 @@ add_reset: ec_iter->act_f = action; } s_iter->node_cnt -= n_cnt; - goto add_free_ok; - } else if (c_iter->nxt_t != NULL) { + } + if (c_iter->nxt_t != NULL) { if (ec_iter->nxt_t != NULL) { /* jump to the next level */ c_prev = c_iter; @@ -1155,11 +1238,8 @@ add_reset: s_iter->node_cnt += (s_new->node_cnt-1); goto add_free_match; } - } else { - /* we should never be here! */ - rc = -EFAULT; - goto add_free; - } + } else + goto add_free_ok; } else { /* need to check other nodes on this level */ if (db_chain_lt(c_iter, ec_iter)) { diff --git a/src/db.h b/src/db.h index d686e03..d0d9ff1 100644 --- a/src/db.h +++ b/src/db.h @@ -80,8 +80,13 @@ struct db_arg_chain_tree { (((x)->arg > (y)->arg) || \ (((x)->arg == (y)->arg) && (((x)->op > (y)->op) || \ (((x)->mask & (y)->mask) != (y)->mask)))) -#define db_chain_leaf(x) \ +#define db_chain_action(x) \ (((x)->act_t_flg) || ((x)->act_f_flg)) +#define db_chain_zombie(x) \ + ((x)->nxt_t == NULL && !((x)->act_t_flg) && \ + (x)->nxt_f == NULL && !((x)->act_f_flg)) +#define db_chain_leaf(x) \ + ((x)->nxt_t == NULL && (x)->nxt_f == NULL) #define db_chain_eq_result(x,y) \ ((((x)->nxt_t != NULL && (y)->nxt_t != NULL) || \ ((x)->nxt_t == NULL && (y)->nxt_t == NULL)) && \ -- cgit v1.2.1 From c659c39814e65e086a66eeeafbea4b6980b78680 Mon Sep 17 00:00:00 2001 From: Paul Moore Date: Fri, 18 Oct 2013 07:57:07 -0400 Subject: db: fix a realloc() problem in db_col_merge() Another stupid mistake of mine; we weren't correctly reassigning a pointer after a successful realloc() in db_col_merge(). Signed-off-by: Paul Moore --- src/db.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/db.c b/src/db.c index ff73741..cf090d9 100644 --- a/src/db.c +++ b/src/db.c @@ -492,6 +492,7 @@ int db_col_merge(struct db_filter_col *col_dst, struct db_filter_col *col_src) (col_dst->filter_cnt + col_src->filter_cnt)); if (dbs == NULL) return -ENOMEM; + col_dst->filters = dbs; /* transfer the architecture filters */ for (iter_a = col_dst->filter_cnt, iter_b = 0; -- cgit v1.2.1 From 779801e35c41a17ba6d1e3f55d46b0b097cf130c Mon Sep 17 00:00:00 2001 From: Paul Moore Date: Thu, 17 Oct 2013 14:12:30 -0400 Subject: bpf: fix a number of valgrind issues This patch fixes a number of uninitialized memory problems caught by valgrind. These aren't the typical uninitialized memory issues, but rather an issue with our block hashing and the structure padding areas not being init/reset. This isn't something that I expect would have caused a lot of problems, but they would have been a major head-scratcher and difficult to reproduce. Signed-off-by: Paul Moore --- src/gen_bpf.c | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/src/gen_bpf.c b/src/gen_bpf.c index f491217..e11e892 100644 --- a/src/gen_bpf.c +++ b/src/gen_bpf.c @@ -892,6 +892,7 @@ static struct bpf_blk *_gen_bpf_chain(struct bpf_state *state, struct bpf_instr *i_iter; const struct db_arg_chain_tree *c_iter; unsigned int iter; + struct bpf_jump nxt_jump_tmp; if (chain == NULL) { b_head = _gen_bpf_action(state, NULL, sys->action); @@ -929,16 +930,18 @@ static struct bpf_blk *_gen_bpf_chain(struct bpf_state *state, if (i_iter->jt.type == TGT_NXT) { if (i_iter->jt.tgt.nxt != 0) goto chain_failure; - i_iter->jt = (b_next == NULL ? - *nxt_jump : - _BPF_JMP_BLK(b_next)); + if (b_next == NULL) + i_iter->jt = *nxt_jump; + else + i_iter->jt=_BPF_JMP_BLK(b_next); } if (i_iter->jf.type == TGT_NXT) { if (i_iter->jf.tgt.nxt != 0) goto chain_failure; - i_iter->jf = (b_next == NULL ? - *nxt_jump : - _BPF_JMP_BLK(b_next)); + if (b_next == NULL) + i_iter->jf = *nxt_jump; + else + i_iter->jf=_BPF_JMP_BLK(b_next); } } b_iter = b_next; @@ -946,16 +949,18 @@ static struct bpf_blk *_gen_bpf_chain(struct bpf_state *state, } /* resolve all of the blocks */ + memset(&nxt_jump_tmp, 0, sizeof(nxt_jump_tmp)); b_iter = b_tail; do { /* b_iter may change after resolving, so save the linkage */ b_prev = b_iter->lvl_prv; b_next = b_iter->lvl_nxt; + nxt_jump_tmp = _BPF_JMP_BLK(b_next); b_iter = _gen_bpf_chain_lvl_res(state, sys, b_iter, (b_next == NULL ? nxt_jump : - &_BPF_JMP_BLK(b_next))); + &nxt_jump_tmp)); if (b_iter == NULL) goto chain_failure; -- cgit v1.2.1 From 5c10b92a1525325e58ca9b32670f34836f65596d Mon Sep 17 00:00:00 2001 From: Paul Moore Date: Fri, 18 Oct 2013 15:46:47 -0400 Subject: tests: small typo fix in testdiff Signed-off-by: Paul Moore --- tests/testdiff | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/testdiff b/tests/testdiff index 4bc5dd5..a6ddbac 100755 --- a/tests/testdiff +++ b/tests/testdiff @@ -118,7 +118,7 @@ stats_failure=0 # display the test output and run the requested tests echo "=============== $(date) ===============" -echo "Comparing Test Output (\"testgen $*\")" +echo "Comparing Test Output (\"testdiff $*\")" diff_tests "$1" "$2" echo "============================================================" -- cgit v1.2.1 From 5e85302663fc6dc172b96a34fd4a440676a4d42d Mon Sep 17 00:00:00 2001 From: Paul Moore Date: Mon, 21 Oct 2013 10:50:18 -0400 Subject: tools: add a basic C style/format checking tool This is far from perfect, but it is something, and it provides an objective answer to "how do I style my code for this project?". Signed-off-by: Paul Moore --- Makefile | 6 ++- tools/check-syntax | 116 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 121 insertions(+), 1 deletion(-) create mode 100755 tools/check-syntax diff --git a/Makefile b/Makefile index 932fb6c..1f61f20 100644 --- a/Makefile +++ b/Makefile @@ -41,7 +41,8 @@ CONFIGS = configure.mk configure.h version_info.mk libseccomp.pc SUBDIRS_BUILD = include src tests tools SUBDIRS_INSTALL = include src tools doc -.PHONY: tarball install check ctags cstags clean dist-clean $(SUBDIRS_BUILD) +.PHONY: tarball install check check-syntax ctags cstags clean dist-clean \ + $(SUBDIRS_BUILD) all: $(SUBDIRS_BUILD) @@ -102,6 +103,9 @@ check: tools tests @$(ECHO_INFO) "checking in directory tests/ ..." @$(MAKE) -C tests check +check-syntax: + @./tools/check-syntax + ctags: @$(ECHO_INFO) "generating ctags for the project ..." @ctags -R * diff --git a/tools/check-syntax b/tools/check-syntax new file mode 100755 index 0000000..b5ae9cc --- /dev/null +++ b/tools/check-syntax @@ -0,0 +1,116 @@ +#!/bin/bash + +# +# libseccomp code syntax checking tool +# +# Copyright (c) 2013 Red Hat +# Author: Paul Moore +# + +# +# 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 . +# + +CHK_C_LIST="include/seccomp.h.in \ + src/*.c src/*.h \ + tests/*.c tests/*.h \ + tools/*.c tools/*.h" +CHK_C_EXCLUDE="src/hash.c" + +#### +# functions + +# +# Dependency verification +# +# Arguments: +# 1 Dependency to check for +# +function verify_deps() { + [[ -z "$1" ]] && return + if ! which "$1" >& /dev/null; then + echo "error: install \"$1\" and include it in your \$PATH" + exit 1 + fi +} + +# +# Print out script usage details +# +function usage() { +cat << EOF +usage: check-syntax [-h] + +libseccomp code syntax checking tool +optional arguments: + -h show this help message and exit +EOF +} + +# +# Check the formatting on a C source/header file +# +# Arguments: +# 1 File to check +# +function tool_c_style() { + [[ -z "$1" || ! -r "$1" ]] && return + + astyle --options=none --lineend=linux --mode=c \ + --style=linux \ + --indent=force-tab=8 \ + --indent-preprocessor \ + --indent-col1-comments \ + --min-conditional-indent=0 \ + --max-instatement-indent=80 \ + --pad-oper \ + --align-pointer=name \ + --align-reference=name \ + --max-code-length=80 \ + --break-after-logical < "$1" \ + | diff -pu --label="$1" "$1" --label="$1 [CORRECTED]" - +} + +# +# Perform all known syntax checks for the configured C sources/headers +# +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" + done +} + +#### +# main + +verify_deps astyle + +while getopts "h" opt; do + case $opt in + h|*) + usage + exit 1 + ;; + esac +done + +# display the results +echo "=============== $(date) ===============" +echo "Code Syntax Check Results (\"check-syntax $*\")" +check_c +echo "============================================================" + +# exit +exit 0 -- cgit v1.2.1 From 53dcfa3ff0eadd09adc0925e676f8ba320a1ca30 Mon Sep 17 00:00:00 2001 From: Paul Moore Date: Fri, 18 Oct 2013 16:17:59 -0400 Subject: all: assorted formatting fixes Since we have a tool to verify the source code style/formatting, let's put it to good use. Signed-off-by: Paul Moore --- include/seccomp.h.in | 2 +- src/arch-arm-syscalls.c | 3 +- src/arch-x86-syscalls.c | 3 +- src/arch-x86_64-syscalls.c | 3 +- src/db.c | 112 +++++++------ src/db.h | 8 +- src/gen_bpf.c | 61 +++---- src/gen_pfc.c | 28 ++-- tests/11-basic-basic_errors.c | 10 +- tests/13-basic-attrs.c | 2 +- tests/24-live-arg_allow.c | 2 +- tests/util.c | 2 +- tools/scmp_arch_detect.c | 2 +- tools/scmp_bpf_disasm.c | 370 +++++++++++++++++++++--------------------- tools/scmp_bpf_sim.c | 7 +- tools/scmp_sys_resolver.c | 2 +- 16 files changed, 313 insertions(+), 304 deletions(-) diff --git a/include/seccomp.h.in b/include/seccomp.h.in index 7897cbf..e150fbd 100644 --- a/include/seccomp.h.in +++ b/include/seccomp.h.in @@ -46,7 +46,7 @@ extern "C" { /** * Filter context/handle */ -typedef void * scmp_filter_ctx; +typedef void *scmp_filter_ctx; /** * Filter attributes diff --git a/src/arch-arm-syscalls.c b/src/arch-arm-syscalls.c index 8083486..66db33b 100644 --- a/src/arch-arm-syscalls.c +++ b/src/arch-arm-syscalls.c @@ -37,8 +37,7 @@ #endif /* NOTE: based on Linux 3.8.0-rc5 */ -const struct arch_syscall_def arm_syscall_table[] = \ -{ +const struct arch_syscall_def arm_syscall_table[] = { \ /* NOTE: arm_sync_file_range() and sync_file_range2() share values */ { "accept", (__NR_SYSCALL_BASE + 285) }, { "accept4", (__NR_SYSCALL_BASE + 366) }, diff --git a/src/arch-x86-syscalls.c b/src/arch-x86-syscalls.c index c44eb06..79f1b91 100644 --- a/src/arch-x86-syscalls.c +++ b/src/arch-x86-syscalls.c @@ -27,8 +27,7 @@ #include "arch-x86.h" /* NOTE: based on Linux 3.4.7 */ -static const struct arch_syscall_def x86_syscall_table[] = \ -{ +static const struct arch_syscall_def x86_syscall_table[] = { \ { "accept", __PNR_accept }, { "accept4", __PNR_accept4 }, { "access", 33 }, diff --git a/src/arch-x86_64-syscalls.c b/src/arch-x86_64-syscalls.c index 2f5253a..af095b8 100644 --- a/src/arch-x86_64-syscalls.c +++ b/src/arch-x86_64-syscalls.c @@ -27,8 +27,7 @@ #include "arch-x86_64.h" /* NOTE: based on Linux 3.4.7 */ -const struct arch_syscall_def x86_64_syscall_table[] = \ -{ +const struct arch_syscall_def x86_64_syscall_table[] = { \ { "accept", 43 }, { "accept4", 288 }, { "access", 21 }, diff --git a/src/db.c b/src/db.c index cf090d9..345a654 100644 --- a/src/db.c +++ b/src/db.c @@ -200,9 +200,9 @@ static int _db_tree_act_check(struct db_arg_chain_tree *tree, uint32_t action) * */ static int _db_tree_sub_prune(struct db_arg_chain_tree **prev, - struct db_arg_chain_tree *existing, - struct db_arg_chain_tree *new, - struct db_prune_state *state) + struct db_arg_chain_tree *existing, + struct db_arg_chain_tree *new, + struct db_prune_state *state) { int rc = 0; int rc_tmp; @@ -292,10 +292,10 @@ static int _db_tree_sub_prune(struct db_arg_chain_tree **prev, if (ec_iter->nxt_t) { rc_tmp = _db_tree_sub_prune((prev ? - &ec_iter : NULL), - ec_iter->nxt_t, - c_iter, - &state_new); + &ec_iter : NULL), + ec_iter->nxt_t, + c_iter, + &state_new); rc += (rc_tmp > 0 ? rc_tmp : 0); } if (ec_iter->nxt_f) { @@ -542,6 +542,8 @@ int db_col_arch_exist(struct db_filter_col *col, uint32_t arch_token) int db_col_attr_get(const struct db_filter_col *col, enum scmp_filter_attr attr, uint32_t *value) { + int rc = 0; + switch (attr) { case SCMP_FLTATR_ACT_DEFAULT: *value = col->attr.act_default; @@ -553,11 +555,11 @@ int db_col_attr_get(const struct db_filter_col *col, *value = col->attr.nnp_enable; break; default: - return -EEXIST; + rc = -EEXIST; break; } - return 0; + return rc; } /** @@ -573,6 +575,8 @@ int db_col_attr_get(const struct db_filter_col *col, int db_col_attr_set(struct db_filter_col *col, enum scmp_filter_attr attr, uint32_t value) { + int rc = 0; + switch (attr) { case SCMP_FLTATR_ACT_DEFAULT: /* read only */ @@ -588,11 +592,11 @@ int db_col_attr_set(struct db_filter_col *col, col->attr.nnp_enable = (value ? 1 : 0); break; default: - return -EEXIST; + rc = -EEXIST; break; } - return 0; + return rc; } /** @@ -876,30 +880,30 @@ static struct db_sys_list *_db_rule_gen_64(const struct arch_def *arch, c_iter_lo->arg_offset = arch_arg_offset_lo(arch, c_iter_lo->arg); switch (chain[iter].op) { - case SCMP_CMP_GT: - c_iter_hi->op = SCMP_CMP_GE; - c_iter_lo->op = SCMP_CMP_GT; - tf_flag = true; - break; - case SCMP_CMP_NE: - c_iter_hi->op = SCMP_CMP_EQ; - c_iter_lo->op = SCMP_CMP_EQ; - tf_flag = false; - break; - case SCMP_CMP_LT: - c_iter_hi->op = SCMP_CMP_GE; - c_iter_lo->op = SCMP_CMP_GE; - tf_flag = false; - break; - case SCMP_CMP_LE: - c_iter_hi->op = SCMP_CMP_GE; - c_iter_lo->op = SCMP_CMP_GT; - tf_flag = false; - break; - default: - c_iter_hi->op = chain[iter].op; - c_iter_lo->op = chain[iter].op; - tf_flag = true; + case SCMP_CMP_GT: + c_iter_hi->op = SCMP_CMP_GE; + c_iter_lo->op = SCMP_CMP_GT; + tf_flag = true; + break; + case SCMP_CMP_NE: + c_iter_hi->op = SCMP_CMP_EQ; + c_iter_lo->op = SCMP_CMP_EQ; + tf_flag = false; + break; + case SCMP_CMP_LT: + c_iter_hi->op = SCMP_CMP_GE; + c_iter_lo->op = SCMP_CMP_GE; + tf_flag = false; + break; + case SCMP_CMP_LE: + c_iter_hi->op = SCMP_CMP_GE; + c_iter_lo->op = SCMP_CMP_GT; + tf_flag = false; + break; + default: + c_iter_hi->op = chain[iter].op; + c_iter_lo->op = chain[iter].op; + tf_flag = true; } c_iter_hi->mask = D64_HI(chain[iter].mask); c_iter_lo->mask = D64_LO(chain[iter].mask); @@ -996,20 +1000,20 @@ static struct db_sys_list *_db_rule_gen_32(const struct arch_def *arch, /* rewrite the op to reduce the op/datum combos */ switch (c_iter->op) { - case SCMP_CMP_NE: - c_iter->op = SCMP_CMP_EQ; - tf_flag = false; - break; - case SCMP_CMP_LT: - c_iter->op = SCMP_CMP_GE; - tf_flag = false; - break; - case SCMP_CMP_LE: - c_iter->op = SCMP_CMP_GT; - tf_flag = false; - break; - default: - tf_flag = true; + case SCMP_CMP_NE: + c_iter->op = SCMP_CMP_EQ; + tf_flag = false; + break; + case SCMP_CMP_LT: + c_iter->op = SCMP_CMP_GE; + tf_flag = false; + break; + case SCMP_CMP_LE: + c_iter->op = SCMP_CMP_GT; + tf_flag = false; + break; + default: + tf_flag = true; } /* fixup the mask/datum */ @@ -1173,8 +1177,8 @@ add_reset: if (ec_iter->act_t_flg == ec_iter->act_f_flg && ec_iter->act_t == ec_iter->act_f) { n_cnt = _db_tree_remove( - &(s_iter->chains), - ec_iter); + &(s_iter->chains), + ec_iter); s_iter->node_cnt -= n_cnt; goto add_free_ok; } @@ -1217,7 +1221,8 @@ add_reset: /* add a new branch */ c_prev = c_iter; ec_iter->nxt_t = c_iter->nxt_t; - s_iter->node_cnt += (s_new->node_cnt-1); + s_iter->node_cnt += + (s_new->node_cnt - 1); goto add_free_match; } } else if (c_iter->nxt_f != NULL) { @@ -1236,7 +1241,8 @@ add_reset: /* add a new branch */ c_prev = c_iter; ec_iter->nxt_f = c_iter->nxt_f; - s_iter->node_cnt += (s_new->node_cnt-1); + s_iter->node_cnt += + (s_new->node_cnt - 1); goto add_free_match; } } else diff --git a/src/db.h b/src/db.h index d0d9ff1..c0472a5 100644 --- a/src/db.h +++ b/src/db.h @@ -70,16 +70,16 @@ struct db_arg_chain_tree { #define ARG_MASK_MAX ((uint32_t)-1) #define db_chain_lt(x,y) \ (((x)->arg < (y)->arg) || \ - (((x)->arg == (y)->arg) && (((x)->op < (y)->op) || \ - (((x)->mask & (y)->mask) == (y)->mask)))) + (((x)->arg == (y)->arg) && \ + (((x)->op < (y)->op) || (((x)->mask & (y)->mask) == (y)->mask)))) #define db_chain_eq(x,y) \ (((x)->arg == (y)->arg) && \ ((x)->op == (y)->op) && ((x)->datum == (y)->datum) && \ ((x)->mask == (y)->mask)) #define db_chain_gt(x,y) \ (((x)->arg > (y)->arg) || \ - (((x)->arg == (y)->arg) && (((x)->op > (y)->op) || \ - (((x)->mask & (y)->mask) != (y)->mask)))) + (((x)->arg == (y)->arg) && \ + (((x)->op > (y)->op) || (((x)->mask & (y)->mask) != (y)->mask)))) #define db_chain_action(x) \ (((x)->act_t_flg) || ((x)->act_f_flg)) #define db_chain_zombie(x) \ diff --git a/src/gen_bpf.c b/src/gen_bpf.c index e11e892..8c96f87 100644 --- a/src/gen_bpf.c +++ b/src/gen_bpf.c @@ -701,8 +701,8 @@ static struct bpf_blk *_gen_bpf_node(struct bpf_state *state, /* reload the accumulator */ a_state->offset = acc_offset; a_state->mask = ARG_MASK_MAX; - _BPF_INSTR(instr, BPF_LD+BPF_ABS, - _BPF_JMP_NO, _BPF_JMP_NO, _BPF_K(acc_offset)); + _BPF_INSTR(instr, BPF_LD + BPF_ABS, + _BPF_JMP_NO, _BPF_JMP_NO, _BPF_K(acc_offset)); blk = _blk_append(state, blk, &instr); if (blk == NULL) goto node_failure; @@ -710,8 +710,8 @@ static struct bpf_blk *_gen_bpf_node(struct bpf_state *state, if (acc_mask != a_state->mask) { /* apply the bitmask */ a_state->mask = acc_mask; - _BPF_INSTR(instr, BPF_ALU+BPF_AND, - _BPF_JMP_NO, _BPF_JMP_NO, _BPF_K(acc_mask)); + _BPF_INSTR(instr, BPF_ALU + BPF_AND, + _BPF_JMP_NO, _BPF_JMP_NO, _BPF_K(acc_mask)); blk = _blk_append(state, blk, &instr); if (blk == NULL) goto node_failure; @@ -721,15 +721,15 @@ static struct bpf_blk *_gen_bpf_node(struct bpf_state *state, switch (node->op) { case SCMP_CMP_MASKED_EQ: case SCMP_CMP_EQ: - _BPF_INSTR(instr, BPF_JMP+BPF_JEQ, + _BPF_INSTR(instr, BPF_JMP + BPF_JEQ, _BPF_JMP_NO, _BPF_JMP_NO, _BPF_K(node->datum)); - break; + break; case SCMP_CMP_GT: - _BPF_INSTR(instr, BPF_JMP+BPF_JGT, + _BPF_INSTR(instr, BPF_JMP + BPF_JGT, _BPF_JMP_NO, _BPF_JMP_NO, _BPF_K(node->datum)); break; case SCMP_CMP_GE: - _BPF_INSTR(instr, BPF_JMP+BPF_JGE, + _BPF_INSTR(instr, BPF_JMP + BPF_JGE, _BPF_JMP_NO, _BPF_JMP_NO, _BPF_K(node->datum)); break; case SCMP_CMP_NE: @@ -933,7 +933,8 @@ static struct bpf_blk *_gen_bpf_chain(struct bpf_state *state, if (b_next == NULL) i_iter->jt = *nxt_jump; else - i_iter->jt=_BPF_JMP_BLK(b_next); + i_iter->jt = + _BPF_JMP_BLK(b_next); } if (i_iter->jf.type == TGT_NXT) { if (i_iter->jf.tgt.nxt != 0) @@ -941,7 +942,8 @@ static struct bpf_blk *_gen_bpf_chain(struct bpf_state *state, if (b_next == NULL) i_iter->jf = *nxt_jump; else - i_iter->jf=_BPF_JMP_BLK(b_next); + i_iter->jf = + _BPF_JMP_BLK(b_next); } } b_iter = b_next; @@ -1019,8 +1021,8 @@ static struct bpf_blk *_gen_bpf_syscall(struct bpf_state *state, /* setup the accumulator state */ if (acc_reset) { - _BPF_INSTR(instr, BPF_LD+BPF_ABS, _BPF_JMP_NO, _BPF_JMP_NO, - _BPF_SYSCALL); + _BPF_INSTR(instr, BPF_LD + BPF_ABS, _BPF_JMP_NO, _BPF_JMP_NO, + _BPF_SYSCALL); blk_s = _blk_append(state, NULL, &instr); if (blk_s == NULL) return NULL; @@ -1038,7 +1040,7 @@ static struct bpf_blk *_gen_bpf_syscall(struct bpf_state *state, return NULL; /* syscall check */ - _BPF_INSTR(instr, BPF_JMP+BPF_JEQ, + _BPF_INSTR(instr, BPF_JMP + BPF_JEQ, _BPF_JMP_HSH(blk_c->hash), _BPF_JMP_HSH(nxt_hash), _BPF_K(sys->num)); blk_s = _blk_append(state, blk_s, &instr); @@ -1117,7 +1119,7 @@ static struct bpf_blk *_gen_bpf_arch(struct bpf_state *state, if (s_head != NULL) { s_iter_b = s_head; while ((s_iter_b->pri_nxt != NULL) && - (s_iter->priority <= s_iter_b->priority)) + (s_iter->priority <= s_iter_b->priority)) s_iter_b = s_iter_b->pri_nxt; if (s_iter->priority > s_iter_b->priority) { @@ -1127,8 +1129,10 @@ static struct bpf_blk *_gen_bpf_arch(struct bpf_state *state, s_head->pri_prv = s_iter; s_head = s_iter; } else { - s_iter->pri_prv->pri_nxt=s_iter; - s_iter->pri_nxt->pri_prv=s_iter; + s_iter->pri_prv->pri_nxt = + s_iter; + s_iter->pri_nxt->pri_prv = + s_iter; } } else { s_iter->pri_prv = s_tail; @@ -1160,7 +1164,8 @@ static struct bpf_blk *_gen_bpf_arch(struct bpf_state *state, b_new = _gen_bpf_syscall(state, s_iter, (b_head == NULL ? state->def_hsh : b_head->hash), - (s_iter == s_head ? acc_reset:false)); + (s_iter == s_head ? + acc_reset : false)); if (b_new == NULL) goto arch_failure; @@ -1183,25 +1188,25 @@ static struct bpf_blk *_gen_bpf_arch(struct bpf_state *state, /* additional ABI filtering */ if ((db->arch->token == SCMP_ARCH_X86_64 || db->arch->token == SCMP_ARCH_X32) && (db_secondary == NULL)) { - _BPF_INSTR(instr, BPF_LD+BPF_ABS, _BPF_JMP_NO, _BPF_JMP_NO, + _BPF_INSTR(instr, BPF_LD + BPF_ABS, _BPF_JMP_NO, _BPF_JMP_NO, _BPF_SYSCALL); b_new = _blk_append(state, NULL, &instr); if (b_new == NULL) goto arch_failure; if (db->arch->token == SCMP_ARCH_X86_64) { /* filter out x32 */ - _BPF_INSTR(instr, BPF_JMP+BPF_JGE, - _BPF_JMP_NXT(blk_cnt++), _BPF_JMP_NO, - _BPF_K(X32_SYSCALL_BIT)); + _BPF_INSTR(instr, BPF_JMP + BPF_JGE, + _BPF_JMP_NXT(blk_cnt++), _BPF_JMP_NO, + _BPF_K(X32_SYSCALL_BIT)); if (b_head != NULL) instr.jf = _BPF_JMP_HSH(b_head->hash); else instr.jf = _BPF_JMP_HSH(state->def_hsh); } else if (db->arch->token == SCMP_ARCH_X32) { /* filter out x86_64 */ - _BPF_INSTR(instr, BPF_JMP+BPF_JGE, - _BPF_JMP_NO, _BPF_JMP_NXT(blk_cnt++), - _BPF_K(X32_SYSCALL_BIT)); + _BPF_INSTR(instr, BPF_JMP + BPF_JGE, + _BPF_JMP_NO, _BPF_JMP_NXT(blk_cnt++), + _BPF_K(X32_SYSCALL_BIT)); if (b_head != NULL) instr.jt = _BPF_JMP_HSH(b_head->hash); else @@ -1222,7 +1227,7 @@ static struct bpf_blk *_gen_bpf_arch(struct bpf_state *state, } /* do the ABI/architecture check */ - _BPF_INSTR(instr, BPF_JMP+BPF_JEQ, + _BPF_INSTR(instr, BPF_JMP + BPF_JEQ, _BPF_JMP_NO, _BPF_JMP_NXT(blk_cnt++), _BPF_K(db->arch->token_bpf)); if (b_head != NULL) @@ -1411,7 +1416,7 @@ static int _gen_bpf_build_jmp(struct bpf_state *state, return -EFAULT; /* we need to insert a long jump - create one */ - _BPF_INSTR(instr, BPF_JMP+BPF_JA, + _BPF_INSTR(instr, BPF_JMP + BPF_JA, _BPF_JMP_NO, _BPF_JMP_NO, _BPF_JMP_HSH(tgt_hash)); b_new = _blk_append(state, NULL, &instr); if (b_new == NULL) @@ -1478,7 +1483,7 @@ static int _gen_bpf_build_bpf(struct bpf_state *state, state->def_hsh = b_default->hash; /* load the architecture token/number */ - _BPF_INSTR(instr, BPF_LD+BPF_ABS, _BPF_JMP_NO, _BPF_JMP_NO, + _BPF_INSTR(instr, BPF_LD + BPF_ABS, _BPF_JMP_NO, _BPF_JMP_NO, _BPF_K(offsetof(struct seccomp_data, arch))); b_head = _blk_append(state, NULL, &instr); if (b_head == NULL) @@ -1575,7 +1580,7 @@ static int _gen_bpf_build_bpf(struct bpf_state *state, b_jmp->next = b_iter->next; b_iter->next = b_jmp; if (b_jmp->next) - b_jmp->next->prev=b_jmp; + b_jmp->next->prev = b_jmp; } } if (b_jmp != NULL) { diff --git a/src/gen_pfc.c b/src/gen_pfc.c index 75c96d6..954feab 100644 --- a/src/gen_pfc.c +++ b/src/gen_pfc.c @@ -151,20 +151,20 @@ static void _gen_pfc_chain(const struct arch_def *arch, fprintf(fds, "if ("); _pfc_arg(fds, arch, c_iter); switch (c_iter->op) { - case SCMP_CMP_EQ: - fprintf(fds, " == "); - break; - case SCMP_CMP_GE: - fprintf(fds, " >= "); - break; - case SCMP_CMP_GT: - fprintf(fds, " > "); - break; - case SCMP_CMP_MASKED_EQ: - fprintf(fds, " & 0x%.8x == ", c_iter->mask); - break; - default: - fprintf(fds, " ??? "); + case SCMP_CMP_EQ: + fprintf(fds, " == "); + break; + case SCMP_CMP_GE: + fprintf(fds, " >= "); + break; + case SCMP_CMP_GT: + fprintf(fds, " > "); + break; + case SCMP_CMP_MASKED_EQ: + fprintf(fds, " & 0x%.8x == ", c_iter->mask); + break; + default: + fprintf(fds, " ??? "); } fprintf(fds, "%u)\n", c_iter->datum); diff --git a/tests/11-basic-basic_errors.c b/tests/11-basic-basic_errors.c index c328577..c695e8b 100644 --- a/tests/11-basic-basic_errors.c +++ b/tests/11-basic-basic_errors.c @@ -30,7 +30,7 @@ int main(int argc, char *argv[]) scmp_filter_ctx ctx; /* seccomp_init errors */ - ctx = seccomp_init(SCMP_ACT_ALLOW+1); + ctx = seccomp_init(SCMP_ACT_ALLOW + 1); if (ctx != NULL) return -1; @@ -41,7 +41,7 @@ int main(int argc, char *argv[]) ctx = NULL; /* seccomp_reset error */ - rc = seccomp_reset(ctx, SCMP_ACT_KILL+1); + rc = seccomp_reset(ctx, SCMP_ACT_KILL + 1); if (rc != -EINVAL) return -1; rc = seccomp_reset(ctx, SCMP_ACT_KILL); @@ -82,7 +82,7 @@ int main(int argc, char *argv[]) rc = seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(read), 0); if (rc != -EPERM) return -1; - rc = seccomp_rule_add(ctx, SCMP_ACT_KILL-1, SCMP_SYS(read), 0); + rc = seccomp_rule_add(ctx, SCMP_ACT_KILL - 1, SCMP_SYS(read), 0); if (rc != -EINVAL) return -1; rc = seccomp_rule_add(ctx, SCMP_ACT_KILL, SCMP_SYS(read), 6); @@ -141,7 +141,7 @@ int main(int argc, char *argv[]) if (ctx == NULL) return -1; else { - rc = seccomp_export_pfc(ctx, sysconf(_SC_OPEN_MAX)-1); + rc = seccomp_export_pfc(ctx, sysconf(_SC_OPEN_MAX) - 1); if (rc != EBADF) return -1; } @@ -157,7 +157,7 @@ int main(int argc, char *argv[]) if (ctx == NULL) return -1; else { - rc = seccomp_export_bpf(ctx, sysconf(_SC_OPEN_MAX)-1); + rc = seccomp_export_bpf(ctx, sysconf(_SC_OPEN_MAX) - 1); if (rc != -EBADF) return -1; } diff --git a/tests/13-basic-attrs.c b/tests/13-basic-attrs.c index 46518a5..99e8dcb 100644 --- a/tests/13-basic-attrs.c +++ b/tests/13-basic-attrs.c @@ -29,7 +29,7 @@ int main(int argc, char *argv[]) { int rc; - uint32_t val = (uint32_t)-1; + uint32_t val = (uint32_t)(-1); scmp_filter_ctx ctx; ctx = seccomp_init(SCMP_ACT_ALLOW); diff --git a/tests/24-live-arg_allow.c b/tests/24-live-arg_allow.c index fd6e289..e071dda 100644 --- a/tests/24-live-arg_allow.c +++ b/tests/24-live-arg_allow.c @@ -48,7 +48,7 @@ int main(int argc, char *argv[]) if (rc != 0) goto out; - fd = open("/dev/null", O_WRONLY|O_CREAT, S_IRUSR|S_IWUSR); + fd = open("/dev/null", O_WRONLY | O_CREAT, S_IRUSR | S_IWUSR); if (fd < 0) { rc = errno; goto out; diff --git a/tests/util.c b/tests/util.c index 02b0043..9c069d6 100644 --- a/tests/util.c +++ b/tests/util.c @@ -194,7 +194,7 @@ int util_file_write(const char *path) const char buf[] = "testing"; ssize_t buf_len = strlen(buf); - fd = open(path, O_WRONLY|O_CREAT, S_IRUSR|S_IWUSR); + fd = open(path, O_WRONLY | O_CREAT, S_IRUSR | S_IWUSR); if (fd < 0) return errno; if (write(fd, buf, buf_len) < buf_len) { diff --git a/tools/scmp_arch_detect.c b/tools/scmp_arch_detect.c index 0aca5a8..e90f92b 100644 --- a/tools/scmp_arch_detect.c +++ b/tools/scmp_arch_detect.c @@ -51,7 +51,7 @@ int main(int argc, char *argv[]) uint32_t arch; /* parse the command line */ - while ((opt = getopt(argc, argv, "ht"))> 0) { + while ((opt = getopt(argc, argv, "ht")) > 0) { switch (opt) { case 't': token = 1; diff --git a/tools/scmp_bpf_disasm.c b/tools/scmp_bpf_disasm.c index 5b63fe8..8474eb1 100644 --- a/tools/scmp_bpf_disasm.c +++ b/tools/scmp_bpf_disasm.c @@ -44,125 +44,125 @@ static void bpf_decode_op(const bpf_instr_raw *bpf) { switch (bpf->code) { - case BPF_LD+BPF_W+BPF_IMM: - case BPF_LD+BPF_W+BPF_ABS: - case BPF_LD+BPF_W+BPF_IND: - case BPF_LD+BPF_W+BPF_MEM: - case BPF_LD+BPF_W+BPF_LEN: - case BPF_LD+BPF_W+BPF_MSH: - printf(_OP_FMT, "ld"); - break; - case BPF_LD+BPF_H+BPF_IMM: - case BPF_LD+BPF_H+BPF_ABS: - case BPF_LD+BPF_H+BPF_IND: - case BPF_LD+BPF_H+BPF_MEM: - case BPF_LD+BPF_H+BPF_LEN: - case BPF_LD+BPF_H+BPF_MSH: - printf(_OP_FMT, "ldh"); - break; - case BPF_LD+BPF_B+BPF_IMM: - case BPF_LD+BPF_B+BPF_ABS: - case BPF_LD+BPF_B+BPF_IND: - case BPF_LD+BPF_B+BPF_MEM: - case BPF_LD+BPF_B+BPF_LEN: - case BPF_LD+BPF_B+BPF_MSH: - printf(_OP_FMT, "ldb"); - break; - case BPF_LDX+BPF_W+BPF_IMM: - case BPF_LDX+BPF_W+BPF_ABS: - case BPF_LDX+BPF_W+BPF_IND: - case BPF_LDX+BPF_W+BPF_MEM: - case BPF_LDX+BPF_W+BPF_LEN: - case BPF_LDX+BPF_W+BPF_MSH: - case BPF_LDX+BPF_H+BPF_IMM: - case BPF_LDX+BPF_H+BPF_ABS: - case BPF_LDX+BPF_H+BPF_IND: - case BPF_LDX+BPF_H+BPF_MEM: - case BPF_LDX+BPF_H+BPF_LEN: - case BPF_LDX+BPF_H+BPF_MSH: - case BPF_LDX+BPF_B+BPF_IMM: - case BPF_LDX+BPF_B+BPF_ABS: - case BPF_LDX+BPF_B+BPF_IND: - case BPF_LDX+BPF_B+BPF_MEM: - case BPF_LDX+BPF_B+BPF_LEN: - case BPF_LDX+BPF_B+BPF_MSH: - printf(_OP_FMT, "ldx"); - break; - case BPF_ST: - printf(_OP_FMT, "st"); - break; - case BPF_STX: - printf(_OP_FMT, "stx"); - break; - case BPF_ALU+BPF_ADD+BPF_K: - case BPF_ALU+BPF_ADD+BPF_X: - printf(_OP_FMT, "add"); - break; - case BPF_ALU+BPF_SUB+BPF_K: - case BPF_ALU+BPF_SUB+BPF_X: - printf(_OP_FMT, "sub"); - break; - case BPF_ALU+BPF_MUL+BPF_K: - case BPF_ALU+BPF_MUL+BPF_X: - printf(_OP_FMT, "mul"); - break; - case BPF_ALU+BPF_DIV+BPF_K: - case BPF_ALU+BPF_DIV+BPF_X: - printf(_OP_FMT, "div"); - break; - case BPF_ALU+BPF_OR+BPF_K: - case BPF_ALU+BPF_OR+BPF_X: - printf(_OP_FMT, "or"); - break; - case BPF_ALU+BPF_AND+BPF_K: - case BPF_ALU+BPF_AND+BPF_X: - printf(_OP_FMT, "and"); - break; - case BPF_ALU+BPF_LSH+BPF_K: - case BPF_ALU+BPF_LSH+BPF_X: - printf(_OP_FMT, "lsh"); - break; - case BPF_ALU+BPF_RSH+BPF_K: - case BPF_ALU+BPF_RSH+BPF_X: - printf(_OP_FMT, "rsh"); - break; - case BPF_ALU+BPF_NEG+BPF_K: - case BPF_ALU+BPF_NEG+BPF_X: - printf(_OP_FMT, "neg"); - break; - case BPF_JMP+BPF_JA+BPF_K: - case BPF_JMP+BPF_JA+BPF_X: - printf(_OP_FMT, "jmp"); - break; - case BPF_JMP+BPF_JEQ+BPF_K: - case BPF_JMP+BPF_JEQ+BPF_X: - printf(_OP_FMT, "jeq"); - break; - case BPF_JMP+BPF_JGT+BPF_K: - case BPF_JMP+BPF_JGT+BPF_X: - printf(_OP_FMT, "jgt"); - break; - case BPF_JMP+BPF_JGE+BPF_K: - case BPF_JMP+BPF_JGE+BPF_X: - printf(_OP_FMT, "jge"); - break; - case BPF_JMP+BPF_JSET+BPF_K: - case BPF_JMP+BPF_JSET+BPF_X: - printf(_OP_FMT, "jset"); - break; - case BPF_RET+BPF_K: - case BPF_RET+BPF_X: - case BPF_RET+BPF_A: - printf(_OP_FMT, "ret"); - break; - case BPF_MISC+BPF_TAX: - printf(_OP_FMT, "tax"); - break; - case BPF_MISC+BPF_TXA: - printf(_OP_FMT, "txa"); - break; - default: - printf(_OP_FMT, "???"); + case BPF_LD+BPF_W+BPF_IMM: + case BPF_LD+BPF_W+BPF_ABS: + case BPF_LD+BPF_W+BPF_IND: + case BPF_LD+BPF_W+BPF_MEM: + case BPF_LD+BPF_W+BPF_LEN: + case BPF_LD+BPF_W+BPF_MSH: + printf(_OP_FMT, "ld"); + break; + case BPF_LD+BPF_H+BPF_IMM: + case BPF_LD+BPF_H+BPF_ABS: + case BPF_LD+BPF_H+BPF_IND: + case BPF_LD+BPF_H+BPF_MEM: + case BPF_LD+BPF_H+BPF_LEN: + case BPF_LD+BPF_H+BPF_MSH: + printf(_OP_FMT, "ldh"); + break; + case BPF_LD+BPF_B+BPF_IMM: + case BPF_LD+BPF_B+BPF_ABS: + case BPF_LD+BPF_B+BPF_IND: + case BPF_LD+BPF_B+BPF_MEM: + case BPF_LD+BPF_B+BPF_LEN: + case BPF_LD+BPF_B+BPF_MSH: + printf(_OP_FMT, "ldb"); + break; + case BPF_LDX+BPF_W+BPF_IMM: + case BPF_LDX+BPF_W+BPF_ABS: + case BPF_LDX+BPF_W+BPF_IND: + case BPF_LDX+BPF_W+BPF_MEM: + case BPF_LDX+BPF_W+BPF_LEN: + case BPF_LDX+BPF_W+BPF_MSH: + case BPF_LDX+BPF_H+BPF_IMM: + case BPF_LDX+BPF_H+BPF_ABS: + case BPF_LDX+BPF_H+BPF_IND: + case BPF_LDX+BPF_H+BPF_MEM: + case BPF_LDX+BPF_H+BPF_LEN: + case BPF_LDX+BPF_H+BPF_MSH: + case BPF_LDX+BPF_B+BPF_IMM: + case BPF_LDX+BPF_B+BPF_ABS: + case BPF_LDX+BPF_B+BPF_IND: + case BPF_LDX+BPF_B+BPF_MEM: + case BPF_LDX+BPF_B+BPF_LEN: + case BPF_LDX+BPF_B+BPF_MSH: + printf(_OP_FMT, "ldx"); + break; + case BPF_ST: + printf(_OP_FMT, "st"); + break; + case BPF_STX: + printf(_OP_FMT, "stx"); + break; + case BPF_ALU+BPF_ADD+BPF_K: + case BPF_ALU+BPF_ADD+BPF_X: + printf(_OP_FMT, "add"); + break; + case BPF_ALU+BPF_SUB+BPF_K: + case BPF_ALU+BPF_SUB+BPF_X: + printf(_OP_FMT, "sub"); + break; + case BPF_ALU+BPF_MUL+BPF_K: + case BPF_ALU+BPF_MUL+BPF_X: + printf(_OP_FMT, "mul"); + break; + case BPF_ALU+BPF_DIV+BPF_K: + case BPF_ALU+BPF_DIV+BPF_X: + printf(_OP_FMT, "div"); + break; + case BPF_ALU+BPF_OR+BPF_K: + case BPF_ALU+BPF_OR+BPF_X: + printf(_OP_FMT, "or"); + break; + case BPF_ALU+BPF_AND+BPF_K: + case BPF_ALU+BPF_AND+BPF_X: + printf(_OP_FMT, "and"); + break; + case BPF_ALU+BPF_LSH+BPF_K: + case BPF_ALU+BPF_LSH+BPF_X: + printf(_OP_FMT, "lsh"); + break; + case BPF_ALU+BPF_RSH+BPF_K: + case BPF_ALU+BPF_RSH+BPF_X: + printf(_OP_FMT, "rsh"); + break; + case BPF_ALU+BPF_NEG+BPF_K: + case BPF_ALU+BPF_NEG+BPF_X: + printf(_OP_FMT, "neg"); + break; + case BPF_JMP+BPF_JA+BPF_K: + case BPF_JMP+BPF_JA+BPF_X: + printf(_OP_FMT, "jmp"); + break; + case BPF_JMP+BPF_JEQ+BPF_K: + case BPF_JMP+BPF_JEQ+BPF_X: + printf(_OP_FMT, "jeq"); + break; + case BPF_JMP+BPF_JGT+BPF_K: + case BPF_JMP+BPF_JGT+BPF_X: + printf(_OP_FMT, "jgt"); + break; + case BPF_JMP+BPF_JGE+BPF_K: + case BPF_JMP+BPF_JGE+BPF_X: + printf(_OP_FMT, "jge"); + break; + case BPF_JMP+BPF_JSET+BPF_K: + case BPF_JMP+BPF_JSET+BPF_X: + printf(_OP_FMT, "jset"); + break; + case BPF_RET+BPF_K: + case BPF_RET+BPF_X: + case BPF_RET+BPF_A: + printf(_OP_FMT, "ret"); + break; + case BPF_MISC+BPF_TAX: + printf(_OP_FMT, "tax"); + break; + case BPF_MISC+BPF_TXA: + printf(_OP_FMT, "txa"); + break; + default: + printf(_OP_FMT, "???"); } } @@ -178,80 +178,80 @@ static void bpf_decode_op(const bpf_instr_raw *bpf) static void bpf_decode_args(const bpf_instr_raw *bpf, unsigned int line) { switch (BPF_CLASS(bpf->code)) { - case BPF_LD: - case BPF_LDX: - switch (BPF_MODE(bpf->code)) { - case BPF_ABS: - printf("$data[%u]", bpf->k); - break; - case BPF_MEM: - printf("$temp[%u]", bpf->k); - break; - } + case BPF_LD: + case BPF_LDX: + switch (BPF_MODE(bpf->code)) { + case BPF_ABS: + printf("$data[%u]", bpf->k); break; - case BPF_ST: - case BPF_STX: + case BPF_MEM: printf("$temp[%u]", bpf->k); break; - case BPF_ALU: - if (BPF_SRC(bpf->code) == BPF_K) { - switch (BPF_OP(bpf->code)) { - case BPF_OR: - case BPF_AND: - printf("0x%.8x", bpf->k); - break; - default: - printf("%u", bpf->k); - } - } else + } + break; + case BPF_ST: + case BPF_STX: + printf("$temp[%u]", bpf->k); + break; + case BPF_ALU: + if (BPF_SRC(bpf->code) == BPF_K) { + switch (BPF_OP(bpf->code)) { + case BPF_OR: + case BPF_AND: + printf("0x%.8x", bpf->k); + break; + default: printf("%u", bpf->k); - break; - case BPF_JMP: - if (BPF_OP(bpf->code) == BPF_JA) { - printf("%.4u", (line + 1) + bpf->k); - } else { - printf("%-4u true:%.4u false:%.4u", - bpf->k, - (line + 1) + bpf->jt, - (line + 1) + bpf->jf); } - break; - case BPF_RET: - if (BPF_RVAL(bpf->code) == BPF_A) { - /* XXX - accumulator? */ - printf("$acc"); - } else if (BPF_SRC(bpf->code) == BPF_K) { - uint32_t act = bpf->k & SECCOMP_RET_ACTION; - uint32_t data = bpf->k & SECCOMP_RET_DATA; + } else + printf("%u", bpf->k); + break; + case BPF_JMP: + if (BPF_OP(bpf->code) == BPF_JA) { + printf("%.4u", (line + 1) + bpf->k); + } else { + printf("%-4u true:%.4u false:%.4u", + bpf->k, + (line + 1) + bpf->jt, + (line + 1) + bpf->jf); + } + break; + case BPF_RET: + if (BPF_RVAL(bpf->code) == BPF_A) { + /* XXX - accumulator? */ + printf("$acc"); + } else if (BPF_SRC(bpf->code) == BPF_K) { + uint32_t act = bpf->k & SECCOMP_RET_ACTION; + uint32_t data = bpf->k & SECCOMP_RET_DATA; - switch (act) { - case SECCOMP_RET_KILL: - printf("KILL"); - break; - case SECCOMP_RET_TRAP: - printf("TRAP"); - break; - case SECCOMP_RET_ERRNO: - printf("ERRNO(%u)", data); - break; - case SECCOMP_RET_TRACE: - printf("TRACE(%u)", data); - break; - case SECCOMP_RET_ALLOW: - printf("ALLOW"); - break; - default: - printf("0x%.8x", bpf->k); - } - } else if (BPF_SRC(bpf->code) == BPF_X) { - /* XXX - any idea? */ - printf("???"); + switch (act) { + case SECCOMP_RET_KILL: + printf("KILL"); + break; + case SECCOMP_RET_TRAP: + printf("TRAP"); + break; + case SECCOMP_RET_ERRNO: + printf("ERRNO(%u)", data); + break; + case SECCOMP_RET_TRACE: + printf("TRACE(%u)", data); + break; + case SECCOMP_RET_ALLOW: + printf("ALLOW"); + break; + default: + printf("0x%.8x", bpf->k); } - break; - case BPF_MISC: - break; - default: + } else if (BPF_SRC(bpf->code) == BPF_X) { + /* XXX - any idea? */ printf("???"); + } + break; + case BPF_MISC: + break; + default: + printf("???"); } } diff --git a/tools/scmp_bpf_sim.c b/tools/scmp_bpf_sim.c index 94c6648..1b46cc9 100644 --- a/tools/scmp_bpf_sim.c +++ b/tools/scmp_bpf_sim.c @@ -59,9 +59,10 @@ static unsigned int opt_verbose = 0; */ static void exit_usage(const char *program) { - fprintf(stderr, "usage: %s -f [-v]" - " -a -s [-0 ] ... [-5 ]\n", - program); + fprintf(stderr, + "usage: %s -f [-v]" + " -a -s [-0 ] ... [-5 ]\n", + program); exit(EINVAL); } diff --git a/tools/scmp_sys_resolver.c b/tools/scmp_sys_resolver.c index 7e627d4..e86b400 100644 --- a/tools/scmp_sys_resolver.c +++ b/tools/scmp_sys_resolver.c @@ -59,7 +59,7 @@ int main(int argc, char *argv[]) const char *sys_name; /* parse the command line */ - while ((opt = getopt(argc, argv, "a:ht"))> 0) { + while ((opt = getopt(argc, argv, "a:ht")) > 0) { switch (opt) { case 'a': if (strcmp(optarg, "x86") == 0) -- cgit v1.2.1 From 906ab67d32f75ea783e6f5350ae593241154c7e1 Mon Sep 17 00:00:00 2001 From: Paul Moore Date: Mon, 21 Oct 2013 10:34:19 -0400 Subject: all: apply basic formatting fixes to src/hash.c There is still a lot of style/formatting work that should probably be done to this file, but this cleans it up enough so it passes our basic style checks. Signed-off-by: Paul Moore --- src/hash.c | 1259 +++++++++++++++++++++++++++++++--------------------- tools/check-syntax | 2 +- 2 files changed, 752 insertions(+), 509 deletions(-) diff --git a/src/hash.c b/src/hash.c index 6c54e18..5b55679 100644 --- a/src/hash.c +++ b/src/hash.c @@ -112,14 +112,14 @@ rotates. ------------------------------------------------------------------------------- */ #define mix(a,b,c) \ -{ \ - a -= c; a ^= rot(c, 4); c += b; \ - b -= a; b ^= rot(a, 6); a += c; \ - c -= b; c ^= rot(b, 8); b += a; \ - a -= c; a ^= rot(c,16); c += b; \ - b -= a; b ^= rot(a,19); a += c; \ - c -= b; c ^= rot(b, 4); b += a; \ -} + { \ + a -= c; a ^= rot(c, 4); c += b; \ + b -= a; b ^= rot(a, 6); a += c; \ + c -= b; c ^= rot(b, 8); b += a; \ + a -= c; a ^= rot(c,16); c += b; \ + b -= a; b ^= rot(a,19); a += c; \ + c -= b; c ^= rot(b, 4); b += a; \ + } /* ------------------------------------------------------------------------------- @@ -147,15 +147,15 @@ and these came close: ------------------------------------------------------------------------------- */ #define final(a,b,c) \ -{ \ - c ^= b; c -= rot(b,14); \ - a ^= c; a -= rot(c,11); \ - b ^= a; b -= rot(a,25); \ - c ^= b; c -= rot(b,16); \ - a ^= c; a -= rot(c,4); \ - b ^= a; b -= rot(a,14); \ - c ^= b; c -= rot(b,24); \ -} + { \ + c ^= b; c -= rot(b,14); \ + a ^= c; a -= rot(c,11); \ + b ^= a; b -= rot(a,25); \ + c ^= b; c -= rot(b,16); \ + a ^= c; a -= rot(c,4); \ + b ^= a; b -= rot(a,14); \ + c ^= b; c -= rot(b,24); \ + } /* -------------------------------------------------------------------- @@ -171,38 +171,39 @@ and these came close: -------------------------------------------------------------------- */ uint32_t hashword( -const uint32_t *k, /* the key, an array of uint32_t values */ -size_t length, /* the length of the key, in uint32_ts */ -uint32_t initval) /* the previous hash, or an arbitrary value */ + const uint32_t *k, /* the key, an array of uint32_t values */ + size_t length, /* the length of the key, in uint32_ts */ + uint32_t initval) /* the previous hash, or an arbitrary value */ { - uint32_t a,b,c; - - /* Set up the internal state */ - a = b = c = 0xdeadbeef + (((uint32_t)length)<<2) + initval; - - /*------------------------------------------------- handle most of the key */ - while (length > 3) - { - a += k[0]; - b += k[1]; - c += k[2]; - mix(a,b,c); - length -= 3; - k += 3; - } - - /*------------------------------------------- handle the last 3 uint32_t's */ - switch(length) /* all the case statements fall through */ - { - case 3 : c+=k[2]; - case 2 : b+=k[1]; - case 1 : a+=k[0]; - final(a,b,c); - case 0: /* case 0: nothing left to add */ - break; - } - /*------------------------------------------------------ report the result */ - return c; + uint32_t a, b, c; + + /* Set up the internal state */ + a = b = c = 0xdeadbeef + (((uint32_t)length) << 2) + initval; + + /*-------------------------------------------- handle most of the key */ + while (length > 3) { + a += k[0]; + b += k[1]; + c += k[2]; + mix(a, b, c); + length -= 3; + k += 3; + } + + /*-------------------------------------- handle the last 3 uint32_t's */ + switch(length) { /* all the case statements fall through */ + case 3 : + c += k[2]; + case 2 : + b += k[1]; + case 1 : + a += k[0]; + final(a, b, c); + case 0: /* case 0: nothing left to add */ + break; + } + /*------------------------------------------------- report the result */ + return c; } /* @@ -214,40 +215,42 @@ both be initialized with seeds. If you pass in (*pb)==0, the output -------------------------------------------------------------------- */ void hashword2 ( -const uint32_t *k, /* the key, an array of uint32_t values */ -size_t length, /* the length of the key, in uint32_ts */ -uint32_t *pc, /* IN: seed OUT: primary hash value */ -uint32_t *pb) /* IN: more seed OUT: secondary hash value */ + const uint32_t *k, /* the key, an array of uint32_t values */ + size_t length, /* the length of the key, in uint32_ts */ + uint32_t *pc, /* IN: seed OUT: primary hash value */ + uint32_t *pb) /* IN: more seed OUT: secondary hash value */ { - uint32_t a,b,c; - - /* Set up the internal state */ - a = b = c = 0xdeadbeef + ((uint32_t)(length<<2)) + *pc; - c += *pb; - - /*------------------------------------------------- handle most of the key */ - while (length > 3) - { - a += k[0]; - b += k[1]; - c += k[2]; - mix(a,b,c); - length -= 3; - k += 3; - } - - /*------------------------------------------- handle the last 3 uint32_t's */ - switch(length) /* all the case statements fall through */ - { - case 3 : c+=k[2]; - case 2 : b+=k[1]; - case 1 : a+=k[0]; - final(a,b,c); - case 0: /* case 0: nothing left to add */ - break; - } - /*------------------------------------------------------ report the result */ - *pc=c; *pb=b; + uint32_t a, b, c; + + /* Set up the internal state */ + a = b = c = 0xdeadbeef + ((uint32_t)(length << 2)) + *pc; + c += *pb; + + /*-------------------------------------------- handle most of the key */ + while (length > 3) { + a += k[0]; + b += k[1]; + c += k[2]; + mix(a, b, c); + length -= 3; + k += 3; + } + + /*-------------------------------------- handle the last 3 uint32_t's */ + switch(length) { /* all the case statements fall through */ + case 3 : + c += k[2]; + case 2 : + b += k[1]; + case 1 : + a += k[0]; + final(a, b, c); + case 0: /* case 0: nothing left to add */ + break; + } + /*------------------------------------------------- report the result */ + *pc = c; + *pb = b; } /* @@ -278,170 +281,251 @@ acceptable. Do NOT use for cryptographic purposes. */ uint32_t hashlittle( const void *key, size_t length, uint32_t initval) { - uint32_t a,b,c; /* internal state */ - union { const void *ptr; size_t i; } u; /* needed for Mac Powerbook G4 */ - - /* Set up the internal state */ - a = b = c = 0xdeadbeef + ((uint32_t)length) + initval; - - u.ptr = key; - if (HASH_LITTLE_ENDIAN && ((u.i & 0x3) == 0)) { - const uint32_t *k = (const uint32_t *)key; /* read 32-bit chunks */ - - /*------ all but last block: aligned reads and affect 32 bits of (a,b,c) */ - while (length > 12) - { - a += k[0]; - b += k[1]; - c += k[2]; - mix(a,b,c); - length -= 12; - k += 3; - } - - /*----------------------------- handle the last (probably partial) block */ - /* - * "k[2]&0xffffff" actually reads beyond the end of the string, but - * then masks off the part it's not allowed to read. Because the - * string is aligned, the masked-off tail is in the same word as the - * rest of the string. Every machine with memory protection I've seen - * does it on word boundaries, so is OK with this. But VALGRIND will - * still catch it and complain. The masking trick does make the hash - * noticably faster for short strings (like English words). - */ + uint32_t a, b, c; /* internal state */ + union { + const void *ptr; + size_t i; + } u; /* needed for Mac Powerbook G4 */ + + /* Set up the internal state */ + a = b = c = 0xdeadbeef + ((uint32_t)length) + initval; + + u.ptr = key; + if (HASH_LITTLE_ENDIAN && ((u.i & 0x3) == 0)) { + const uint32_t *k = (const uint32_t *)key; /* read 32b chunks */ + + /* all but last block: aligned reads and affect 32-bits + * of (a,b,c) */ + while (length > 12) { + a += k[0]; + b += k[1]; + c += k[2]; + mix(a, b, c); + length -= 12; + k += 3; + } + + /*------------------ handle the last (probably partial) block */ + /* + * "k[2]&0xffffff" actually reads beyond the end of the string, + * but then masks off the part it's not allowed to read. + * Because the string is aligned, the masked-off tail is in the + * same word as the rest of the string. Every machine with + * memory protection I've seen does it on word boundaries, so + * is OK with this. But VALGRIND will still catch it and + * complain. The masking trick does make the hash noticably + * faster for short strings (like English words). + */ #ifndef VALGRIND - switch(length) - { - case 12: c+=k[2]; b+=k[1]; a+=k[0]; break; - case 11: c+=k[2]&0xffffff; b+=k[1]; a+=k[0]; break; - case 10: c+=k[2]&0xffff; b+=k[1]; a+=k[0]; break; - case 9 : c+=k[2]&0xff; b+=k[1]; a+=k[0]; break; - case 8 : b+=k[1]; a+=k[0]; break; - case 7 : b+=k[1]&0xffffff; a+=k[0]; break; - case 6 : b+=k[1]&0xffff; a+=k[0]; break; - case 5 : b+=k[1]&0xff; a+=k[0]; break; - case 4 : a+=k[0]; break; - case 3 : a+=k[0]&0xffffff; break; - case 2 : a+=k[0]&0xffff; break; - case 1 : a+=k[0]&0xff; break; - case 0 : return c; /* zero length strings require no mixing */ - } + switch(length) { + case 12: + c += k[2]; + b += k[1]; + a += k[0]; + break; + case 11: + c += k[2] & 0xffffff; + b += k[1]; + a += k[0]; + break; + case 10: + c += k[2] & 0xffff; + b += k[1]; + a += k[0]; + break; + case 9 : + c += k[2] & 0xff; + b += k[1]; + a += k[0]; + break; + case 8 : + b += k[1]; + a += k[0]; + break; + case 7 : + b += k[1] & 0xffffff; + a += k[0]; + break; + case 6 : + b += k[1] & 0xffff; + a += k[0]; + break; + case 5 : + b += k[1] & 0xff; + a += k[0]; + break; + case 4 : + a += k[0]; + break; + case 3 : + a += k[0] & 0xffffff; + break; + case 2 : + a += k[0] & 0xffff; + break; + case 1 : + a += k[0] & 0xff; + break; + case 0 : + return c; /* zero length strings require no mixing */ + } #else /* make valgrind happy */ - k8 = (const uint8_t *)k; - switch(length) - { - case 12: c+=k[2]; b+=k[1]; a+=k[0]; break; - case 11: c+=((uint32_t)k8[10])<<16; /* fall through */ - case 10: c+=((uint32_t)k8[9])<<8; /* fall through */ - case 9 : c+=k8[8]; /* fall through */ - case 8 : b+=k[1]; a+=k[0]; break; - case 7 : b+=((uint32_t)k8[6])<<16; /* fall through */ - case 6 : b+=((uint32_t)k8[5])<<8; /* fall through */ - case 5 : b+=k8[4]; /* fall through */ - case 4 : a+=k[0]; break; - case 3 : a+=((uint32_t)k8[2])<<16; /* fall through */ - case 2 : a+=((uint32_t)k8[1])<<8; /* fall through */ - case 1 : a+=k8[0]; break; - case 0 : return c; - } + k8 = (const uint8_t *)k; + switch(length) { + case 12: + c += k[2]; + b += k[1]; + a += k[0]; + break; + case 11: + c += ((uint32_t)k8[10]) << 16; /* fall through */ + case 10: + c += ((uint32_t)k8[9]) << 8; /* fall through */ + case 9 : + c += k8[8]; /* fall through */ + case 8 : + b += k[1]; + a += k[0]; + break; + case 7 : + b += ((uint32_t)k8[6]) << 16; /* fall through */ + case 6 : + b += ((uint32_t)k8[5]) << 8; /* fall through */ + case 5 : + b += k8[4]; /* fall through */ + case 4 : + a += k[0]; + break; + case 3 : + a += ((uint32_t)k8[2]) << 16; /* fall through */ + case 2 : + a += ((uint32_t)k8[1]) << 8; /* fall through */ + case 1 : + a += k8[0]; + break; + case 0 : + return c; + } #endif /* !valgrind */ - } else if (HASH_LITTLE_ENDIAN && ((u.i & 0x1) == 0)) { - const uint16_t *k = (const uint16_t *)key; /* read 16-bit chunks */ - const uint8_t *k8; - - /*--------------- all but last block: aligned reads and different mixing */ - while (length > 12) - { - a += k[0] + (((uint32_t)k[1])<<16); - b += k[2] + (((uint32_t)k[3])<<16); - c += k[4] + (((uint32_t)k[5])<<16); - mix(a,b,c); - length -= 12; - k += 6; - } - - /*----------------------------- handle the last (probably partial) block */ - k8 = (const uint8_t *)k; - switch(length) - { - case 12: c+=k[4]+(((uint32_t)k[5])<<16); - b+=k[2]+(((uint32_t)k[3])<<16); - a+=k[0]+(((uint32_t)k[1])<<16); - break; - case 11: c+=((uint32_t)k8[10])<<16; /* fall through */ - case 10: c+=k[4]; - b+=k[2]+(((uint32_t)k[3])<<16); - a+=k[0]+(((uint32_t)k[1])<<16); - break; - case 9 : c+=k8[8]; /* fall through */ - case 8 : b+=k[2]+(((uint32_t)k[3])<<16); - a+=k[0]+(((uint32_t)k[1])<<16); - break; - case 7 : b+=((uint32_t)k8[6])<<16; /* fall through */ - case 6 : b+=k[2]; - a+=k[0]+(((uint32_t)k[1])<<16); - break; - case 5 : b+=k8[4]; /* fall through */ - case 4 : a+=k[0]+(((uint32_t)k[1])<<16); - break; - case 3 : a+=((uint32_t)k8[2])<<16; /* fall through */ - case 2 : a+=k[0]; - break; - case 1 : a+=k8[0]; - break; - case 0 : return c; /* zero length requires no mixing */ - } - - } else { /* need to read the key one byte at a time */ - const uint8_t *k = (const uint8_t *)key; - - /*--------------- all but the last block: affect some 32 bits of (a,b,c) */ - while (length > 12) - { - a += k[0]; - a += ((uint32_t)k[1])<<8; - a += ((uint32_t)k[2])<<16; - a += ((uint32_t)k[3])<<24; - b += k[4]; - b += ((uint32_t)k[5])<<8; - b += ((uint32_t)k[6])<<16; - b += ((uint32_t)k[7])<<24; - c += k[8]; - c += ((uint32_t)k[9])<<8; - c += ((uint32_t)k[10])<<16; - c += ((uint32_t)k[11])<<24; - mix(a,b,c); - length -= 12; - k += 12; - } - - /*-------------------------------- last block: affect all 32 bits of (c) */ - switch(length) /* all the case statements fall through */ - { - case 12: c+=((uint32_t)k[11])<<24; - case 11: c+=((uint32_t)k[10])<<16; - case 10: c+=((uint32_t)k[9])<<8; - case 9 : c+=k[8]; - case 8 : b+=((uint32_t)k[7])<<24; - case 7 : b+=((uint32_t)k[6])<<16; - case 6 : b+=((uint32_t)k[5])<<8; - case 5 : b+=k[4]; - case 4 : a+=((uint32_t)k[3])<<24; - case 3 : a+=((uint32_t)k[2])<<16; - case 2 : a+=((uint32_t)k[1])<<8; - case 1 : a+=k[0]; - break; - case 0 : return c; - } - } - - final(a,b,c); - return c; + } else if (HASH_LITTLE_ENDIAN && ((u.i & 0x1) == 0)) { + const uint16_t *k = (const uint16_t *)key; /* read 16b chunks */ + const uint8_t *k8; + + /*---- all but last block: aligned reads and different mixing */ + while (length > 12) { + a += k[0] + (((uint32_t)k[1]) << 16); + b += k[2] + (((uint32_t)k[3]) << 16); + c += k[4] + (((uint32_t)k[5]) << 16); + mix(a, b, c); + length -= 12; + k += 6; + } + + /*------------------ handle the last (probably partial) block */ + k8 = (const uint8_t *)k; + switch(length) { + case 12: + c += k[4] + (((uint32_t)k[5]) << 16); + b += k[2] + (((uint32_t)k[3]) << 16); + a += k[0] + (((uint32_t)k[1]) << 16); + break; + case 11: + c += ((uint32_t)k8[10]) << 16; /* fall through */ + case 10: + c += k[4]; + b += k[2] + (((uint32_t)k[3]) << 16); + a += k[0] + (((uint32_t)k[1]) << 16); + break; + case 9 : + c += k8[8]; /* fall through */ + case 8 : + b += k[2] + (((uint32_t)k[3]) << 16); + a += k[0] + (((uint32_t)k[1]) << 16); + break; + case 7 : + b += ((uint32_t)k8[6]) << 16; /* fall through */ + case 6 : + b += k[2]; + a += k[0] + (((uint32_t)k[1]) << 16); + break; + case 5 : + b += k8[4]; /* fall through */ + case 4 : + a += k[0] + (((uint32_t)k[1]) << 16); + break; + case 3 : + a += ((uint32_t)k8[2]) << 16; /* fall through */ + case 2 : + a += k[0]; + break; + case 1 : + a += k8[0]; + break; + case 0 : + return c; /* zero length requires no mixing */ + } + + } else { /* need to read the key one byte at a time */ + const uint8_t *k = (const uint8_t *)key; + + /*---- all but the last block: affect some 32 bits of (a,b,c) */ + while (length > 12) { + a += k[0]; + a += ((uint32_t)k[1]) << 8; + a += ((uint32_t)k[2]) << 16; + a += ((uint32_t)k[3]) << 24; + b += k[4]; + b += ((uint32_t)k[5]) << 8; + b += ((uint32_t)k[6]) << 16; + b += ((uint32_t)k[7]) << 24; + c += k[8]; + c += ((uint32_t)k[9]) << 8; + c += ((uint32_t)k[10]) << 16; + c += ((uint32_t)k[11]) << 24; + mix(a, b, c); + length -= 12; + k += 12; + } + + /*--------------------- last block: affect all 32 bits of (c) */ + switch(length) { /* all the case statements fall through */ + case 12: + c += ((uint32_t)k[11]) << 24; + case 11: + c += ((uint32_t)k[10]) << 16; + case 10: + c += ((uint32_t)k[9]) << 8; + case 9 : + c += k[8]; + case 8 : + b += ((uint32_t)k[7]) << 24; + case 7 : + b += ((uint32_t)k[6]) << 16; + case 6 : + b += ((uint32_t)k[5]) << 8; + case 5 : + b += k[4]; + case 4 : + a += ((uint32_t)k[3]) << 24; + case 3 : + a += ((uint32_t)k[2]) << 16; + case 2 : + a += ((uint32_t)k[1]) << 8; + case 1 : + a += k[0]; + break; + case 0 : + return c; + } + } + + final(a, b, c); + return c; } /* @@ -455,176 +539,266 @@ uint32_t hashlittle( const void *key, size_t length, uint32_t initval) * a 64-bit value do something like "*pc + (((uint64_t)*pb)<<32)". */ void hashlittle2( - const void *key, /* the key to hash */ - size_t length, /* length of the key */ - uint32_t *pc, /* IN: primary initval, OUT: primary hash */ - uint32_t *pb) /* IN: secondary initval, OUT: secondary hash */ + const void *key, /* the key to hash */ + size_t length, /* length of the key */ + uint32_t *pc, /* IN: primary initval, OUT: primary hash */ + uint32_t *pb) /* IN: secondary initval, OUT: secondary hash */ { - uint32_t a,b,c; /* internal state */ - union { const void *ptr; size_t i; } u; /* needed for Mac Powerbook G4 */ - - /* Set up the internal state */ - a = b = c = 0xdeadbeef + ((uint32_t)length) + *pc; - c += *pb; - - u.ptr = key; - if (HASH_LITTLE_ENDIAN && ((u.i & 0x3) == 0)) { - const uint32_t *k = (const uint32_t *)key; /* read 32-bit chunks */ - - /*------ all but last block: aligned reads and affect 32 bits of (a,b,c) */ - while (length > 12) - { - a += k[0]; - b += k[1]; - c += k[2]; - mix(a,b,c); - length -= 12; - k += 3; - } - - /*----------------------------- handle the last (probably partial) block */ - /* - * "k[2]&0xffffff" actually reads beyond the end of the string, but - * then masks off the part it's not allowed to read. Because the - * string is aligned, the masked-off tail is in the same word as the - * rest of the string. Every machine with memory protection I've seen - * does it on word boundaries, so is OK with this. But VALGRIND will - * still catch it and complain. The masking trick does make the hash - * noticably faster for short strings (like English words). - */ + uint32_t a, b, c; /* internal state */ + union { + const void *ptr; + size_t i; + } u; /* needed for Mac Powerbook G4 */ + + /* Set up the internal state */ + a = b = c = 0xdeadbeef + ((uint32_t)length) + *pc; + c += *pb; + + u.ptr = key; + if (HASH_LITTLE_ENDIAN && ((u.i & 0x3) == 0)) { + const uint32_t *k = (const uint32_t *)key; /* read 32b chunks */ + + /* all but last block: aligned reads and affect 32 bits + * of (a,b,c) */ + while (length > 12) { + a += k[0]; + b += k[1]; + c += k[2]; + mix(a, b, c); + length -= 12; + k += 3; + } + + /*------------------ handle the last (probably partial) block */ + /* + * "k[2]&0xffffff" actually reads beyond the end of the string, + * but then masks off the part it's not allowed to read. + * Because the string is aligned, the masked-off tail is in the + * same word as the rest of the string. Every machine with + * memory protection I've seen does it on word boundaries, so + * is OK with this. But VALGRIND will still catch it and + * complain. The masking trick does make the hash noticably + * faster for short strings (like English words). + */ #ifndef VALGRIND - switch(length) - { - case 12: c+=k[2]; b+=k[1]; a+=k[0]; break; - case 11: c+=k[2]&0xffffff; b+=k[1]; a+=k[0]; break; - case 10: c+=k[2]&0xffff; b+=k[1]; a+=k[0]; break; - case 9 : c+=k[2]&0xff; b+=k[1]; a+=k[0]; break; - case 8 : b+=k[1]; a+=k[0]; break; - case 7 : b+=k[1]&0xffffff; a+=k[0]; break; - case 6 : b+=k[1]&0xffff; a+=k[0]; break; - case 5 : b+=k[1]&0xff; a+=k[0]; break; - case 4 : a+=k[0]; break; - case 3 : a+=k[0]&0xffffff; break; - case 2 : a+=k[0]&0xffff; break; - case 1 : a+=k[0]&0xff; break; - case 0 : *pc=c; *pb=b; return; /* zero length strings require no mixing */ - } + switch(length) { + case 12: + c += k[2]; + b += k[1]; + a += k[0]; + break; + case 11: + c += k[2] & 0xffffff; + b += k[1]; + a += k[0]; + break; + case 10: + c += k[2] & 0xffff; + b += k[1]; + a += k[0]; + break; + case 9 : + c += k[2] & 0xff; + b += k[1]; + a += k[0]; + break; + case 8 : + b += k[1]; + a += k[0]; + break; + case 7 : + b += k[1] & 0xffffff; + a += k[0]; + break; + case 6 : + b += k[1] & 0xffff; + a += k[0]; + break; + case 5 : + b += k[1] & 0xff; + a += k[0]; + break; + case 4 : + a += k[0]; + break; + case 3 : + a += k[0] & 0xffffff; + break; + case 2 : + a += k[0] & 0xffff; + break; + case 1 : + a += k[0] & 0xff; + break; + case 0 : + *pc = c; + *pb = b; + return; /* zero length strings require no mixing */ + } #else /* make valgrind happy */ - k8 = (const uint8_t *)k; - switch(length) - { - case 12: c+=k[2]; b+=k[1]; a+=k[0]; break; - case 11: c+=((uint32_t)k8[10])<<16; /* fall through */ - case 10: c+=((uint32_t)k8[9])<<8; /* fall through */ - case 9 : c+=k8[8]; /* fall through */ - case 8 : b+=k[1]; a+=k[0]; break; - case 7 : b+=((uint32_t)k8[6])<<16; /* fall through */ - case 6 : b+=((uint32_t)k8[5])<<8; /* fall through */ - case 5 : b+=k8[4]; /* fall through */ - case 4 : a+=k[0]; break; - case 3 : a+=((uint32_t)k8[2])<<16; /* fall through */ - case 2 : a+=((uint32_t)k8[1])<<8; /* fall through */ - case 1 : a+=k8[0]; break; - case 0 : *pc=c; *pb=b; return; /* zero length strings require no mixing */ - } + k8 = (const uint8_t *)k; + switch(length) { + case 12: + c += k[2]; + b += k[1]; + a += k[0]; + break; + case 11: + c += ((uint32_t)k8[10]) << 16; /* fall through */ + case 10: + c += ((uint32_t)k8[9]) << 8; /* fall through */ + case 9 : + c += k8[8]; /* fall through */ + case 8 : + b += k[1]; + a += k[0]; + break; + case 7 : + b += ((uint32_t)k8[6]) << 16; /* fall through */ + case 6 : + b += ((uint32_t)k8[5]) << 8; /* fall through */ + case 5 : + b += k8[4]; /* fall through */ + case 4 : + a += k[0]; + break; + case 3 : + a += ((uint32_t)k8[2]) << 16; /* fall through */ + case 2 : + a += ((uint32_t)k8[1]) << 8; /* fall through */ + case 1 : + a += k8[0]; + break; + case 0 : + *pc = c; + *pb = b; + return; /* zero length strings require no mixing */ + } #endif /* !valgrind */ - } else if (HASH_LITTLE_ENDIAN && ((u.i & 0x1) == 0)) { - const uint16_t *k = (const uint16_t *)key; /* read 16-bit chunks */ - const uint8_t *k8; - - /*--------------- all but last block: aligned reads and different mixing */ - while (length > 12) - { - a += k[0] + (((uint32_t)k[1])<<16); - b += k[2] + (((uint32_t)k[3])<<16); - c += k[4] + (((uint32_t)k[5])<<16); - mix(a,b,c); - length -= 12; - k += 6; - } - - /*----------------------------- handle the last (probably partial) block */ - k8 = (const uint8_t *)k; - switch(length) - { - case 12: c+=k[4]+(((uint32_t)k[5])<<16); - b+=k[2]+(((uint32_t)k[3])<<16); - a+=k[0]+(((uint32_t)k[1])<<16); - break; - case 11: c+=((uint32_t)k8[10])<<16; /* fall through */ - case 10: c+=k[4]; - b+=k[2]+(((uint32_t)k[3])<<16); - a+=k[0]+(((uint32_t)k[1])<<16); - break; - case 9 : c+=k8[8]; /* fall through */ - case 8 : b+=k[2]+(((uint32_t)k[3])<<16); - a+=k[0]+(((uint32_t)k[1])<<16); - break; - case 7 : b+=((uint32_t)k8[6])<<16; /* fall through */ - case 6 : b+=k[2]; - a+=k[0]+(((uint32_t)k[1])<<16); - break; - case 5 : b+=k8[4]; /* fall through */ - case 4 : a+=k[0]+(((uint32_t)k[1])<<16); - break; - case 3 : a+=((uint32_t)k8[2])<<16; /* fall through */ - case 2 : a+=k[0]; - break; - case 1 : a+=k8[0]; - break; - case 0 : *pc=c; *pb=b; return; /* zero length strings require no mixing */ - } - - } else { /* need to read the key one byte at a time */ - const uint8_t *k = (const uint8_t *)key; - - /*--------------- all but the last block: affect some 32 bits of (a,b,c) */ - while (length > 12) - { - a += k[0]; - a += ((uint32_t)k[1])<<8; - a += ((uint32_t)k[2])<<16; - a += ((uint32_t)k[3])<<24; - b += k[4]; - b += ((uint32_t)k[5])<<8; - b += ((uint32_t)k[6])<<16; - b += ((uint32_t)k[7])<<24; - c += k[8]; - c += ((uint32_t)k[9])<<8; - c += ((uint32_t)k[10])<<16; - c += ((uint32_t)k[11])<<24; - mix(a,b,c); - length -= 12; - k += 12; - } - - /*-------------------------------- last block: affect all 32 bits of (c) */ - switch(length) /* all the case statements fall through */ - { - case 12: c+=((uint32_t)k[11])<<24; - case 11: c+=((uint32_t)k[10])<<16; - case 10: c+=((uint32_t)k[9])<<8; - case 9 : c+=k[8]; - case 8 : b+=((uint32_t)k[7])<<24; - case 7 : b+=((uint32_t)k[6])<<16; - case 6 : b+=((uint32_t)k[5])<<8; - case 5 : b+=k[4]; - case 4 : a+=((uint32_t)k[3])<<24; - case 3 : a+=((uint32_t)k[2])<<16; - case 2 : a+=((uint32_t)k[1])<<8; - case 1 : a+=k[0]; - break; - case 0 : *pc=c; *pb=b; return; /* zero length strings require no mixing */ - } - } - - final(a,b,c); - *pc=c; *pb=b; + } else if (HASH_LITTLE_ENDIAN && ((u.i & 0x1) == 0)) { + const uint16_t *k = (const uint16_t *)key; /* read 16b chunks */ + const uint8_t *k8; + + /*---- all but last block: aligned reads and different mixing */ + while (length > 12) { + a += k[0] + (((uint32_t)k[1]) << 16); + b += k[2] + (((uint32_t)k[3]) << 16); + c += k[4] + (((uint32_t)k[5]) << 16); + mix(a, b, c); + length -= 12; + k += 6; + } + + /*------------------ handle the last (probably partial) block */ + k8 = (const uint8_t *)k; + switch(length) { + case 12: + c += k[4] + (((uint32_t)k[5]) << 16); + b += k[2] + (((uint32_t)k[3]) << 16); + a += k[0] + (((uint32_t)k[1]) << 16); + break; + case 11: + c += ((uint32_t)k8[10]) << 16; /* fall through */ + case 10: + c += k[4]; + b += k[2] + (((uint32_t)k[3]) << 16); + a += k[0] + (((uint32_t)k[1]) << 16); + break; + case 9 : + c += k8[8]; /* fall through */ + case 8 : + b += k[2] + (((uint32_t)k[3]) << 16); + a += k[0] + (((uint32_t)k[1]) << 16); + break; + case 7 : + b += ((uint32_t)k8[6]) << 16; /* fall through */ + case 6 : + b += k[2]; + a += k[0] + (((uint32_t)k[1]) << 16); + break; + case 5 : + b += k8[4]; /* fall through */ + case 4 : + a += k[0] + (((uint32_t)k[1]) << 16); + break; + case 3 : + a += ((uint32_t)k8[2]) << 16; /* fall through */ + case 2 : + a += k[0]; + break; + case 1 : + a += k8[0]; + break; + case 0 : + *pc = c; + *pb = b; + return; /* zero length strings require no mixing */ + } + + } else { /* need to read the key one byte at a time */ + const uint8_t *k = (const uint8_t *)key; + + /*---- all but the last block: affect some 32 bits of (a,b,c) */ + while (length > 12) { + a += k[0]; + a += ((uint32_t)k[1]) << 8; + a += ((uint32_t)k[2]) << 16; + a += ((uint32_t)k[3]) << 24; + b += k[4]; + b += ((uint32_t)k[5]) << 8; + b += ((uint32_t)k[6]) << 16; + b += ((uint32_t)k[7]) << 24; + c += k[8]; + c += ((uint32_t)k[9]) << 8; + c += ((uint32_t)k[10]) << 16; + c += ((uint32_t)k[11]) << 24; + mix(a, b, c); + length -= 12; + k += 12; + } + + /*--------------------- last block: affect all 32 bits of (c) */ + switch(length) { /* all the case statements fall through */ + case 12: + c += ((uint32_t)k[11]) << 24; + case 11: + c += ((uint32_t)k[10]) << 16; + case 10: + c += ((uint32_t)k[9]) << 8; + case 9 : + c += k[8]; + case 8 : + b += ((uint32_t)k[7]) << 24; + case 7 : + b += ((uint32_t)k[6]) << 16; + case 6 : + b += ((uint32_t)k[5]) << 8; + case 5 : + b += k[4]; + case 4 : + a += ((uint32_t)k[3]) << 24; + case 3 : + a += ((uint32_t)k[2]) << 16; + case 2 : + a += ((uint32_t)k[1]) << 8; + case 1 : + a += k[0]; + break; + case 0 : + *pc = c; + *pb = b; + return; /* zero length strings require no mixing */ + } + } + + final(a, b, c); + *pc = c; + *pb = b; } /* @@ -635,122 +809,191 @@ void hashlittle2( */ uint32_t hashbig( const void *key, size_t length, uint32_t initval) { - uint32_t a,b,c; - union { const void *ptr; size_t i; } u; /* to cast key to (size_t) happily */ - - /* Set up the internal state */ - a = b = c = 0xdeadbeef + ((uint32_t)length) + initval; - - u.ptr = key; - if (HASH_BIG_ENDIAN && ((u.i & 0x3) == 0)) { - const uint32_t *k = (const uint32_t *)key; /* read 32-bit chunks */ - - /*------ all but last block: aligned reads and affect 32 bits of (a,b,c) */ - while (length > 12) - { - a += k[0]; - b += k[1]; - c += k[2]; - mix(a,b,c); - length -= 12; - k += 3; - } - - /*----------------------------- handle the last (probably partial) block */ - /* - * "k[2]<<8" actually reads beyond the end of the string, but - * then shifts out the part it's not allowed to read. Because the - * string is aligned, the illegal read is in the same word as the - * rest of the string. Every machine with memory protection I've seen - * does it on word boundaries, so is OK with this. But VALGRIND will - * still catch it and complain. The masking trick does make the hash - * noticably faster for short strings (like English words). - */ + uint32_t a, b, c; + union { + const void *ptr; + size_t i; + } u; /* to cast key to (size_t) happily */ + + /* Set up the internal state */ + a = b = c = 0xdeadbeef + ((uint32_t)length) + initval; + + u.ptr = key; + if (HASH_BIG_ENDIAN && ((u.i & 0x3) == 0)) { + const uint32_t *k = (const uint32_t *)key; /* read 32b chunks */ + + /* all but last block: aligned reads and affect 32 bits + * of (a,b,c) */ + while (length > 12) { + a += k[0]; + b += k[1]; + c += k[2]; + mix(a, b, c); + length -= 12; + k += 3; + } + + /*------------------ handle the last (probably partial) block */ + /* + * "k[2]<<8" actually reads beyond the end of the string, but + * then shifts out the part it's not allowed to read. Because + * the string is aligned, the illegal read is in the same word + * as the rest of the string. Every machine with memory + * protection I've seen does it on word boundaries, so is OK + * with this. But VALGRIND will still catch it and complain. + * The masking trick does make the hash noticably faster for + * short strings (like English words). + */ #ifndef VALGRIND - switch(length) - { - case 12: c+=k[2]; b+=k[1]; a+=k[0]; break; - case 11: c+=k[2]&0xffffff00; b+=k[1]; a+=k[0]; break; - case 10: c+=k[2]&0xffff0000; b+=k[1]; a+=k[0]; break; - case 9 : c+=k[2]&0xff000000; b+=k[1]; a+=k[0]; break; - case 8 : b+=k[1]; a+=k[0]; break; - case 7 : b+=k[1]&0xffffff00; a+=k[0]; break; - case 6 : b+=k[1]&0xffff0000; a+=k[0]; break; - case 5 : b+=k[1]&0xff000000; a+=k[0]; break; - case 4 : a+=k[0]; break; - case 3 : a+=k[0]&0xffffff00; break; - case 2 : a+=k[0]&0xffff0000; break; - case 1 : a+=k[0]&0xff000000; break; - case 0 : return c; /* zero length strings require no mixing */ - } + switch(length) { + case 12: + c += k[2]; + b += k[1]; + a += k[0]; + break; + case 11: + c += k[2] & 0xffffff00; + b += k[1]; + a += k[0]; + break; + case 10: + c += k[2] & 0xffff0000; + b += k[1]; + a += k[0]; + break; + case 9 : + c += k[2] & 0xff000000; + b += k[1]; + a += k[0]; + break; + case 8 : + b += k[1]; + a += k[0]; + break; + case 7 : + b += k[1] & 0xffffff00; + a += k[0]; + break; + case 6 : + b += k[1] & 0xffff0000; + a += k[0]; + break; + case 5 : + b += k[1] & 0xff000000; + a += k[0]; + break; + case 4 : + a += k[0]; + break; + case 3 : + a += k[0] & 0xffffff00; + break; + case 2 : + a += k[0] & 0xffff0000; + break; + case 1 : + a += k[0] & 0xff000000; + break; + case 0 : + return c; /* zero length strings require no mixing */ + } #else /* make valgrind happy */ - k8 = (const uint8_t *)k; - switch(length) /* all the case statements fall through */ - { - case 12: c+=k[2]; b+=k[1]; a+=k[0]; break; - case 11: c+=((uint32_t)k8[10])<<8; /* fall through */ - case 10: c+=((uint32_t)k8[9])<<16; /* fall through */ - case 9 : c+=((uint32_t)k8[8])<<24; /* fall through */ - case 8 : b+=k[1]; a+=k[0]; break; - case 7 : b+=((uint32_t)k8[6])<<8; /* fall through */ - case 6 : b+=((uint32_t)k8[5])<<16; /* fall through */ - case 5 : b+=((uint32_t)k8[4])<<24; /* fall through */ - case 4 : a+=k[0]; break; - case 3 : a+=((uint32_t)k8[2])<<8; /* fall through */ - case 2 : a+=((uint32_t)k8[1])<<16; /* fall through */ - case 1 : a+=((uint32_t)k8[0])<<24; break; - case 0 : return c; - } + k8 = (const uint8_t *)k; + switch(length) { /* all the case statements fall through */ + case 12: + c += k[2]; + b += k[1]; + a += k[0]; + break; + case 11: + c += ((uint32_t)k8[10]) << 8; /* fall through */ + case 10: + c += ((uint32_t)k8[9]) << 16; /* fall through */ + case 9 : + c += ((uint32_t)k8[8]) << 24; /* fall through */ + case 8 : + b += k[1]; + a += k[0]; + break; + case 7 : + b += ((uint32_t)k8[6]) << 8; /* fall through */ + case 6 : + b += ((uint32_t)k8[5]) << 16; /* fall through */ + case 5 : + b += ((uint32_t)k8[4]) << 24; /* fall through */ + case 4 : + a += k[0]; + break; + case 3 : + a += ((uint32_t)k8[2]) << 8; /* fall through */ + case 2 : + a += ((uint32_t)k8[1]) << 16; /* fall through */ + case 1 : + a += ((uint32_t)k8[0]) << 24; + break; + case 0 : + return c; + } #endif /* !VALGRIND */ - } else { /* need to read the key one byte at a time */ - const uint8_t *k = (const uint8_t *)key; - - /*--------------- all but the last block: affect some 32 bits of (a,b,c) */ - while (length > 12) - { - a += ((uint32_t)k[0])<<24; - a += ((uint32_t)k[1])<<16; - a += ((uint32_t)k[2])<<8; - a += ((uint32_t)k[3]); - b += ((uint32_t)k[4])<<24; - b += ((uint32_t)k[5])<<16; - b += ((uint32_t)k[6])<<8; - b += ((uint32_t)k[7]); - c += ((uint32_t)k[8])<<24; - c += ((uint32_t)k[9])<<16; - c += ((uint32_t)k[10])<<8; - c += ((uint32_t)k[11]); - mix(a,b,c); - length -= 12; - k += 12; - } - - /*-------------------------------- last block: affect all 32 bits of (c) */ - switch(length) /* all the case statements fall through */ - { - case 12: c+=k[11]; - case 11: c+=((uint32_t)k[10])<<8; - case 10: c+=((uint32_t)k[9])<<16; - case 9 : c+=((uint32_t)k[8])<<24; - case 8 : b+=k[7]; - case 7 : b+=((uint32_t)k[6])<<8; - case 6 : b+=((uint32_t)k[5])<<16; - case 5 : b+=((uint32_t)k[4])<<24; - case 4 : a+=k[3]; - case 3 : a+=((uint32_t)k[2])<<8; - case 2 : a+=((uint32_t)k[1])<<16; - case 1 : a+=((uint32_t)k[0])<<24; - break; - case 0 : return c; - } - } - - final(a,b,c); - return c; + } else { /* need to read the key one byte at a time */ + const uint8_t *k = (const uint8_t *)key; + + /*---- all but the last block: affect some 32 bits of (a,b,c) */ + while (length > 12) { + a += ((uint32_t)k[0]) << 24; + a += ((uint32_t)k[1]) << 16; + a += ((uint32_t)k[2]) << 8; + a += ((uint32_t)k[3]); + b += ((uint32_t)k[4]) << 24; + b += ((uint32_t)k[5]) << 16; + b += ((uint32_t)k[6]) << 8; + b += ((uint32_t)k[7]); + c += ((uint32_t)k[8]) << 24; + c += ((uint32_t)k[9]) << 16; + c += ((uint32_t)k[10]) << 8; + c += ((uint32_t)k[11]); + mix(a, b, c); + length -= 12; + k += 12; + } + + /*--------------------- last block: affect all 32 bits of (c) */ + switch(length) { /* all the case statements fall through */ + case 12: + c += k[11]; + case 11: + c += ((uint32_t)k[10]) << 8; + case 10: + c += ((uint32_t)k[9]) << 16; + case 9 : + c += ((uint32_t)k[8]) << 24; + case 8 : + b += k[7]; + case 7 : + b += ((uint32_t)k[6]) << 8; + case 6 : + b += ((uint32_t)k[5]) << 16; + case 5 : + b += ((uint32_t)k[4]) << 24; + case 4 : + a += k[3]; + case 3 : + a += ((uint32_t)k[2]) << 8; + case 2 : + a += ((uint32_t)k[1]) << 16; + case 1 : + a += ((uint32_t)k[0]) << 24; + break; + case 0 : + return c; + } + } + + final(a, b, c); + return c; } - diff --git a/tools/check-syntax b/tools/check-syntax index b5ae9cc..f356a46 100755 --- a/tools/check-syntax +++ b/tools/check-syntax @@ -25,7 +25,7 @@ CHK_C_LIST="include/seccomp.h.in \ src/*.c src/*.h \ tests/*.c tests/*.h \ tools/*.c tools/*.h" -CHK_C_EXCLUDE="src/hash.c" +CHK_C_EXCLUDE="" #### # functions -- cgit v1.2.1 From d0a3b33eb62f31954526689042b8d2e6744518b5 Mon Sep 17 00:00:00 2001 From: Paul Moore Date: Mon, 21 Oct 2013 16:00:15 -0400 Subject: hash: cleanup the Jenkins hash source to better match our code Style improvements as well as a wrapper function to select the "best" hash for a given situation. Some unused functions were also removed. Signed-off-by: Paul Moore --- src/hash.c | 805 ++++++++++++++++++------------------------------------------- 1 file changed, 240 insertions(+), 565 deletions(-) diff --git a/src/hash.c b/src/hash.c index 5b55679..cb52b3b 100644 --- a/src/hash.c +++ b/src/hash.c @@ -1,116 +1,95 @@ +/** + * Seccomp Library hash code + * + * Release under the Public Domain + * Author: Bob Jenkins + */ + /* -------------------------------------------------------------------------------- -lookup3.c, by Bob Jenkins, May 2006, Public Domain. - -These are functions for producing 32-bit hashes for hash table lookup. -hashword(), hashlittle(), hashlittle2(), hashbig(), mix(), and final() -are externally useful functions. Routines to test the hash are included -if SELF_TEST is defined. You can use this free for any purpose. It's in -the public domain. It has no warranty. - -You probably want to use hashlittle(). hashlittle() and hashbig() -hash byte arrays. hashlittle() is is faster than hashbig() on -little-endian machines. Intel and AMD are little-endian machines. -On second thought, you probably want hashlittle2(), which is identical to -hashlittle() except it returns two 32-bit hashes for the price of one. -You could implement hashbig2() if you wanted but I haven't bothered here. - -If you want to find a hash of, say, exactly 7 integers, do - a = i1; b = i2; c = i3; - mix(a,b,c); - a += i4; b += i5; c += i6; - mix(a,b,c); - a += i7; - final(a,b,c); -then use c as the hash value. If you have a variable length array of -4-byte integers to hash, use hashword(). If you have a byte array (like -a character string), use hashlittle(). If you have several byte arrays, or -a mix of things, see the comments above hashlittle(). - -Why is this so big? I read 12 bytes at a time into 3 4-byte integers, -then mix those integers. This is fast (you can do a lot more thorough -mixing with 12*3 instructions on 3 integers than you can with 3 instructions -on 1 byte), but shoehorning those bytes into integers efficiently is messy. -------------------------------------------------------------------------------- -*/ - -#include /* defines uint32_t etc */ -#include /* attempt to define endianness */ -#ifdef linux -# include /* attempt to define endianness */ -#endif + * lookup3.c, by Bob Jenkins, May 2006, Public Domain. + * + * These are functions for producing 32-bit hashes for hash table lookup. + * jhash_word(), jhash_le(), jhash_be(), mix(), and final() are externally useful + * functions. Routines to test the hash are included if SELF_TEST is defined. + * You can use this free for any purpose. It's in the public domain. It has + * no warranty. + * + * You probably want to use jhash_le(). jhash_le() and jhash_be() hash byte + * arrays. jhash_le() is is faster than jhash_be() on little-endian machines. + * Intel and AMD are little-endian machines. + * + * If you want to find a hash of, say, exactly 7 integers, do + * a = i1; b = i2; c = i3; + * mix(a,b,c); + * a += i4; b += i5; c += i6; + * mix(a,b,c); + * a += i7; + * final(a,b,c); + * + * then use c as the hash value. If you have a variable length array of + * 4-byte integers to hash, use jhash_word(). If you have a byte array (like + * a character string), use jhash_le(). If you have several byte arrays, or + * a mix of things, see the comments above jhash_le(). + * + * Why is this so big? I read 12 bytes at a time into 3 4-byte integers, then + * mix those integers. This is fast (you can do a lot more thorough mixing + * with 12*3 instructions on 3 integers than you can with 3 instructions on 1 + * byte), but shoehorning those bytes into integers efficiently is messy. + */ + +#include +#include "arch.h" #include "hash.h" -#define hashlittle jhash -/* - * My best guess at if you are big-endian or little-endian. This may - * need adjustment. - */ -#if (defined(__BYTE_ORDER) && defined(__LITTLE_ENDIAN) && \ - __BYTE_ORDER == __LITTLE_ENDIAN) || \ - (defined(i386) || defined(__i386__) || defined(__i486__) || \ - defined(__i586__) || defined(__i686__) || defined(vax) || defined(MIPSEL)) -# define HASH_LITTLE_ENDIAN 1 -# define HASH_BIG_ENDIAN 0 -#elif (defined(__BYTE_ORDER) && defined(__BIG_ENDIAN) && \ - __BYTE_ORDER == __BIG_ENDIAN) || \ - (defined(sparc) || defined(POWERPC) || defined(mc68000) || defined(sel)) -# define HASH_LITTLE_ENDIAN 0 -# define HASH_BIG_ENDIAN 1 -#else -# define HASH_LITTLE_ENDIAN 0 -# define HASH_BIG_ENDIAN 0 -#endif - -#define hashsize(n) ((uint32_t)1<<(n)) -#define hashmask(n) (hashsize(n)-1) -#define rot(x,k) (((x)<<(k)) | ((x)>>(32-(k)))) +#define hashsize(n) ((uint32_t)1<<(n)) +#define hashmask(n) (hashsize(n)-1) +#define rot(x,k) (((x)<<(k)) | ((x)>>(32-(k)))) -/* -------------------------------------------------------------------------------- -mix -- mix 3 32-bit values reversibly. - -This is reversible, so any information in (a,b,c) before mix() is -still in (a,b,c) after mix(). - -If four pairs of (a,b,c) inputs are run through mix(), or through -mix() in reverse, there are at least 32 bits of the output that -are sometimes the same for one pair and different for another pair. -This was tested for: -* pairs that differed by one bit, by two bits, in any combination - of top bits of (a,b,c), or in any combination of bottom bits of - (a,b,c). -* "differ" is defined as +, -, ^, or ~^. For + and -, I transformed - the output delta to a Gray code (a^(a>>1)) so a string of 1's (as - is commonly produced by subtraction) look like a single 1-bit - difference. -* the base values were pseudorandom, all zero but one bit set, or - all zero plus a counter that starts at zero. - -Some k values for my "a-=c; a^=rot(c,k); c+=b;" arrangement that -satisfy this are - 4 6 8 16 19 4 - 9 15 3 18 27 15 - 14 9 3 7 17 3 -Well, "9 15 3 18 27 15" didn't quite get 32 bits diffing -for "differ" defined as + with a one-bit base and a two-bit delta. I -used http://burtleburtle.net/bob/hash/avalanche.html to choose -the operations, constants, and arrangements of the variables. - -This does not achieve avalanche. There are input bits of (a,b,c) -that fail to affect some output bits of (a,b,c), especially of a. The -most thoroughly mixed value is c, but it doesn't really even achieve -avalanche in c. - -This allows some parallelism. Read-after-writes are good at doubling -the number of bits affected, so the goal of mixing pulls in the opposite -direction as the goal of parallelism. I did what I could. Rotates -seem to cost as much as shifts on every machine I could lay my hands -on, and rotates are much kinder to the top and bottom bits, so I used -rotates. -------------------------------------------------------------------------------- -*/ +/** + * Mix 3 32-bit values reversibly + * @param a 32-bit value + * @param b 32-bit value + * @param c 32-bit value + * + * This is reversible, so any information in (a,b,c) before mix() is still + * in (a,b,c) after mix(). + * + * If four pairs of (a,b,c) inputs are run through mix(), or through mix() in + * reverse, there are at least 32 bits of the output that are sometimes the + * same for one pair and different for another pair. + * + * This was tested for: + * - pairs that differed by one bit, by two bits, in any combination of top + * bits of (a,b,c), or in any combination of bottom bits of (a,b,c). + * - "differ" is defined as +, -, ^, or ~^. For + and -, I transformed the + * output delta to a Gray code (a^(a>>1)) so a string of 1's (as is commonly + * produced by subtraction) look like a single 1-bit difference. + * - the base values were pseudorandom, all zero but one bit set, or all zero + * plus a counter that starts at zero. + * + * Some k values for my "a-=c; a^=rot(c,k); c+=b;" arrangement that + * satisfy this are + * 4 6 8 16 19 4 + * 9 15 3 18 27 15 + * 14 9 3 7 17 3 + * + * Well, "9 15 3 18 27 15" didn't quite get 32 bits diffing for "differ" + * defined as + with a one-bit base and a two-bit delta. I used + * http://burtleburtle.net/bob/hash/avalanche.html to choose the operations, + * constants, and arrangements of the variables. + * + * This does not achieve avalanche. There are input bits of (a,b,c) that fail + * to affect some output bits of (a,b,c), especially of a. The most thoroughly + * mixed value is c, but it doesn't really even achieve avalanche in c. + * + * This allows some parallelism. Read-after-writes are good at doubling the + * number of bits affected, so the goal of mixing pulls in the opposite + * direction as the goal of parallelism. I did what I could. Rotates seem to + * cost as much as shifts on every machine I could lay my hands on, and rotates + * are much kinder to the top and bottom bits, so I used rotates. + * + */ #define mix(a,b,c) \ { \ a -= c; a ^= rot(c, 4); c += b; \ @@ -121,31 +100,31 @@ rotates. c -= b; c ^= rot(b, 4); b += a; \ } -/* -------------------------------------------------------------------------------- -final -- final mixing of 3 32-bit values (a,b,c) into c - -Pairs of (a,b,c) values differing in only a few bits will usually -produce values of c that look totally different. This was tested for -* pairs that differed by one bit, by two bits, in any combination - of top bits of (a,b,c), or in any combination of bottom bits of - (a,b,c). -* "differ" is defined as +, -, ^, or ~^. For + and -, I transformed - the output delta to a Gray code (a^(a>>1)) so a string of 1's (as - is commonly produced by subtraction) look like a single 1-bit - difference. -* the base values were pseudorandom, all zero but one bit set, or - all zero plus a counter that starts at zero. - -These constants passed: - 14 11 25 16 4 14 24 - 12 14 25 16 4 14 24 -and these came close: - 4 8 15 26 3 22 24 - 10 8 15 26 3 22 24 - 11 8 15 26 3 22 24 -------------------------------------------------------------------------------- -*/ +/** + * Final mixing of 3 32-bit values (a,b,c) into c + * @param a 32-bit value + * @param b 32-bit value + * @param c 32-bit value + * + * Pairs of (a,b,c) values differing in only a few bits will usually produce + * values of c that look totally different. This was tested for: + * - pairs that differed by one bit, by two bits, in any combination of top + * bits of (a,b,c), or in any combination of bottom bits of (a,b,c). + * - "differ" is defined as +, -, ^, or ~^. For + and -, I transformed the + * output delta to a Gray code (a^(a>>1)) so a string of 1's (as is commonly + * produced by subtraction) look like a single 1-bit difference. + * - the base values were pseudorandom, all zero but one bit set, or all zero + * plus a counter that starts at zero. + * + * These constants passed: + * 14 11 25 16 4 14 24 + * 12 14 25 16 4 14 24 + * and these came close: + * 4 8 15 26 3 22 24 + * 10 8 15 26 3 22 24 + * 11 8 15 26 3 22 24 + * + */ #define final(a,b,c) \ { \ c ^= b; c -= rot(b,14); \ @@ -157,30 +136,31 @@ and these came close: c ^= b; c -= rot(b,24); \ } -/* --------------------------------------------------------------------- - This works on all machines. To be useful, it requires - -- that the key be an array of uint32_t's, and - -- that the length be the number of uint32_t's in the key - - The function hashword() is identical to hashlittle() on little-endian - machines, and identical to hashbig() on big-endian machines, - except that the length has to be measured in uint32_ts rather than in - bytes. hashlittle() is more complicated than hashword() only because - hashlittle() has to dance around fitting the key bytes into registers. --------------------------------------------------------------------- -*/ -uint32_t hashword( - const uint32_t *k, /* the key, an array of uint32_t values */ - size_t length, /* the length of the key, in uint32_ts */ - uint32_t initval) /* the previous hash, or an arbitrary value */ +/** + * Hash an array of 32-bit values + * @param k the key, an array of uint32_t values + * @param length the number of array elements + * @param initval the previous hash, or an arbitrary value + * + * This works on all machines. To be useful, it requires: + * - that the key be an array of uint32_t's, and + * - that the length be the number of uint32_t's in the key + * + * The function jhash_word() is identical to jhash_le() on little-endian + * machines, and identical to jhash_be() on big-endian machines, except that + * the length has to be measured in uint32_ts rather than in bytes. jhash_le() + * is more complicated than jhash_word() only because jhash_le() has to dance + * around fitting the key bytes into registers. + * + */ +static uint32_t jhash_word(const uint32_t *k, size_t length, uint32_t initval) { uint32_t a, b, c; - /* Set up the internal state */ + /* set up the internal state */ a = b = c = 0xdeadbeef + (((uint32_t)length) << 2) + initval; - /*-------------------------------------------- handle most of the key */ + /* handle most of the key */ while (length > 3) { a += k[0]; b += k[1]; @@ -190,8 +170,8 @@ uint32_t hashword( k += 3; } - /*-------------------------------------- handle the last 3 uint32_t's */ - switch(length) { /* all the case statements fall through */ + /* handle the last 3 uint32_t's */ + switch(length) { case 3 : c += k[2]; case 2 : @@ -199,103 +179,51 @@ uint32_t hashword( case 1 : a += k[0]; final(a, b, c); - case 0: /* case 0: nothing left to add */ + case 0: + /* nothing left to add */ break; } - /*------------------------------------------------- report the result */ + return c; } -/* --------------------------------------------------------------------- -hashword2() -- same as hashword(), but take two seeds and return two -32-bit values. pc and pb must both be nonnull, and *pc and *pb must -both be initialized with seeds. If you pass in (*pb)==0, the output -(*pc) will be the same as the return value from hashword(). --------------------------------------------------------------------- -*/ -void hashword2 ( - const uint32_t *k, /* the key, an array of uint32_t values */ - size_t length, /* the length of the key, in uint32_ts */ - uint32_t *pc, /* IN: seed OUT: primary hash value */ - uint32_t *pb) /* IN: more seed OUT: secondary hash value */ +/** + * Hash a variable-length key into a 32-bit value + * @param k 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 + * + * Returns a 32-bit value. Every bit of the key affects every bit of the + * return value. Two keys differing by one or two bits will have totally + * different hash values. + * + * The best hash table sizes are powers of 2. There is no need to do mod a + * prime (mod is sooo slow!). If you need less than 32 bits, use a bitmask. + * For example, if you need only 10 bits, do: + * h = (h & hashmask(10)); + * In which case, the hash table should have hashsize(10) elements. + * + * If you are hashing n strings (uint8_t **)k, do it like this: + * for (i=0, h=0; i 3) { - a += k[0]; - b += k[1]; - c += k[2]; - mix(a, b, c); - length -= 3; - k += 3; - } - - /*-------------------------------------- handle the last 3 uint32_t's */ - switch(length) { /* all the case statements fall through */ - case 3 : - c += k[2]; - case 2 : - b += k[1]; - case 1 : - a += k[0]; - final(a, b, c); - case 0: /* case 0: nothing left to add */ - break; - } - /*------------------------------------------------- report the result */ - *pc = c; - *pb = b; -} - -/* -------------------------------------------------------------------------------- -hashlittle() -- hash a variable-length key into a 32-bit value - k : the key (the unaligned variable-length array of bytes) - length : the length of the key, counting by bytes - initval : can be any 4-byte value -Returns a 32-bit value. Every bit of the key affects every bit of -the return value. Two keys differing by one or two bits will have -totally different hash values. - -The best hash table sizes are powers of 2. There is no need to do -mod a prime (mod is sooo slow!). If you need less than 32 bits, -use a bitmask. For example, if you need only 10 bits, do - h = (h & hashmask(10)); -In which case, the hash table should have hashsize(10) elements. - -If you are hashing n strings (uint8_t **)k, do it like this: - for (i=0, h=0; iendian == ARCH_ENDIAN_LITTLE) && + ((u.i & 0x3) == 0)) { + /* read 32-bit chunks */ + const uint32_t *k = (const uint32_t *)key; - /* all but last block: aligned reads and affect 32-bits - * of (a,b,c) */ while (length > 12) { a += k[0]; b += k[1]; @@ -305,17 +233,14 @@ uint32_t hashlittle( const void *key, size_t length, uint32_t initval) k += 3; } - /*------------------ handle the last (probably partial) block */ - /* - * "k[2]&0xffffff" actually reads beyond the end of the string, + /* "k[2]&0xffffff" actually reads beyond the end of the string, * but then masks off the part it's not allowed to read. * Because the string is aligned, the masked-off tail is in the * same word as the rest of the string. Every machine with * memory protection I've seen does it on word boundaries, so * is OK with this. But VALGRIND will still catch it and * complain. The masking trick does make the hash noticably - * faster for short strings (like English words). - */ + * faster for short strings (like English words). */ #ifndef VALGRIND switch(length) { @@ -368,7 +293,8 @@ uint32_t hashlittle( const void *key, size_t length, uint32_t initval) a += k[0] & 0xff; break; case 0 : - return c; /* zero length strings require no mixing */ + /* zero length strings require no mixing */ + return c; } #else /* make valgrind happy */ @@ -381,28 +307,28 @@ uint32_t hashlittle( const void *key, size_t length, uint32_t initval) a += k[0]; break; case 11: - c += ((uint32_t)k8[10]) << 16; /* fall through */ + c += ((uint32_t)k8[10]) << 16; case 10: - c += ((uint32_t)k8[9]) << 8; /* fall through */ + c += ((uint32_t)k8[9]) << 8; case 9 : - c += k8[8]; /* fall through */ + c += k8[8]; case 8 : b += k[1]; a += k[0]; break; case 7 : - b += ((uint32_t)k8[6]) << 16; /* fall through */ + b += ((uint32_t)k8[6]) << 16; case 6 : - b += ((uint32_t)k8[5]) << 8; /* fall through */ + b += ((uint32_t)k8[5]) << 8; case 5 : - b += k8[4]; /* fall through */ + b += k8[4]; case 4 : a += k[0]; break; case 3 : - a += ((uint32_t)k8[2]) << 16; /* fall through */ + a += ((uint32_t)k8[2]) << 16; case 2 : - a += ((uint32_t)k8[1]) << 8; /* fall through */ + a += ((uint32_t)k8[1]) << 8; case 1 : a += k8[0]; break; @@ -412,11 +338,12 @@ uint32_t hashlittle( const void *key, size_t length, uint32_t initval) #endif /* !valgrind */ - } else if (HASH_LITTLE_ENDIAN && ((u.i & 0x1) == 0)) { - const uint16_t *k = (const uint16_t *)key; /* read 16b chunks */ + } else if ((arch_def_native->endian == ARCH_ENDIAN_LITTLE) && + ((u.i & 0x1) == 0)) { + /* read 16-bit chunks */ + const uint16_t *k = (const uint16_t *)key; const uint8_t *k8; - /*---- all but last block: aligned reads and different mixing */ while (length > 12) { a += k[0] + (((uint32_t)k[1]) << 16); b += k[2] + (((uint32_t)k[3]) << 16); @@ -426,7 +353,6 @@ uint32_t hashlittle( const void *key, size_t length, uint32_t initval) k += 6; } - /*------------------ handle the last (probably partial) block */ k8 = (const uint8_t *)k; switch(length) { case 12: @@ -435,31 +361,31 @@ uint32_t hashlittle( const void *key, size_t length, uint32_t initval) a += k[0] + (((uint32_t)k[1]) << 16); break; case 11: - c += ((uint32_t)k8[10]) << 16; /* fall through */ + c += ((uint32_t)k8[10]) << 16; case 10: c += k[4]; b += k[2] + (((uint32_t)k[3]) << 16); a += k[0] + (((uint32_t)k[1]) << 16); break; case 9 : - c += k8[8]; /* fall through */ + c += k8[8]; case 8 : b += k[2] + (((uint32_t)k[3]) << 16); a += k[0] + (((uint32_t)k[1]) << 16); break; case 7 : - b += ((uint32_t)k8[6]) << 16; /* fall through */ + b += ((uint32_t)k8[6]) << 16; case 6 : b += k[2]; a += k[0] + (((uint32_t)k[1]) << 16); break; case 5 : - b += k8[4]; /* fall through */ + b += k8[4]; case 4 : a += k[0] + (((uint32_t)k[1]) << 16); break; case 3 : - a += ((uint32_t)k8[2]) << 16; /* fall through */ + a += ((uint32_t)k8[2]) << 16; case 2 : a += k[0]; break; @@ -467,13 +393,14 @@ uint32_t hashlittle( const void *key, size_t length, uint32_t initval) a += k8[0]; break; case 0 : - return c; /* zero length requires no mixing */ + /* zero length requires no mixing */ + return c; } - } else { /* need to read the key one byte at a time */ + } else { + /* need to read the key one byte at a time */ const uint8_t *k = (const uint8_t *)key; - /*---- all but the last block: affect some 32 bits of (a,b,c) */ while (length > 12) { a += k[0]; a += ((uint32_t)k[1]) << 8; @@ -492,8 +419,7 @@ uint32_t hashlittle( const void *key, size_t length, uint32_t initval) k += 12; } - /*--------------------- last block: affect all 32 bits of (c) */ - switch(length) { /* all the case statements fall through */ + switch(length) { case 12: c += ((uint32_t)k[11]) << 24; case 11: @@ -528,286 +454,18 @@ uint32_t hashlittle( const void *key, size_t length, uint32_t initval) return c; } -/* - * hashlittle2: return 2 32-bit hash values +/** + * Hash a variable-length key into a 32-bit value + * @param k 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 + * + * This is the same as jhash_word() on big-endian machines. It is different + * from jhash_le() on all machines. jhash_be() takes advantage of big-endian + * byte ordering. * - * This is identical to hashlittle(), except it returns two 32-bit hash - * values instead of just one. This is good enough for hash table - * lookup with 2^^64 buckets, or if you want a second hash if you're not - * happy with the first, or if you want a probably-unique 64-bit ID for - * the key. *pc is better mixed than *pb, so use *pc first. If you want - * a 64-bit value do something like "*pc + (((uint64_t)*pb)<<32)". - */ -void hashlittle2( - const void *key, /* the key to hash */ - size_t length, /* length of the key */ - uint32_t *pc, /* IN: primary initval, OUT: primary hash */ - uint32_t *pb) /* IN: secondary initval, OUT: secondary hash */ -{ - uint32_t a, b, c; /* internal state */ - union { - const void *ptr; - size_t i; - } u; /* needed for Mac Powerbook G4 */ - - /* Set up the internal state */ - a = b = c = 0xdeadbeef + ((uint32_t)length) + *pc; - c += *pb; - - u.ptr = key; - if (HASH_LITTLE_ENDIAN && ((u.i & 0x3) == 0)) { - const uint32_t *k = (const uint32_t *)key; /* read 32b chunks */ - - /* all but last block: aligned reads and affect 32 bits - * of (a,b,c) */ - while (length > 12) { - a += k[0]; - b += k[1]; - c += k[2]; - mix(a, b, c); - length -= 12; - k += 3; - } - - /*------------------ handle the last (probably partial) block */ - /* - * "k[2]&0xffffff" actually reads beyond the end of the string, - * but then masks off the part it's not allowed to read. - * Because the string is aligned, the masked-off tail is in the - * same word as the rest of the string. Every machine with - * memory protection I've seen does it on word boundaries, so - * is OK with this. But VALGRIND will still catch it and - * complain. The masking trick does make the hash noticably - * faster for short strings (like English words). - */ -#ifndef VALGRIND - - switch(length) { - case 12: - c += k[2]; - b += k[1]; - a += k[0]; - break; - case 11: - c += k[2] & 0xffffff; - b += k[1]; - a += k[0]; - break; - case 10: - c += k[2] & 0xffff; - b += k[1]; - a += k[0]; - break; - case 9 : - c += k[2] & 0xff; - b += k[1]; - a += k[0]; - break; - case 8 : - b += k[1]; - a += k[0]; - break; - case 7 : - b += k[1] & 0xffffff; - a += k[0]; - break; - case 6 : - b += k[1] & 0xffff; - a += k[0]; - break; - case 5 : - b += k[1] & 0xff; - a += k[0]; - break; - case 4 : - a += k[0]; - break; - case 3 : - a += k[0] & 0xffffff; - break; - case 2 : - a += k[0] & 0xffff; - break; - case 1 : - a += k[0] & 0xff; - break; - case 0 : - *pc = c; - *pb = b; - return; /* zero length strings require no mixing */ - } - -#else /* make valgrind happy */ - - k8 = (const uint8_t *)k; - switch(length) { - case 12: - c += k[2]; - b += k[1]; - a += k[0]; - break; - case 11: - c += ((uint32_t)k8[10]) << 16; /* fall through */ - case 10: - c += ((uint32_t)k8[9]) << 8; /* fall through */ - case 9 : - c += k8[8]; /* fall through */ - case 8 : - b += k[1]; - a += k[0]; - break; - case 7 : - b += ((uint32_t)k8[6]) << 16; /* fall through */ - case 6 : - b += ((uint32_t)k8[5]) << 8; /* fall through */ - case 5 : - b += k8[4]; /* fall through */ - case 4 : - a += k[0]; - break; - case 3 : - a += ((uint32_t)k8[2]) << 16; /* fall through */ - case 2 : - a += ((uint32_t)k8[1]) << 8; /* fall through */ - case 1 : - a += k8[0]; - break; - case 0 : - *pc = c; - *pb = b; - return; /* zero length strings require no mixing */ - } - -#endif /* !valgrind */ - - } else if (HASH_LITTLE_ENDIAN && ((u.i & 0x1) == 0)) { - const uint16_t *k = (const uint16_t *)key; /* read 16b chunks */ - const uint8_t *k8; - - /*---- all but last block: aligned reads and different mixing */ - while (length > 12) { - a += k[0] + (((uint32_t)k[1]) << 16); - b += k[2] + (((uint32_t)k[3]) << 16); - c += k[4] + (((uint32_t)k[5]) << 16); - mix(a, b, c); - length -= 12; - k += 6; - } - - /*------------------ handle the last (probably partial) block */ - k8 = (const uint8_t *)k; - switch(length) { - case 12: - c += k[4] + (((uint32_t)k[5]) << 16); - b += k[2] + (((uint32_t)k[3]) << 16); - a += k[0] + (((uint32_t)k[1]) << 16); - break; - case 11: - c += ((uint32_t)k8[10]) << 16; /* fall through */ - case 10: - c += k[4]; - b += k[2] + (((uint32_t)k[3]) << 16); - a += k[0] + (((uint32_t)k[1]) << 16); - break; - case 9 : - c += k8[8]; /* fall through */ - case 8 : - b += k[2] + (((uint32_t)k[3]) << 16); - a += k[0] + (((uint32_t)k[1]) << 16); - break; - case 7 : - b += ((uint32_t)k8[6]) << 16; /* fall through */ - case 6 : - b += k[2]; - a += k[0] + (((uint32_t)k[1]) << 16); - break; - case 5 : - b += k8[4]; /* fall through */ - case 4 : - a += k[0] + (((uint32_t)k[1]) << 16); - break; - case 3 : - a += ((uint32_t)k8[2]) << 16; /* fall through */ - case 2 : - a += k[0]; - break; - case 1 : - a += k8[0]; - break; - case 0 : - *pc = c; - *pb = b; - return; /* zero length strings require no mixing */ - } - - } else { /* need to read the key one byte at a time */ - const uint8_t *k = (const uint8_t *)key; - - /*---- all but the last block: affect some 32 bits of (a,b,c) */ - while (length > 12) { - a += k[0]; - a += ((uint32_t)k[1]) << 8; - a += ((uint32_t)k[2]) << 16; - a += ((uint32_t)k[3]) << 24; - b += k[4]; - b += ((uint32_t)k[5]) << 8; - b += ((uint32_t)k[6]) << 16; - b += ((uint32_t)k[7]) << 24; - c += k[8]; - c += ((uint32_t)k[9]) << 8; - c += ((uint32_t)k[10]) << 16; - c += ((uint32_t)k[11]) << 24; - mix(a, b, c); - length -= 12; - k += 12; - } - - /*--------------------- last block: affect all 32 bits of (c) */ - switch(length) { /* all the case statements fall through */ - case 12: - c += ((uint32_t)k[11]) << 24; - case 11: - c += ((uint32_t)k[10]) << 16; - case 10: - c += ((uint32_t)k[9]) << 8; - case 9 : - c += k[8]; - case 8 : - b += ((uint32_t)k[7]) << 24; - case 7 : - b += ((uint32_t)k[6]) << 16; - case 6 : - b += ((uint32_t)k[5]) << 8; - case 5 : - b += k[4]; - case 4 : - a += ((uint32_t)k[3]) << 24; - case 3 : - a += ((uint32_t)k[2]) << 16; - case 2 : - a += ((uint32_t)k[1]) << 8; - case 1 : - a += k[0]; - break; - case 0 : - *pc = c; - *pb = b; - return; /* zero length strings require no mixing */ - } - } - - final(a, b, c); - *pc = c; - *pb = b; -} - -/* - * hashbig(): - * This is the same as hashword() on big-endian machines. It is different - * from hashlittle() on all machines. hashbig() takes advantage of - * big-endian byte ordering. */ -uint32_t hashbig( const void *key, size_t length, uint32_t initval) +static uint32_t jhash_be( const void *key, size_t length, uint32_t initval) { uint32_t a, b, c; union { @@ -815,15 +473,15 @@ uint32_t hashbig( const void *key, size_t length, uint32_t initval) size_t i; } u; /* to cast key to (size_t) happily */ - /* Set up the internal state */ + /* set up the internal state */ a = b = c = 0xdeadbeef + ((uint32_t)length) + initval; u.ptr = key; - if (HASH_BIG_ENDIAN && ((u.i & 0x3) == 0)) { - const uint32_t *k = (const uint32_t *)key; /* read 32b chunks */ + if ((arch_def_native->endian == ARCH_ENDIAN_BIG) && + ((u.i & 0x3) == 0)) { + /* read 32-bit chunks */ + const uint32_t *k = (const uint32_t *)key; - /* all but last block: aligned reads and affect 32 bits - * of (a,b,c) */ while (length > 12) { a += k[0]; b += k[1]; @@ -833,17 +491,14 @@ uint32_t hashbig( const void *key, size_t length, uint32_t initval) k += 3; } - /*------------------ handle the last (probably partial) block */ - /* - * "k[2]<<8" actually reads beyond the end of the string, but + /* "k[2]<<8" actually reads beyond the end of the string, but * then shifts out the part it's not allowed to read. Because * the string is aligned, the illegal read is in the same word * as the rest of the string. Every machine with memory * protection I've seen does it on word boundaries, so is OK * with this. But VALGRIND will still catch it and complain. * The masking trick does make the hash noticably faster for - * short strings (like English words). - */ + * short strings (like English words). */ #ifndef VALGRIND switch(length) { @@ -896,41 +551,42 @@ uint32_t hashbig( const void *key, size_t length, uint32_t initval) a += k[0] & 0xff000000; break; case 0 : - return c; /* zero length strings require no mixing */ + /* zero length strings require no mixing */ + return c; } #else /* make valgrind happy */ k8 = (const uint8_t *)k; - switch(length) { /* all the case statements fall through */ + switch(length) { case 12: c += k[2]; b += k[1]; a += k[0]; break; case 11: - c += ((uint32_t)k8[10]) << 8; /* fall through */ + c += ((uint32_t)k8[10]) << 8; case 10: - c += ((uint32_t)k8[9]) << 16; /* fall through */ + c += ((uint32_t)k8[9]) << 16; case 9 : - c += ((uint32_t)k8[8]) << 24; /* fall through */ + c += ((uint32_t)k8[8]) << 24; case 8 : b += k[1]; a += k[0]; break; case 7 : - b += ((uint32_t)k8[6]) << 8; /* fall through */ + b += ((uint32_t)k8[6]) << 8; case 6 : - b += ((uint32_t)k8[5]) << 16; /* fall through */ + b += ((uint32_t)k8[5]) << 16; case 5 : - b += ((uint32_t)k8[4]) << 24; /* fall through */ + b += ((uint32_t)k8[4]) << 24; case 4 : a += k[0]; break; case 3 : - a += ((uint32_t)k8[2]) << 8; /* fall through */ + a += ((uint32_t)k8[2]) << 8; case 2 : - a += ((uint32_t)k8[1]) << 16; /* fall through */ + a += ((uint32_t)k8[1]) << 16; case 1 : a += ((uint32_t)k8[0]) << 24; break; @@ -940,10 +596,10 @@ uint32_t hashbig( const void *key, size_t length, uint32_t initval) #endif /* !VALGRIND */ - } else { /* need to read the key one byte at a time */ + } else { + /* need to read the key one byte at a time */ const uint8_t *k = (const uint8_t *)key; - /*---- all but the last block: affect some 32 bits of (a,b,c) */ while (length > 12) { a += ((uint32_t)k[0]) << 24; a += ((uint32_t)k[1]) << 16; @@ -962,8 +618,7 @@ uint32_t hashbig( const void *key, size_t length, uint32_t initval) k += 12; } - /*--------------------- last block: affect all 32 bits of (c) */ - switch(length) { /* all the case statements fall through */ + switch(length) { case 12: c += k[11]; case 11: @@ -997,3 +652,23 @@ uint32_t hashbig( const void *key, size_t length, uint32_t initval) final(a, b, c); return c; } + +/** + * Hash a variable-length key into a 32-bit value + * @param k 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 + * + * A small wrapper function that selects the proper hash function based on the + * native machine's byte-ordering. + * + */ +uint32_t jhash(const void *key, size_t length, uint32_t initval) +{ + if (length % sizeof(uint32_t) == 0) + return jhash_word(key, (length / sizeof(uint32_t)), initval); + else if (arch_def_native->endian == ARCH_ENDIAN_BIG) + return jhash_be(key, length, initval); + else + return jhash_le(key, length, initval); +} -- cgit v1.2.1 From 9de19061978d990dc9fc25a20e145218cf66806c Mon Sep 17 00:00:00 2001 From: Paul Moore Date: Mon, 21 Oct 2013 17:13:47 -0400 Subject: tests: fix a problem with the python bindings and the bpf-valgrind tests Reported-by: Andy Lutomirski Signed-off-by: Paul Moore --- tests/regression | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/tests/regression b/tests/regression index bb1c33d..790d5e1 100755 --- a/tests/regression +++ b/tests/regression @@ -546,6 +546,12 @@ function run_test_bpf_valgrind() { local rc local testcmd + # we only support the native/c test mode here + if [[ $mode != "c" ]]; then + stats_skipped=$(($stats_skipped+1)) + return + fi + # print out the input test data to the log file print_data "$1" "$2" -- cgit v1.2.1 From 8e1b4634733dcd59713c43d7d1e53c277767b2fb Mon Sep 17 00:00:00 2001 From: Andy Lutomirski Date: Tue, 22 Oct 2013 09:35:50 -0700 Subject: python: Remove file object support from Arg It's still possible to pass file descriptors into the Arg data, but safe uses are already complicated enough that making the user call fileno() themselves seems reasonable. Signed-off-by: Andy Lutomirski (corrected the python test cases to take into account the change) Signed-off-by: Paul Moore --- src/python/seccomp.pyx | 10 ++-------- tests/07-sim-db_bug_looping.py | 4 ++-- tests/16-sim-arch_basic.py | 6 +++--- tests/17-sim-arch_merge.py | 6 +++--- 4 files changed, 10 insertions(+), 16 deletions(-) diff --git a/src/python/seccomp.pyx b/src/python/seccomp.pyx index ed7c1bb..47d2ae1 100644 --- a/src/python/seccomp.pyx +++ b/src/python/seccomp.pyx @@ -165,14 +165,8 @@ cdef class Arg: """ self._arg.arg = arg self._arg.op = op - if isinstance(datum_a, file): - self._arg.datum_a = datum_a.fileno() - else: - self._arg.datum_a = datum_a - if isinstance(datum_b, file): - self._arg.datum_b = datum_b.fileno() - else: - self._arg.datum_b = datum_b + self._arg.datum_a = datum_a + self._arg.datum_b = datum_b def to_c(self): """ Convert the object into a C structure. diff --git a/tests/07-sim-db_bug_looping.py b/tests/07-sim-db_bug_looping.py index 0b6e988..3314a3e 100755 --- a/tests/07-sim-db_bug_looping.py +++ b/tests/07-sim-db_bug_looping.py @@ -32,9 +32,9 @@ def test(args): f = SyscallFilter(KILL) # the next three seccomp_rule_add_exact() calls for read must go together # in this order to catch an infinite loop. - f.add_rule(ALLOW, "read", Arg(0, EQ, sys.stdout)) + f.add_rule(ALLOW, "read", Arg(0, EQ, sys.stdout.fileno())) f.add_rule(ALLOW, "read", Arg(1, EQ, 0)) - f.add_rule(ALLOW, "read", Arg(0, EQ, sys.stdin)) + f.add_rule(ALLOW, "read", Arg(0, EQ, sys.stdin.fileno())) return f args = util.get_opt() diff --git a/tests/16-sim-arch_basic.py b/tests/16-sim-arch_basic.py index 4484ac5..d29a5ff 100755 --- a/tests/16-sim-arch_basic.py +++ b/tests/16-sim-arch_basic.py @@ -38,9 +38,9 @@ def test(args): f.add_arch(Arch.X32) if not f.exist_arch(Arch.ARM): f.add_arch(Arch.ARM) - f.add_rule(ALLOW, "read", Arg(0, EQ, sys.stdin)) - f.add_rule(ALLOW, "write", Arg(0, EQ, sys.stdout)) - f.add_rule(ALLOW, "write", Arg(0, EQ, sys.stderr)) + f.add_rule(ALLOW, "read", Arg(0, EQ, sys.stdin.fileno())) + f.add_rule(ALLOW, "write", Arg(0, EQ, sys.stdout.fileno())) + f.add_rule(ALLOW, "write", Arg(0, EQ, sys.stderr.fileno())) f.add_rule(ALLOW, "close") f.add_rule(ALLOW, "socket") f.add_rule(ALLOW, "connect") diff --git a/tests/17-sim-arch_merge.py b/tests/17-sim-arch_merge.py index 0221764..44e9cc4 100755 --- a/tests/17-sim-arch_merge.py +++ b/tests/17-sim-arch_merge.py @@ -37,9 +37,9 @@ def test(args): if not f64.exist_arch(Arch.X86_64): f64.add_arch(Arch.X86_64) f64.remove_arch(Arch.NATIVE) - f32.add_rule(ALLOW, "read", Arg(0, EQ, sys.stdin)) - f32.add_rule(ALLOW, "write", Arg(0, EQ, sys.stdout)) - f32.add_rule(ALLOW, "write", Arg(0, EQ, sys.stderr)) + f32.add_rule(ALLOW, "read", Arg(0, EQ, sys.stdin.fileno())) + f32.add_rule(ALLOW, "write", Arg(0, EQ, sys.stdout.fileno())) + f32.add_rule(ALLOW, "write", Arg(0, EQ, sys.stderr.fileno())) f32.add_rule(ALLOW, "close") f64.add_rule(ALLOW, "socket") f64.add_rule(ALLOW, "connect") -- cgit v1.2.1 From f95041f5dd08e98f5c5a5a7fb2e5a17da17eb1ef Mon Sep 17 00:00:00 2001 From: Andy Lutomirski Date: Tue, 22 Oct 2013 09:36:53 -0700 Subject: build: Hide non-public symbols Set -fvisibility=hidden and explicitly unhide public APIs. This overrides it with -fvisibility=default for Python because otherwise initseccomp gets hidden and the module won't load. Signed-off-by: Andy Lutomirski (minor style fixes and macro renames) Signed-off-by: Paul Moore --- macros.mk | 5 +++-- src/api.c | 68 +++++++++++++++++++++++++++++++++++---------------------------- 2 files changed, 41 insertions(+), 32 deletions(-) diff --git a/macros.mk b/macros.mk index 15529f6..6df5b3a 100644 --- a/macros.mk +++ b/macros.mk @@ -45,8 +45,9 @@ V ?= 0 CPPFLAGS += -I$(TOPDIR) -I$(TOPDIR)/include LIBFLAGS = -CFLAGS ?= -Wl,-z,relro -Wall -O0 -g +CFLAGS ?= -Wl,-z,relro -Wall -O0 -g -fvisibility=hidden CFLAGS += -fPIC +PYCFLAGS ?= -fvisibility=default LDFLAGS ?= -z relro -g # @@ -107,7 +108,7 @@ VERSION_HDR = version.h PY_DISTUTILS = \ VERSION_RELEASE="$(VERSION_RELEASE)" \ - CFLAGS="$(CFLAGS) $(CPPFLAGS)" LDFLAGS="$(LDFLAGS)" \ + CFLAGS="$(CFLAGS) $(CPPFLAGS) $(PYCFLAGS)" LDFLAGS="$(LDFLAGS)" \ $(PYTHON) ./setup.py ifeq ($(V),0) diff --git a/src/api.c b/src/api.c index 63d31c8..a5a1a9a 100644 --- a/src/api.c +++ b/src/api.c @@ -37,6 +37,8 @@ #include "gen_bpf.h" #include "system.h" +#define API __attribute__((visibility("default"))) + /** * Validate a filter context * @param ctx the filter context @@ -66,7 +68,7 @@ static int _syscall_valid(int syscall) } /* NOTE - function header comment in include/seccomp.h */ -scmp_filter_ctx seccomp_init(uint32_t def_action) +API scmp_filter_ctx seccomp_init(uint32_t def_action) { struct db_filter_col *col; struct db_filter *db; @@ -94,7 +96,7 @@ init_failure_col: } /* NOTE - function header comment in include/seccomp.h */ -int seccomp_reset(scmp_filter_ctx ctx, uint32_t def_action) +API int seccomp_reset(scmp_filter_ctx ctx, uint32_t def_action) { int rc; struct db_filter_col *col = (struct db_filter_col *)ctx; @@ -116,7 +118,7 @@ int seccomp_reset(scmp_filter_ctx ctx, uint32_t def_action) } /* NOTE - function header comment in include/seccomp.h */ -void seccomp_release(scmp_filter_ctx ctx) +API void seccomp_release(scmp_filter_ctx ctx) { if (_ctx_valid(ctx)) return; @@ -125,7 +127,8 @@ void seccomp_release(scmp_filter_ctx ctx) } /* NOTE - function header comment in include/seccomp.h */ -int seccomp_merge(scmp_filter_ctx ctx_dst, scmp_filter_ctx ctx_src) +API int seccomp_merge(scmp_filter_ctx ctx_dst, + scmp_filter_ctx ctx_src) { struct db_filter_col *col_dst = (struct db_filter_col *)ctx_dst; struct db_filter_col *col_src = (struct db_filter_col *)ctx_src; @@ -142,13 +145,14 @@ int seccomp_merge(scmp_filter_ctx ctx_dst, scmp_filter_ctx ctx_src) } /* NOTE - function header comment in include/seccomp.h */ -uint32_t seccomp_arch_native(void) +API uint32_t seccomp_arch_native(void) { return arch_def_native->token; } /* NOTE - function header comment in include/seccomp.h */ -int seccomp_arch_exist(const scmp_filter_ctx ctx, uint32_t arch_token) +API int seccomp_arch_exist(const scmp_filter_ctx ctx, + uint32_t arch_token) { struct db_filter_col *col = (struct db_filter_col *)ctx; @@ -162,7 +166,7 @@ int seccomp_arch_exist(const scmp_filter_ctx ctx, uint32_t arch_token) } /* NOTE - function header comment in include/seccomp.h */ -int seccomp_arch_add(scmp_filter_ctx ctx, uint32_t arch_token) +API int seccomp_arch_add(scmp_filter_ctx ctx, uint32_t arch_token) { int rc; const struct arch_def *arch; @@ -191,7 +195,7 @@ int seccomp_arch_add(scmp_filter_ctx ctx, uint32_t arch_token) } /* NOTE - function header comment in include/seccomp.h */ -int seccomp_arch_remove(scmp_filter_ctx ctx, uint32_t arch_token) +API int seccomp_arch_remove(scmp_filter_ctx ctx, uint32_t arch_token) { struct db_filter_col *col = (struct db_filter_col *)ctx; @@ -207,7 +211,7 @@ int seccomp_arch_remove(scmp_filter_ctx ctx, uint32_t arch_token) } /* NOTE - function header comment in include/seccomp.h */ -int seccomp_load(const scmp_filter_ctx ctx) +API int seccomp_load(const scmp_filter_ctx ctx) { int rc; struct db_filter_col *col; @@ -236,8 +240,8 @@ int seccomp_load(const scmp_filter_ctx ctx) } /* NOTE - function header comment in include/seccomp.h */ -int seccomp_attr_get(const scmp_filter_ctx ctx, - enum scmp_filter_attr attr, uint32_t *value) +API int seccomp_attr_get(const scmp_filter_ctx ctx, + enum scmp_filter_attr attr, uint32_t *value) { if (_ctx_valid(ctx)) return -EINVAL; @@ -246,8 +250,8 @@ int seccomp_attr_get(const scmp_filter_ctx ctx, } /* NOTE - function header comment in include/seccomp.h */ -int seccomp_attr_set(scmp_filter_ctx ctx, - enum scmp_filter_attr attr, uint32_t value) +API int seccomp_attr_set(scmp_filter_ctx ctx, + enum scmp_filter_attr attr, uint32_t value) { if (_ctx_valid(ctx)) return -EINVAL; @@ -256,7 +260,7 @@ int seccomp_attr_set(scmp_filter_ctx ctx, } /* NOTE - function header comment in include/seccomp.h */ -char *seccomp_syscall_resolve_num_arch(uint32_t arch_token, int num) +API char *seccomp_syscall_resolve_num_arch(uint32_t arch_token, int num) { const struct arch_def *arch; const char *name; @@ -277,7 +281,7 @@ char *seccomp_syscall_resolve_num_arch(uint32_t arch_token, int num) } /* NOTE - function header comment in include/seccomp.h */ -int seccomp_syscall_resolve_name_arch(uint32_t arch_token, const char *name) +API int seccomp_syscall_resolve_name_arch(uint32_t arch_token, const char *name) { const struct arch_def *arch; @@ -296,13 +300,14 @@ int seccomp_syscall_resolve_name_arch(uint32_t arch_token, const char *name) } /* NOTE - function header comment in include/seccomp.h */ -int seccomp_syscall_resolve_name(const char *name) +API int seccomp_syscall_resolve_name(const char *name) { return seccomp_syscall_resolve_name_arch(SCMP_ARCH_NATIVE, name); } /* NOTE - function header comment in include/seccomp.h */ -int seccomp_syscall_priority(scmp_filter_ctx ctx, int syscall, uint8_t priority) +API int seccomp_syscall_priority(scmp_filter_ctx ctx, + int syscall, uint8_t priority) { int rc = 0, rc_tmp; unsigned int iter; @@ -484,9 +489,10 @@ rule_add_return: } /* NOTE - function header comment in include/seccomp.h */ -int seccomp_rule_add_array(scmp_filter_ctx ctx, - uint32_t action, int syscall, unsigned int arg_cnt, - const struct scmp_arg_cmp *arg_array) +API int seccomp_rule_add_array(scmp_filter_ctx ctx, + uint32_t action, int syscall, + unsigned int arg_cnt, + const struct scmp_arg_cmp *arg_array) { if (arg_cnt < 0 || arg_cnt > ARG_COUNT_MAX) return -EINVAL; @@ -497,8 +503,9 @@ int seccomp_rule_add_array(scmp_filter_ctx ctx, /* NOTE - function header comment in include/seccomp.h */ -int seccomp_rule_add(scmp_filter_ctx ctx, - uint32_t action, int syscall, unsigned int arg_cnt, ...) +API int seccomp_rule_add(scmp_filter_ctx ctx, + uint32_t action, int syscall, + unsigned int arg_cnt, ...) { int rc; int iter; @@ -519,10 +526,10 @@ int seccomp_rule_add(scmp_filter_ctx ctx, /* NOTE - function header comment in include/seccomp.h */ -int seccomp_rule_add_exact_array(scmp_filter_ctx ctx, - uint32_t action, int syscall, - unsigned int arg_cnt, - const struct scmp_arg_cmp *arg_array) +API int seccomp_rule_add_exact_array(scmp_filter_ctx ctx, + uint32_t action, int syscall, + unsigned int arg_cnt, + const struct scmp_arg_cmp *arg_array) { if (arg_cnt < 0 || arg_cnt > ARG_COUNT_MAX) return -EINVAL; @@ -533,8 +540,9 @@ int seccomp_rule_add_exact_array(scmp_filter_ctx ctx, /* NOTE - function header comment in include/seccomp.h */ -int seccomp_rule_add_exact(scmp_filter_ctx ctx, uint32_t action, - int syscall, unsigned int arg_cnt, ...) +API int seccomp_rule_add_exact(scmp_filter_ctx ctx, + uint32_t action, int syscall, + unsigned int arg_cnt, ...) { int rc; int iter; @@ -555,7 +563,7 @@ int seccomp_rule_add_exact(scmp_filter_ctx ctx, uint32_t action, } /* NOTE - function header comment in include/seccomp.h */ -int seccomp_export_pfc(const scmp_filter_ctx ctx, int fd) +API int seccomp_export_pfc(const scmp_filter_ctx ctx, int fd) { if (_ctx_valid(ctx)) return -EINVAL; @@ -564,7 +572,7 @@ int seccomp_export_pfc(const scmp_filter_ctx ctx, int fd) } /* NOTE - function header comment in include/seccomp.h */ -int seccomp_export_bpf(const scmp_filter_ctx ctx, int fd) +API int seccomp_export_bpf(const scmp_filter_ctx ctx, int fd) { int rc; struct bpf_program *program; -- cgit v1.2.1 From bbac038b75ec9df641e774b470d56d9e0a587850 Mon Sep 17 00:00:00 2001 From: Paul Moore Date: Tue, 22 Oct 2013 17:36:55 -0400 Subject: api: fix some vertical whitespace mistakes Signed-off-by: Paul Moore --- src/api.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/api.c b/src/api.c index a5a1a9a..86e5f9d 100644 --- a/src/api.c +++ b/src/api.c @@ -501,7 +501,6 @@ API int seccomp_rule_add_array(scmp_filter_ctx ctx, 0, action, syscall, arg_cnt, arg_array); } - /* NOTE - function header comment in include/seccomp.h */ API int seccomp_rule_add(scmp_filter_ctx ctx, uint32_t action, int syscall, @@ -524,7 +523,6 @@ API int seccomp_rule_add(scmp_filter_ctx ctx, return rc; } - /* NOTE - function header comment in include/seccomp.h */ API int seccomp_rule_add_exact_array(scmp_filter_ctx ctx, uint32_t action, int syscall, @@ -538,7 +536,6 @@ API int seccomp_rule_add_exact_array(scmp_filter_ctx ctx, 1, action, syscall, arg_cnt, arg_array); } - /* NOTE - function header comment in include/seccomp.h */ API int seccomp_rule_add_exact(scmp_filter_ctx ctx, uint32_t action, int syscall, -- cgit v1.2.1