Coder Social home page Coder Social logo

kernel-builder's Introduction

kernel-builder

A small suite of tools to build a Linux kernel, optionally patched with grsecurity.

Getting started

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.

Enabling grsecurity patches

You must have a grsecurity subscription in order to fetch the patches for use in building. Export your credentials:

export GRSECURITY_USERNAME=foo
export GRSECURITY_PASSWORD=bar
export GRSECURITY=1
make

The resulting packages will used the 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. The build requires docker, so make sure your TemplateVM has docker configured.

qvm-create sd-kernel-builder --template debian-11 --label purple
qvm-prefs sd-kernel-builder vcpus $(nproc)
qvm-volume resize sd-kernel-builder:private 50G

Then add the following customization to the AppVM to ensure the private volume bind-dir is used for the build:

sudo mkdir -p /rw/config/qubes-bind-dirs.d
echo "binds+=( '/var/lib/docker' )" | sudo tee -a /rw/config/qubes-bind-dirs.d/50_user.conf

And reboot the AppVM. Otherwise, you will need a large system partition. Finally, make sure you've got the grsec env vars exported in your environment, or set in e.g. ~/grsec-env, as below. Now build:

rm -rf ~/kernel-builder
git clone https://github.com/freedomofpress/kernel-builder
cd kernel-builder
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

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.

โš ๏ธ 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.

  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 [email protected].
  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.

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 CONFIG_GCC_PLUGIN_RANDSTRUCT or CONFIG_GRKERNSEC_RANDSTRUCT) will prevent reproducibility. For more info, see the kernel docs on reproducibility.

Additionally, the script to fetch grsecurity patches works by choosing the most recent patch available. If you wish to rebuild an older kernel version, you'll need to rebuild from the original source tarball, and set environment variables such as SOURCE_DATE_EPOCH. Even then, structure randomization may prevent an identical build.

Building your own kernel

Please see the SOURCE_OFFER for details on how to get the source for kernels we've published. If you've received a source tarball, you should be able to treat it the same as an upstream kernel tarball. If you're unsure how to build from source, the documentation from the kernelnewbies.org site may be useful.

Note that despite using the same exact source, your kernel will not be bit-for-bit identical to the published SecureDrop kernels because of the above-mentioned randomization of struct fields.

References

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.

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

kernel-builder's People

Contributors

cfm avatar conorsch avatar eaon avatar emkll avatar legoktm avatar rocodes avatar sssoleileraaa avatar zenmonkeykstop avatar

Stargazers

 avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

kernel-builder's Issues

Provide build log file

https://github.com/freedomofpress/build-logs contains the build logs for all the production artifacts we release. Given the lack of reproducibility of the builds (#3), we should make it easy for a developer to submit build logs. We could tee the output to a unique file on disk, and have the developer commit that file to https://github.com/freedomofpress/build-logs.

In the meantime, setting the terminal scrollback to infinite and copy-pasting the console output is sufficient as a manual workaround.

Determine security requirements for automating kernel builds

Splitting from freedomofpress/securedrop#6514

On a technical level, to build packages one needs a machine (currently a clean Qubes VM) that has Docker installed, and then:

  1. run make securedrop-core-5.15, wait 2+ hours
  2. run make securedrop-workstation-5.15, wait 2+ hours
  3. upload the build logs to the build-logs repo
  4. sign and upload the source tarballs to S3
  5. copy and upload the debs to apt-test, to kick off kernel testing

Currently these steps are done manually, on maintainer laptops. This seems ripe for automation, especially because it's a slow process.

