aboutgitcodelistschat:MatrixIRC
diff options
context:
space:
mode:
-rw-r--r--Makefile4
-rwxr-xr-xfilter.sh265
-rwxr-xr-xnr_syscalls.sh63
3 files changed, 65 insertions, 267 deletions
diff --git a/Makefile b/Makefile
index 1555c5c..c2b600e 100644
--- a/Makefile
+++ b/Makefile
@@ -34,8 +34,8 @@ seitan: seitan.c transform.h
filter.h: qemu_filter
./filter.sh qemu_filter
-numbers.h: qemu_filter
- ./filter.sh qemu_filter
+numbers.h:
+ ./nr_syscalls.sh
transform.h: qemu_filter
./transform.sh qemu_filter
diff --git a/filter.sh b/filter.sh
deleted file mode 100755
index b3b85a2..0000000
--- a/filter.sh
+++ /dev/null
@@ -1,265 +0,0 @@
-#!/bin/sh -eu
-#
-# SPDX-License-Identifier: AGPL-3.0-or-later
-#
-# SEITAN - Syscall Expressive Interpreter, Transformer and Notifier
-#
-# filter.sh - Build binary-search tree BPF program with SECCOMP_RET_USER_NOTIF
-#
-# Copyright (c) 2022 Red Hat GmbH
-# Author: Stefano Brivio <sbrivio@redhat.com>
-
-TMP="$(mktemp)"
-IN="${@}"
-OUT="filter.h"
-OUT_NUMBERS="numbers.h"
-
-HEADER="/* This file was automatically generated by $(basename ${0}) */
-
-#ifndef AUDIT_ARCH_PPC64LE
-#define AUDIT_ARCH_PPC64LE (AUDIT_ARCH_PPC64 | __AUDIT_ARCH_LE)
-#endif"
-
-HEADER_NUMBERS="/* This file was automatically generated by $(basename ${0}) */
-struct syscall_numbers numbers[] = {"
-
-FOOTER_NUMBERS="};"
-
-# Prefix for each profile: check that 'arch' in seccomp_data is matching
-PRE='
-struct sock_filter @PROFILE@[] = {
- /* cppcheck-suppress badBitmaskCheck */
- BPF_STMT(BPF_LD | BPF_W | BPF_ABS,
- (offsetof(struct seccomp_data, arch))),
- BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, SEITAN_AUDIT_ARCH, 0, @KILL@),
- /* cppcheck-suppress badBitmaskCheck */
- BPF_STMT(BPF_LD | BPF_W | BPF_ABS,
- (offsetof(struct seccomp_data, nr))),
-
-'
-
-# Suffix for each profile: return actions
-POST=' BPF_STMT(BPF_RET | BPF_K, SECCOMP_RET_ALLOW),
- BPF_STMT(BPF_RET | BPF_K, SECCOMP_RET_USER_NOTIF),
-};
-'
-
-# Syscall, @NR@: number, @ALLOW@: offset to RET_ALLOW, @NAME@: syscall name
-CALL=' BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, @NR@, @ALLOW@, 0), /* @NAME@ */'
-
-# Binary search tree node or leaf, @NR@: value, @R@: right jump, @L@: left jump
-BST=' BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, @NR@, @R@, @L@),'
-
-# cleanup() - Remove temporary file if it exists
-cleanup() {
- rm -f "${TMP}"
-}
-#trap "cleanup" EXIT
-
-# sub() - Substitute in-place file line with processed template line
-# $1: Line number
-# $2: Template name (variable name)
-# $@: Replacement for @KEY@ in the form KEY:value
-sub() {
- IFS=
- __line_no="${1}"
- __template="$(eval printf '%s' "\${${2}}")"
- shift; shift
-
- sed -i "${__line_no}s#.*#${__template}#" "${TMP}"
-
- IFS=' '
- for __def in ${@}; do
- __key="@${__def%%:*}@"
- __value="${__def#*:}"
- sed -i "${__line_no}s/${__key}/${__value}/" "${TMP}"
- done
- unset IFS
-}
-
-# finish() - Finalise header file from temporary files with prefix and suffix
-# $1: Variable name of prefix
-# $@: Replacements for prefix variable
-finish() {
- IFS=
- __out="$(eval printf '%s' "\${${1}}")"
- shift
-
- IFS=' '
- for __def in ${@}; do
- __key="@${__def%%:*}@"
- __value="${__def#*:}"
- __out="$(printf '%s' "${__out}" | sed "s#${__key}#${__value}#")"
- done
-
- printf '%s\n' "${__out}" >> "${OUT}"
- cat "${TMP}" >> "${OUT}"
- rm "${TMP}"
- printf '%s' "${POST}" >> "${OUT}"
- unset IFS
-}
-
-# log2() - Binary logarithm
-# $1: Operand
-log2() {
- __x=-1
- __y=${1}
- while [ ${__y} -gt 0 ]; do : $((__y >>= 1)); __x=$((__x + 1)); done
- echo ${__x}
-}
-
-# syscall_nr - Get syscall number from compiler, also note in numbers.h
-# $1: Name of syscall
-syscall_nr() {
- __in="$(printf "#include <asm-generic/unistd.h>\n#include <sys/syscall.h>\n__NR_%s" ${1})"
- __out="$(echo "${__in}" | cc -E -xc - -o - | tail -1)"
- [ "${__out}" = "__NR_$1" ] && return 1
-
- # Output might be in the form "(x + y)" (seen on armv6l, armv7l)
- __out="$(eval echo $((${__out})))"
- echo "${__out}"
-
- printf "\t{ \"%s\",\t\t%i },\n" "${1}" "${__out}" >> "${OUT_NUMBERS}"
-}
-
-filter() {
- __filtered=
- for __c in ${@}; do
- __arch_match=0
- case ${__c} in
- *:*)
- case ${__c} in
- $(uname -m):*)
- __arch_match=1
- __c=${__c##*:}
- ;;
- esac
- ;;
- *)
- __arch_match=1
- ;;
- esac
- [ ${__arch_match} -eq 0 ] && continue
-
- IFS='| '
- __found=0
- for __name in ${__c}; do
- syscall_nr "${__name}" >/dev/null && __found=1 && break
- done
- unset IFS
-
- if [ ${__found} -eq 0 ]; then
- echo
- echo "Warning: no syscall number for ${__c}" >&2
- echo " none of these syscalls will be allowed" >&2
- continue
- fi
-
- __filtered="${__filtered} ${__name}"
- done
-
- echo "${__filtered}" | tr ' ' '\n' | sort -u
-}
-
-# gen_profile() - Build struct sock_filter for a single profile
-# $1: Profile name
-# $@: Names of allowed system calls, amount padded to next power of two
-gen_profile() {
- __profile="${1}"
- shift
-
- __statements_calls=${#}
- __bst_levels=$(log2 $(( __statements_calls / 4 )) )
- __statements_bst=$(( __statements_calls / 4 - 1 ))
- __statements=$((__statements_calls + __statements_bst))
-
- [ ${__bst_levels} -eq 0 ] && __statements_bst=0
- for __i in $(seq 1 ${__statements_bst} ); do
- echo -1 >> "${TMP}"
- done
-
- for __i in $(seq 1 ${__statements_calls} ); do
- __syscall_name="$(eval echo \${${__i}})"
- if ! syscall_nr ${__syscall_name} >> "${TMP}"; then
- echo "Cannot get syscall number for ${__syscall_name}"
- exit 1
- fi
- eval __syscall_nr_$(tail -1 "${TMP}")="${__syscall_name}"
- done
- sort -go "${TMP}" "${TMP}"
-
- __level_nodes=1
- __distance=$(( __statements_calls / 2 ))
- __ll=0
- __line=1
- for __level in $(seq 1 $(( __bst_levels - 1 )) ); do
- # Nodes
- __cmp_pos=${__distance}
-
- for __node in $(seq 1 ${__level_nodes}); do
- __cmp_line=$(( __statements_bst + __cmp_pos ))
- __lr=$(( __ll + 1 ))
- __nr="$(sed -n ${__cmp_line}p "${TMP}")"
-
- sub ${__line} BST "NR:${__nr}" "L:${__ll}" "R:${__lr}"
-
- __ll=${__lr}
- __line=$(( __line + 1 ))
- __cmp_pos=$(( __cmp_pos + __distance * 2 ))
- done
-
- __distance=$(( __distance / 2 ))
- __level_nodes=$(( __level_nodes * 2 ))
- done
-
- # Leaves
- if [ ${__bst_levels} -eq 0 ]; then
- __ll=0
- else
- __ll=$(( __level_nodes - 1 ))
- fi
- __lr=$(( __ll + __distance - 1 ))
- __cmp_pos=${__distance}
-
- for __leaf in $(seq 1 ${__level_nodes}); do
- __cmp_line=$(( __statements_bst + __cmp_pos ))
- __nr="$(sed -n ${__cmp_line}p "${TMP}")"
- sub ${__line} BST "NR:${__nr}" "L:${__ll}" "R:${__lr}"
-
- __ll=$(( __lr + __distance - 1 ))
- __lr=$(( __ll + __distance))
- __line=$(( __line + 1 ))
- __cmp_pos=$(( __cmp_pos + __distance * 2 ))
- done
-
- # Calls
- [ ${__bst_levels} -eq 0 ] && __statements_bst=$((__statements_bst + 1))
- for __i in $(seq $(( __statements_bst + 1 )) ${__statements}); do
- __nr="$(sed -n ${__i}p "${TMP}")"
- eval __name="\${__syscall_nr_${__nr}}"
- __allow=$(( __statements - __i + 1))
- sub ${__i} CALL "NR:${__nr}" "NAME:${__name}" "ALLOW:${__allow}"
- done
- finish PRE "PROFILE:${__profile}" "KILL:$(( __statements + 1))"
-}
-
-printf '%s\n' "${HEADER}" > "${OUT}"
-printf '%s\n' "${HEADER_NUMBERS}" > "${OUT_NUMBERS}"
-__profiles="${IN}"
-for __p in ${__profiles}; do
- __calls="$(sed -n 's/^\([^# \t]\{1,\}\).*/\1/p' "${__p}")"
- __calls="$(filter ${__calls})"
- echo "seccomp profile ${__p} handles: ${__calls}" | tr '\n' ' ' | fmt -t
-
- # Pad here to keep gen_profile() "simple"
- __count=0
- for __c in ${__calls}; do __count=$(( __count + 1 )); done
- __padded=$(( 1 << (( $(log2 ${__count}) + 1 )) ))
- for __i in $( seq ${__count} $(( __padded - 1 )) ); do
- __calls="${__calls} read"
- done
-
- gen_profile "${__p}" ${__calls}
-done
-
-printf '%s\n' "${FOOTER_NUMBERS}" >> "${OUT_NUMBERS}"
diff --git a/nr_syscalls.sh b/nr_syscalls.sh
new file mode 100755
index 0000000..9ad3d19
--- /dev/null
+++ b/nr_syscalls.sh
@@ -0,0 +1,63 @@
+#!/bin/sh -eu
+#
+# SPDX-License-Identifier: AGPL-3.0-or-later
+#
+# SEITAN - Syscall Expressive Interpreter, Transformer and Notifier
+#
+# filter.sh - Build binary-search tree BPF program with SECCOMP_RET_USER_NOTIF
+#
+# Copyright (c) 2022 Red Hat GmbH
+# Author: Stefano Brivio <sbrivio@redhat.com>
+
+IN="${@}"
+OUT_NUMBERS="numbers.h"
+
+HEADER_NUMBERS="/* This file was automatically generated by $(basename ${0}) */
+#ifndef NUMBERS_H_
+#define NUMBERS_H_
+
+struct syscall_numbers {
+ char name[1024];
+ long number;
+};
+
+struct syscall_numbers numbers[] = {"
+
+FOOTER_NUMBERS="};
+
+#endif"
+
+syscalls=(
+ "accept"
+ "bind"
+ "connect"
+ "getpeername"
+ "getsockname"
+ "getsockopt"
+ "listen"
+ "mount"
+ "openat"
+ "recvfrom"
+ "recvmmsg"
+ "recvmsg"
+ "sendmmsg"
+ "sendmsg"
+ "sendto"
+ "setsockopt"
+ "shutdown"
+ "socket"
+ "socketpair"
+)
+
+printf '%s\n' "${HEADER_NUMBERS}" > "${OUT_NUMBERS}"
+# syscall_nr - Get syscall number from compiler, also note in numbers.h
+__in="$(printf "#include <asm-generic/unistd.h>\n#include <sys/syscall.h>\n__NR_%s" ${syscalls[@]})"
+__out="$(echo "${__in}" |cc -E -xc - -o - |sed -n '/\#.*$/!p'| sed '/^$/d')"
+
+awk -v AS="${syscalls[*]}" -v BS="${__out[*]}" \
+'BEGIN { MAX=split(AS,a, / /); split(BS,b, / /);
+for (x = 1; x <= MAX; x++)
+ { printf "\t{\"%s\",\t%d},\n", a[x], b[x] }
+ }' >> "${OUT_NUMBERS}"
+
+printf '%s\n' "${FOOTER_NUMBERS}" >> "${OUT_NUMBERS}"