Skip to content

Commit

Permalink
kernelCTF: GHA: add build releaser workflow
Browse files Browse the repository at this point in the history
  • Loading branch information
koczkatamas committed Oct 20, 2023
1 parent 90d419b commit d8211d8
Show file tree
Hide file tree
Showing 9 changed files with 408 additions and 0 deletions.
38 changes: 38 additions & 0 deletions .github/workflows/kernelctf-auto-releaser.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
name: kernelCTF auto releaser
on:
workflow_dispatch:
schedule:
- cron: '0 12 * * *' # every day at 12:00 UTC
permissions:
contents: read
defaults:
run:
shell: bash
working-directory: kernelctf
jobs:
get_new_builds:
runs-on: ubuntu-latest
steps:
- name: Checkout repo
uses: actions/checkout@v3

- name: Install prerequisites
run: sudo apt install -yq --no-install-recommends python3-lxml

- id: check
name: Check latest kernel versions
run: ./get_latest_kernel_versions.py
outputs:
releases: ${{ steps.check.outputs.releases }}

build_release:
needs: get_new_builds
strategy:
matrix:
release: ${{ fromJSON(needs.get_new_builds.outputs.releases) }}
fail-fast: false # do not cancel other builds
uses: ./.github/workflows/kernelctf-release-build.yaml
secrets: inherit
with:
releaseId: ${{ matrix.release.releaseId }}
branch: ${{ matrix.release.branch }}
73 changes: 73 additions & 0 deletions .github/workflows/kernelctf-release-build.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
name: kernelCTF release build
on:
workflow_dispatch:
inputs:
releaseId:
description: 'Release ID'
type: string
required: true
branch:
description: 'Branch, tag or commit'
type: string
required: false
workflow_call:
inputs:
releaseId:
type: string
branch:
type: string
run-name: 'kernelCTF release: ${{inputs.releaseId}}'
permissions:
contents: read
defaults:
run:
shell: bash
working-directory: kernelctf
jobs:
build:
runs-on: ubuntu-latest
steps:
- name: Checkout repo
uses: actions/checkout@v3

- name: Check release does not exist yet
run: curl --fail -I https://storage.googleapis.com/kernelctf-build/releases/${{inputs.releaseId}}/bzImage && exit 1 || true

- name: Install prerequisites
run: sudo apt install -yq --no-install-recommends build-essential flex bison bc ca-certificates libelf-dev libssl-dev cpio pahole

- name: Build
run: ./build_release.sh ${{inputs.releaseId}} ${{inputs.branch}}

- name: Show releases
run: find releases -type f|xargs ls -al

- name: Upload release artifact
uses: actions/upload-artifact@v3
with:
name: ${{inputs.releaseId}}
path: kernelctf/releases/${{inputs.releaseId}}
if-no-files-found: error

upload:
runs-on: ubuntu-latest
needs: build
steps:
- name: Download exploit
uses: actions/download-artifact@v3
with:
name: ${{inputs.releaseId}}
path: ./kernelctf/releases/${{inputs.releaseId}}

- name: Authenticate to Google Cloud
uses: google-github-actions/auth@v1
with:
credentials_json: '${{secrets.KERNELCTF_GCS_SA_KEY}}'

- name: Upload release
uses: 'google-github-actions/upload-cloud-storage@v1'
with:
path: kernelctf/releases/${{inputs.releaseId}}
destination: kernelctf-build/releases
predefinedAcl: publicRead
process_gcloudignore: false # removes warnings that .gcloudignore file does not exist
2 changes: 2 additions & 0 deletions kernelctf/.gitignore
Original file line number Diff line number Diff line change
@@ -1,2 +1,4 @@
.cache/
__pycache__/
builds/
releases/
108 changes: 108 additions & 0 deletions kernelctf/build_release.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
#!/bin/bash
set -ex

usage() {
echo "Usage: $0 (lts|cos|mitigation)-<version> [<branch-tag-or-commit>]";
exit 1;
}

