Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for 6.6.x workstation kernels #45

Merged
merged 13 commits into from Apr 22, 2024
Merged
61 changes: 25 additions & 36 deletions .github/workflows/ci.yml
Expand Up @@ -3,8 +3,18 @@ name: CI
on: [push, pull_request]

jobs:
vanilla:
build:
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
target:
- tiny-5.15
- tiny-6.6
# Build twice for comparison
build:
- one
- two
outputs:
artifact_id: ${{ steps.upload.outputs.artifact-id }}
steps:
Expand All @@ -14,57 +24,36 @@ jobs:
- name: Install dependencies
run: sudo apt-get update && sudo apt-get install -y make build-essential

- name: Build vanilla kernel
run: make vanilla
- name: Build tiny kernel
run: make ${{ matrix.target }}

- uses: actions/upload-artifact@v4
id: upload
with:
name: build1
path: build
if-no-files-found: error

vanilla2:
runs-on: ubuntu-latest
outputs:
artifact_id: ${{ steps.upload.outputs.artifact-id }}
steps:
- name: Checkout code
uses: actions/checkout@v4

- name: Install dependencies
run: sudo apt-get update && sudo apt-get install -y make build-essential

- name: Build vanilla kernel
run: make vanilla

- uses: actions/upload-artifact@v4
id: upload
with:
name: build2
name: ${{ matrix.target }}-${{ matrix.build }}
path: build
if-no-files-found: error

