X-Git-Url: http://git.ieval.ro/?p=linux-seccomp.git;a=blobdiff_plain;f=libseccomp%2Fsrc%2Farch-syscall-validate;fp=libseccomp%2Fsrc%2Farch-syscall-validate;h=2a83098b7a105ce34ce844694ea4797b9dd91682;hp=0000000000000000000000000000000000000000;hb=8befd5cc4d2b478c697d81a5ac191083c203d081;hpb=bcf524c10c0ad85fcef711acffc3251bb8472352 diff --git a/libseccomp/src/arch-syscall-validate b/libseccomp/src/arch-syscall-validate new file mode 100755 index 0000000..2a83098 --- /dev/null +++ b/libseccomp/src/arch-syscall-validate @@ -0,0 +1,648 @@ +#!/bin/bash + +# +# libseccomp syscall validation script +# +# Copyright (c) 2014 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 . +# + +LIB_SYS_DUMP="./arch-syscall-dump" + +#### +# functions + +# +# Dependency check +# +# Arguments: +# 1 Dependency to check for +# +function check_deps() { + [[ -z "$1" ]] && return + which "$1" >& /dev/null + return $? +} + +# +# Dependency verification +# +# Arguments: +# 1 Dependency to check for +# +function verify_deps() { + [[ -z "$1" ]] && return + if ! check_deps "$1"; then + echo "error: install \"$1\" and include it in your \$PATH" + exit 1 + fi +} + +# +# Print out script usage details +# +function usage() { +cat << EOF +usage: arch-syscall-validate [-h] [-a ] + +libseccomp syscall validation script +optional arguments: + -h show this help message and exit + -a architecture + -l output the library's syscall definitions + -s output the system's syscall definitions +EOF +} + +# +# Dump the library syscall table for a given architecture +# +# Arguments: +# 1 architecture +# 2 offset (optional) +# +# +# Dump the library's syscall table to stdout. +# +function dump_lib_arch() { + local offset_str="" + + [[ -z $1 ]] && return + + [[ -n $2 ]] && offset_str="-o $2" + $LIB_SYS_DUMP -a $1 $offset_str | sed -e '/[^\t]\+\t-[0-9]\+/d' +} + +# +# Dump the x86 system syscall table +# +# Arguments: +# 1 path to the kernel source +# +# Dump the architecture's syscall table to stdout. +# +function dump_sys_x86() { + cat $1/arch/x86/entry/syscalls/syscall_32.tbl | \ + grep -v "^#" | awk '{ print $3"\t"$1 }' | sed '/^[ \t]*$/d' | \ + sort +} + +# +# Dump the x86 library syscall table +# +# Dump the library's syscall table to stdout. +# +function dump_lib_x86() { + dump_lib_arch x86 +} + +# +# Dump the x86_64 system syscall table +# +# Arguments: +# 1 path to the kernel source +# +# Dump the architecture's syscall table to stdout. +# +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 +} + +# +# Dump the x86_64 library syscall table +# +# Dump the library's syscall table to stdout. +# +function dump_lib_x86_64() { + dump_lib_arch x86_64 +} + +# +# Dump the x32 system syscall table +# +# Arguments: +# 1 path to the kernel source +# +# Dump the architecture's syscall table to stdout. +# +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 +} + +# +# Dump the x32 library syscall table +# +# Dump the library's syscall table to stdout. +# +function dump_lib_x32() { + # 1073741824 == 0x40000000 + dump_lib_arch x32 1073741824 +} + +# +# Dump the arm system syscall table +# +# Arguments: +# 1 path to the kernel source +# +# Dump the architecture's syscall table to stdout. +# +function dump_sys_arm() { + # NOTE: arm_sync_file_range() and sync_file_range2() share values + gcc -E -dM -D__ARM_EABI__ $1/arch/arm/include/uapi/asm/unistd.h | \ + grep "^#define __\(ARM_\)*NR_" | \ + grep -v "^#define __NR_OABI_SYSCALL_BASE" | \ + grep -v "^#define __NR_SYSCALL_BASE" | \ + grep -v "^#define __ARM_NR_BASE" | \ + sed -e 's/#define[ \t]\+__NR_\([^ \t]\+\)[ \t]\+(__NR_SYSCALL_BASE[ \t]*+[ \t]*\([0-9]\+\)).*/\1\t\2/;s/#define[ \t]\+__ARM_NR_\([^ \t]\+\)[ \t]\+(__ARM_NR_BASE[ \t]*+[ \t]*\([0-9]\+\)).*/\1\t983040 + \2/' | \ + while read line; do \ + if echo "$line" | grep -q "+"; then \ + echo "$line" | awk '{ print $1"\t"$2+$4 }'; \ + else \ + echo "$line"; \ + fi; \ + done | \ + sed -e '/#define __NR_sync_file_range2[ \t]\+__NR_arm_sync_file_range/d' | \ + sort +} + +# +# Dump the arm library syscall table +# +# Dump the library's syscall table to stdout. +# +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 the aarch64 system syscall table +# +# Arguments: +# 1 path to the kernel source +# +# Dump the architecture's syscall table to stdout. +# +function dump_sys_aarch64() { + gcc -E -dM -I$1/include/uapi -D__BITS_PER_LONG=64 $1/include/uapi/asm-generic/unistd.h | \ + grep "^#define __NR_" | \ + 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/__NR3264_statfs/43/' | \ + sed -e 's/__NR3264_ftruncate/46/' | \ + sed -e 's/__NR3264_truncate/45/' | \ + sed -e 's/__NR3264_lseek/62/' | \ + sed -e 's/__NR3264_sendfile/71/' | \ + sed -e 's/__NR3264_fstatat/79/' | \ + sed -e 's/__NR3264_fstatfs/44/' | \ + sed -e 's/__NR3264_fcntl/25/' | \ + sed -e 's/__NR3264_fadvise64/223/' | \ + sed -e 's/__NR3264_mmap/222/' | \ + sed -e 's/__NR3264_fstat/80/' | \ + sed -e 's/__NR3264_lstat/1039/' | \ + sed -e 's/__NR3264_stat/1038/' | \ + sort +} + +# +# Dump the aarch64 library syscall table +# +# Dump the library's syscall table to stdout. +# +function dump_lib_aarch64() { + dump_lib_arch aarch64 +} + +# +# Dump the mips system syscall table +# +# Arguments: +# 1 path to the kernel source +# +# Dump the architecture's syscall table to stdout. +# +function dump_sys_mips() { + # _MIPS_SIM values: + # _MIPS_SIM_ABI32 == 1 + # _MIPS_SIM_NABI32 == 2 + # _MIPS_SIM_ABI64 == 3 + gcc -E -dM -I$1/arch/mips/include/uapi -D_MIPS_SIM=1 $1/arch/mips/include/uapi/asm/unistd.h | \ + grep "^#define __NR_" | \ + grep -v "^#define __NR_O32_" | \ + grep -v "^#define __NR_N32_" | \ + grep -v "^#define __NR_64_" | \ + grep -v "^#define __NR_Linux" | \ + grep -v "^#define __NR_unused" | \ + grep -v "^#define __NR_reserved" | \ + sed -e 's/#define[ \t]\+__NR_\([^ \t]\+\)[ \t]\+(__NR_Linux[ \t]*+[ \t]*\([0-9]\+\)).*/\1\t\2/' | \ + sort +} + +# +# Dump the mips library syscall table +# +# Dump the library's syscall table to stdout. +# +function dump_lib_mips() { + dump_lib_arch mips 4000 +} + +# +# Dump the mips64 system syscall table +# +# Arguments: +# 1 path to the kernel source +# +# Dump the architecture's syscall table to stdout. +# +function dump_sys_mips64() { + # _MIPS_SIM values: + # _MIPS_SIM_ABI32 == 1 + # _MIPS_SIM_NABI32 == 2 + # _MIPS_SIM_ABI64 == 3 + gcc -E -dM -I$1/arch/mips/include/uapi -D_MIPS_SIM=3 $1/arch/mips/include/uapi/asm/unistd.h | \ + grep "^#define __NR_" | \ + grep -v "^#define __NR_O32_" | \ + grep -v "^#define __NR_N32_" | \ + grep -v "^#define __NR_64_" | \ + grep -v "^#define __NR_Linux" | \ + grep -v "^#define __NR_unused" | \ + grep -v "^#define __NR_reserved" | \ + sed -e 's/#define[ \t]\+__NR_\([^ \t]\+\)[ \t]\+(__NR_Linux[ \t]*+[ \t]*\([0-9]\+\)).*/\1\t\2/' | \ + sort +} + +# +# Dump the mips64 library syscall table +# +# Dump the library's syscall table to stdout. +# +function dump_lib_mips64() { + dump_lib_arch mips64 5000 +} + +# +# Dump the mips64n32 system syscall table +# +# Arguments: +# 1 path to the kernel source +# +# Dump the architecture's syscall table to stdout. +# +function dump_sys_mips64n32() { + # _MIPS_SIM values: + # _MIPS_SIM_ABI32 == 1 + # _MIPS_SIM_NABI32 == 2 + # _MIPS_SIM_ABI64 == 3 + gcc -E -dM -I$1/arch/mips/include/uapi -D_MIPS_SIM=2 $1/arch/mips/include/uapi/asm/unistd.h | \ + grep "^#define __NR_" | \ + grep -v "^#define __NR_O32_" | \ + grep -v "^#define __NR_N32_" | \ + grep -v "^#define __NR_64_" | \ + grep -v "^#define __NR_Linux" | \ + grep -v "^#define __NR_unused" | \ + grep -v "^#define __NR_reserved" | \ + sed -e 's/#define[ \t]\+__NR_\([^ \t]\+\)[ \t]\+(__NR_Linux[ \t]*+[ \t]*\([0-9]\+\)).*/\1\t\2/' | \ + sort +} + +# +# Dump the mips64n32 library syscall table +# +# Dump the library's syscall table to stdout. +# +function dump_lib_mips64n32() { + dump_lib_arch mips64n32 6000 +} + +# +# Dump the ppc system syscall table +# +# Arguments: +# 1 path to the kernel source +# +# Dump the architecture's syscall table to stdout. +# +function dump_sys_ppc() { + gcc -E -dM $1/arch/powerpc/include/uapi/asm/unistd.h | \ + grep "^#define __NR_" | \ + sed -e 's/#define[ \t]\+__NR_\([a-z0-9_]\+\)[ \t]\+\([0-9]\+\)/\1\t\2/' | \ + sort +} + +# +# Dump the ppc library syscall table +# +# Dump the library's syscall table to stdout. +# +function dump_lib_ppc() { + dump_lib_arch ppc +} + +# +# Dump the ppc64 system syscall table +# +# Arguments: +# 1 path to the kernel source +# +# Dump the architecture's syscall table to stdout. +# +function dump_sys_ppc64() { + gcc -E -dM -D__powerpc64__ $1/arch/powerpc/include/uapi/asm/unistd.h | \ + grep "^#define __NR_" | \ + sed -e 's/#define[ \t]\+__NR_\([a-z0-9_]\+\)[ \t]\+\([0-9]\+\)/\1\t\2/' | \ + sort +} + +# +# Dump the ppc64 library syscall table +# +# Dump the library's syscall table to stdout. +# +function dump_lib_ppc64() { + dump_lib_arch ppc64 +} + +# +# Dump the s390 system syscall table +# +# Arguments: +# 1 path to the kernel source +# +# Dump the architecture's syscall table to stdout. +# +function dump_sys_s390() { + gcc -E -dM $1/arch/s390/include/uapi/asm/unistd.h | grep __NR | \ + sed -e 's/#define[ \t]\+__NR_\([^ \t]\+\)[ \t]\+(__NR_timer_create[ \t]*+[ \t]*\([0-9]\+\)).*/\1\t254 + \2/' | \ + while read line; do \ + if echo "$line" | grep -q "+"; then \ + echo "$line" | awk '{ print $1"\t"$2+$4 }'; \ + else \ + echo "$line"; \ + fi; \ + done | \ + sed 's/#define __NR_//g' | sed 's/ /\t/g' | sort +} + +# +# Dump the s390 library syscall table +# +# Dump the library's syscall table to stdout. +# +function dump_lib_s390() { + dump_lib_arch s390 +} + +# +# Dump the s390x system syscall table +# +# Arguments: +# 1 path to the kernel source +# +# Dump the architecture's syscall table to stdout. +# +function dump_sys_s390x() { + gcc -E -dM -D __s390x__ $1/arch/s390/include/uapi/asm/unistd.h | grep __NR | \ + sed -e 's/#define[ \t]\+__NR_\([^ \t]\+\)[ \t]\+(__NR_timer_create[ \t]*+[ \t]*\([0-9]\+\)).*/\1\t254 + \2/' | \ + while read line; do \ + if echo "$line" | grep -q "+"; then \ + echo "$line" | awk '{ print $1"\t"$2+$4 }'; \ + else \ + echo "$line"; \ + fi; \ + done | \ + sed 's/#define __NR_//g' | sed 's/ /\t/g' | sort +} + +# +# Dump the s390x library syscall table +# +# Dump the library's syscall table to stdout. +# +function dump_lib_s390x() { + dump_lib_arch s390x +} + +# +# Dump the system syscall table +# +# Arguments: +# 1 architecture +# 2 path to the kernel source +# +# Dump the system's syscall table to stdout using the given architecture. +# +function dump_sys() { + case $1 in + x86) + dump_sys_x86 "$2" + ;; + x86_64) + dump_sys_x86_64 "$2" + ;; + x32) + dump_sys_x32 "$2" + ;; + arm) + dump_sys_arm "$2" + ;; + aarch64) + dump_sys_aarch64 "$2" + ;; + mips) + dump_sys_mips "$2" + ;; + mips64) + dump_sys_mips64 "$2" + ;; + mips64n32) + dump_sys_mips64n32 "$2" + ;; + ppc) + dump_sys_ppc "$2" + ;; + ppc64) + dump_sys_ppc64 "$2" + ;; + s390) + dump_sys_s390 "$2" + ;; + s390x) + dump_sys_s390x "$2" + ;; + *) + echo "" + return 1 + ;; + esac + + return 0 +} + +# +# Dump the library syscall table +# +# Arguments: +# 1 architecture +# +# Dump the library's syscall table to stdout using the given architecture. +# +function dump_lib() { + case $1 in + x86) + dump_lib_x86 + ;; + x86_64) + dump_lib_x86_64 + ;; + x32) + dump_lib_x32 + ;; + arm) + dump_lib_arm + ;; + aarch64) + dump_lib_aarch64 + ;; + mips) + dump_lib_mips + ;; + mips64) + dump_lib_mips64 + ;; + mips64n32) + dump_lib_mips64n32 + ;; + ppc) + dump_lib_ppc "$2" + ;; + ppc64) + dump_lib_ppc64 "$2" + ;; + s390) + dump_lib_s390 "$2" + ;; + s390x) + dump_lib_s390x "$2" + ;; + *) + echo "" + return 1 + ;; + esac + + return 0 +} + +#### +# main + +verify_deps diff +verify_deps gcc +verify_deps grep +verify_deps mktemp +verify_deps sed +if [[ ! -x $LIB_SYS_DUMP ]]; then + echo "error: \"$LIB_SYS_DUMP\" is not in the current working directory" + exit 1 +fi + +opt_arches="" +opt_sys="" +opt_lib="" + +while getopts "a:slh" opt; do + case $opt in + a) + opt_arches+="$OPTARG " + ;; + s) + opt_sys=1 + opt_lib=0 + ;; + l) + opt_sys=0 + opt_lib=1 + ;; + h|*) + usage + exit 1 + ;; + esac +done +shift $(($OPTIND - 1)) + +# defaults +if [[ $opt_arches == "" ]]; then + opt_arches=" \ + x86 x86_64 x32 \ + arm aarch64 \ + mips mips64 mips64n32 \ + ppc ppc64 \ + s390 s390x" +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 +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 + +# cleanup and exit +rm -f $tmp_lib $tmp_sys + +exit 0