#!/bin/bash
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program 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 General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software Foundation,
# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.

SECCOMP_CONTAINERS_FILE="/usr/share/containers/seccomp.json"
SYSCALLS_TO_DENY=("sched_setscheduler" "sched_setattr")

QM_PATH_SECCOMP="/usr/share/qm/seccomp-no-rt.json"
QM_DIR="${QM_PATH_SECCOMP%/*}"

function remove_seccomp_entry_from_allow() {
    local syscall_name=$1
    local seccomp_file_path=$2

    temp_file=$(mktemp)
    jq --tab \
        --arg syscall "$syscall_name" \
        '(.syscalls[] | select(.names[] == $syscall and .action == "SCMP_ACT_ALLOW").names) |= map(select(. != $syscall))' \
        "${seccomp_file_path}" > "$temp_file" && mv "$temp_file" "${seccomp_file_path}"

    rm "$temp_file" &> /dev/null
}

function add_syscall_deny_list() {
    local syscall_name="$1"
    local seccomp_file_path="$2"

    temp_file=$(mktemp)
    jq --tab \
       --arg syscall "$syscall_name" \
       '.syscalls += [{"names": [$syscall], "action": "SCMP_ACT_ERRNO", "args": [], "errnoRet": 1, "errno": "EPERM"}]' \
       "${seccomp_file_path}" > "$temp_file" && mv "$temp_file" "${seccomp_file_path}"

    rm "$temp_file" &> /dev/null
}

# Main
if [ ! -f "${SECCOMP_CONTAINERS_FILE}" ]; then
    echo "Exiting... unable to find ${SECCOMP_CONTAINERS_FILE}"
    exit 1
fi

if [ ! -d "${QM_DIR}" ]; then
    echo "Exiting... unable to find ${QM_DIR}"
    exit 1
fi

# Copying original seccomp.json
cp "${SECCOMP_CONTAINERS_FILE}" "${QM_PATH_SECCOMP}"

for syscall in "${SYSCALLS_TO_DENY[@]}"; do
    # Remove syscall entry from the allow list
    remove_seccomp_entry_from_allow "${syscall}" "${QM_PATH_SECCOMP}"

    # Add syscall to the deny list
    add_syscall_deny_list "${syscall}" "${QM_PATH_SECCOMP}"
done