reproducible:
runs-on: ubuntu-latest
container: debian:bookworm
needs:
- vanilla
- vanilla2
- build
strategy:
fail-fast: false
matrix:
target:
- tiny-5.15
- tiny-6.6
steps:
- name: Install dependencies
run: |
apt-get update && apt-get install --yes diffoscope-minimal python3-debian \
apt-get update && apt-get install --yes diffoscope-minimal python3-debian xz-utils \
--no-install-recommends
- uses: actions/download-artifact@v4
with:
pattern: "*"
pattern: "${{ matrix.target }}*"
- name: diffoscope
run: |
find . -name '*.deb' -exec sha256sum {} \;
# TODO: Ideally we'd just be able to diff the .changes files and let diffoscope find
# all the individual debs, but the source packages are not identical. When they are,
for deb in `find build1/ -name '*.deb' -exec basename {} \;`; do
echo "Diffoscoping $deb"
diffoscope build1/$deb build2/$deb
done;
# We need to exclude .buildinfo because the `Build-Date` will be different
diffoscope ${{ matrix.target }}-one/*.changes ${{ matrix.target }}-two/*.changes --exclude '*.buildinfo'
23 changes: 11 additions & 12 deletions Dockerfile
@@ -1,5 +1,5 @@
# debian:buster 2021-12-20
FROM debian@sha256:94ccfd1c5115a6903cbb415f043a0b04e307be3f37b768cf6d6d3edff0021da3
ARG BUILD_DISTRO=bookworm
FROM debian:$BUILD_DISTRO

ARG UID=1000
ARG GID=1000
Expand All @@ -14,31 +14,31 @@ RUN apt-get update && \
bison \
build-essential \
cpio \
curl \
debhelper \
fakeroot \
flex \
gcc-8-plugin-dev \
git \
kmod \
libelf-dev \
liblz4-tool \
libssl-dev \
lsb-release \
ncurses-dev \
python3 \
python3-jinja2 \
python3-requests \
rsync \
wget \
xz-utils
# See https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=657962, there's no
# unversioned name for this package
RUN apt-get install --yes gcc-$(gcc -dumpversion)-plugin-dev

RUN groupadd -g ${GID} ${USERNAME} && useradd -m -d /home/${USERNAME} -g ${GID} -u ${UID} ${USERNAME}

COPY build-kernel.sh /usr/local/bin/build-kernel.sh
COPY build-kernel.py /usr/local/bin/build-kernel.py
COPY grsecurity-urls.py /usr/local/bin/grsecurity-urls.py
COPY scripts/mkdebian /usr/local/bin/mkdebian

COPY securedrop-grsec /securedrop-grsec
COPY securedrop-workstation-grsec /securedrop-workstation-grsec
COPY debian /debian
COPY pubkeys/ /pubkeys

RUN mkdir -p -m 0755 /kernel /patches-grsec /output
RUN chown ${USERNAME}:${USERNAME} /kernel /patches-grsec /output
Expand All @@ -47,6 +47,5 @@ WORKDIR /kernel
# VOLUME ["/kernel"]

USER ${USERNAME}
COPY pubkeys/ /pubkeys

CMD ["/usr/local/bin/build-kernel.sh"]
CMD ["/usr/local/bin/build-kernel.py"]
35 changes: 29 additions & 6 deletions Makefile
Expand Up @@ -3,10 +3,22 @@ IMG_NAME = fpf.local/kernel-builder
SCRIPT_OUTPUT_PREFIX=$(PWD)/build/$(shell date +%Y%m%d)
SCRIPT_OUTPUT_EXT=log

.PHONY: vanilla
vanilla: OUT:=$(SCRIPT_OUTPUT_PREFIX)-vanilla.$(SCRIPT_OUTPUT_EXT)
vanilla: ## Builds latest stable kernel, unpatched
LINUX_MAJOR_VERSION="5.15" \
.PHONY: tiny-5.15
tiny-5.15: OUT:=$(SCRIPT_OUTPUT_PREFIX)-tiny-5.15.$(SCRIPT_OUTPUT_EXT)
tiny-5.15: ## Builds latest 5.15 kernel, unpatched
LINUX_MAJOR_VERSION="5.15" LOCALVERSION="tiny" \
BUILD_DISTRO="buster" \
LINUX_LOCAL_CONFIG_PATH="$(PWD)/configs/tinyconfig-5.15" \
script \
--command ./scripts/build-kernel-wrapper \
--return \
$(OUT)

.PHONY: tiny-6.6
tiny-6.6: OUT:=$(SCRIPT_OUTPUT_PREFIX)-tiny-6.6.$(SCRIPT_OUTPUT_EXT)
legoktm marked this conversation as resolved.
Show resolved Hide resolved
tiny-6.6: ## Builds latest 6.6 kernel, unpatched
LINUX_MAJOR_VERSION="6.6" LOCALVERSION="tiny" \
LINUX_LOCAL_CONFIG_PATH="$(PWD)/configs/tinyconfig-6.6" \
script \
--command ./scripts/build-kernel-wrapper \
--return \
Expand All @@ -27,14 +39,15 @@ reprotest: ## Builds simple kernel multiple times to confirm reproducibility

.PHONY: reprotest-sd
reprotest-sd: ## DEBUG Builds SD kernel config without grsec in CI
GRSECURITY=0 LOCALVERSION="-securedrop" \
GRSECURITY=0 LOCALVERSION="securedrop" \
LINUX_LOCAL_CONFIG_PATH="$(PWD)/configs/config-securedrop-5.15" \
LINUX_LOCAL_PATCHES_PATH="$(PWD)/patches" \
./scripts/reproducibility-test

securedrop-core-5.15: OUT:=$(SCRIPT_OUTPUT_PREFIX)-securedrop-core-5.15.$(SCRIPT_OUTPUT_EXT)
securedrop-core-5.15: ## Builds kernels for SecureDrop servers, 5.15.x
GRSECURITY=1 GRSECURITY_PATCH_TYPE=stable6 LOCALVERSION="-securedrop" \
GRSECURITY=1 GRSECURITY_PATCH_TYPE=stable6 LOCALVERSION="securedrop" \
BUILD_DISTRO="buster" \
LINUX_LOCAL_CONFIG_PATH="$(PWD)/configs/config-securedrop-5.15" \
LINUX_LOCAL_PATCHES_PATH="$(PWD)/patches" \
script \
Expand All @@ -45,12 +58,22 @@ securedrop-core-5.15: ## Builds kernels for SecureDrop servers, 5.15.x
securedrop-workstation-5.15: OUT:=$(SCRIPT_OUTPUT_PREFIX)-securedrop-workstation-5.15.$(SCRIPT_OUTPUT_EXT)
securedrop-workstation-5.15: ## Builds kernels for SecureDrop Workstation, 5.15.x
GRSECURITY=1 GRSECURITY_PATCH_TYPE=stable6 LOCALVERSION="-workstation" \
BUILD_DISTRO="buster" \
LINUX_LOCAL_CONFIG_PATH="$(PWD)/configs/config-workstation-5.15" \
script \
--command ./scripts/build-kernel-wrapper \
--return \
$(OUT)

securedrop-workstation-6.6: OUT:=$(SCRIPT_OUTPUT_PREFIX)-securedrop-workstation-6.6.$(SCRIPT_OUTPUT_EXT)
securedrop-workstation-6.6: ## Builds kernels for SecureDrop Workstation, 6.6.x
GRSECURITY=1 GRSECURITY_PATCH_TYPE=stable9 LOCALVERSION="workstation" \
LINUX_LOCAL_CONFIG_PATH="$(PWD)/configs/config-workstation-6.6" \
script \
--command ./scripts/build-kernel-wrapper \
--return \
$(OUT)

.PHONY: help
help: ## Prints this message and exits.
@printf "Subcommands:\n\n"
Expand Down
60 changes: 32 additions & 28 deletions README.md
@@ -1,12 +1,18 @@
# kernel-builder

A small suite of tools to build a Linux kernel, optionally patched with [grsecurity].
A suite of tools to build a Debian-packaged Linux kernel, optionally patched with [grsecurity]
for the [SecureDrop](https://securedrop.org/) project.

## Getting started
## Prerequistes

Make sure you have docker installed. Then just run `make`.
The script will look up the most recent stable Linux version from https://www.kernel.org
and build that. Artifacts will be available in `./build/` afterward.
* Docker
* GNU make

## Using

Select which config flavor you want to build and run `make <config>`. The script will
automatically fetch the most recent Linux version for that flavor, patch if necessary,
and leave built packages in `./build/`.

## Enabling grsecurity patches

Expand All @@ -17,22 +23,13 @@ Export your credentials:
export GRSECURITY_USERNAME=foo
export GRSECURITY_PASSWORD=bar
export GRSECURITY=1
make
make <config>
```

The resulting packages will used the patch set. If you're working on SecureDrop,
The resulting packages will use the grsecurity patch set. If you're working on SecureDrop,
request these credentials from a team member, and store them securely
in your password manager.

## Using a custom kernel config

Since the build uses docker, the host machine's kernel and config are visible
to the build environment, and will be included via `make olddefconfig` prior
to building. If you wish to provide a different kernel config, mount the file
at `/config` inside the container. It will be copied into place prior to building.
Note that `make olddefconfig` will be run regardless to ensure the latest
options have been applied.

## Building kernels in Qubes

Here's how to set up a build environment in [Qubes], suitable for use with [SecureDrop].
Expand Down Expand Up @@ -66,26 +63,33 @@ source ~/grsec-env # credentials for grsecurity access
make securedrop-workstation # to build Workstation kernels
# grab a coffee or tea, builds take ~1h with 4 cores.
sha256sum build/*
# then copy the terminal history from your emulator and store build log,
# e.g. via Edit->Select All in gnome-terminal
```

The build output will automatically be captured in a log file.

## Release

Development/staging packages are placed on apt-test.freedom.press for installation in Debian-based TemplateVMs, and production packages are placed on apt.freedom.press.
Packages are first placed on apt-test.freedom.press for [QA testing and validation](https://developers.securedrop.org/en/latest/kernel.html), and then promoted to apt.freedom.press.

⚠️ Before you add a package to one of our apt repos, you *must* upload the kernel source tarball to our S3 bucket following the instructions below.
⚠️ Before you add a package to one of our apt repos, you *must* upload the kernel source tarball internally following the instructions below.

1. Add a detached signature to the kernel source tarball using a staff (`*@freedom.press`) GPG key.
2. If you do not have an AWS account and you are a maintainer, ask someone from the infrastructure team to set one up for you. They will provide you with instructions on where and how your credentials should be stored in Qubes.
3. Now hop over to our private wiki page on how to use a script to upload the kernel source tarball to our S3 bucket and verify that your upload was successful. There, you'll also learn how to later respond to a source request email sent to `source-offer@freedom.press`.
4. Now you can submit a `securedrop-workstation-grsec` changelog PR in `securedrop-debian-packaging` and a .deb LFS PR to https://github.com/freedomofpress/securedrop-dev-packages-lfs, which another maintainer reviews and merges, thereby deploying the new packages to https://apt-test.freedom.press.
5. After QA, the same kernel packages on `apt-test` can be promoted to prod by submitting a .deb LFS PR to https://github.com/freedomofpress/securedrop-debian-packages-lfs.
2. Now hop over to our private wiki page on how to use a script to upload the kernel source tarball internally and verify that your upload was successful.
3. You can now propose your packages for inclusion in the `apt-test` repository.
4. After QA, the same kernel packages on `apt-test` can be promoted to prod.

## Architecture

This builds on the `make deb-pkg` command in Linux. The upstream command dynamically
generates a `debian/` directory and then executes it. Instead, we prepare and commit
the `debian/` directory so we can customize the packages and add in our metadata.
Our `debian/rules` is roughly the same as what would be generated, except it has some compat
to handle different versions. Future updates of major kernel versions may require adjusting
`debian/rules` if upstream has also made changes.

## Reproducible builds
In the spirit of [reproducible builds], this repo attempts to make fully reproducible
kernel images. There are some catches, however: a custom kernel patch is included
to munge the changelog timestamp, and certain kernel config options (notably
kernel images. There are some catches, however: certain kernel config options (notably
`CONFIG_GCC_PLUGIN_RANDSTRUCT` or `CONFIG_GRKERNSEC_RANDSTRUCT`) will prevent reproducibility.
For more info, see the [kernel docs on reproducibility].

Expand All @@ -107,10 +111,10 @@ SecureDrop kernels because of the above-mentioned randomization of struct fields

These configurations were developed by [Freedom of the Press Foundation] for
use in all [SecureDrop] instances. Experienced sysadmins can leverage these
roles to compile custom kernels for SecureDrop or non-SecureDrop projects.
scripts to compile custom kernels for SecureDrop or non-SecureDrop projects.

The logic here is intended to supersede the legacy build logic at
https://github.com/freedomofpress/ansible-role-grsecurity-build/.
https://github.com/freedomofpres s/ansible-role-grsecurity-build/.

[Freedom of the Press Foundation]: https://freedom.press
[SecureDrop]: https://securedrop.org
Expand Down