One important note is that these builds are currently not reproducible (see #3).

So if we were to automate this process, what are the requirements for the build host? Would we be OK if:

  1. it was entirely run on a CircleCI pipeline (or other cloud CI provider, e.g. CodeFresh)?
  2. it was entirely run on a DO droplet we/infra controls?
  3. it was entirely run on a physical machine under FPF control (e.g. in NYO)?
  4. status quo, entirely run on a maintainer laptop

Pinging @L3th3 & @lsd-cat for security input

Support distro strings in changelog

Right now, all builds are marked "unstable":

make clean
sh ./scripts/package/mkdebian
Using default distribution of 'unstable' in the changelog
Install lsb-release or set $KDEB_CHANGELOG_DIST explicitly

Use the KDEB_CHANGELOG_DIST var, and/or install lsb-release to use the host os.

kernel hardening flags

Description

I'm not sure if there's a dedicated repository for the kernel used on the SecureDrop servers anymore, so let me know where to put this. But this is a continuation of some prior updates I recommended to the configuration you're using to build. Thanks to a new tool from @a13xp0p0v called kconfig-hardened-check, we no longer have to manually watch changelogs, etc. for when security features and new config flags land in mainline (for those who are unaware, the KSPP has been porting a lot of grsecurity/PaX-inspired features into Linux proper). A brief chat I had with Spender a long time ago confirmed that these generally don't conflict or interfere with grsec.

As this article by @nettrino describes, Linux distributions are hit and miss and many are not taking advantage of the features.

The first obstacle is that you're still on 4.4, so that will narrow the modifications we can make to the config since much of this work landed with 4.14. We'd have to figure out which are available, which are too new, and perform enough testing and quality assurance of the new kernel.

In any event, as a launching-off point, I'm pasting the output of the kconfig-hardened-check script against the current SecureDrop kernel config.

[+] Detected architecture: X86_64
[+] Checking "config-4.4.167-grsec" against hardening preferences...
  option name                            | desired val | decision |       reason       ||        check result        
  ===================================================================================================================
  CONFIG_BUG                             |      y      |defconfig |  self_protection   ||             OK             
  CONFIG_STRICT_KERNEL_RWX               |      y      |defconfig |  self_protection   ||CONFIG_DEBUG_RODATA: OK ("y")
  CONFIG_STACKPROTECTOR_STRONG           |      y      |defconfig |  self_protection   ||      FAIL: not found       
  CONFIG_SLUB_DEBUG                      |      y      |defconfig |  self_protection   ||             OK             
  CONFIG_STRICT_MODULE_RWX               |      y      |defconfig |  self_protection   ||      FAIL: not found       
  CONFIG_PAGE_TABLE_ISOLATION            |      y      |defconfig |  self_protection   ||      FAIL: not found       
  CONFIG_RANDOMIZE_MEMORY                |      y      |defconfig |  self_protection   ||      FAIL: not found       
  CONFIG_RANDOMIZE_BASE                  |      y      |defconfig |  self_protection   ||      FAIL: not found       
  CONFIG_RETPOLINE                       |      y      |defconfig |  self_protection   ||             OK             
  CONFIG_X86_SMAP                        |      y      |defconfig |  self_protection   ||             OK             
  CONFIG_X86_INTEL_UMIP                  |      y      |defconfig |  self_protection   ||      FAIL: not found       
  CONFIG_SYN_COOKIES                     |      y      |defconfig |  self_protection   ||             OK             
  CONFIG_VMAP_STACK                      |      y      |defconfig |  self_protection   ||      FAIL: not found       
  CONFIG_THREAD_INFO_IN_TASK             |      y      |defconfig |  self_protection   ||      FAIL: not found       
  CONFIG_BUG_ON_DATA_CORRUPTION          |      y      |   kspp   |  self_protection   ||      FAIL: not found       
  CONFIG_DEBUG_WX                        |      y      |   kspp   |  self_protection   ||     FAIL: "is not set"     
  CONFIG_SCHED_STACK_END_CHECK           |      y      |   kspp   |  self_protection   ||     FAIL: "is not set"     
  CONFIG_PAGE_POISONING                  |      y      |   kspp   |  self_protection   ||      FAIL: not found       
  CONFIG_SLAB_FREELIST_HARDENED          |      y      |   kspp   |  self_protection   ||      FAIL: not found       
  CONFIG_SLAB_FREELIST_RANDOM            |      y      |   kspp   |  self_protection   ||      FAIL: not found       
  CONFIG_HARDENED_USERCOPY               |      y      |   kspp   |  self_protection   ||      FAIL: not found       
  CONFIG_HARDENED_USERCOPY_FALLBACK      | is not set  |   kspp   |  self_protection   ||       OK: not found        
  CONFIG_FORTIFY_SOURCE                  |      y      |   kspp   |  self_protection   ||      FAIL: not found       
  CONFIG_GCC_PLUGINS                     |      y      |   kspp   |  self_protection   ||             OK             
  CONFIG_GCC_PLUGIN_RANDSTRUCT           |      y      |   kspp   |  self_protection   ||      FAIL: not found       
  CONFIG_GCC_PLUGIN_STRUCTLEAK           |      y      |   kspp   |  self_protection   ||      FAIL: not found       
  CONFIG_GCC_PLUGIN_STRUCTLEAK_BYREF_ALL |      y      |   kspp   |  self_protection   ||      FAIL: not found       
  CONFIG_GCC_PLUGIN_LATENT_ENTROPY       |      y      |   kspp   |  self_protection   ||      FAIL: not found       
  CONFIG_DEBUG_LIST                      |      y      |   kspp   |  self_protection   ||             OK             
  CONFIG_DEBUG_SG                        |      y      |   kspp   |  self_protection   ||     FAIL: "is not set"     
  CONFIG_DEBUG_CREDENTIALS               |      y      |   kspp   |  self_protection   ||     FAIL: "is not set"     
  CONFIG_DEBUG_NOTIFIERS                 |      y      |   kspp   |  self_protection   ||     FAIL: "is not set"     
  CONFIG_MODULE_SIG                      |      y      |   kspp   |  self_protection   ||             OK             
  CONFIG_MODULE_SIG_ALL                  |      y      |   kspp   |  self_protection   ||             OK             
  CONFIG_MODULE_SIG_SHA512               |      y      |   kspp   |  self_protection   ||             OK             
  CONFIG_MODULE_SIG_FORCE                |      y      |   kspp   |  self_protection   ||     FAIL: "is not set"     
  CONFIG_DEFAULT_MMAP_MIN_ADDR           |    65536    |   kspp   |  self_protection   ||             OK             
  CONFIG_REFCOUNT_FULL                   |      y      |   kspp   |  self_protection   ||      FAIL: not found       
  CONFIG_GCC_PLUGIN_STACKLEAK            |      y      |    my    |  self_protection   ||      FAIL: not found       
  CONFIG_LOCK_DOWN_KERNEL                |      y      |    my    |  self_protection   ||      FAIL: not found       
  CONFIG_SLUB_DEBUG_ON                   |      y      |    my    |  self_protection   ||     FAIL: "is not set"     
  CONFIG_SECURITY_DMESG_RESTRICT         |      y      |    my    |  self_protection   ||     FAIL: "is not set"     
  CONFIG_STATIC_USERMODEHELPER           |      y      |    my    |  self_protection   ||      FAIL: not found       
  CONFIG_SECURITY_LOADPIN                |      y      |    my    |  self_protection   ||      FAIL: not found       
  CONFIG_PAGE_POISONING_NO_SANITY        | is not set  |    my    |  self_protection   ||       OK: not found        
  CONFIG_PAGE_POISONING_ZERO             | is not set  |    my    |  self_protection   ||       OK: not found        
  CONFIG_SLAB_MERGE_DEFAULT              | is not set  |    my    |  self_protection   ||       OK: not found        
  CONFIG_SECURITY                        |      y      |defconfig |  security_policy   ||             OK             
  CONFIG_SECURITY_YAMA                   |      y      |   kspp   |  security_policy   ||      FAIL: not found       
  CONFIG_SECURITY_SELINUX_DISABLE        | is not set  |   kspp   |  security_policy   ||         FAIL: "y"          
  CONFIG_SECCOMP                         |      y      |defconfig | cut_attack_surface ||             OK             
  CONFIG_SECCOMP_FILTER                  |      y      |defconfig | cut_attack_surface ||             OK             
  CONFIG_STRICT_DEVMEM                   |      y      |defconfig | cut_attack_surface ||             OK             
  CONFIG_IO_STRICT_DEVMEM                |      y      |   kspp   | cut_attack_surface ||      FAIL: not found       
  CONFIG_ACPI_CUSTOM_METHOD              | is not set  |   kspp   | cut_attack_surface ||       OK: not found        
  CONFIG_COMPAT_BRK                      | is not set  |   kspp   | cut_attack_surface ||             OK             
  CONFIG_DEVKMEM                         | is not set  |   kspp   | cut_attack_surface ||       OK: not found        
  CONFIG_COMPAT_VDSO                     | is not set  |   kspp   | cut_attack_surface ||       OK: not found        
  CONFIG_BINFMT_MISC                     | is not set  |   kspp   | cut_attack_surface ||         FAIL: "m"          
  CONFIG_INET_DIAG                       | is not set  |   kspp   | cut_attack_surface ||         FAIL: "m"          
  CONFIG_KEXEC                           | is not set  |   kspp   | cut_attack_surface ||       OK: not found        
  CONFIG_PROC_KCORE                      | is not set  |   kspp   | cut_attack_surface ||       OK: not found        
  CONFIG_LEGACY_PTYS                     | is not set  |   kspp   | cut_attack_surface ||         FAIL: "y"          
  CONFIG_HIBERNATION                     | is not set  |   kspp   | cut_attack_surface ||       OK: not found        
  CONFIG_LEGACY_VSYSCALL_NONE            |      y      |   kspp   | cut_attack_surface ||     FAIL: "is not set"     
  CONFIG_IA32_EMULATION                  | is not set  |   kspp   | cut_attack_surface ||         FAIL: "y"          
  CONFIG_X86_X32                         | is not set  |   kspp   | cut_attack_surface ||         FAIL: "y"          
  CONFIG_MODIFY_LDT_SYSCALL              | is not set  |   kspp   | cut_attack_surface ||         FAIL: "y"          
  CONFIG_X86_PTDUMP                      | is not set  |grsecurity| cut_attack_surface ||       OK: not found        
  CONFIG_ZSMALLOC_STAT                   | is not set  |grsecurity| cut_attack_surface ||       OK: not found        
  CONFIG_PAGE_OWNER                      | is not set  |grsecurity| cut_attack_surface ||       OK: not found        
  CONFIG_DEBUG_KMEMLEAK                  | is not set  |grsecurity| cut_attack_surface ||       OK: not found        
  CONFIG_BINFMT_AOUT                     | is not set  |grsecurity| cut_attack_surface ||       OK: not found        
  CONFIG_KPROBES                         | is not set  |grsecurity| cut_attack_surface ||         FAIL: "y"          
  CONFIG_UPROBES                         | is not set  |grsecurity| cut_attack_surface ||             OK             
  CONFIG_GENERIC_TRACER                  | is not set  |grsecurity| cut_attack_surface ||       OK: not found        
  CONFIG_PROC_VMCORE                     | is not set  |grsecurity| cut_attack_surface ||       OK: not found        
  CONFIG_PROC_PAGE_MONITOR               | is not set  |grsecurity| cut_attack_surface ||       OK: not found        
  CONFIG_USELIB                          | is not set  |grsecurity| cut_attack_surface ||       OK: not found        
  CONFIG_CHECKPOINT_RESTORE              | is not set  |grsecurity| cut_attack_surface ||       OK: not found        
  CONFIG_USERFAULTFD                     | is not set  |grsecurity| cut_attack_surface ||             OK             
  CONFIG_HWPOISON_INJECT                 | is not set  |grsecurity| cut_attack_surface ||       OK: not found        
  CONFIG_MEM_SOFT_DIRTY                  | is not set  |grsecurity| cut_attack_surface ||       OK: not found        
  CONFIG_DEVPORT                         | is not set  |grsecurity| cut_attack_surface ||       OK: not found        
  CONFIG_DEBUG_FS                        | is not set  |grsecurity| cut_attack_surface ||       OK: not found        
  CONFIG_NOTIFIER_ERROR_INJECTION        | is not set  |grsecurity| cut_attack_surface ||       OK: not found        
  CONFIG_ACPI_TABLE_UPGRADE              | is not set  | lockdown | cut_attack_surface ||       OK: not found        
  CONFIG_ACPI_APEI_EINJ                  | is not set  | lockdown | cut_attack_surface ||       OK: not found        
  CONFIG_PROFILING                       | is not set  | lockdown | cut_attack_surface ||         FAIL: "y"          
  CONFIG_BPF_SYSCALL                     | is not set  | lockdown | cut_attack_surface ||             OK             
  CONFIG_MMIOTRACE_TEST                  | is not set  | lockdown | cut_attack_surface ||       OK: not found        
  CONFIG_MMIOTRACE                       | is not set  |    my    | cut_attack_surface ||       OK: not found        
  CONFIG_KEXEC_FILE                      | is not set  |    my    | cut_attack_surface ||             OK             
  CONFIG_LIVEPATCH                       | is not set  |    my    | cut_attack_surface ||       OK: not found        
  CONFIG_USER_NS                         | is not set  |    my    | cut_attack_surface ||         FAIL: "y"          
  CONFIG_IP_DCCP                         | is not set  |    my    | cut_attack_surface ||         FAIL: "m"          
  CONFIG_IP_SCTP                         | is not set  |    my    | cut_attack_surface ||         FAIL: "m"          
  CONFIG_FTRACE                          | is not set  |    my    | cut_attack_surface ||       OK: not found        
  CONFIG_BPF_JIT                         | is not set  |    my    | cut_attack_surface ||         FAIL: "y"          
  CONFIG_ARCH_MMAP_RND_BITS              |     32      |    my    |userspace_protection||      FAIL: not found       

[-] config check is NOT PASSED: 48 errors```

Build a common kernel for the servers and Qubes workstation.

For Qubes v4.0, the u2mfn module was required - this meant that a separate grsec kernel build for SecureDrop Workstation was also required. Said module is no longer needed AFAICT for 4.1, so we should look into building a single kernel that will work for both the servers and workstation.

Potential upsides: reduced maintenance, simultaneous updates across the system.

Potential downsides/blockers: there may be device support etc that we need for servers but would prefer not to include for the workstation appVMs.

Add CI config

Builds should run in CI to confirm that logic changes don't break builds. At least a vanilla kernel build, don't need any creds to start with.

Build kernel images from source tarball

The project meant to be replaced by this kernel-builder project provides the user with the ability to rebuild a kernel image from a source tarball: https://github.com/freedomofpress/ansible-role-grsecurity-build/blob/2f01f43697992c7353db3083e5689493c36ea4e5/Makefile#L4 .In order to provide feature parity with that repository, we should add the option to rebuild a kernel from a local tarball (without fetching patches or any configuration changes, simply building a kernel from the tarball).

bug: if grsecurity patch fails with "patch: **** out of memory" error, build continues instead of failing

As observed in https://raw.githubusercontent.com/freedomofpress/build-logs/main/core/focal/20231011-securedrop-core-5.15.log, if the grsecurity patch isn't applied due to an OOM error, the build script doesn't error out but keeps going, producing the expected packages with no grsecurity changes.

Luckily this doesn't affect the most recent prod kernels, looking at https://raw.githubusercontent.com/freedomofpress/build-logs/main/core/focal/20230906-securedrop-core-5.15.log the patch was applied properly (and hardware tests would have caught it anyway).

Update: I encountered this on a Qubes-based build with 12GB max RAM. Naively bumping it to 20GB didn't help, and the VM's usage didn't get over about 3GB before the patch command failed.

Update the second: Applying the patch to the source tree outside of docker works fine! Patch itself is 14MB or so.

Extract updated kernel configuration after olddefconfig

Currently the script will run make olddefconfig on the appropriate kernel config provided in the configs folder. Because we would like to commit to version control the exact config that is shipping in built kernels, we can add a step during the build process to copy the config of the build kernel into the configs folder to allow a developer to easily commit the config to version control after the kernel was built (and avoid the manual step to fetching the configuration, either by booting into the kernel or inspecting the source tarball produced by the build)

Document various version environment variables

At #34 (review) @rocodes wrote:

Slight nit is it could be good to have a bit more documentation for our future selves (specifically, that setting LINUX_MAJOR_VERSION overrides LINUX_VERSION, were both to be set in build-kernel.sh), but not worth a hold-up. Thank you for these changes!

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.