RELEASE_NAME="$1"
BRANCH="$2"

if [[ ! "$RELEASE_NAME" =~ ^(lts|cos|mitigation)-(.*) ]]; then usage; fi
TARGET="${BASH_REMATCH[1]}"
VERSION="${BASH_REMATCH[2]}"

case $TARGET in
lts)
REPO="https://github.com/gregkh/linux"
DEFAULT_BRANCH="v${VERSION}"
CONFIG_FN="lts.config"
;;
cos)
REPO="https://cos.googlesource.com/third_party/kernel"
;;
mitigation)
REPO="https://github.com/thejh/linux"
case $VERSION in
v3-6.1.55)
DEFAULT_BRANCH="mitigations-next"
CONFIG_FN="mitigation-v3.config"
CONFIG_FULL_FN="mitigation-v3-full.config"
;;
6.1 | 6.1-v2)
DEFAULT_BRANCH="slub-virtual-v6.1"
CONFIG_FN="mitigation-v1.config"
;;
esac ;;
*)
usage ;;
esac

BRANCH="${BRANCH:-$DEFAULT_BRANCH}"
if [ -z "$BRANCH" ]; then usage; fi

echo "REPO=$REPO"
echo "BRANCH=$BRANCH"

BASEDIR=`pwd`
BUILD_DIR="$BASEDIR/builds/$RELEASE_NAME"
RELEASE_DIR="$BASEDIR/releases/$RELEASE_NAME"
CONFIGS_DIR="$BASEDIR/kernel_configs"

if [ -d "$RELEASE_DIR" ]; then echo "Release directory already exists. Stopping."; exit 1; fi

mkdir -p $BUILD_DIR 2>/dev/null || true
cd $BUILD_DIR
if [ ! -d ".git" ]; then git init && git remote add origin $REPO; fi

if ! git checkout $BRANCH; then
git fetch --depth 1 origin $BRANCH:$BRANCH || true # TODO: hack, solve it better
git checkout $BRANCH
fi

if [ "$TARGET" == "cos" ]; then
rm lakitu_defconfig || true
make lakitu_defconfig
cp .config lakitu_defconfig
else
curl 'https://cos.googlesource.com/third_party/kernel/+/refs/heads/cos-6.1/arch/x86/configs/lakitu_defconfig?format=text'|base64 -d > lakitu_defconfig
cp lakitu_defconfig .config
fi

# build everything into the kernel instead of modules
# note: this can increase the attack surface!
sed -i s/=m/=y/g .config

if [ ! -z "$CONFIG_FN" ]; then
cp $CONFIGS_DIR/$CONFIG_FN kernel/configs/
make $CONFIG_FN
fi

make olddefconfig

if [ ! -z "$CONFIG_FN" ]; then
if scripts/diffconfig $CONFIGS_DIR/$CONFIG_FN .config|grep "^[^+]"; then
echo "Config did not apply cleanly."
exit 1
fi
fi

if [ ! -z "$CONFIG_FULL_FN" ]; then
if scripts/diffconfig $CONFIGS_DIR/$CONFIG_FULL_FN .config|grep "^[^+]"; then
echo "The full config has differences compared to the applied config. Check if the base config changed since custom config was created."
exit 1
fi
fi

make -j`nproc`

mkdir -p $RELEASE_DIR 2>/dev/null || true

echo "REPOSITORY_URL=$REPO" > $RELEASE_DIR/COMMIT_INFO
(echo -n "COMMIT_HASH="; git rev-parse HEAD) >> $RELEASE_DIR/COMMIT_INFO

cp $BUILD_DIR/arch/x86/boot/bzImage $RELEASE_DIR/
cp $BUILD_DIR/lakitu_defconfig $RELEASE_DIR/
cp $BUILD_DIR/.config $RELEASE_DIR/
gzip -c $BUILD_DIR/vmlinux > $RELEASE_DIR/vmlinux.gz
35 changes: 35 additions & 0 deletions kernelctf/get_latest_kernel_versions.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
#!/usr/bin/env -S python3 -u
import json
from utils import *
from lxml import etree

