Skip to content

Instantly share code, notes, and snippets.

@pcmoore
Created March 20, 2020 03:46
Show Gist options
  • Select an option

  • Save pcmoore/c33e64237798f05b3ecafca19c5221e5 to your computer and use it in GitHub Desktop.

Select an option

Save pcmoore/c33e64237798f05b3ecafca19c5221e5 to your computer and use it in GitHub Desktop.
arch: rework/fix the arch-syscall-validate script
arch: rework/fix the arch-syscall-validate script
From: Paul Moore <paul@paul-moore.com>
Update the arch-syscall-validate script to be "CSV friendly" in
preparation for follow-up work to move the libseccomp internal
syscall tables into a single CVS file. This is a rather crude
effort, but it works and should serve to get things moving; we can
optimize it later.
In this process of making this change, a few unrelated problems with
the script were identified and fixed.
Signed-off-by: Paul Moore <paul@paul-moore.com>
---
src/arch-syscall-validate | 222 ++++++++++++++++++++++++++++++---------------
1 file changed, 147 insertions(+), 75 deletions(-)
diff --git a/src/arch-syscall-validate b/src/arch-syscall-validate
index a699c6a..1a508bf 100755
--- a/src/arch-syscall-validate
+++ b/src/arch-syscall-validate
@@ -4,6 +4,8 @@
# libseccomp syscall validation script
#
# Copyright (c) 2014 Red Hat <pmoore@redhat.com>
+# Copyright (c) 2020 Cisco Systems, Inc. <pmoore2@cisco.com>
+#
# Author: Paul Moore <paul@paul-moore.com>
#
@@ -57,17 +59,34 @@ function verify_deps() {
#
function usage() {
cat << EOF
-usage: arch-syscall-validate [-h] [-a <arch>] <kernel_directory>
+usage: arch-syscall-validate [-h] [-c] [-a <arch>] <kernel_directory>
libseccomp syscall validation script
optional arguments:
-h show this help message and exit
-a architecture
-l output the library's syscall definitions
- -s output the system's syscall definitions
+ -s output the kernel's syscall definitions
+ -c generate a CSV of the kernel's syscall definitions
EOF
}
+#
+# Dump the kernel version
+#
+# Arguments:
+# 1 path to the kernel source
+#
+# Dump the kernel's version information to stdout.
+#
+function kernel_version() {
+ local maj=$(cat $1/Makefile | grep "^VERSION =" | awk -F "= " '{ print $2 }')
+ local min=$(cat $1/Makefile | grep "^PATCHLEVEL =" | awk -F "= " '{ print $2 }')
+ local sub=$(cat $1/Makefile | grep "^SUBLEVEL =" | awk -F "= " '{ print $2 }')
+ local xtr=$(cat $1/Makefile | grep "^EXTRAVERSION =" | awk -F "= " '{ print $2 }')
+ echo "${maj}.${min}.${sub}${xtr}"
+}
+
#
# Dump the library syscall table for a given architecture
#
@@ -84,7 +103,9 @@ function dump_lib_arch() {
[[ -z $1 ]] && return
[[ -n $2 ]] && offset_str="-o $2"
- $LIB_SYS_DUMP -a $1 $offset_str | sed -e '/[^\t]\+\t-[0-9]\+/d' | sort
+ $LIB_SYS_DUMP -a $1 $offset_str | \
+ sed -e 's/\t/,/' | sed -e '/ -[0-9]\+$/d' | \
+ sort
}
#
@@ -97,11 +118,7 @@ function dump_lib_arch() {
#
function dump_sys_x86() {
cat $1/arch/x86/entry/syscalls/syscall_32.tbl | \
- grep -v "^#" | awk '{ print $3"\t"$1 }' | sed '/^[ \t]*$/d' | \
- grep -P -v '^accept4\t|^^bind\t|^connect\t|^getpeername\t|^getsockname\t|^getsockopt\t|^listen\t' | \
- grep -P -v '^recvfrom\t|^recvmmsg\t|^sendmmsg\t|^sendmsg\t|^sendto\t|^setsockopt\t|^shmat\t|^shmctl\t' | \
- grep -P -v '^shmdt\t|^shmget\t|^shutdown\t|^socket\t|^socketpair\t' | \
- grep -P -v '^msgctl\t|^msgget\t|^msgrcv\t|^msgsnd\t|^semctl\t|^semget\t' | \
+ grep -v "^#" | awk '{ print $3","$1 }' | \
sort
}
@@ -124,8 +141,10 @@ function dump_lib_x86() {
#
function dump_sys_x86_64() {
cat $1/arch/x86/entry/syscalls/syscall_64.tbl | \
- grep -v "^#" | awk '{ print $2,$3,$1 }' | sed -e '/^x32/d' | \
- awk '{ print $2"\t"$3 }' | sed '/^[ \t]*$/d' | sort
+ grep -v "^#" | sed '/^$/d' | awk '{ print $2,$3,$1 }' | \
+ sed -e '/^x32/d' | \
+ awk '{ print $2","$3 }' | \
+ sort
}
#
@@ -147,8 +166,9 @@ function dump_lib_x86_64() {
#
function dump_sys_x32() {
cat $1/arch/x86/entry/syscalls/syscall_64.tbl | \
- grep -v "^#" | awk '{ print $2,$3,$1 }' | sed -e '/^64/d' | \
- awk '{ print $2"\t"$3 }' | sed '/^[ \t]*$/d' | sort
+ grep -v "^#" | sed '/^$/d' | awk '{ print $2,$3,$1 }' | \
+ sed -e '/^64/d' | awk '{ print $2","$3 }' | \
+ sort
}
#
@@ -172,11 +192,11 @@ function dump_lib_x32() {
function dump_sys_arm() {
cat $1/arch/arm/tools/syscall.tbl | grep -v "^#" | \
sed -ne "/[0-9]\+[ \t]\+\(common\|eabi\)/p" | \
- awk '{ print $3"\t"$1 }' | sort | (cat -; \
+ awk '{ print $3","$1 }' | sort | (cat -; \
(cat $1/arch/arm/include/uapi/asm/unistd.h | \
grep "^#define __ARM_NR_" | grep -v "^#define __ARM_NR_BASE" | \
sed -e 's/#define __ARM_NR_\([a-z0-9_]*\)[ \t]\+(__ARM_NR_BASE+\(.*\))/\1 983040 + \2/' | \
- awk '{ print $1"\t"$2+$4 }')) | sort
+ awk '{ print $1","$2+$4 }')) | sort
}
#
@@ -186,7 +206,7 @@ function dump_sys_arm() {
#
function dump_lib_arm() {
# NOTE: arm_sync_file_range() and sync_file_range2() share values
- dump_lib_arch arm | sed -e '/sync_file_range2[ \t]\+341/d'
+ dump_lib_arch arm | sed -e '/sync_file_range2,\+341/d'
}
#
@@ -205,7 +225,7 @@ function dump_sys_aarch64() {
grep "^#define __NR_" | \
sed -e '/__NR_syscalls/d' | \
sed -e '/__NR_arch_specific_syscall/d' | \
- sed -e 's/#define[ \t]\+__NR_\([^ \t]\+\)[ \t]\+\(.*\)/\1\t\2/' | \
+ sed -e 's/#define[ \t]\+__NR_\([^ \t]\+\)[ \t]\+\(.*\)/\1,\2/' | \
sed -e 's/__NR3264_statfs/43/' | \
sed -e 's/__NR3264_ftruncate/46/' | \
sed -e 's/__NR3264_truncate/45/' | \
@@ -255,7 +275,7 @@ function dump_sys_mips() {
grep -v "^#define __NR_Linux" | \
grep -v "^#define __NR_unused" | \
grep -v "^#define __NR_reserved" | \
- sed -e 's/#define[ \t]\+__NR_\([^ \t]\+\)[ \t]\+(__NR_Linux[ \t]*+[ \t]*\([0-9]\+\)).*/\1\t\2/' | \
+ sed -e 's/#define[ \t]\+__NR_\([^ \t]\+\)[ \t]\+(__NR_Linux[ \t]*+[ \t]*\([0-9]\+\)).*/\1,\2/' | \
sort
}
@@ -292,7 +312,7 @@ function dump_sys_mips64() {
grep -v "^#define __NR_Linux" | \
grep -v "^#define __NR_unused" | \
grep -v "^#define __NR_reserved" | \
- sed -e 's/#define[ \t]\+__NR_\([^ \t]\+\)[ \t]\+(__NR_Linux[ \t]*+[ \t]*\([0-9]\+\)).*/\1\t\2/' | \
+ sed -e 's/#define[ \t]\+__NR_\([^ \t]\+\)[ \t]\+(__NR_Linux[ \t]*+[ \t]*\([0-9]\+\)).*/\1,\2/' | \
sort
}
@@ -329,7 +349,7 @@ function dump_sys_mips64n32() {
grep -v "^#define __NR_Linux" | \
grep -v "^#define __NR_unused" | \
grep -v "^#define __NR_reserved" | \
- sed -e 's/#define[ \t]\+__NR_\([^ \t]\+\)[ \t]\+(__NR_Linux[ \t]*+[ \t]*\([0-9]\+\)).*/\1\t\2/' | \
+ sed -e 's/#define[ \t]\+__NR_\([^ \t]\+\)[ \t]\+(__NR_Linux[ \t]*+[ \t]*\([0-9]\+\)).*/\1,\2/' | \
sort
}
@@ -353,11 +373,11 @@ function dump_lib_mips64n32() {
function dump_sys_ppc() {
cat $1/arch/powerpc/kernel/syscalls/syscall.tbl | grep -v "^#" | \
sed -ne "/[0-9]\+[ \t]\+\(common\|nospu\|32\)/p" | \
- awk '{ print $3"\t"$1 }' | sort | (cat -; \
+ awk '{ print $3","$1 }' | sort | (cat -; \
(cat $1/arch/powerpc/include/uapi/asm/unistd.h | \
grep "^#define __PPC_NR_" | grep -v "^#define __PPC_NR_BASE" | \
sed -e 's/#define _PPC_NR_\([a-z0-9_]*\)[ \t]\+(__PPC_NR_BASE+\(.*\))/\1 983040 + \2/' | \
- awk '{ print $1"\t"$2+$4 }')) | sort
+ awk '{ print $1","$2+$4 }')) | sort
}
#
@@ -380,11 +400,11 @@ function dump_lib_ppc() {
function dump_sys_ppc64() {
cat $1/arch/powerpc/kernel/syscalls/syscall.tbl | grep -v "^#" | \
sed -ne "/[0-9]\+[ \t]\+\(common\|nospu\|64\)/p" | \
- awk '{ print $3"\t"$1 }' | sort | (cat -; \
+ awk '{ print $3","$1 }' | sort | (cat -; \
(cat $1/arch/powerpc/include/uapi/asm/unistd.h | \
grep "^#define __PPC_NR_" | grep -v "^#define __PPC_NR_BASE" | \
sed -e 's/#define _PPC_NR_\([a-z0-9_]*\)[ \t]\+(__PPC_NR_BASE+\(.*\))/\1 983040 + \2/' | \
- awk '{ print $1"\t"$2+$4 }')) | sort
+ awk '{ print $1","$2+$4 }')) | sort
}
#
@@ -407,11 +427,12 @@ function dump_lib_ppc64() {
function dump_sys_riscv64() {
gcc -E -dM -I$1/include/uapi \
-D__BITS_PER_LONG=64 -D__ARCH_WANT_NEW_STAT \
- $1/include/uapi/asm-generic/unistd.h | \
+ $1/arch/riscv/include/uapi/asm/unistd.h | \
grep "^#define __NR_" | \
sed -e '/__NR_syscalls/d' | \
+ sed -e 's/(__NR_arch_specific_syscall + 15)/259/' | \
sed -e '/__NR_arch_specific_syscall/d' | \
- sed -e 's/#define[ \t]\+__NR_\([^ \t]\+\)[ \t]\+\(.*\)/\1\t\2/' | \
+ sed -e 's/#define[ \t]\+__NR_\([^ \t]\+\)[ \t]\+\(.*\)/\1,\2/' | \
sed -e 's/__NR3264_fadvise64/223/' | \
sed -e 's/__NR3264_fcntl/25/' | \
sed -e 's/__NR3264_fstatat/79/' | \
@@ -446,15 +467,8 @@ function dump_lib_riscv64() {
function dump_sys_s390() {
cat $1/arch/s390/kernel/syscalls/syscall.tbl | grep -v "^#" | \
sed -ne "/[0-9]\+[ \t]\+\(common\|32\)/p" | \
- awk '{ print $3"\t"$1 }' | sort | (cat -; \
- (cat $1/arch/s390/include/uapi/asm/unistd.h | \
- grep "^#define __PPC_NR_" | grep -v "^#define __PPC_NR_BASE" | \
- sed -e 's/#define _PPC_NR_\([a-z0-9_]*\)[ \t]\+(__PPC_NR_BASE+\(.*\))/\1 983040 + \2/' | \
- awk '{ print $1"\t"$2+$4 }')) | \
- grep -P -v '^accept4\t|^^bind\t|^connect\t|^getpeername\t|^getsockname\t|^getsockopt\t|^listen\t' | \
- grep -P -v '^recvfrom\t|^recvmmsg\t|^sendmmsg\t|^sendmsg\t|^sendto\t|^setsockopt\t|^shmat\t|^shmctl\t' | \
- grep -P -v '^shmdt\t|^shmget\t|^shutdown\t|^socket\t|^socketpair\t' | \
- sort
+ awk '{ print $3","$1 }' | \
+ sort
}
#
@@ -477,15 +491,8 @@ function dump_lib_s390() {
function dump_sys_s390x() {
cat $1/arch/s390/kernel/syscalls/syscall.tbl | grep -v "^#" | \
sed -ne "/[0-9]\+[ \t]\+\(common\|64\)/p" | \
- awk '{ print $3"\t"$1 }' | sort | (cat -; \
- (cat $1/arch/s390/include/uapi/asm/unistd.h | \
- grep "^#define __PPC_NR_" | grep -v "^#define __PPC_NR_BASE" | \
- sed -e 's/#define _PPC_NR_\([a-z0-9_]*\)[ \t]\+(__PPC_NR_BASE+\(.*\))/\1 983040 + \2/' | \
- awk '{ print $1"\t"$2+$4 }')) | \
- grep -P -v '^accept4\t|^^bind\t|^connect\t|^getpeername\t|^getsockname\t|^getsockopt\t|^listen\t' | \
- grep -P -v '^recvfrom\t|^recvmmsg\t|^sendmmsg\t|^sendmsg\t|^sendto\t|^setsockopt\t|^shmat\t|^shmctl\t' | \
- grep -P -v '^shmdt\t|^shmget\t|^shutdown\t|^socket\t|^socketpair\t' | \
- sort
+ awk '{ print $3","$1 }' | \
+ sort
}
#
@@ -614,6 +621,60 @@ function dump_lib() {
return 0
}
+#
+# Generate the syscall csv file
+#
+# Arguments:
+# 1 path to the kernel source
+#
+# Generare a syscall csv file from the given kernel sources.
+#
+function gen_csv() {
+
+ # NOTE: we can do soooo much better than this, but this is a quick
+ # hack and it seems to work
+
+ # abi list
+ abi_list=""
+ abi_list+=" x86 x86_64 x32"
+ abi_list+=" arm aarch64"
+ abi_list+=" mips mips64 mips64n32"
+ abi_list+=" ppc ppc64"
+ abi_list+=" riscv64"
+ abi_list+=" s390 s390x"
+
+ # get the full syscall list
+ sc_list=$((dump_sys_x86 "$1"; dump_sys_x86_64 "$1"; dump_sys_x32 "$1"; \
+ dump_sys_arm "$1"; dump_sys_aarch64 "$1"; \
+ dump_sys_mips "$1"; dump_sys_mips64 "$1";
+ dump_sys_mips64n32 "$1"; \
+ dump_sys_ppc "$1"; dump_sys_ppc64 "$1"; \
+ dump_sys_riscv64 "$1"; \
+ dump_sys_s390 "$1"; dump_sys_s390x "$1") | \
+ awk -F "," '{ print $1 }' | sort -u)
+
+ # output a simple header
+ printf "# libseccomp syscall table\n"
+ printf "#\n"
+ printf "# kernel: %s (%s)\n" "$(kernel_version "$1")" "$(TZ=UTC date -R)"
+ printf "#\n"
+ printf "#syscall"
+ for abi in $abi_list; do
+ printf ",%s" $abi
+ done
+ printf "\n"
+ # output the syscall csv details
+ for sc in $sc_list; do
+ printf "%s" $sc
+ for abi in $abi_list; do
+ num=$(dump_sys_$abi "$1" | grep "^$sc," | awk -F "," '{ print $2 }' )
+ [[ -z $num ]] && num="PNR"
+ printf ",%s" $num
+ done
+ printf "\n"
+ done
+}
+
####
# main
@@ -628,14 +689,18 @@ if [[ ! -x $LIB_SYS_DUMP ]]; then
fi
opt_arches=""
+opt_csv=""
opt_sys=""
opt_lib=""
-while getopts "a:slh" opt; do
+while getopts "a:cslh" opt; do
case $opt in
a)
opt_arches+="$OPTARG "
;;
+ c)
+ opt_csv=1
+ ;;
s)
opt_sys=1
opt_lib=0
@@ -664,43 +729,50 @@ fi
# sanity checks
kernel_dir="$1"
-if [[ -z $kernel_dir ]]; then
- usage
- exit 1
-fi
-if [[ ! -d $kernel_dir ]]; then
- echo "error: \"$1\" is not a valid directory"
- exit 1
+if [[ $opt_csv -eq 1 || $opt_sys -eq 1 ]]; then
+ if [[ -z $kernel_dir ]]; then
+ usage
+ exit 1
+ fi
+ if [[ ! -d $kernel_dir ]]; then
+ echo "error: \"$1\" is not a valid directory"
+ exit 1
+ fi
fi
# generate some temp files
tmp_lib=$(mktemp -t syscall_validate_XXXXXX)
tmp_sys=$(mktemp -t syscall_validate_XXXXXX)
-# loop through the architectures and compare
-for i in $opt_arches; do
- # dump the syscall tables
- dump_lib $i > $tmp_lib
- if [[ $? -ne 0 ]]; then
- echo "error: unknown arch $i"
- exit 1
- fi
- dump_sys $i "$kernel_dir" > $tmp_sys
- if [[ $? -ne 0 ]]; then
- echo "error: unknown arch $i"
- exit 1
- fi
-
- if [[ $opt_lib -eq 1 ]]; then
- cat $tmp_lib
- elif [[ $opt_sys -eq 1 ]]; then
- cat $tmp_sys
- else
- # compare the lib and sys output
- diff -u --label="$i [library]" $tmp_lib \
- --label "$i [system]" $tmp_sys
- fi
-done
+if [[ $opt_csv -eq 1 ]]; then
+ # generate the syscall csv file
+ gen_csv $kernel_dir
+else
+ # loop through the architectures and compare
+ for i in $opt_arches; do
+ # dump the syscall tables
+ dump_lib $i > $tmp_lib
+ if [[ $? -ne 0 ]]; then
+ echo "error: unknown arch $i"
+ exit 1
+ fi
+ dump_sys $i "$kernel_dir" > $tmp_sys
+ if [[ $? -ne 0 ]]; then
+ echo "error: unknown arch $i"
+ exit 1
+ fi
+
+ if [[ $opt_lib -eq 1 ]]; then
+ cat $tmp_lib
+ elif [[ $opt_sys -eq 1 ]]; then
+ cat $tmp_sys
+ else
+ # compare the lib and sys output
+ diff -u --label="$i [library]" $tmp_lib \
+ --label "$i [system]" $tmp_sys
+ fi
+ done
+fi
# cleanup and exit
rm -f $tmp_lib $tmp_sys
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment