xen: nuke half of the builder

- Removes the non-slim build instructions, massively simplifying
everything in the package.

- Removes unecessary patches.

- Inherits functions from lib instead of repeating lib.* everywhere.

Signed-off-by: Fernando Rodrigues <alpha@sigmasquadron.net>
This commit is contained in:
Fernando Rodrigues 2024-10-06 02:59:17 +00:00
parent d2bb9a9ca5
commit 9279ecc1c4
No known key found for this signature in database
GPG Key ID: CC3AE2EA00000000
3 changed files with 222 additions and 510 deletions

View File

@ -1,27 +0,0 @@
Hack to make etherboot use pre-fetched iPXE.
diff --git a/tools/firmware/etherboot/Makefile b/tools/firmware/etherboot/Makefile
index ed9e11305f..979a3acea8 100644
--- a/tools/firmware/etherboot/Makefile
+++ b/tools/firmware/etherboot/Makefile
@@ -16,6 +16,7 @@ IPXE_TARBALL_URL ?= $(XEN_EXTFILES_URL)/ipxe-git-$(IPXE_GIT_TAG).tar.gz
D=ipxe
T=ipxe.tar.gz
+G=ipxe.git
ROMS = $(addprefix $D/src/bin/, $(addsuffix .rom, $(ETHERBOOT_NICS)))
ROM = $D/src/bin/ipxe.bin
@@ -41,9 +42,9 @@ $T:
fi
mv _$T $T
-$D/src/arch/i386/Makefile: $T Config
- rm -rf $D
- gzip -dc $T | tar xf -
+$D/src/arch/i386/Makefile: $G Config
+ mkdir $D
+ cp -a $G/* $D
for i in $$(cat patches/series) ; do \
patch -d $D -p1 --quiet <patches/$$i || exit 1 ; \
done

View File

@ -3,14 +3,11 @@
stdenv, stdenv,
autoPatchelfHook, autoPatchelfHook,
cmake, cmake,
ninja,
pkg-config, pkg-config,
testers, testers,
which, which,
fetchgit, fetchgit,
fetchpatch, fetchpatch,
fetchFromGitHub,
# Xen # Xen
acpica-tools, acpica-tools,
@ -32,31 +29,11 @@
zlib, zlib,
zstd, zstd,
slim ? false, # Optional Components
# Xen Optional
withInternalQEMU ? !slim,
pixman,
glib,
withInternalSeaBIOS ? !slim,
withSeaBIOS ? !withInternalSeaBIOS,
seabios, seabios,
withInternalOVMF ? !slim,
withOVMF ? !withInternalOVMF,
OVMF, OVMF,
nasm,
withInternalIPXE ? !slim,
withIPXE ? !withInternalIPXE,
ipxe, ipxe,
withFlask ? false,
checkpolicy, checkpolicy,
efiVendor ? "nixos", # Allow downstreams with custom branding to quickly override the EFI Vendor string.
withEFI ? true,
binutils-unwrapped, binutils-unwrapped,
# Documentation # Documentation
@ -76,198 +53,90 @@
nbd, nbd,
openvswitch, openvswitch,
util-linux, util-linux,
...
}: }:
versionDefinition: {
pname,
branch ? lib.versions.majorMinor version,
version,
vendor ? "nixos",
withEFI ? true,
withFlask ? false,
withSeaBIOS ? true,
withOVMF ? true,
withIPXE ? true,
useDefaultPatchList ? true,
rev,
hash,
patches ? [ ],
meta ? { },
}:
let let
#TODO: fix paths instead. # Inherit helper functions from lib and builtins.
scriptEnvPath = lib.strings.makeSearchPathOutput "out" "bin" [ inherit (builtins) elemAt isAttrs;
bridge-utils inherit (lib.strings)
coreutils concatLines
diffutils enableFeature
gawk makeSearchPathOutput
gnugrep optionalString
gnused removeSuffix
inetutils versionOlder
iproute2
iptables
multipath-tools
nbd
openvswitch
perl
util-linux.bin
which
];
# Inherit attributes from a versionDefinition.
inherit (versionDefinition)
pname
branch
version
latest
genericPatchList
pkg
; ;
inherit (lib.platforms) linux aarch64;
inherit (lib) teams;
inherit (lib.licenses)
cc-by-40
gpl2Only
lgpl21Only
mit
;
inherit (lib.meta) getExe;
inherit (lib.lists)
count
flatten
optional
optionals
range
remove
zipListsWith
;
inherit (lib.attrsets) attrByPath;
# Mark versions older than minSupportedVersion as EOL. # Mark versions older than minSupportedVersion as EOL.
minSupportedVersion = "4.16"; minSupportedVersion = "4.16";
## Generic Patch Handling ## ## Generic Patch Handling ##
mappedGenericPatches = builtins.map (patch: upstreamPatches.${patch}) genericPatchList;
upstreamPatches = import ./patches.nix { upstreamPatches = import ./patches.nix {
inherit lib fetchpatch; inherit lib fetchpatch;
}; };
upstreamPatchList = lib.lists.flatten mappedGenericPatches; upstreamPatchList = flatten (
with upstreamPatches;
## Pre-fetched Source Handling ## [
QUBES_REPRODUCIBLE_BUILDS
# Main attribute set for sources needed to build tools and firmwares. XSA_460
# Each source takes in: XSA_461
# * A `src` attribute, which contains the actual fetcher, XSA_462
# * A 'patches` attribute, which is a list of patches that need to be applied in the source. ]
# * A `path` attribute, which is the destination of the source inside the Xen tree. );
prefetchedSources =
lib.attrsets.optionalAttrs withInternalQEMU {
qemu = {
src = fetchgit {
url = "https://xenbits.xenproject.org/git-http/qemu-xen.git";
fetchSubmodules = true;
inherit (pkg.qemu) rev hash;
};
patches = lib.lists.optionals (lib.attrsets.hasAttrByPath [ "patches" ] pkg.qemu) pkg.qemu.patches;
path = "tools/qemu-xen";
};
}
// lib.attrsets.optionalAttrs withInternalSeaBIOS {
seaBIOS = {
src = fetchgit {
url = "https://xenbits.xenproject.org/git-http/seabios.git";
inherit (pkg.seaBIOS) rev hash;
};
patches = lib.lists.optionals (lib.attrsets.hasAttrByPath [
"patches"
] pkg.seaBIOS) pkg.seaBIOS.patches;
path = "tools/firmware/seabios-dir-remote";
};
}
// lib.attrsets.optionalAttrs withInternalOVMF {
ovmf = {
src = fetchgit {
url = "https://xenbits.xenproject.org/git-http/ovmf.git";
fetchSubmodules = true;
inherit (pkg.ovmf) rev hash;
};
patches = lib.lists.optionals (lib.attrsets.hasAttrByPath [ "patches" ] pkg.ovmf) pkg.ovmf.patches;
path = "tools/firmware/ovmf-dir-remote";
};
}
// lib.attrsets.optionalAttrs withInternalIPXE {
ipxe = {
src = fetchFromGitHub {
owner = "ipxe";
repo = "ipxe";
inherit (pkg.ipxe) rev hash;
};
patches = lib.lists.optionals (lib.attrsets.hasAttrByPath [ "patches" ] pkg.ipxe) pkg.ipxe.patches;
path = "tools/firmware/etherboot/ipxe.git";
};
};
# Gets a list containing the names of the top-level attribute for each pre-fetched
# source, to be used in the map functions below.
prefetchedSourcesList = lib.attrsets.mapAttrsToList (name: value: name) prefetchedSources;
# Produces bash commands that will copy each pre-fetched source.
copyPrefetchedSources =
# Finish the deployment by concatnating the list of commands together.
lib.strings.concatLines (
# Iterate on each pre-fetched source.
builtins.map (
source:
# Only produce a copy command if patches exist.
lib.strings.optionalString (lib.attrsets.hasAttrByPath [ "${source}" ] prefetchedSources)
# The actual copy command. `src` is always an absolute path to a fetcher output
# inside the /nix/store, and `path` is always a path relative to the Xen root.
# We need to `mkdir -p` the target directory first, and `chmod +w` the contents last,
# as the copied files will still be edited by the postPatchPhase.
''
echo "Copying ${prefetchedSources.${source}.src} -> ${prefetchedSources.${source}.path}"
mkdir --parents ${prefetchedSources.${source}.path}
cp --recursive --no-target-directory ${prefetchedSources.${source}.src} ${
prefetchedSources.${source}.path
}
chmod --recursive +w ${prefetchedSources.${source}.path}
''
) prefetchedSourcesList
);
# Produces strings with `patch` commands to be ran on postPatch.
# These deploy the .patch files for each pre-fetched source.
deployPrefetchedSourcesPatches =
# Finish the deployment by concatnating the list of commands together.
lib.strings.concatLines (
# The double map functions create a list of lists. Flatten it so we can concatnate it.
lib.lists.flatten (
# Iterate on each pre-fetched source.
builtins.map (
source:
# Iterate on each available patch.
(builtins.map (
patch:
# Only produce a patch command if patches exist.
lib.strings.optionalString
(lib.attrsets.hasAttrByPath [
"${source}"
"patches"
] prefetchedSources)
# The actual patch command. It changes directories to the correct source each time.
''
echo "Applying patch ${patch} to ${source}."
patch --directory ${prefetchedSources.${source}.path} --strip 1 < ${patch}
''
) prefetchedSources.${source}.patches)
) prefetchedSourcesList
)
);
## XSA Patches Description Builder ## ## XSA Patches Description Builder ##
# Sometimes patches are sourced through a path, like ./0000-xen.patch.
# This would break the patch attribute parser functions, so we normalise
# all patches sourced through paths by setting them to a { type = "path"; }
# attribute set.
# Patches from fetchpatch are already attribute sets.
normalisedPatchList = builtins.map (
patch:
if !builtins.isAttrs patch then
if builtins.isPath patch then
{ type = "path"; }
else
throw "xen/generic/default.nix: normalisedPatchList attempted to normalise something that is not a Path or an Attribute Set."
else
patch
) pkg.xen.patches;
# Simple counter for the number of attrsets (patches) in the patches list after normalisation. # Simple counter for the number of attrsets (patches) in the patches list after normalisation.
numberOfPatches = lib.lists.count (patch: builtins.isAttrs patch) normalisedPatchList; numberOfPatches = count (patch: isAttrs patch) upstreamPatchList;
# builtins.elemAt's index begins at 0, so we subtract 1 from the number of patches in order to # builtins.elemAt's index begins at 0, so we subtract 1 from the number of patches in order to
# produce the range that will be used in the following builtin.map calls. # produce the range that will be used in the following builtin.map calls.
availablePatchesToTry = lib.lists.range 0 (numberOfPatches - 1); availablePatchesToTry = range 0 (numberOfPatches - 1);
# Takes in an attrByPath input, and outputs the attribute value for each patch in a list. # Takes in an attrByPath input, and outputs the attribute value for each patch in a list.
# If a patch does not have a given attribute, returns `null`. Use lib.lists.remove null # If a patch does not have a given attribute, returns `null`. Use lib.lists.remove null
# to remove these junk values, if necessary. # to remove these junk values, if necessary.
retrievePatchAttributes = retrievePatchAttributes =
attributeName: attributeName:
builtins.map ( map (x: attrByPath attributeName null (elemAt upstreamPatchList x)) availablePatchesToTry;
x: lib.attrsets.attrByPath attributeName null (builtins.elemAt normalisedPatchList x)
) availablePatchesToTry;
# Produces a list of newline-separated strings that lists the vulnerabilities this # Produces a list of newline-separated strings that lists the vulnerabilities this
# Xen is NOT affected by, due to the applied Xen Security Advisory patches. This is # Xen is NOT affected by, due to the applied Xen Security Advisory patches. This is
@ -286,27 +155,27 @@ let
# * [CVE-1999-00002](https://www.cve.org/CVERecord?id=CVE-1999-00002) # * [CVE-1999-00002](https://www.cve.org/CVERecord?id=CVE-1999-00002)
# * [CVE-1999-00003](https://www.cve.org/CVERecord?id=CVE-1999-00003) # * [CVE-1999-00003](https://www.cve.org/CVERecord?id=CVE-1999-00003)
writeAdvisoryDescription = writeAdvisoryDescription =
if (lib.lists.remove null (retrievePatchAttributes [ "xsa" ]) != [ ]) then if (remove null (retrievePatchAttributes [ "xsa" ]) != [ ]) then
lib.lists.zipListsWith (a: b: a + b) zipListsWith (a: b: a + b)
(lib.lists.zipListsWith (a: b: a + "**" + b + ".**\n >") (zipListsWith (a: b: a + "**" + b + ".**\n >")
(lib.lists.zipListsWith (a: b: "* [Xen Security Advisory #" + a + "](" + b + "): ") (zipListsWith (a: b: "* [Xen Security Advisory #" + a + "](" + b + "): ")
(lib.lists.remove null (retrievePatchAttributes [ "xsa" ])) (remove null (retrievePatchAttributes [ "xsa" ]))
( (
lib.lists.remove null (retrievePatchAttributes [ remove null (retrievePatchAttributes [
"meta" "meta"
"homepage" "homepage"
]) ])
) )
) )
( (
lib.lists.remove null (retrievePatchAttributes [ remove null (retrievePatchAttributes [
"meta" "meta"
"description" "description"
]) ])
) )
) )
( (
lib.lists.remove null (retrievePatchAttributes [ remove null (retrievePatchAttributes [
"meta" "meta"
"longDescription" "longDescription"
]) ])
@ -327,198 +196,142 @@ let
doInstallCheck = false; # We get a spurious failure otherwise, due to a host/target mismatch. doInstallCheck = false; # We get a spurious failure otherwise, due to a host/target mismatch.
meta.mainProgram = "ld"; # We only really care for `ld`. meta.mainProgram = "ld"; # We only really care for `ld`.
}); });
#TODO: fix paths instead.
scriptEnvPath = makeSearchPathOutput "out" "bin" [
bridge-utils
coreutils
diffutils
gawk
gnugrep
gnused
inetutils
iproute2
iptables
multipath-tools
nbd
openvswitch
perl
util-linux.bin
which
];
in in
stdenv.mkDerivation (finalAttrs: { stdenv.mkDerivation (finalAttrs: {
inherit pname version; inherit pname version;
# TODO: Split $out in $bin for binaries and $lib for libraries.
# TODO: Python package to be in separate output/package.
outputs = [ outputs = [
"out" # TODO: Split $out in $bin for binaries and $lib for libraries. "out"
"man" # Manual pages for Xen userspace utilities. "man"
"doc" # The full Xen documentation in HTML format. "doc"
"dev" # Development headers. "dev"
"boot" # xen.gz kernel, policy file if Flask is enabled, xen.efi if EFI is enabled. "boot"
# TODO: Python package to be in separate output/package.
]; ];
# Main Xen source. # Main Xen source.
src = fetchgit { src = fetchgit {
url = "https://xenbits.xenproject.org/git-http/xen.git"; url = "https://xenbits.xenproject.org/git-http/xen.git";
inherit (pkg.xen) rev hash; inherit rev hash;
}; };
patches = patches = optionals useDefaultPatchList upstreamPatchList ++ patches;
# Generic Xen patches that apply to all Xen versions.
[ ./0000-xen-ipxe-src-generic.patch ]
# Gets the patches from the pkg.xen.patches attribute from the versioned files.
++ lib.lists.optionals (lib.attrsets.hasAttrByPath [ "patches" ] pkg.xen) pkg.xen.patches
++ upstreamPatchList;
nativeBuildInputs = nativeBuildInputs = [
[ autoPatchelfHook
autoPatchelfHook bison
bison cmake
cmake flex
flex pandoc
pandoc pkg-config
pkg-config python3Packages.setuptools
python3Packages.setuptools ];
] buildInputs = [
++ lib.lists.optionals withInternalQEMU [ # Xen
ninja acpica-tools
python3Packages.sphinx bzip2
]; dev86
buildInputs = e2fsprogs.dev
[ libnl
# Xen libuuid
acpica-tools lzo
bzip2 ncurses
dev86 perl
e2fsprogs.dev python3Packages.python
libnl xz
libuuid yajl
lzo zlib
ncurses zstd
perl
python3Packages.python
xz
yajl
zlib
zstd
# oxenstored # oxenstored
ocamlPackages.findlib ocamlPackages.findlib
ocamlPackages.ocaml ocamlPackages.ocaml
# Python Fixes # Python Fixes
python3Packages.wrapPython python3Packages.wrapPython
] ] ++ optional withFlask checkpolicy ++ optional (versionOlder version "4.19") systemdMinimal;
++ lib.lists.optionals withInternalQEMU [
glib
pixman
]
++ lib.lists.optional withInternalOVMF nasm
++ lib.lists.optional withFlask checkpolicy
++ lib.lists.optional (lib.strings.versionOlder version "4.19") systemdMinimal;
configureFlags = configureFlags = [
[ "--enable-systemd"
"--enable-systemd" "--disable-qemu-traditional"
"--disable-qemu-traditional" "--with-system-qemu"
] (if withSeaBIOS then "--with-system-seabios=${seabios}/share/seabios" else "--disable-seabios")
++ lib.lists.optional (!withInternalQEMU) "--with-system-qemu" (if withOVMF then "--with-system-ovmf=${OVMF.firmware}" else "--disable-ovmf")
(if withIPXE then "--with-system-ipxe=${ipxe}" else "--disable-ipxe")
++ lib.lists.optional withSeaBIOS "--with-system-seabios=${seabios}/share/seabios" (enableFeature withFlask "xsmpolicy")
++ lib.lists.optional (!withInternalSeaBIOS && !withSeaBIOS) "--disable-seabios" ];
++ lib.lists.optional withOVMF "--with-system-ovmf=${OVMF.firmware}"
++ lib.lists.optional withInternalOVMF "--enable-ovmf"
++ lib.lists.optional withIPXE "--with-system-ipxe=${ipxe}"
++ lib.lists.optional withInternalIPXE "--enable-ipxe"
++ lib.lists.optional withFlask "--enable-xsmpolicy";
makeFlags = makeFlags =
[ [
"SUBSYSTEMS=${toString finalAttrs.buildFlags}"
"PREFIX=$(out)" "PREFIX=$(out)"
"CONFIG_DIR=/etc"
"XEN_SCRIPT_DIR=$(CONFIG_DIR)/xen/scripts"
"BASH_COMPLETION_DIR=$(PREFIX)/share/bash-completion/completions" "BASH_COMPLETION_DIR=$(PREFIX)/share/bash-completion/completions"
"XEN_WHOAMI=${pname}"
"XEN_DOMAIN=${vendor}"
"GIT=${coreutils}/bin/false"
"WGET=${coreutils}/bin/false"
] ]
++ lib.lists.optionals withEFI [ ++ optionals withEFI [
"EFI_VENDOR=${efiVendor}" "EFI_VENDOR=${vendor}"
"INSTALL_EFI_STRIP=1" "INSTALL_EFI_STRIP=1"
"LD=${lib.meta.getExe efiBinutils}" # See the comment in the efiBinutils definition above. "LD=${getExe efiBinutils}" # See the comment in the efiBinutils definition above.
] ]
# These flags set the CONFIG_* options in /boot/xen.config # These flags set the CONFIG_* options in /boot/xen.config
# and define if the default policy file is built. However, # and define if the default policy file is built. However,
# the Flask binaries always get compiled by default. # the Flask binaries always get compiled by default.
++ lib.lists.optionals withFlask [ ++ optionals withFlask [
"XSM_ENABLE=y" "XSM_ENABLE=y"
"FLASK_ENABLE=y" "FLASK_ENABLE=y"
] ];
++ (pkg.xen.makeFlags or [ ]);
buildFlags = [ buildFlags = [
"xen" # Build the Xen Hypervisor. "xen"
"tools" # Build the userspace tools, such as `xl`. "tools"
"docs" # Build the Xen Documentation "docs"
]; ];
enableParallelBuilding = true; enableParallelBuilding = true;
env.NIX_CFLAGS_COMPILE = builtins.toString ( env.NIX_CFLAGS_COMPILE = toString [
[ "-Wno-error=maybe-uninitialized"
"-Wno-error=maybe-uninitialized" "-Wno-error=array-bounds"
"-Wno-error=array-bounds" ];
]
++ lib.lists.optionals withInternalOVMF [
"-Wno-error=format-security"
"-Wno-error=use-after-free"
"-Wno-error=vla-parameter"
"-Wno-error=dangling-pointer"
"-Wno-error=stringop-overflow"
]
);
dontUseCmakeConfigure = true; dontUseCmakeConfigure = true;
dontUseNinjaBuild = withInternalQEMU;
prePatch = # Remove in-tree QEMU sources, we don't need them in any circumstance.
# Xen's stubdoms, tools and firmwares need various sources that prePatch = "rm --recursive --force tools/qemu-xen tools/qemu-xen-traditional";
# are usually fetched at build time using wget and git. We can't
# have that, so we pre-fetch them in the versioned Nix expressions,
# and produce fake wget and git executables for debugging purposes.
#
# We also produce a fake hostname executable to prevent spurious
# command-not-found errors during compilation.
#
# The snippet below produces executables that simply print in stdout
# what they were supposed to fetch, and exit gracefully.
''
mkdir fake-bin
cat > fake-bin/wget << EOF
#!${stdenv.shell} -e
echo ===== FAKE WGET: Not fetching \$*
[ -e \$3 ]
EOF
cat > fake-bin/git << EOF
#!${stdenv.shell}
echo ===== FAKE GIT: Not cloning \$*
[ -e \$3 ]
EOF
cat > fake-bin/hostname << EOF
#!${stdenv.shell}
echo ${efiVendor}
[ -e \$3 ]
EOF
chmod +x fake-bin/*
export PATH=$PATH:$PWD/fake-bin
''
# Remove in-tree QEMU sources, as we either pre-fetch them through
# the versioned Nix expressions if withInternalQEMU is true, or we
# don't build QEMU at all if withInternalQEMU is false.
+ ''
rm --recursive --force tools/qemu-xen tools/qemu-xen-traditional
''
# Call copyPrefetchedSources, which copies all aviable sources to their correct positions.
+ ''
${copyPrefetchedSources}
'';
postPatch = postPatch =
# The following patch forces Xen to install xen.efi on $out/boot # The following patch forces Xen to install xen.efi on $out/boot
# instead of $out/boot/efi/efi/nixos, as the latter directory # instead of $out/boot/efi/efi/nixos, as the latter directory
# would otherwise need to be created manually. This also creates # would otherwise need to be created manually. This also creates
# a more consistent output for downstreams who override the # a more consistent output for downstreams who override the
# efiVendor attribute above. # vendor attribute above.
'' ''
substituteInPlace xen/Makefile \ substituteInPlace xen/Makefile \
--replace-fail "\$(D)\$(EFI_MOUNTPOINT)/efi/\$(EFI_VENDOR)/\$(T)-\$(XEN_FULLVERSION).efi" \ --replace-fail "\$(D)\$(EFI_MOUNTPOINT)/efi/\$(EFI_VENDOR)/\$(T)-\$(XEN_FULLVERSION).efi" \
@ -541,46 +354,18 @@ stdenv.mkDerivation (finalAttrs: {
substituteInPlace \ substituteInPlace \
tools/hotplug/Linux/systemd/{xen-qemu-dom0-disk-backend,xenconsoled}.service.in \ tools/hotplug/Linux/systemd/{xen-qemu-dom0-disk-backend,xenconsoled}.service.in \
--replace-fail "/bin/mkdir" "${coreutils}/bin/mkdir" --replace-fail "/bin/mkdir" "${coreutils}/bin/mkdir"
''
# # Call deployPrefetchedSourcesPatches, which patches all pre-fetched sources with their specified patchlists.
+ ''
${deployPrefetchedSourcesPatches}
''
# Patch shebangs for QEMU and OVMF build scripts.
+ lib.strings.optionalString withInternalQEMU ''
patchShebangs --build tools/qemu-xen/scripts/tracetool.py
''
+ lib.strings.optionalString withInternalOVMF ''
patchShebangs --build tools/firmware/ovmf-dir-remote/OvmfPkg/build.sh tools/firmware/ovmf-dir-remote/BaseTools/BinWrappers/PosixLike/{AmlToC,BrotliCompress,build,GenFfs,GenFv,GenFw,GenSec,LzmaCompress,TianoCompress,Trim,VfrCompile}
''; '';
installPhase = installPhase = ''
let runHook preInstall
cpFlags = builtins.toString [
"--preserve=mode,ownership,timestamps,link"
"--recursive"
"--verbose"
"--no-dereference"
];
in
# Run the preInstall tasks.
''
runHook preInstall
''
# Create $out directories and copy build output. mkdir --parents $out $out/share $boot
+ '' cp -prvd dist/install/nix/store/*/* $out/
mkdir --parents $out $out/share $boot cp -prvd dist/install/etc $out
cp ${cpFlags} dist/install/nix/store/*/* $out/ cp -prvd dist/install/boot $boot
cp ${cpFlags} dist/install/etc $out
cp ${cpFlags} dist/install/boot $boot
''
# Run the postInstall tasks. runHook postInstall
+ '' '';
runHook postInstall
'';
postInstall = postInstall =
# Wrap xencov_split, xenmon and xentrace_format. # Wrap xencov_split, xenmon and xentrace_format.
@ -603,7 +388,6 @@ stdenv.mkDerivation (finalAttrs: {
''; '';
postFixup = postFixup =
# Fix binaries in $out/libexec/xen/bin.
'' ''
addAutoPatchelfSearchPath $out/lib addAutoPatchelfSearchPath $out/lib
autoPatchelf $out/libexec/xen/bin autoPatchelf $out/libexec/xen/bin
@ -611,7 +395,7 @@ stdenv.mkDerivation (finalAttrs: {
# Flask is particularly hard to disable. Even after # Flask is particularly hard to disable. Even after
# setting the make flags to `n`, it still gets compiled. # setting the make flags to `n`, it still gets compiled.
# If withFlask is disabled, delete the extra binaries. # If withFlask is disabled, delete the extra binaries.
+ lib.strings.optionalString (!withFlask) '' + optionalString (!withFlask) ''
rm -f $out/bin/flask-* rm -f $out/bin/flask-*
''; '';
@ -623,11 +407,6 @@ stdenv.mkDerivation (finalAttrs: {
"boot/xenpolicy-${version}" "boot/xenpolicy-${version}"
else else
throw "This Xen was compiled without FLASK support."; throw "This Xen was compiled without FLASK support.";
qemu-system-i386 =
if withInternalQEMU then
"libexec/xen/bin/qemu-system-i386"
else
throw "This Xen was compiled without a built-in QEMU.";
# This test suite is very simple, as Xen's userspace # This test suite is very simple, as Xen's userspace
# utilities require the hypervisor to be booted. # utilities require the hypervisor to be booted.
tests = { tests = {
@ -654,103 +433,63 @@ stdenv.mkDerivation (finalAttrs: {
}; };
}; };
meta = meta = {
if inherit branch;
!(lib.attrsets.hasAttrByPath [
"meta"
] versionDefinition)
then
{
inherit branch;
# Short description for Xen. description = "Type-1 hypervisor intended for embedded and hyperscale use cases";
description = longDescription =
"Xen Project Hypervisor" ''
# The "and related components" addition is automatically hidden if said components aren't being built. The Xen Project Hypervisor is a virtualisation technology defined as a *type-1
+ lib.strings.optionalString (prefetchedSources != { }) " and related components" hypervisor*, which allows multiple virtual machines, known as domains, to run
+ " (${if slim then "Without Internal Components" else "Standard"})"; concurrently with the host on the physical machine. On a typical *type-2
hypervisor*, the virtual machines run as applications on top of the
host. NixOS runs as the privileged **Domain 0**, and can paravirtualise or fully
virtualise **Unprivileged Domains**.
# Long description for Xen. Use with the `qemu_xen` package.
longDescription = ''
( # Then, if any of the optional with* components are being built, add the "Includes:" string.
if slim then + optionalString (withEFI || withFlask) (
'' "\nIncludes:"
Slimmed-down version of the Xen Project Hypervisor that reuses nixpkgs packages # Originally, this was a call for the complicated withPrefetchedSources. Since there aren't
as much as possible. Instead of using the Xen Project forks for various internal # that many optional components, we just use lib.strings.optionalString, because it's simpler.
components, this version uses `seabios`, `ovmf` and `ipxe` from Nixpkgs. These # Optional components that aren't being built are automatically hidden.
components may ocasionally get out of sync with the hypervisor itself, but this + optionalString withEFI "\n* `xen.efi`: The Xen Project's [EFI binary](https://xenbits.xenproject.org/docs/${branch}-testing/misc/efi.html), available on the `boot` output of this package."
builds faster and uses less space than the default derivation. + optionalString withFlask "\n* `xsm-flask`: The [FLASK Xen Security Module](https://wiki.xenproject.org/wiki/Xen_Security_Modules_:_XSM-FLASK). The `xenpolicy-${version}` file is available on the `boot` output of this package."
'' + optionalString withSeaBIOS "\n* `seabios`: Support for the SeaBIOS boot firmware on HVM domains."
else + optionalString withOVMF "\n* `ovmf`: Support for the OVMF UEFI boot firmware on HVM domains."
'' + optionalString withIPXE "\n* `ipxe`: Support for the iPXE boot firmware on HVM domains."
Standard version of the Xen Project Hypervisor. Uses forks of QEMU, SeaBIOS, )
OVMF and iPXE provided by the Xen Project. This provides the vanilla Xen # Finally, we write a notice explaining which vulnerabilities this Xen is NOT vulnerable to.
experience, but wastes space and build time. A typical NixOS setup that runs # This will hopefully give users the peace of mind that their Xen is secure, without needing
lots of VMs will usually need to build two different versions of QEMU when using # to search the source code for the XSA patches.
this Xen derivation (one fork and upstream). + optionalString (writeAdvisoryDescription != [ ]) (
'' "\n\nThis Xen Project Hypervisor (${version}) has been patched against the following known security vulnerabilities:\n"
) + removeSuffix "\n" (concatLines writeAdvisoryDescription)
+ lib.strings.optionalString (!withInternalQEMU) ( );
"\nUse with `qemu_xen_${lib.strings.stringAsChars (x: if x == "." then "_" else x) branch}`"
+ lib.strings.optionalString latest " or `qemu_xen`"
+ ".\n"
)
# Then, if any of the optional with* components are being built, add the "Includes:" string.
+
lib.strings.optionalString
(
withInternalQEMU
|| withInternalSeaBIOS
|| withInternalOVMF
|| withInternalIPXE
|| withEFI
|| withFlask
)
(
"\nIncludes:"
# Originally, this was a call for the complicated withPrefetchedSources. Since there aren't
# that many optional components, we just use lib.strings.optionalString, because it's simpler.
# Optional components that aren't being built are automatically hidden.
+ lib.strings.optionalString withEFI "\n* `xen.efi`: The Xen Project's [EFI binary](https://xenbits.xenproject.org/docs/${branch}-testing/misc/efi.html), available on the `boot` output of this package."
+ lib.strings.optionalString withFlask "\n* `xsm-flask`: The [FLASK Xen Security Module](https://wiki.xenproject.org/wiki/Xen_Security_Modules_:_XSM-FLASK). The `xenpolicy-${version}` file is available on the `boot` output of this package."
+ lib.strings.optionalString withInternalQEMU "\n* `qemu-xen`: The Xen Project's mirror of [QEMU](https://www.qemu.org/)."
+ lib.strings.optionalString withInternalSeaBIOS "\n* `seabios-xen`: The Xen Project's mirror of [SeaBIOS](https://www.seabios.org/SeaBIOS)."
+ lib.strings.optionalString withInternalOVMF "\n* `ovmf-xen`: The Xen Project's mirror of [OVMF](https://github.com/tianocore/tianocore.github.io/wiki/OVMF)."
+ lib.strings.optionalString withInternalIPXE "\n* `ipxe-xen`: The Xen Project's pinned version of [iPXE](https://ipxe.org/)."
)
# Finally, we write a notice explaining which vulnerabilities this Xen is NOT vulnerable to.
# This will hopefully give users the peace of mind that their Xen is secure, without needing
# to search the source code for the XSA patches.
+ lib.strings.optionalString (writeAdvisoryDescription != [ ]) (
"\n\nThis Xen Project Hypervisor (${version}) has been patched against the following known security vulnerabilities:\n"
+ lib.strings.removeSuffix "\n" (lib.strings.concatLines writeAdvisoryDescription)
);
homepage = "https://xenproject.org/"; homepage = "https://xenproject.org/";
downloadPage = "https://downloads.xenproject.org/release/xen/${version}/"; downloadPage = "https://downloads.xenproject.org/release/xen/${version}/";
changelog = "https://wiki.xenproject.org/wiki/Xen_Project_${branch}_Release_Notes"; changelog = "https://wiki.xenproject.org/wiki/Xen_Project_${branch}_Release_Notes";
license = with lib.licenses; [ license = [
# Documentation. # Documentation.
cc-by-40 cc-by-40
# Most of Xen is licensed under the GPL v2.0. # Most of Xen is licensed under the GPL v2.0.
gpl2Only gpl2Only
# Xen Libraries and the `xl` command-line utility. # Xen Libraries and the `xl` command-line utility.
lgpl21Only lgpl21Only
# Development headers in $dev/include. # Development headers in $dev/include.
mit mit
]; ];
# This automatically removes maintainers from EOL versions of Xen, so we aren't bothered about versions we don't explictly support. maintainers = teams.xen.members;
maintainers = lib.lists.optionals (lib.strings.versionAtLeast version minSupportedVersion) lib.teams.xen.members; knownVulnerabilities = optional (versionOlder version minSupportedVersion) "The Xen Project Hypervisor version ${version} is no longer supported by the Xen Project Security Team. See https://xenbits.xenproject.org/docs/unstable/support-matrix.html";
knownVulnerabilities = lib.lists.optional (lib.strings.versionOlder version minSupportedVersion) "The Xen Project Hypervisor version ${version} is no longer supported by the Xen Project Security Team. See https://xenbits.xenproject.org/docs/unstable/support-matrix.html";
mainProgram = "xl"; mainProgram = "xl";
# Evaluates to x86_64-linux. #TODO: Migrate meta.platforms to the new lib.systems.inspect.patterns.* format.
platforms = lib.lists.intersectLists lib.platforms.linux lib.platforms.x86_64; platforms = linux;
badPlatforms = aarch64;
} } // meta;
else
versionDefinition.meta;
}) })

View File

@ -6,6 +6,9 @@
{ lib, fetchpatch }: { lib, fetchpatch }:
let let
inherit (builtins) concatStringsSep;
inherit (lib.strings) optionalString concatMapStrings;
xsaPatch = xsaPatch =
{ {
id, id,
@ -16,8 +19,7 @@ let
cve ? null, cve ? null,
}: }:
(fetchpatch { (fetchpatch {
name = name = "XSA-" + id + optionalString (cve != null) ("-" + concatStringsSep "+" cve);
"XSA-" + id + lib.strings.optionalString (cve != null) ("-" + builtins.concatStringsSep "+" cve);
url = "https://xenbits.xen.org/xsa/xsa${id}.patch"; url = "https://xenbits.xen.org/xsa/xsa${id}.patch";
inherit hash; inherit hash;
passthru = { passthru = {
@ -37,9 +39,7 @@ let
" _No CVE was assigned to this XSA._" " _No CVE was assigned to this XSA._"
else else
" Fixes:${ " Fixes:${
lib.strings.concatMapStrings ( concatMapStrings (x: "\n * [" + x + "](https://www.cve.org/CVERecord?id=" + x + ")") cve
x: "\n * [" + x + "](https://www.cve.org/CVERecord?id=" + x + ")"
) cve
}" }"
); );
homepage = "https://xenbits.xenproject.org/xsa/advisory-${id}.html"; homepage = "https://xenbits.xenproject.org/xsa/advisory-${id}.html";