releases = []

def add_release(release_id, branch=None):
url = f"https://storage.googleapis.com/kernelctf-build/releases/{release_id}/bzImage"
status_code = requests.head(url).status_code
if status_code == 200:
print(" -> Release already exists, skipping...")
return
if status_code != 403:
fail(f"Unexpected HTTP status code for release check: {status_code} (url = {url})")

global releases
releases.append({ "releaseId": release_id, "branch": branch })

latest_lts = run("git ls-remote --tags --sort='-v:refname' https://github.com/gregkh/linux 'v6.1.*[0-9]'")[0].split("refs/tags/")[1]
print(f"Latest LTS: {latest_lts}")
add_release(f"lts-{latest_lts[1:]}")

for cos_milestone in [97, 105]:
release_notes = fetch(f"https://cloud.google.com/feeds/cos-{cos_milestone}-release-notes.xml")
tree = etree.XML(release_notes.encode('utf-8'))
entries = tree.xpath("//*[local-name() = 'content']/text()")
latest_entry = entries[0]
version_tuple = checkOnlyOne(list(set(re.findall(f"cos-{cos_milestone}-(\d+)-(\d+)-(\d+)", latest_entry))), "too many versions were found")
release_id = f"cos-{cos_milestone}-{'.'.join(version_tuple)}"
commit = checkOnlyOne(re.findall("https://cos.googlesource.com/third_party/kernel/\+/([0-9a-f]{40})", latest_entry), "multiple commits were found")
print(f"Latest COS {cos_milestone}: {release_id}, commit = {commit}")
add_release(release_id, commit)

ghSet("OUTPUT", "releases=" + json.dumps(releases))
2 changes: 2 additions & 0 deletions kernelctf/kernel_configs/lts.config
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
# CONFIG_IO_URING is not set
CONFIG_SYSTEM_TRUSTED_KEYS=""
12 changes: 12 additions & 0 deletions kernelctf/kernel_configs/mitigation-v1.config
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
# CONFIG_IO_URING is not set
CONFIG_SYSTEM_TRUSTED_KEYS=""

## required by CONFIG_SLAB_VIRTUAL
CONFIG_DEBUG_VIRTUAL=y

## required by CONFIG_KMALLOC_SPLIT_VARSIZE
# CONFIG_SLAB_MERGE_DEFAULT is not set

## turns on Jann's hardening
CONFIG_KMALLOC_SPLIT_VARSIZE=y
CONFIG_SLAB_VIRTUAL=y
113 changes: 113 additions & 0 deletions kernelctf/kernel_configs/mitigation-v3-full.config
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
################### General hardening ##########################################

# Panic instead of failing gracefully and printing a warning when detecting data
# corruption (e.g. in list debugging and SLAB_VIRTUAL)
CONFIG_BUG_ON_DATA_CORRUPTION=y
# Check linked lists for corruption. Must be enabled together with
# CONFIG_BUG_ON_DATA_CORRUPTION.
CONFIG_DEBUG_LIST=y
# Prevent overflows and other overwrites in copy_from/to_user
CONFIG_HARDENED_USERCOPY=y
# Detect some buffer overflows in strcpy/memcpy
CONFIG_FORTIFY_SOURCE=y
# Sets kernel.dmesg_restrict to 1 by default
CONFIG_SECURITY_DMESG_RESTRICT=y
# Prevent processes belonging to the same (unprivileged) user from ptracing each
# other except for parents ptracing their children
CONFIG_SECURITY_YAMA=y
# Zero stack frames on function entry, makes some uninitialized variable uses
# unexploitable
CONFIG_INIT_STACK_ALL_ZERO=y
# Print a warning if there are WX mappings at boot
CONFIG_DEBUG_WX=y
# Stack canaries
CONFIG_STACKPROTECTOR=y
CONFIG_STACKPROTECTOR_STRONG=y
# Guard pages for kernel stacks
CONFIG_VMAP_STACK=y
# Randomize the offset of data on the kernel stack in syscalls
CONFIG_RANDOMIZE_KSTACK_OFFSET=y
CONFIG_RANDOMIZE_KSTACK_OFFSET_DEFAULT=y
# Text KASLR
CONFIG_RANDOMIZE_BASE=y
# Other KASLR
CONFIG_RANDOMIZE_MEMORY=y
# Enforce W^X in the kernel
CONFIG_STRICT_KERNEL_RWX=y
CONFIG_STRICT_MODULE_RWX=y
# Enable UMIP on the CPU to prevent using sidt/sgdt in userspace to leak kernel
# pointers (if the CPU supports UMIP)
CONFIG_X86_UMIP=y

