Skip to content

Commit

Permalink
Pre jail unit test (#1835)
Browse files Browse the repository at this point in the history
#1825 improved the sandbox mode. This PR adds a unit test to catch obvious sandbox configuration oversights.

It works by creating a small application that installs a seccomp filter. Any syscalls, except a small subset, invoked by AWS-LC will trigger the filter. We both check that the filter will trip on AWS-LC without configuration sandbox mode and that the filter doesn't trip when sandbox mode is configured.
  • Loading branch information
torben-hansen authored Sep 9, 2024
1 parent 8835f07 commit 8968399
Show file tree
Hide file tree
Showing 4 changed files with 163 additions and 0 deletions.
28 changes: 28 additions & 0 deletions .github/workflows/misc-tests.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
name: Misc tests
on:
push:
branches: [ '*' ]
pull_request:
branches: [ '*' ]
concurrency:
group: ${{ github.workflow }}-${{ github.ref_name }}
cancel-in-progress: true
jobs:
pre-sandbox:
if: github.repository_owner == 'aws'
runs-on: ubuntu-latest
steps:
- name: Install OS Dependencies
run: |
sudo apt-get update -o Acquire::Languages=none -o Acquire::Translation=none
sudo apt-get -y --no-install-recommends install \
cmake clang ninja-build golang
echo "CC=clang" >> $GITHUB_ENV
echo "CXX=clang++" >> $GITHUB_ENV
- name: Install seccomp dependencies
run: |
sudo apt-get -y --no-install-recommends install libseccomp-dev
- uses: actions/checkout@v3
- name: Test sandbox configuration
run: |
./tests/ci/run_presandbox_tests.sh
5 changes: 5 additions & 0 deletions SANDBOXING.md
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,11 @@ Once initialized, this mechanism does not require system calls in the steady
state, though note the configured page will be inherited across privilege
transitions.

### Snapsafe protection

Similar considerations to fork protection. The Snapsafe protection
implementation maps a page that can trip sandboxes.

## C and C++ standard library

BoringSSL depends on the C and C++ standard libraries which, themselves, do not
Expand Down
70 changes: 70 additions & 0 deletions tests/ci/run_presandbox_tests.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
#!/usr/bin/env bash
# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
# SPDX-License-Identifier: Apache-2.0 OR ISC

# We expect an executable failure in this test. Hence, don't use -e.
set -xo pipefail

source tests/ci/common_posix_setup.sh

# libseccomp is required to run this tests. Typically this package is named
# either libseccomp-dev or libseccomp-devel.

# Set up environment.

# SYS_ROOT
# |
# - SRC_ROOT(aws-lc)
# |
# - SCRATCH_FOLDER
# |
# - seccomp app binary
# - AWS_LC_BUILD_FOLDER
# - AWS_LC_INSTALL_FOLDER

# Assumes script is executed from the root of aws-lc directory
SCRATCH_FOLDER=${SYS_ROOT}/"SCRATCH_AWSLC_PRESANDBOX_TEST"
AWS_LC_BUILD_FOLDER="${SCRATCH_FOLDER}/aws-lc-build"
AWS_LC_INSTALL_FOLDER="${SCRATCH_FOLDER}/aws-lc-install"
: "${CC:=gcc}"

# Make script execution idempotent.
mkdir -p ${SCRATCH_FOLDER}
rm -rf "${SCRATCH_FOLDER:?}"/*
cd ${SCRATCH_FOLDER}

aws_lc_build "$SRC_ROOT" "$AWS_LC_BUILD_FOLDER" "$AWS_LC_INSTALL_FOLDER" \
-DBUILD_TESTING=OFF -DBUILD_TOOL=OFF -DCMAKE_BUILD_TYPE=RelWithDebInfo \
-DBUILD_SHARED_LIBS=OFF

# Check which AWS-LC library folder name we must use.
if [ -d ${AWS_LC_INSTALL_FOLDER}/lib64 ]; then
AWS_LC_LIBRARY_FOLDER="lib64"
else
AWS_LC_LIBRARY_FOLDER="lib"
fi

function seccomp_build() {
__CFLAGS=${1}
${CC} -I${SRC_ROOT}/include ${__CFLAGS} \
${SRC_ROOT}/tests/ci/test_apps/seccomp_app.c -o seccomp_app \
-lseccomp -L${AWS_LC_INSTALL_FOLDER}/${AWS_LC_LIBRARY_FOLDER} -lcrypto -pthread
}

echo "Test that AWS-LC performs syscalls that will trip the seccomp filter."
seccomp_build ""
./seccomp_app
if [ $? -eq 0 ]; then
echo "Failure: expected AWS-LC syscalls to trip the seccomp filter."
exit 1
fi

echo "Test that when AWS-LC is sandbox configured, the seccomp filter does not trip."
seccomp_build "-DUSE_AWS_LC_PRE_SANDBOX"
./seccomp_app
if [ $? -ne 0 ]; then
echo "Failure: AWS-LC is sandbox configured but something tripped the seccomp filter."
exit 1
fi

echo "Pre-sandbox test succeeded."
60 changes: 60 additions & 0 deletions tests/ci/test_apps/seccomp_app.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0 OR ISC

#include <seccomp.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

#include <openssl/crypto.h>
#include <openssl/rand.h>

static void enable_seccomp(void) {

// Kill on all system calls by default.
scmp_filter_ctx ctx = seccomp_init(SCMP_ACT_KILL);
if (ctx == NULL) {
exit(EXIT_FAILURE);
}

// Allow write and exit system calls. In addition, on success we exit with
// exit_group. Hence, allow that as well.
seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(write), 0);
seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(exit), 0);
seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(exit_group), 0);

if (seccomp_load(ctx) < 0) {
seccomp_release(ctx);
exit(EXIT_FAILURE);
}

seccomp_release(ctx);
}

int main() {

const char notice[] = "\nTesting AWS-LC pre-sandbox.\n";
#if defined(USE_AWS_LC_PRE_SANDBOX)
const char status[] = "Pre-sandbox configuration is ENABLED, expect success.\n\n";
#else
const char status[] = "Pre-sandbox configuration is DISABLED, expect failure.\n\n";
#endif

write(STDOUT_FILENO, notice, sizeof(notice));
write(STDOUT_FILENO, status, sizeof(status));

#if defined(USE_AWS_LC_PRE_SANDBOX)
// Must be invoked before enabling seccomp filter.
CRYPTO_pre_sandbox_init();
#endif

// Enable seccomp filter.
enable_seccomp();

uint8_t buffer[10];
if (RAND_bytes(buffer, 10) != 1) {
return EXIT_FAILURE;
}

return EXIT_SUCCESS;
}

0 comments on commit 8968399

Please sign in to comment.