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

basil-tools-docker: tweaks to support use in Basil #25

Merged
merged 6 commits into from
Dec 19, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 15 additions & 2 deletions basil-shell.nix
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,25 @@
, clang-aarch64
, asli
, ddisasm
, bap-aslp
, bap-asli-plugin
, gtirb-pprinter
, gtirb-semantics
, pkgsCross
}:
let
packages = [
gcc-aarch64
clang-aarch64
pkgsCross.aarch64-multiplatform.pkgsBuildHost.gcc
pkgsCross.aarch64-multiplatform.pkgsBuildHost.clang

pkgsCross.aarch64-multiplatform-musl.pkgsBuildHost.gcc
pkgsCross.aarch64-multiplatform-musl.pkgsBuildHost.clang

asli

bap-aslp
bap-asli-plugin

ddisasm
gtirb-pprinter
gtirb-semantics
Expand All @@ -29,4 +40,6 @@ in mkShell {
meta = {
description = "shell containing tools used in the BASIL pipeline";
};

hardeningDisable = [ "all" ];
}
186 changes: 186 additions & 0 deletions docker-tools.nix
Original file line number Diff line number Diff line change
@@ -0,0 +1,186 @@
{ lib
, dockerTools
, bashInteractive
, writeText
, writeShellScriptBin
, devShellTools
, cacert
, storeDir ? builtins.storeDir
}:

# This file extracts streamNixShellImage from:
# https://github.com/NixOS/nixpkgs/blob/master/pkgs/build-support/docker/default.nix
# This is needed because the original implementation does not let you
# customise the container image after it is constructed from the shell.
#
# We add a simple binary at a known location which executes commands
# in the context of the shell.

let
inherit (dockerTools) streamLayeredImage binSh usrBinEnv fakeNss;
inherit (devShellTools) valueToString;
inherit (lib) optionalString;
in
{
# This function streams a docker image that behaves like a nix-shell for a derivation
# Docs: doc/build-helpers/images/dockertools.section.md
# Tests: nixos/tests/docker-tools-nix-shell.nix
streamNixShellImage =
{ drv
, name ? drv.name + "-env"
, tag ? null
, uid ? 1000
, gid ? 1000
, homeDirectory ? "/build"
, shell ? bashInteractive + "/bin/bash"
, command ? null
, run ? null
}:
assert lib.assertMsg (! (drv.drvAttrs.__structuredAttrs or false))
"streamNixShellImage: Does not work with the derivation ${drv.name} because it uses __structuredAttrs";
assert lib.assertMsg (command == null || run == null)
"streamNixShellImage: Can't specify both command and run";
let

# A binary that calls the command to build the derivation
builder = writeShellScriptBin "buildDerivation" ''
exec ${lib.escapeShellArg (valueToString drv.drvAttrs.builder)} ${lib.escapeShellArgs (map valueToString drv.drvAttrs.args)}
'';

staticPath = "${dirOf shell}:${lib.makeBinPath [ builder ]}";

# https://github.com/NixOS/nix/blob/2.8.0/src/nix-build/nix-build.cc#L493-L526
rcfile = writeText "nix-shell-rc" ''
unset PATH
dontAddDisableDepTrack=1
# TODO: https://github.com/NixOS/nix/blob/2.8.0/src/nix-build/nix-build.cc#L506
[ -e $stdenv/setup ] && source $stdenv/setup
PATH=${staticPath}:"$PATH"
SHELL=${lib.escapeShellArg shell}
BASH=${lib.escapeShellArg shell}
set +e
[ -n "$PS1" -a -z "$NIX_SHELL_PRESERVE_PROMPT" ] && PS1='\n\[\033[1;32m\][nix-shell:\w]\$\[\033[0m\] '
if [ "$(type -t runHook)" = function ]; then
runHook shellHook
fi
unset NIX_ENFORCE_PURITY
shopt -u nullglob
shopt -s execfail
${optionalString (command != null || run != null) ''
${optionalString (command != null) command}
${optionalString (run != null) run}
exit
''}
'';

# https://github.com/NixOS/nix/blob/2.8.0/src/libstore/globals.hh#L464-L465
sandboxBuildDir = "/build";

drvEnv =
devShellTools.unstructuredDerivationInputEnv { inherit (drv) drvAttrs; }
// devShellTools.derivationOutputEnv { outputList = drv.outputs; outputMap = drv; };

# Environment variables set in the image
envVars = {

# Root certificates for internet access
SSL_CERT_FILE = "${cacert}/etc/ssl/certs/ca-bundle.crt";
NIX_SSL_CERT_FILE = "${cacert}/etc/ssl/certs/ca-bundle.crt";

# https://github.com/NixOS/nix/blob/2.8.0/src/libstore/build/local-derivation-goal.cc#L1027-L1030
# PATH = "/path-not-set";
# Allows calling bash and `buildDerivation` as the Cmd
PATH = staticPath;

# https://github.com/NixOS/nix/blob/2.8.0/src/libstore/build/local-derivation-goal.cc#L1032-L1038
HOME = homeDirectory;

# https://github.com/NixOS/nix/blob/2.8.0/src/libstore/build/local-derivation-goal.cc#L1040-L1044
NIX_STORE = storeDir;

# https://github.com/NixOS/nix/blob/2.8.0/src/libstore/build/local-derivation-goal.cc#L1046-L1047
# TODO: Make configurable?
NIX_BUILD_CORES = "1";

} // drvEnv // {

# https://github.com/NixOS/nix/blob/2.8.0/src/libstore/build/local-derivation-goal.cc#L1008-L1010
NIX_BUILD_TOP = sandboxBuildDir;

# https://github.com/NixOS/nix/blob/2.8.0/src/libstore/build/local-derivation-goal.cc#L1012-L1013
TMPDIR = sandboxBuildDir;
TEMPDIR = sandboxBuildDir;
TMP = sandboxBuildDir;
TEMP = sandboxBuildDir;

# https://github.com/NixOS/nix/blob/2.8.0/src/libstore/build/local-derivation-goal.cc#L1015-L1019
PWD = sandboxBuildDir;

# https://github.com/NixOS/nix/blob/2.8.0/src/libstore/build/local-derivation-goal.cc#L1071-L1074
# We don't set it here because the output here isn't handled in any special way
# NIX_LOG_FD = "2";

# https://github.com/NixOS/nix/blob/2.8.0/src/libstore/build/local-derivation-goal.cc#L1076-L1077
TERM = "xterm-256color";
};


in streamLayeredImage {
inherit name tag;
contents = [
binSh
usrBinEnv
(fakeNss.override {
# Allows programs to look up the build user's home directory
# https://github.com/NixOS/nix/blob/ffe155abd36366a870482625543f9bf924a58281/src/libstore/build/local-derivation-goal.cc#L906-L910
# Slightly differs however: We use the passed-in homeDirectory instead of sandboxBuildDir.
# We're doing this because it's arguably a bug in Nix that sandboxBuildDir is used here: https://github.com/NixOS/nix/issues/6379
extraPasswdLines = [
"nixbld:x:${toString uid}:${toString gid}:Build user:${homeDirectory}:/noshell"
];
extraGroupLines = [
"nixbld:!:${toString gid}:"
];
})
];

fakeRootCommands = ''
# Effectively a single-user installation of Nix, giving the user full
# control over the Nix store. Needed for building the derivation this
# shell is for, but also in case one wants to use Nix inside the
# image
mkdir -p ./nix/{store,var/nix} ./etc/nix
chown -R ${toString uid}:${toString gid} ./nix ./etc/nix

# Gives the user control over the build directory
mkdir -p .${sandboxBuildDir}
chown -R ${toString uid}:${toString gid} .${sandboxBuildDir}

mkdir -p ./tmp
chmod a+rwx ./tmp

cat <<'EOF' > ./usr/bin/_exec
#!${shell}
if [[ "$shell" != 1 ]]; then
oldShellHook="$shellHook"
unset shellHook
export noDumpEnvVars=1
fi
source ${rcfile}
exec "$@"
EOF
chmod +x ./usr/bin/_exec
'';

# Run this image as the given uid/gid
config.User = "${toString uid}:${toString gid}";
config.Cmd =
# https://github.com/NixOS/nix/blob/2.8.0/src/nix-build/nix-build.cc#L185-L186
# https://github.com/NixOS/nix/blob/2.8.0/src/nix-build/nix-build.cc#L534-L536
if run == null
then [ shell "--rcfile" rcfile ]
else [ shell rcfile ];
config.WorkingDir = sandboxBuildDir;
config.Env = lib.mapAttrsToList (name: value: "${name}=${value}") envVars;
};
}
5 changes: 2 additions & 3 deletions overlay.nix
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,8 @@ let
update = prev.callPackage ./update.nix { };

basil-tools-shell = prev.callPackage ./basil-shell.nix { };
basil-tools-docker = prev.dockerTools.streamNixShellImage {
name = "basil-tools-docker";
tag = "latest";
basil-tools-docker = (prev.callPackage ./docker-tools.nix { }).streamNixShellImage {
name = "ghcr.io/uq-pac/basil-tools-docker";
drv = final.basil-tools-shell;
};

Expand Down
Loading