################### CPU side channels ##########################################

# Meltdown mitigation
CONFIG_PAGE_TABLE_ISOLATION=y
# Spectre mitigations
CONFIG_RETPOLINE=y
CONFIG_CPU_IBPB_ENTRY=y
CONFIG_CPU_IBRS_ENTRY=y

################### Memory allocator ###########################################

# SLUB because SLAB_VIRTUAL doesn't support SLAB or SLOB and those are
# deprecated anyway
CONFIG_SLUB=y
# Randomize the order of the freelist when a new slab is created
CONFIG_SLAB_FREELIST_RANDOM=y
# Prevent attacks on the SLUB freelists
CONFIG_SLAB_FREELIST_HARDENED=y
# Don't merge slab caches (makes random caches/varsize useless and cross-cache easier)
CONFIG_SLAB_MERGE_DEFAULT=n
# Allocate msg_msg and some other useful objects in separate -cg caches
CONFIG_CGROUPS=y
CONFIG_MEMCG=y

################### BPF ########################################################

# Allow sandboxing with seccomp
CONFIG_SECCOMP=y
CONFIG_SECCOMP_FILTER=y
# This is required for jitting seccomp filters (probably)
CONFIG_BPF_SYSCALL=y
# Remove Spectre gadgets in the BPF interpreter
CONFIG_BPF_JIT=y
CONFIG_BPF_JIT_ALWAYS_ON=y
# Makes the kernel.unprivileged_bpf_disabled default to 2
CONFIG_BPF_UNPRIV_DEFAULT_OFF=y

################### Attack surface reduction ###################################

# Disable io_uring
CONFIG_IO_URING=n
# Prevent attackers from stopping the kernel inside copy_from/to_user
CONFIG_USERFAULTFD=n
CONFIG_FUSE_FS=n
# Disable staging drivers, which may be more buggy
CONFIG_STAGING=n

################## Extra mitigations/not upstreamed ############################

# Protects against cross-cache attacks. Must be enabled together with
# CONFIG_BUG_ON_DATA_CORRUPTION
CONFIG_SLAB_VIRTUAL=y
# Splits kmalloc caches in fixed-size and dynamic size to make UaF exploitation
# harder
CONFIG_KMALLOC_SPLIT_VARSIZE=y
# Create multiple copies of the normal and -cg kmalloc caches to make spraying
# harder
CONFIG_RANDOM_KMALLOC_CACHES=y

################### Make the kernel less annyoing to debug #####################

# Compile the kernel with debug info
CONFIG_DEBUG_INFO_DWARF_TOOLCHAIN_DEFAULT=y
# Have all symbols in kallsyms
CONFIG_KALLSYMS=y
CONFIG_KALLSYMS_ALL=y
CONFIG_TRIM_UNUSED_KSYMS=n
# Include the kernel configuration in the bzImage/vmlinux
CONFIG_IKCONFIG=y
CONFIG_IKCONFIG_PROC=y
# SLUB stats in /sys/slab
SLUB_DEBUG=y
Loading

0 comments on commit d8211d8

Please sign in to comment.