xen: nuke, move to by-name. (#345192)

This commit is contained in:
Emily
2024-10-07 03:48:37 +01:00
committed by GitHub
22 changed files with 815 additions and 1580 deletions
+3 -1
View File
@@ -385,9 +385,11 @@
- changed-files:
- any-glob-to-any-file:
- nixos/modules/virtualisation/xen*
- pkgs/applications/virtualization/xen/**
- pkgs/by-name/xe/xen/*
- pkgs/by-name/qe/qemu_xen/*
- pkgs/by-name/xe/xen-guest-agent/*
- pkgs/by-name/xt/xtf/*
- pkgs/build-support/xen/*
- pkgs/development/ocaml-modules/xen*/*
- pkgs/development/ocaml-modules/vchan/*
@@ -54,12 +54,11 @@
was added through the `boot.initrd.systemd.dmVerity` option.
- The [Xen Project Hypervisor](https://xenproject.org) is once again available as a virtualisation option under [`virtualisation.xen`](#opt-virtualisation.xen.enable).
- This release includes Xen [4.17.5](https://wiki.xenproject.org/wiki/Xen_Project_4.17_Release_Notes), [4.18.3](https://wiki.xenproject.org/wiki/Xen_Project_4.18_Release_Notes) and [4.19.0](https://wiki.xenproject.org/wiki/Xen_Project_4.19_Release_Notes), as well as support for booting the hypervisor on EFI systems.
- This release includes Xen [4.19.0](https://wiki.xenproject.org/wiki/Xen_Project_4.19_Release_Notes) and support for booting the hypervisor on EFI systems.
::: {.warning}
Booting into the Xen Project Hypervisor through a legacy BIOS bootloader or with the legacy script-based Stage 1 initrd have been **deprecated**. Only EFI booting and the new systemd-based Stage 1 initrd are supported.
:::
- There are two flavours of Xen available by default: `xen`, which includes all built-in components, and `xen-slim`, which replaces the built-in components with their Nixpkgs equivalents.
- The `qemu-xen-traditional` component has been deprecated by the upstream Xen Project, and is no longer available in any of the Xen Project Hypervisor packages.
- The `qemu-xen-traditional` component has been deprecated by the upstream Xen Project, and is no longer included in the Xen build.
- The OCaml-based Xen Store can now be configured using [`virtualisation.xen.store.settings`](#opt-virtualisation.xen.store.settings).
- The `virtualisation.xen.bridge` options have been deprecated in this release cycle. Users who need network bridges are encouraged to set up their own networking configurations.
+147 -146
View File
@@ -8,6 +8,35 @@
}:
let
inherit (builtins) readFile;
inherit (lib.modules) mkRemovedOptionModule mkRenamedOptionModule mkIf;
inherit (lib.options)
mkOption
mkEnableOption
literalExpression
mkPackageOption
;
inherit (lib.types)
listOf
str
ints
lines
enum
path
submodule
addCheck
float
bool
int
nullOr
;
inherit (lib.lists) optional optionals;
inherit (lib.strings) hasSuffix optionalString;
inherit (lib.meta) getExe;
inherit (lib.attrsets) optionalAttrs;
inherit (lib.trivial) boolToString;
inherit (lib.teams.xen) members;
cfg = config.virtualisation.xen;
xenBootBuilder = pkgs.writeShellApplication {
@@ -22,7 +51,7 @@ let
gnused
jq
])
++ lib.lists.optionals (cfg.efi.bootBuilderVerbosity == "info") (
++ optionals (cfg.efi.bootBuilderVerbosity == "info") (
with pkgs;
[
bat
@@ -36,12 +65,12 @@ let
# We disable SC2016 because we don't want to expand the regexes in the sed commands.
excludeShellChecks = [ "SC2016" ];
text = builtins.readFile ./xen-boot-builder.sh;
text = readFile ./xen-boot-builder.sh;
};
in
{
imports = with lib.modules; [
imports = [
(mkRemovedOptionModule
[
"virtualisation"
@@ -123,59 +152,33 @@ in
options.virtualisation.xen = {
enable = lib.options.mkEnableOption "the Xen Project Hypervisor, a virtualisation technology defined as a *type-1 hypervisor*, which allows multiple virtual machines, known as *domains*, to run concurrently on the physical machine. NixOS runs as the privileged *Domain 0*. This option requires a reboot into a Xen kernel to take effect";
enable = mkEnableOption "the Xen Project Hypervisor, a virtualisation technology defined as a *type-1 hypervisor*, which allows multiple virtual machines, known as *domains*, to run concurrently on the physical machine. NixOS runs as the privileged *Domain 0*. This option requires a reboot into a Xen kernel to take effect";
debug = lib.options.mkEnableOption "Xen debug features for Domain 0. This option enables some hidden debugging tests and features, and should not be used in production";
debug = mkEnableOption "Xen debug features for Domain 0. This option enables some hidden debugging tests and features, and should not be used in production";
trace = lib.options.mkOption {
type = lib.types.bool;
trace = mkOption {
type = bool;
default = cfg.debug;
defaultText = lib.options.literalExpression "false";
defaultText = literalExpression "false";
example = true;
description = "Whether to enable Xen debug tracing and logging for Domain 0.";
};
package = lib.options.mkOption {
type = lib.types.package;
default = pkgs.xen;
defaultText = lib.options.literalExpression "pkgs.xen";
example = lib.options.literalExpression "pkgs.xen-slim";
description = ''
The package used for Xen Project Hypervisor.
'';
relatedPackages = [
"xen"
"xen-slim"
];
};
package = mkPackageOption pkgs "Xen Hypervisor" { default = [ "xen" ]; };
qemu = {
package = lib.options.mkOption {
type = lib.types.package;
default = pkgs.xen;
defaultText = lib.options.literalExpression "pkgs.xen";
example = lib.options.literalExpression "pkgs.qemu_xen";
description = ''
The package with QEMU binaries that runs in Domain 0
and virtualises the unprivileged domains.
'';
relatedPackages = [
"xen"
{
name = "qemu_xen";
comment = "For use with `pkgs.xen-slim`.";
}
];
package = mkPackageOption pkgs "QEMU (with Xen Hypervisor support)" {
default = [ "qemu_xen" ];
};
pidFile = lib.options.mkOption {
type = lib.types.path;
pidFile = mkOption {
type = path;
default = "/run/xen/qemu-dom0.pid";
example = "/var/run/xen/qemu-dom0.pid";
description = "Path to the QEMU PID file.";
};
};
bootParams = lib.options.mkOption {
bootParams = mkOption {
default = [ ];
example = ''
[
@@ -184,7 +187,7 @@ in
"vga=ask"
]
'';
type = lib.types.listOf lib.types.str;
type = listOf str;
description = ''
Xen Command Line parameters passed to Domain 0 at boot time.
Note: these are different from `boot.kernelParams`. See
@@ -193,8 +196,8 @@ in
};
efi = {
bootBuilderVerbosity = lib.options.mkOption {
type = lib.types.enum [
bootBuilderVerbosity = mkOption {
type = enum [
"default"
"info"
"debug"
@@ -218,11 +221,11 @@ in
'';
};
path = lib.options.mkOption {
type = lib.types.path;
path = mkOption {
type = path;
default = "${cfg.package.boot}/${cfg.package.efi}";
defaultText = lib.options.literalExpression "\${config.virtualisation.xen.package.boot}/\${config.virtualisation.xen.package.efi}";
example = lib.options.literalExpression "\${config.virtualisation.xen.package}/boot/efi/efi/nixos/xen-\${config.virtualisation.xen.package.version}.efi";
defaultText = literalExpression "\${config.virtualisation.xen.package.boot}/\${config.virtualisation.xen.package.efi}";
example = literalExpression "\${config.virtualisation.xen.package}/boot/efi/efi/nixos/xen-\${config.virtualisation.xen.package.version}.efi";
description = ''
Path to xen.efi. `pkgs.xen` is patched to install the xen.efi file
on `$boot/boot/xen.efi`, but an unpatched Xen build may install it
@@ -234,10 +237,10 @@ in
};
dom0Resources = {
maxVCPUs = lib.options.mkOption {
maxVCPUs = mkOption {
default = 0;
example = 4;
type = lib.types.ints.unsigned;
type = ints.unsigned;
description = ''
Amount of virtual CPU cores allocated to Domain 0 on boot.
If set to 0, all cores are assigned to Domain 0, and
@@ -245,10 +248,10 @@ in
'';
};
memory = lib.options.mkOption {
memory = mkOption {
default = 0;
example = 512;
type = lib.types.ints.unsigned;
type = ints.unsigned;
description = ''
Amount of memory (in MiB) allocated to Domain 0 on boot.
If set to 0, all memory is assigned to Domain 0, and
@@ -256,11 +259,11 @@ in
'';
};
maxMemory = lib.options.mkOption {
maxMemory = mkOption {
default = cfg.dom0Resources.memory;
defaultText = lib.options.literalExpression "config.virtualisation.xen.dom0Resources.memory";
defaultText = literalExpression "config.virtualisation.xen.dom0Resources.memory";
example = 1024;
type = lib.types.ints.unsigned;
type = ints.unsigned;
description = ''
Maximum amount of memory (in MiB) that Domain 0 can
dynamically allocate to itself. Does nothing if set
@@ -271,8 +274,8 @@ in
};
domains = {
extraConfig = lib.options.mkOption {
type = lib.types.lines;
extraConfig = mkOption {
type = lines;
default = "";
example = ''
XENDOMAINS_SAVE=/persist/xen/save
@@ -288,28 +291,28 @@ in
};
store = {
path = lib.options.mkOption {
type = lib.types.path;
path = mkOption {
type = path;
default = "${cfg.package}/bin/oxenstored";
defaultText = lib.options.literalExpression "\${config.virtualisation.xen.package}/bin/oxenstored";
example = lib.options.literalExpression "\${config.virtualisation.xen.package}/bin/xenstored";
defaultText = literalExpression "\${config.virtualisation.xen.package}/bin/oxenstored";
example = literalExpression "\${config.virtualisation.xen.package}/bin/xenstored";
description = ''
Path to the Xen Store Daemon. This option is useful to
switch between the legacy C-based Xen Store Daemon, and
the newer OCaml-based Xen Store Daemon, `oxenstored`.
'';
};
type = lib.options.mkOption {
type = lib.types.enum [
type = mkOption {
type = enum [
"c"
"ocaml"
];
default = if (lib.strings.hasSuffix "oxenstored" cfg.store.path) then "ocaml" else "c";
default = if (hasSuffix "oxenstored" cfg.store.path) then "ocaml" else "c";
internal = true;
readOnly = true;
description = "Helper internal option that determines the type of the Xen Store Daemon based on cfg.store.path.";
};
settings = lib.options.mkOption {
settings = mkOption {
default = { };
example = {
enableMerge = false;
@@ -324,34 +327,34 @@ in
The OCaml-based Xen Store Daemon configuration. This
option does nothing with the C-based `xenstored`.
'';
type = lib.types.submodule {
type = submodule {
options = {
pidFile = lib.options.mkOption {
pidFile = mkOption {
default = "/run/xen/xenstored.pid";
example = "/var/run/xen/xenstored.pid";
type = lib.types.path;
type = path;
description = "Path to the Xen Store Daemon PID file.";
};
testEAGAIN = lib.options.mkOption {
testEAGAIN = mkOption {
default = cfg.debug;
defaultText = lib.options.literalExpression "config.virtualisation.xen.debug";
defaultText = literalExpression "config.virtualisation.xen.debug";
example = true;
type = lib.types.bool;
type = bool;
visible = false;
description = "Randomly fail a transaction with EAGAIN. This option is used for debugging purposes only.";
};
enableMerge = lib.options.mkOption {
enableMerge = mkOption {
default = true;
example = false;
type = lib.types.bool;
type = bool;
description = "Whether to enable transaction merge support.";
};
conflict = {
burstLimit = lib.options.mkOption {
burstLimit = mkOption {
default = 5.0;
example = 15.0;
type = lib.types.addCheck (
lib.types.float
type = addCheck (
float
// {
name = "nonnegativeFloat";
description = "nonnegative floating point number, meaning >=0";
@@ -369,12 +372,12 @@ in
domain's requests are ignored.
'';
};
maxHistorySeconds = lib.options.mkOption {
maxHistorySeconds = mkOption {
default = 5.0e-2;
example = 1.0;
type = lib.types.addCheck (
lib.types.float // { description = "nonnegative floating point number, meaning >=0"; }
) (n: n >= 0);
type = addCheck (float // { description = "nonnegative floating point number, meaning >=0"; }) (
n: n >= 0
);
description = ''
Limits applied to domains whose writes cause other domains' transaction
commits to fail. Must include decimal point.
@@ -384,10 +387,10 @@ in
is the minimum pause-time during which a domain will be ignored.
'';
};
rateLimitIsAggregate = lib.options.mkOption {
rateLimitIsAggregate = mkOption {
default = true;
example = false;
type = lib.types.bool;
type = bool;
description = ''
If the conflict.rateLimitIsAggregate option is `true`, then after each
tick one point of conflict-credit is given to just one domain: the
@@ -408,16 +411,16 @@ in
};
};
perms = {
enable = lib.options.mkOption {
enable = mkOption {
default = true;
example = false;
type = lib.types.bool;
type = bool;
description = "Whether to enable the node permission system.";
};
enableWatch = lib.options.mkOption {
enableWatch = mkOption {
default = true;
example = false;
type = lib.types.bool;
type = bool;
description = ''
Whether to enable the watch permission system.
@@ -432,144 +435,142 @@ in
};
};
quota = {
enable = lib.options.mkOption {
enable = mkOption {
default = true;
example = false;
type = lib.types.bool;
type = bool;
description = "Whether to enable the quota system.";
};
maxEntity = lib.options.mkOption {
maxEntity = mkOption {
default = 1000;
example = 1024;
type = lib.types.ints.positive;
type = ints.positive;
description = "Entity limit for transactions.";
};
maxSize = lib.options.mkOption {
maxSize = mkOption {
default = 2048;
example = 4096;
type = lib.types.ints.positive;
type = ints.positive;
description = "Size limit for transactions.";
};
maxWatch = lib.options.mkOption {
maxWatch = mkOption {
default = 100;
example = 256;
type = lib.types.ints.positive;
type = ints.positive;
description = "Maximum number of watches by the Xenstore Watchdog.";
};
transaction = lib.options.mkOption {
transaction = mkOption {
default = 10;
example = 50;
type = lib.types.ints.positive;
type = ints.positive;
description = "Maximum number of transactions.";
};
maxRequests = lib.options.mkOption {
maxRequests = mkOption {
default = 1024;
example = 1024;
type = lib.types.ints.positive;
type = ints.positive;
description = "Maximum number of requests per transaction.";
};
maxPath = lib.options.mkOption {
maxPath = mkOption {
default = 1024;
example = 1024;
type = lib.types.ints.positive;
type = ints.positive;
description = "Path limit for the quota system.";
};
maxOutstanding = lib.options.mkOption {
maxOutstanding = mkOption {
default = 1024;
example = 1024;
type = lib.types.ints.positive;
type = ints.positive;
description = "Maximum outstanding requests, i.e. in-flight requests / domain.";
};
maxWatchEvents = lib.options.mkOption {
maxWatchEvents = mkOption {
default = 1024;
example = 2048;
type = lib.types.ints.positive;
type = ints.positive;
description = "Maximum number of outstanding watch events per watch.";
};
};
persistent = lib.options.mkOption {
persistent = mkOption {
default = false;
example = true;
type = lib.types.bool;
type = bool;
description = "Whether to activate the filed base backend.";
};
xenstored = {
log = {
file = lib.options.mkOption {
file = mkOption {
default = "/var/log/xen/xenstored.log";
example = "/dev/null";
type = lib.types.path;
type = path;
description = "Path to the Xen Store log file.";
};
level = lib.options.mkOption {
level = mkOption {
default = if cfg.trace then "debug" else null;
defaultText = lib.options.literalExpression "if (config.virtualisation.xen.trace == true) then \"debug\" else null";
defaultText = literalExpression "if (config.virtualisation.xen.trace == true) then \"debug\" else null";
example = "error";
type = lib.types.nullOr (
lib.types.enum [
"debug"
"info"
"warn"
"error"
]
);
type = nullOr (enum [
"debug"
"info"
"warn"
"error"
]);
description = "Logging level for the Xen Store.";
};
# The hidden options below have no upstream documentation whatsoever.
# The nb* options appear to alter the log rotation behaviour, and
# the specialOps option appears to affect the Xenbus logging logic.
nbFiles = lib.options.mkOption {
nbFiles = mkOption {
default = 10;
example = 16;
type = lib.types.int;
type = int;
visible = false;
description = "Set `xenstored-log-nb-files`.";
};
};
accessLog = {
file = lib.options.mkOption {
file = mkOption {
default = "/var/log/xen/xenstored-access.log";
example = "/var/log/security/xenstored-access.log";
type = lib.types.path;
type = path;
description = "Path to the Xen Store access log file.";
};
nbLines = lib.options.mkOption {
nbLines = mkOption {
default = 13215;
example = 16384;
type = lib.types.int;
type = int;
visible = false;
description = "Set `access-log-nb-lines`.";
};
nbChars = lib.options.mkOption {
nbChars = mkOption {
default = 180;
example = 256;
type = lib.types.int;
type = int;
visible = false;
description = "Set `acesss-log-nb-chars`.";
};
specialOps = lib.options.mkOption {
specialOps = mkOption {
default = false;
example = true;
type = lib.types.bool;
type = bool;
visible = false;
description = "Set `access-log-special-ops`.";
};
};
xenfs = {
kva = lib.options.mkOption {
kva = mkOption {
default = "/proc/xen/xsd_kva";
example = cfg.store.settings.xenstored.xenfs.kva;
type = lib.types.path;
type = path;
visible = false;
description = ''
Path to the Xen Store Daemon KVA location inside the XenFS pseudo-filesystem.
While it is possible to alter this value, some drivers may be hardcoded to follow the default paths.
'';
};
port = lib.options.mkOption {
port = mkOption {
default = "/proc/xen/xsd_port";
example = cfg.store.settings.xenstored.xenfs.port;
type = lib.types.path;
type = path;
visible = false;
description = ''
Path to the Xen Store Daemon userspace port inside the XenFS pseudo-filesystem.
@@ -578,11 +579,11 @@ in
};
};
};
ringScanInterval = lib.options.mkOption {
ringScanInterval = mkOption {
default = 20;
example = 30;
type = lib.types.addCheck (
lib.types.int
type = addCheck (
int
// {
name = "nonzeroInt";
description = "nonzero signed integer, meaning !=0";
@@ -602,7 +603,7 @@ in
## Implementation ##
config = lib.modules.mkIf cfg.enable {
config = mkIf cfg.enable {
assertions = [
{
assertion = pkgs.stdenv.hostPlatform.isx86_64;
@@ -639,18 +640,18 @@ in
];
virtualisation.xen.bootParams =
lib.lists.optionals cfg.trace [
optionals cfg.trace [
"loglvl=all"
"guest_loglvl=all"
]
++
lib.lists.optional (cfg.dom0Resources.memory != 0)
optional (cfg.dom0Resources.memory != 0)
"dom0_mem=${toString cfg.dom0Resources.memory}M${
lib.strings.optionalString (
optionalString (
cfg.dom0Resources.memory != cfg.dom0Resources.maxMemory
) ",max:${toString cfg.dom0Resources.maxMemory}M"
}"
++ lib.lists.optional (
++ optional (
cfg.dom0Resources.maxVCPUs != 0
) "dom0_max_vcpus=${toString cfg.dom0Resources.maxVCPUs}";
@@ -701,7 +702,7 @@ in
# See the `xenBootBuilder` script in the main `let...in` statement of this file.
loader.systemd-boot.extraInstallCommands = ''
${lib.meta.getExe xenBootBuilder} ${cfg.efi.bootBuilderVerbosity}
${getExe xenBootBuilder} ${cfg.efi.bootBuilderVerbosity}
'';
};
@@ -744,7 +745,7 @@ in
XENSTORED="${cfg.store.path}"
QEMU_XEN="${cfg.qemu.package}/${cfg.qemu.package.qemu-system-i386}"
${lib.strings.optionalString cfg.trace ''
${optionalString cfg.trace ''
XENSTORED_TRACE=yes
XENCONSOLED_TRACE=all
''}
@@ -756,10 +757,10 @@ in
'';
}
# The OCaml-based Xen Store Daemon requires /etc/xen/oxenstored.conf to start.
// lib.attrsets.optionalAttrs (cfg.store.type == "ocaml") {
// optionalAttrs (cfg.store.type == "ocaml") {
"xen/oxenstored.conf".text = ''
pid-file = ${cfg.store.settings.pidFile}
test-eagain = ${lib.trivial.boolToString cfg.store.settings.testEAGAIN}
test-eagain = ${boolToString cfg.store.settings.testEAGAIN}
merge-activate = ${toString cfg.store.settings.enableMerge}
conflict-burst-limit = ${toString cfg.store.settings.conflict.burstLimit}
conflict-max-history-seconds = ${toString cfg.store.settings.conflict.maxHistorySeconds}
@@ -775,7 +776,7 @@ in
quota-path-max = ${toString cfg.store.settings.quota.maxPath}
quota-maxoutstanding = ${toString cfg.store.settings.quota.maxOutstanding}
quota-maxwatchevents = ${toString cfg.store.settings.quota.maxWatchEvents}
persistent = ${lib.trivial.boolToString cfg.store.settings.persistent}
persistent = ${boolToString cfg.store.settings.persistent}
xenstored-log-file = ${cfg.store.settings.xenstored.log.file}
xenstored-log-level = ${
if isNull cfg.store.settings.xenstored.log.level then
@@ -787,7 +788,7 @@ in
access-log-file = ${cfg.store.settings.xenstored.accessLog.file}
access-log-nb-lines = ${toString cfg.store.settings.xenstored.accessLog.nbLines}
acesss-log-nb-chars = ${toString cfg.store.settings.xenstored.accessLog.nbChars}
access-log-special-ops = ${lib.trivial.boolToString cfg.store.settings.xenstored.accessLog.specialOps}
access-log-special-ops = ${boolToString cfg.store.settings.xenstored.accessLog.specialOps}
ring-scan-interval = ${toString cfg.store.settings.ringScanInterval}
xenstored-kva = ${cfg.store.settings.xenstored.xenfs.kva}
xenstored-port = ${cfg.store.settings.xenstored.xenfs.port}
@@ -870,5 +871,5 @@ in
};
};
};
meta.maintainers = lib.teams.xen.members;
meta.maintainers = members;
}
@@ -38,6 +38,8 @@
, hostCpuOnly ? false
, hostCpuTargets ? (if toolsOnly
then [ ]
else if xenSupport
then [ "i386-softmmu" ]
else if hostCpuOnly
then (lib.optional stdenv.hostPlatform.isx86_64 "i386-softmmu"
++ ["${stdenv.hostPlatform.qemuArch}-softmmu"])
@@ -50,6 +52,8 @@
, qemu-utils # for tests attribute
}:
assert lib.assertMsg (xenSupport -> hostCpuTargets == [ "i386-softmmu" ]) "Xen should not use any other QEMU architecture other than i386.";
let
hexagonSupport = hostCpuTargets == null || lib.elem "hexagon" hostCpuTargets;
@@ -1,56 +0,0 @@
{
lib,
fetchpatch,
callPackage,
ocaml-ng,
...
}@genericDefinition:
let
upstreamPatches = import ../generic/patches.nix {
inherit lib;
inherit fetchpatch;
};
upstreamPatchList = lib.lists.flatten (
with upstreamPatches;
[
QUBES_REPRODUCIBLE_BUILDS
XSA_462
]
);
in
callPackage (import ../generic/default.nix {
pname = "xen";
branch = "4.17";
version = "4.17.5";
latest = false;
pkg = {
xen = {
rev = "430ce6cd936546ad883ecd1c85ddea32d790604b";
hash = "sha256-UoMdXRW0yWSaQPPV0rgoTZVO2ghdnqWruBHn7+ZjKzI=";
patches = [ ] ++ upstreamPatchList;
};
qemu = {
rev = "ffb451126550b22b43b62fb8731a0d78e3376c03";
hash = "sha256-G0hMPid9d3fd1jAY7CiZ33xUZf1hdy96T1VUKFGeHSk=";
patches = [ ];
};
seaBIOS = {
rev = "d239552ce7220e448ae81f41515138f7b9e3c4db";
hash = "sha256-UKMceJhIprN4/4Xe4EG2EvKlanxVcEi5Qcrrk3Ogiik=";
patches = [ ];
};
ovmf = {
rev = "7b4a99be8a39c12d3a7fc4b8db9f0eab4ac688d5";
hash = "sha256-Qq2RgktCkJZBsq6Ch+6tyRHhme4lfcN7d2oQfxwhQt8=";
patches = [ ];
};
ipxe = {
rev = "1d1cf74a5e58811822bee4b3da3cff7282fcdfca";
hash = "sha256-8pwoPrmkpL6jIM+Y/C0xSvyrBM/Uv0D1GuBwNm+0DHU=";
patches = [ ];
};
};
}) ({ ocamlPackages = ocaml-ng.ocamlPackages_4_14; } // genericDefinition)
@@ -1,56 +0,0 @@
{
lib,
fetchpatch,
callPackage,
ocaml-ng,
...
}@genericDefinition:
let
upstreamPatches = import ../generic/patches.nix {
inherit lib;
inherit fetchpatch;
};
upstreamPatchList = lib.lists.flatten (
with upstreamPatches;
[
QUBES_REPRODUCIBLE_BUILDS
XSA_462
]
);
in
callPackage (import ../generic/default.nix {
pname = "xen";
branch = "4.18";
version = "4.18.3";
latest = false;
pkg = {
xen = {
rev = "bd51e573a730efc569646379cd59ccba967cde97";
hash = "sha256-OFiFdpPCXR+sWjzFHCORtY4DkWyggvxkcsGdgEyO1ts=";
patches = [ ] ++ upstreamPatchList;
};
qemu = {
rev = "0df9387c8983e1b1e72d8c574356f572342c03e6";
hash = "sha256-BX+LXfNzwdUMALwwI1ZDW12dJ357oynjnrboLHREDGQ=";
patches = [ ];
};
seaBIOS = {
rev = "ea1b7a0733906b8425d948ae94fba63c32b1d425";
hash = "sha256-J2FuT+FXn9YoFLSfxDOxyKZvKrys59a6bP1eYvEXVNU=";
patches = [ ];
};
ovmf = {
rev = "ba91d0292e593df8528b66f99c1b0b14fadc8e16";
hash = "sha256-htOvV43Hw5K05g0SF3po69HncLyma3BtgpqYSdzRG4s=";
patches = [ ];
};
ipxe = {
rev = "1d1cf74a5e58811822bee4b3da3cff7282fcdfca";
hash = "sha256-8pwoPrmkpL6jIM+Y/C0xSvyrBM/Uv0D1GuBwNm+0DHU=";
patches = [ ];
};
};
}) ({ ocamlPackages = ocaml-ng.ocamlPackages_4_14; } // genericDefinition)
@@ -1,58 +0,0 @@
{
lib,
fetchpatch,
callPackage,
ocaml-ng,
...
}@genericDefinition:
let
upstreamPatches = import ../generic/patches.nix {
inherit lib;
inherit fetchpatch;
};
upstreamPatchList = lib.lists.flatten (
with upstreamPatches;
[
QUBES_REPRODUCIBLE_BUILDS
XSA_460
XSA_461
XSA_462
]
);
in
callPackage (import ../generic/default.nix {
pname = "xen";
branch = "4.19";
version = "4.19.0";
latest = true;
pkg = {
xen = {
rev = "026c9fa29716b0ff0f8b7c687908e71ba29cf239";
hash = "sha256-Q6x+2fZ4ITBz6sKICI0NHGx773Rc919cl+wzI89UY+Q=";
patches = [ ] ++ upstreamPatchList;
};
qemu = {
rev = "0df9387c8983e1b1e72d8c574356f572342c03e6";
hash = "sha256-BX+LXfNzwdUMALwwI1ZDW12dJ357oynjnrboLHREDGQ=";
patches = [ ];
};
seaBIOS = {
rev = "a6ed6b701f0a57db0569ab98b0661c12a6ec3ff8";
hash = "sha256-hWemj83cxdY8p+Jhkh5GcPvI0Sy5aKYZJCsKDjHTUUk=";
patches = [ ];
};
ovmf = {
rev = "ba91d0292e593df8528b66f99c1b0b14fadc8e16";
hash = "sha256-htOvV43Hw5K05g0SF3po69HncLyma3BtgpqYSdzRG4s=";
patches = [ ];
};
ipxe = {
rev = "1d1cf74a5e58811822bee4b3da3cff7282fcdfca";
hash = "sha256-8pwoPrmkpL6jIM+Y/C0xSvyrBM/Uv0D1GuBwNm+0DHU=";
patches = [ ];
};
};
}) ({ ocamlPackages = ocaml-ng.ocamlPackages_4_14; } // genericDefinition)
@@ -1,209 +0,0 @@
<p align="center">
<a href="https://xenproject.org/">
<picture>
<source
media="(prefers-color-scheme: light)"
srcset="https://downloads.xenproject.org/Branding/Logos/Green+Black/xen_project_logo_dualcolor_2000x832.png">
<source
media="(prefers-color-scheme: dark)"
srcset="https://xenproject.org/wp-content/uploads/sites/79/2018/09/logo_xenproject.png">
<img
src="https://downloads.xenproject.org/Branding/Logos/Green+Black/xen_project_logo_dualcolor_2000x832.png"
width="512px"
alt="Xen Project Logo">
</picture>
</a>
</p>
# Xen Project Hypervisor <a href="https://xenproject.org/"><img src="https://downloads.xenproject.org/Branding/Mascots/Xen-Fu-Panda-2000px.png" width="48px" align="top" alt="Xen Fu Panda"></a>
This directory includes the build recipes for the [Xen Project Hypervisor](https://xenproject.org/).
Some other notable packages that compose the Xen Project Ecosystem include:
- `ocamlPackages.xenstore`: Mirage's `oxenstore` implementation.
- `ocamlPackages.vchan`: Mirage's `xen-vchan` implementation.
- `ocamlPackages.xenstore-tool`: XAPI's `oxenstore` utilities.
- `xen-guest-agent`: Guest drivers for UNIX domUs.
- `win-pvdrivers`: Guest drivers for Windows domUs.
- `xtf`: The Xen Test Framework.
## Updating
### Automatically
An automated update script is available in this directory. To produce up-to-date
files for all supported Xen branches, simply run `./update.sh`, and follow the
instructions given to you by the script. Notably, it will request that you verify
the Xen Project code signing PGP key. This README understands that the fingerprint
of that key is [`23E3 222C 145F 4475 FA80 60A7 83FE 14C9 57E8 2BD9`](https://keys.openpgp.org/search?q=pgp%40xen.org),
but you should verify this information by seeking the fingerprint from other trusted
sources, as this document may be compromised. Once the PGP key is verified, it will
use `git verify-tag` to ascertain the validity of the cloned Xen sources.
After the script is done, follow the steps in
[**For Both Update Methods**](#for-both-update-methods) below.
#### Downstream Patch Names
The script expects local patch names to follow a certain specification.
Please name any required patches using the template below:
```console
0000-project-description-branch.patch
```
Where:
1. The first four numbers define the patch order.
**0001** will be applied after **0000**, and so on.
1. `project` means the name of the source the patch should be applied to.
- If you are applying patches to the main Xen sources, use `xen`.
- For the pre-fetched QEMU, use `qemu`.
- For SeaBIOS, use `seabios`.
- For OVMF, use `ovmf`.
- For iPXE, use `ipxe`.
1. `description` is a string with uppercase and lowercase letters, numbers and
dashes. It describes the patch name and what it does to the upstream code.
1. `branch` is the branch for which this patch is supposed to patch.
It should match the name of the directory it is in.
For example, a patch fixing `xentop`'s output in the 4.15 branch should have
the following name: `0000-xen-xentop-output-4.15.patch`, and it should be added
to the `4.15/` directory.
### Manually
The script is not infallible, and it may break in the future. If that happens,
open a PR fixing the script, and update Xen manually:
1. Check the support matrix to see which branches are security-supported.
1. Create one directory per branch.
1. [Update](https://xenbits.xenproject.org/gitweb/) the `default.nix` files for
the branches that already exist and copy a new one to any branches that do
not yet exist in Nixpkgs.
- Do not forget to set the `branch`, `version`, and `latest` attributes for
each of the `default.nix` files.
- The revisions are preferably commit hashes, but tag names are acceptable
as well.
### For Both Update Methods
1. Update `packages.nix` and `../../../top-level/all-packages.nix` with the new
versions. Don't forget the `slim` packages!
1. Make sure all branches build. (Both the `standard` and `slim` versions)
1. Use the NixOS module to test if dom0 boots successfully on all new versions.
1. Make sure the `meta` attributes evaluate to something that makes sense. The
following one-line command is useful for testing this:
```console
xenToEvaluate=xen; echo -e "\033[1m$(nix eval .#"$xenToEvaluate".meta.description --raw 2> /dev/null)\033[0m\n\n$(nix eval .#"$xenToEvaluate".meta.longDescription --raw 2> /dev/null)"
```
Change the value of `xenToEvaluate` to evaluate all relevant Xen packages.
1. Run `xtf --all --host` as root when booted into the Xen update, and make
sure no tests fail.
1. Clean up your changes and commit them, making sure to follow the
[Nixpkgs Contribution Guidelines](../../../../CONTRIBUTING.md).
1. Open a PR and await a review from the current maintainers.
## Features
### Pre-fetched Sources
On a typical Xen build, the Xen Makefiles will fetch more required sources with
`git` and `wget`. Due to the Nix Sandbox, build-time fetching will fail, so we
pre-fetch the required sources before building.[^1] To accomplish this, we have
a `prefetchedSources` attribute that contains the required derivations, if they
are requested by the main Xen build.
### EFI
Building `xen.efi` requires an `ld` with PE support.[^2]
We use a `makeFlag` to override the `$LD` environment variable to point to our
patched `efiBinutils`. For more information, see the comment in `./generic/default.nix`.
> [!TIP]
> If you are certain you will not be running Xen in an x86 EFI environment, disable
the `withEFI` flag with an [override](https://nixos.org/manual/nixpkgs/stable/#chap-overrides)
to save you the need to compile `efiBinutils`.
### Default Overrides
By default, Xen also builds
[QEMU](https://www.qemu.org/),
[SeaBIOS](https://www.seabios.org/SeaBIOS),
[OVMF](https://github.com/tianocore/tianocore.github.io/wiki/OVMF) and
[iPXE](https://ipxe.org/).
- QEMU is used for stubdomains and handling devices.
- SeaBIOS is the default legacy BIOS ROM for HVM domains.
- OVMF is the default UEFI ROM for HVM domains.
- iPXE provides a PXE boot environment for HVMs.
However, those packages are already available on Nixpkgs, and Xen does not
necessarily need to build them into the main hypervisor build. For this reason,
we also have the `withInternal<Component>` flags, which enables and disables
building those built-in components. The two most popular Xen configurations will
be the default build, with all built-in components, and a `slim` build, with none
of those components. To simplify this process, the `./packages.nix` file includes
the `xen-slim` package overrides that have all `withInternal<Component>` flags
disabled. See the `meta.longDescription` attribute for the `xen-slim` packages
for more information.
## Security
We aim to support all **security-supported** versions of Xen at any given time.
See the [Xen Support Matrix](https://xenbits.xen.org/docs/unstable/support-matrix.html)
for a list of versions. As soon as a version is no longer **security-supported**,
it should be removed from Nixpkgs.
> [!CAUTION]
> Pull requests that introduce XSA patches
should have the `1.severity: security` label.
### Maintainers
Xen is a particularly complex piece of software, so we are always looking for new
maintainers. Help out by [making and triaging issues](https://github.com/NixOS/nixpkgs/issues/new/choose),
[sending build fixes and improvements through PRs](https://github.com/NixOS/nixpkgs/compare),
updating the branches, and [patching security flaws](https://xenbits.xenproject.org/xsa/).
We are also looking for testers, particularly those who can test Xen on AArch64
machines. Open issues for any build failures or runtime errors you find!
## Tests
So far, we only have had one simple automated test that checks for
the correct `pkg-config` output files.
Due to Xen's nature as a type-1 hypervisor, it is not a trivial matter to design
new tests, as even basic functionality requires a machine booted in a dom0
kernel. For this reason, most testing done with this package must be done
manually in a NixOS machine with `virtualisation.xen.enable` set to `true`.
Another unfortunate thing is that none of the Xen commands have a `--version`
flag. This means that `testers.testVersion` cannot ascertain the Xen version.
The only way to verify that you have indeed built the correct version is to
boot into the freshly built Xen kernel and run `xl info`.
<p align="center">
<a href="https://xenproject.org/">
<img
src="https://downloads.xenproject.org/Branding/Mascots/Xen%20Big%20Panda%204242x3129.png"
width="96px"
alt="Xen Fu Panda">
</a>
</p>
[^1]: We also produce fake `git`, `wget` and `hostname` binaries that do nothing,
to prevent the build from failing because Xen cannot fetch the sources that
were already fetched by Nix.
[^2]: From the [Xen Documentation](https://xenbits.xenproject.org/docs/unstable/misc/efi.html):
> For x86, building `xen.efi` requires `gcc` 4.5.x or above (4.6.x or newer
recommended, as 4.5.x was probably never really tested for this purpose)
and `binutils` 2.22 or newer. Additionally, the `binutils` build must be
configured to include support for the x86_64-pep emulation (i.e.
`--enable-targets=x86_64-pep` or an option of equivalent effect should be
passed to the configure script).
@@ -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
@@ -1,728 +0,0 @@
versionDefinition:
{
lib,
stdenv,
autoPatchelfHook,
cmake,
ninja,
pkg-config,
testers,
which,
fetchgit,
fetchFromGitHub,
# Xen
acpica-tools,
bison,
bzip2,
dev86,
e2fsprogs,
flex,
libnl,
libuuid,
lzo,
ncurses,
ocamlPackages,
perl,
python3Packages,
systemdMinimal,
xz,
yajl,
zlib,
zstd,
# Xen Optional
withInternalQEMU ? true,
pixman,
glib,
withInternalSeaBIOS ? true,
withSeaBIOS ? !withInternalSeaBIOS,
seabios,
withInternalOVMF ? true,
withOVMF ? !withInternalOVMF,
OVMF,
nasm,
withInternalIPXE ? true,
withIPXE ? !withInternalIPXE,
ipxe,
withFlask ? false,
checkpolicy,
efiVendor ? "nixos", # Allow downstreams with custom branding to quickly override the EFI Vendor string.
withEFI ? true,
binutils-unwrapped,
# Documentation
pandoc,
# Scripts
bridge-utils,
coreutils,
diffutils,
gawk,
gnugrep,
gnused,
inetutils,
iproute2,
iptables,
multipath-tools,
nbd,
openvswitch,
util-linux,
...
}@packageDefinition:
let
#TODO: fix paths instead.
scriptEnvPath = lib.strings.makeSearchPathOutput "out" "bin" [
bridge-utils
coreutils
diffutils
gawk
gnugrep
gnused
inetutils
iproute2
iptables
multipath-tools
nbd
openvswitch
perl
util-linux.bin
which
];
# Inherit attributes from a versionDefinition.
inherit (versionDefinition)
pname
branch
version
latest
pkg
;
# Mark versions older than minSupportedVersion as EOL.
minSupportedVersion = "4.17";
## Pre-fetched Source Handling ##
# Main attribute set for sources needed to build tools and firmwares.
# Each source takes in:
# * A `src` attribute, which contains the actual fetcher,
# * 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 ##
# 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.
numberOfPatches = lib.lists.count (patch: builtins.isAttrs patch) normalisedPatchList;
# 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.
availablePatchesToTry = lib.lists.range 0 (numberOfPatches - 1);
# 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
# to remove these junk values, if necessary.
retrievePatchAttributes =
attributeName:
builtins.map (
x: lib.attrsets.attrByPath attributeName null (builtins.elemAt normalisedPatchList x)
) availablePatchesToTry;
# 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
# then used in meta.longDescription, to let users know their Xen is patched against
# known vulnerabilities, as the package version isn't always the best indicator.
#
# Produces something like this: (one string for each XSA)
# * [Xen Security Advisory #1](https://xenbits.xenproject.org/xsa/advisory-1.html): **Title for XSA.**
# >Description of issue in XSA
#Extra lines
#are not indented,
#but markdown should be
#fine with it.
# Fixes:
# * [CVE-1999-00001](https://www.cve.org/CVERecord?id=CVE-1999-00001)
# * [CVE-1999-00002](https://www.cve.org/CVERecord?id=CVE-1999-00002)
# * [CVE-1999-00003](https://www.cve.org/CVERecord?id=CVE-1999-00003)
writeAdvisoryDescription =
if (lib.lists.remove null (retrievePatchAttributes [ "xsa" ]) != [ ]) then
lib.lists.zipListsWith (a: b: a + b)
(lib.lists.zipListsWith (a: b: a + "**" + b + ".**\n >")
(lib.lists.zipListsWith (a: b: "* [Xen Security Advisory #" + a + "](" + b + "): ")
(lib.lists.remove null (retrievePatchAttributes [ "xsa" ]))
(
lib.lists.remove null (retrievePatchAttributes [
"meta"
"homepage"
])
)
)
(
lib.lists.remove null (retrievePatchAttributes [
"meta"
"description"
])
)
)
(
lib.lists.remove null (retrievePatchAttributes [
"meta"
"longDescription"
])
)
else
[ ];
## Binutils Override ##
# Originally, there were two versions of binutils being used: the standard one and
# this patched one. Unfortunately, that required patches to the Xen Makefiles, and
# quickly became too complex to maintain. The new solution is to simply build this
# efi-binutils derivation and use it for the whole build process, except if
# enableEFI is disabled; it'll then use `binutils`.
efiBinutils = binutils-unwrapped.overrideAttrs (oldAttrs: {
name = "efi-binutils";
configureFlags = oldAttrs.configureFlags ++ [ "--enable-targets=x86_64-pep" ];
doInstallCheck = false; # We get a spurious failure otherwise, due to a host/target mismatch.
meta.mainProgram = "ld"; # We only really care for `ld`.
});
in
stdenv.mkDerivation (finalAttrs: {
inherit pname version;
outputs = [
"out" # TODO: Split $out in $bin for binaries and $lib for libraries.
"man" # Manual pages for Xen userspace utilities.
"doc" # The full Xen documentation in HTML format.
"dev" # Development headers.
"boot" # xen.gz kernel, policy file if Flask is enabled, xen.efi if EFI is enabled.
# TODO: Python package to be in separate output/package.
];
# Main Xen source.
src = fetchgit {
url = "https://xenbits.xenproject.org/git-http/xen.git";
inherit (pkg.xen) rev hash;
};
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;
nativeBuildInputs =
[
autoPatchelfHook
bison
cmake
flex
pandoc
pkg-config
python3Packages.setuptools
]
++ lib.lists.optionals withInternalQEMU [
ninja
python3Packages.sphinx
];
buildInputs =
[
# Xen
acpica-tools
bzip2
dev86
e2fsprogs.dev
libnl
libuuid
lzo
ncurses
perl
python3Packages.python
xz
yajl
zlib
zstd
# oxenstored
ocamlPackages.findlib
ocamlPackages.ocaml
# Python Fixes
python3Packages.wrapPython
]
++ 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 =
[
"--enable-systemd"
"--disable-qemu-traditional"
]
++ lib.lists.optional (!withInternalQEMU) "--with-system-qemu"
++ lib.lists.optional withSeaBIOS "--with-system-seabios=${seabios}/share/seabios"
++ 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 =
[
"PREFIX=$(out)"
"CONFIG_DIR=/etc"
"XEN_SCRIPT_DIR=$(CONFIG_DIR)/xen/scripts"
"BASH_COMPLETION_DIR=$(PREFIX)/share/bash-completion/completions"
]
++ lib.lists.optionals withEFI [
"EFI_VENDOR=${efiVendor}"
"INSTALL_EFI_STRIP=1"
"LD=${lib.meta.getExe efiBinutils}" # See the comment in the efiBinutils definition above.
]
# These flags set the CONFIG_* options in /boot/xen.config
# and define if the default policy file is built. However,
# the Flask binaries always get compiled by default.
++ lib.lists.optionals withFlask [
"XSM_ENABLE=y"
"FLASK_ENABLE=y"
]
++ (pkg.xen.makeFlags or [ ]);
buildFlags = [
"xen" # Build the Xen Hypervisor.
"tools" # Build the userspace tools, such as `xl`.
"docs" # Build the Xen Documentation
];
enableParallelBuilding = true;
env.NIX_CFLAGS_COMPILE = builtins.toString (
[
"-Wno-error=maybe-uninitialized"
"-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;
dontUseNinjaBuild = withInternalQEMU;
prePatch =
# Xen's stubdoms, tools and firmwares need various sources that
# 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 =
# The following patch forces Xen to install xen.efi on $out/boot
# instead of $out/boot/efi/efi/nixos, as the latter directory
# would otherwise need to be created manually. This also creates
# a more consistent output for downstreams who override the
# efiVendor attribute above.
''
substituteInPlace xen/Makefile \
--replace-fail "\$(D)\$(EFI_MOUNTPOINT)/efi/\$(EFI_VENDOR)/\$(T)-\$(XEN_FULLVERSION).efi" \
"\$(D)\$(BOOT_DIR)/\$(T)-\$(XEN_FULLVERSION).efi"
''
# The following patch fixes the call to /bin/mkdir on the
# launch_xenstore.sh helper script.
+ ''
substituteInPlace tools/hotplug/Linux/launch-xenstore.in \
--replace-fail "/bin/mkdir" "${coreutils}/bin/mkdir"
''
# The following expression fixes the paths called by Xen's systemd
# units, so we can use them in the NixOS module.
+ ''
substituteInPlace \
tools/hotplug/Linux/systemd/{xen-init-dom0,xen-qemu-dom0-disk-backend,xenconsoled,xendomains,xenstored}.service.in \
--replace-fail /bin/grep ${gnugrep}/bin/grep
substituteInPlace \
tools/hotplug/Linux/systemd/{xen-qemu-dom0-disk-backend,xenconsoled}.service.in \
--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 =
let
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 ${cpFlags} dist/install/nix/store/*/* $out/
cp ${cpFlags} dist/install/etc $out
cp ${cpFlags} dist/install/boot $boot
''
# Run the postInstall tasks.
+ ''
runHook postInstall
'';
postInstall =
# Wrap xencov_split, xenmon and xentrace_format.
''
wrapPythonPrograms
''
# We also need to wrap pygrub, which lies in $out/libexec/xen/bin.
+ ''
wrapPythonProgramsIn "$out/libexec/xen/bin" "$out $pythonPath"
''
# Fix shebangs in Xen's various scripts.
#TODO: Remove any and all usage of `sed` and replace these complicated magic runes with readable code.
+ ''
shopt -s extglob
for i in $out/etc/xen/scripts/!(*.sh); do
sed --in-place "2s@^@export PATH=$out/bin:${scriptEnvPath}\n@" $i
done
'';
postFixup =
# Fix binaries in $out/libexec/xen/bin.
''
addAutoPatchelfSearchPath $out/lib
autoPatchelf $out/libexec/xen/bin
''
# Flask is particularly hard to disable. Even after
# setting the make flags to `n`, it still gets compiled.
# If withFlask is disabled, delete the extra binaries.
+ lib.strings.optionalString (!withFlask) ''
rm -f $out/bin/flask-*
'';
passthru = {
efi =
if withEFI then "boot/xen-${version}.efi" else throw "This Xen was compiled without an EFI binary.";
flaskPolicy =
if withFlask then
"boot/xenpolicy-${version}"
else
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
# utilities require the hypervisor to be booted.
tests = {
pkg-config = testers.hasPkgConfigModules {
package = finalAttrs.finalPackage;
moduleNames = [
"xencall"
"xencontrol"
"xendevicemodel"
"xenevtchn"
"xenforeignmemory"
"xengnttab"
"xenguest"
"xenhypfs"
"xenlight"
"xenstat"
"xenstore"
"xentoolcore"
"xentoollog"
"xenvchan"
"xlutil"
];
};
};
};
meta =
if
!(lib.attrsets.hasAttrByPath [
"meta"
] versionDefinition)
then
{
inherit branch;
# Short description for Xen.
description =
"Xen Project Hypervisor"
# The "and related components" addition is automatically hidden if said components aren't being built.
+ lib.strings.optionalString (prefetchedSources != { }) " and related components"
# To alter the description inside the paranthesis, edit ./packages.nix.
+ lib.strings.optionalString (lib.attrsets.hasAttrByPath [
"meta"
"description"
] packageDefinition) " (${packageDefinition.meta.description})";
# Long description for Xen.
longDescription =
# Starts with the longDescription from ./packages.nix.
(packageDefinition.meta.longDescription or "")
+ 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/";
downloadPage = "https://downloads.xenproject.org/release/xen/${version}/";
changelog = "https://wiki.xenproject.org/wiki/Xen_Project_${branch}_Release_Notes";
license = with lib.licenses; [
# Documentation.
cc-by-40
# Most of Xen is licensed under the GPL v2.0.
gpl2Only
# Xen Libraries and the `xl` command-line utility.
lgpl21Only
# Development headers in $dev/include.
mit
];
# This automatically removes maintainers from EOL versions of Xen, so we aren't bothered about versions we don't explictly support.
maintainers = lib.lists.optionals (lib.strings.versionAtLeast version minSupportedVersion) lib.teams.xen.members;
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";
# Evaluates to x86_64-linux.
platforms = lib.lists.intersectLists lib.platforms.linux lib.platforms.x86_64;
}
else
versionDefinition.meta;
})
@@ -1,71 +0,0 @@
{
python3Packages,
python311Packages,
callPackage,
}:
let
standard = {
# Broken with python 3.12+ when using internal QEMU due to https://github.com/NixOS/nixpkgs/issues/253751
python3Packages = python311Packages;
meta = {
description = "Standard";
longDescription = ''
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
experience, but wastes space and build time. A typical NixOS setup that runs
lots of VMs will usually need to build two different versions of QEMU when using
this Xen derivation (one fork and upstream).
'';
};
};
slim = {
inherit python3Packages;
meta = {
description = "Without Internal Components";
longDescription = ''
Slimmed-down version of the Xen Project Hypervisor that reuses nixpkgs packages
as much as possible. Instead of using the Xen Project forks for various internal
components, this version uses `seabios`, `ovmf` and `ipxe` from Nixpkgs. These
components may ocasionally get out of sync with the hypervisor itself, but this
builds faster and uses less space than the default derivation.
'';
};
};
in
# TODO: generalise this to automatically generate both Xen variants for each ./<version>/default.nix.
rec {
xen_4_19 = callPackage ./4.19/default.nix {
inherit (standard) meta python3Packages;
};
xen_4_19-slim = xen_4_19.override {
withInternalQEMU = false;
withInternalSeaBIOS = false;
withInternalOVMF = false;
withInternalIPXE = false;
inherit (slim) meta python3Packages;
};
xen_4_18 = callPackage ./4.18/default.nix {
inherit (standard) meta python3Packages;
};
xen_4_18-slim = xen_4_18.override {
withInternalQEMU = false;
withInternalSeaBIOS = false;
withInternalOVMF = false;
withInternalIPXE = false;
inherit (slim) meta python3Packages;
};
xen_4_17 = callPackage ./4.17/default.nix {
inherit (standard) meta python3Packages;
};
xen_4_17-slim = xen_4_17.override {
withInternalQEMU = false;
withInternalSeaBIOS = false;
withInternalOVMF = false;
withInternalIPXE = false;
inherit (slim) meta;
# Broken with python 3.12+ due to distutils missing.
python3Packages = python311Packages;
};
}
@@ -1,202 +0,0 @@
#!/usr/bin/env nix-shell
#!nix-shell -i bash -p gitMinimal curl gnupg nix-prefetch-git nixfmt-rfc-style
# shellcheck disable=SC2206,SC2207 shell=bash
set -o errexit
set -o pipefail
set -o nounset
#TODO: Use `jq` instead of `sed`.
#TODO: Accept the small security drawback and make this script runnable by r-ryantm.
# This script expects to be called in an interactive terminal somewhere inside Nixpkgs.
echo "Preparing..."
nixpkgs=$(git rev-parse --show-toplevel)
xenPath="$nixpkgs/pkgs/applications/virtualization/xen"
rm -rf /tmp/xenUpdateScript
mkdir /tmp/xenUpdateScript
# Import and verify PGP key.
curl --silent --output /tmp/xenUpdateScript/xen.asc https://keys.openpgp.org/vks/v1/by-fingerprint/23E3222C145F4475FA8060A783FE14C957E82BD9
gpg --homedir /tmp/xenUpdateScript/.gnupg --quiet --import /tmp/xenUpdateScript/xen.asc
fingerprint="$(gpg --homedir /tmp/xenUpdateScript/.gnupg --with-colons --fingerprint "pgp@xen.org" 2>/dev/null | awk -F: '/^pub:.*/ { getline; print $10}')"
echo -e "Please ascertain through multiple external sources that the \e[1;32mXen Project PGP Key Fingerprint\e[0m is indeed \e[1;33m$fingerprint\e[0m. If that is not the case, \e[1;31mexit immediately\e[0m."
read -r -p $'Press \e[1;34menter\e[0m to continue with a pre-filled expected fingerprint, or input an arbitrary PGP fingerprint to match with the key\'s fingerprint: ' userInputFingerprint
userInputFingerprint=${userInputFingerprint:-"23E3222C145F4475FA8060A783FE14C957E82BD9"}
# Clone xen.git.
echo -e "Cloning \e[1;34mxen.git\e[0m..."
git clone --quiet https://xenbits.xenproject.org/git-http/xen.git /tmp/xenUpdateScript/xen
cd /tmp/xenUpdateScript/xen
# Get list of versions and branches.
versionList="$(git tag --list "RELEASE-*" | sed s/RELEASE-//g | sed s/4.1.6.1//g | sort --numeric-sort)"
latestVersion=$(echo "$versionList" | tr ' ' '\n' | tail --lines=1)
branchList=($(echo "$versionList" | tr ' ' '\n' | sed s/\.[0-9]*$//g | awk '!seen[$0]++'))
# Figure out which versions we're actually going to install.
minSupportedBranch="$(grep " minSupportedVersion = " "$xenPath"/generic/default.nix | sed s/' minSupportedVersion = "'//g | sed s/'";'//g)"
supportedBranches=($(for version in "${branchList[@]}"; do if [ "$(printf '%s\n' "$minSupportedBranch" "$version" | sort -V | head -n1)" = "$minSupportedBranch" ]; then echo "$version"; fi; done))
supportedVersions=($(for version in "${supportedBranches[@]}"; do echo "$versionList" | tr ' ' '\n' | grep "$version" | tail --lines=1; done))
echo -e "\e[1mNOTE\e[0m: As we're also pre-fetching the submodules, QEMU and OVMF may take a very long time to fetch."
# Main loop that installs every supportedVersion.
for version in "${supportedVersions[@]}"; do
echo -e "\n------------------------------------------------"
branch=${version/%.[0-9]/}
if [[ "$version" == "$latestVersion" ]]; then
latest=true
echo -e "\nFound \e[1;34mlatest\e[0m release: \e[1;32mXen $version\e[0m in branch \e[1;36m$branch\e[0m."
else
latest=false
echo -e "\nFound \e[1;33msecurity-supported\e[0m release: \e[1;32mXen $version\e[0m in branch \e[1;36m$branch\e[0m."
fi
# Verify PGP key automatically. If the fingerprint matches what the user specified, or the default fingerprint, then we consider it trusted.
cd /tmp/xenUpdateScript/xen
if [[ "$fingerprint" = "$userInputFingerprint" ]]; then
echo "$fingerprint:6:" | gpg --homedir /tmp/xenUpdateScript/.gnupg --quiet --import-ownertrust
(git verify-tag RELEASE-"$version" 2>/dev/null && echo -e "\n\e[1;32mSuccessfully authenticated Xen $version.\e[0m") || (echo -e "\e[1;31merror:\e[0m Unable to verify tag \e[1;32mRELEASE-$version\e[0m.\n- It is possible that \e[1;33mthis script has broken\e[0m, the Xen Project has \e[1;33mcycled their PGP keys\e[0m, or a \e[1;31msupply chain attack is in progress\e[0m.\n\n\e[1;31mPlease update manually.\e[0m" && exit 1)
else
echo -e "\e[1;31merror:\e[0m Unable to verify \e[1;34mpgp@xen.org\e[0m's fingerprint.\n- It is possible that \e[1;33mthis script has broken\e[0m, the Xen Project has \e[1;33mcycled their PGP keys\e[0m, or an \e[1;31mimpersonation attack is in progress\e[0m.\n\n\e[1;31mPlease update manually.\e[0m" && exit 1
fi
git switch --quiet --detach RELEASE-"$version"
# Originally we told people to go check the Makefile themselves.
echo -e -n "\nDetermining source versions from Xen Makefiles..."
qemuVersion="$(grep "QEMU_UPSTREAM_REVISION ?=" /tmp/xenUpdateScript/xen/Config.mk | sed s/"QEMU_UPSTREAM_REVISION ?= "//g)"
seaBIOSVersion="$(grep "SEABIOS_UPSTREAM_REVISION ?= rel-" /tmp/xenUpdateScript/xen/Config.mk | sed s/"SEABIOS_UPSTREAM_REVISION ?= "//g)"
ovmfVersion="$(grep "OVMF_UPSTREAM_REVISION ?=" /tmp/xenUpdateScript/xen/Config.mk | sed s/"OVMF_UPSTREAM_REVISION ?= "//g)"
miniOSVersion="$(grep "MINIOS_UPSTREAM_REVISION ?=" /tmp/xenUpdateScript/xen/Config.mk | sed s/"MINIOS_UPSTREAM_REVISION ?= "//g)"
ipxeVersion="$(grep "IPXE_GIT_TAG :=" /tmp/xenUpdateScript/xen/tools/firmware/etherboot/Makefile | sed s/"IPXE_GIT_TAG := "//g)"
echo "done!"
# Use `nix-prefetch-git` to fetch `rev`s and `hash`es.
echo "Pre-fetching sources and determining hashes..."
echo -e -n " \e[1;32mXen\e[0m..."
fetchXen=$(nix-prefetch-git --url https://xenbits.xenproject.org/git-http/xen.git --rev RELEASE-"$version" --quiet)
finalVersion="$(echo "$fetchXen" | tr ', ' '\n ' | grep -ie rev | sed s/' "rev": "'//g | sed s/'"'//g)"
hash="$(echo "$fetchXen" | tr ', ' '\n ' | grep -ie hash | sed s/' "hash": "'//g | sed s/'"'//g)"
echo "done!"
echo -e -n " \e[1;36mQEMU\e[0m..."
fetchQEMU=$(nix-prefetch-git --url https://xenbits.xenproject.org/git-http/qemu-xen.git --rev "$qemuVersion" --quiet --fetch-submodules)
finalQEMUVersion="$(echo "$fetchQEMU" | tr ', ' '\n ' | grep -ie rev | sed s/' "rev": "'//g | sed s/'"'//g)"
qemuHash="$(echo "$fetchQEMU" | tr ', ' '\n ' | grep -ie hash | sed s/' "hash": "'//g | sed s/'"'//g)"
echo "done!"
echo -e -n " \e[1;36mSeaBIOS\e[0m..."
fetchSeaBIOS=$(nix-prefetch-git --url https://xenbits.xenproject.org/git-http/seabios.git --rev "$seaBIOSVersion" --quiet)
finalSeaBIOSVersion="$(echo "$fetchSeaBIOS" | tr ', ' '\n ' | grep -ie rev | sed s/' "rev": "'//g | sed s/'"'//g)"
seaBIOSHash="$(echo "$fetchSeaBIOS" | tr ', ' '\n ' | grep -ie hash | sed s/' "hash": "'//g | sed s/'"'//g)"
echo "done!"
echo -e -n " \e[1;36mOVMF\e[0m..."
ovmfHash="$(nix-prefetch-git --url https://xenbits.xenproject.org/git-http/ovmf.git --rev "$ovmfVersion" --quiet --fetch-submodules | grep -ie hash | sed s/' "hash": "'//g | sed s/'",'//g)"
echo "done!"
echo -e -n " \e[1;36miPXE\e[0m..."
ipxeHash="$(nix-prefetch-git --url https://github.com/ipxe/ipxe.git --rev "$ipxeVersion" --quiet | grep -ie hash | sed s/' "hash": "'//g | sed s/'",'//g)"
echo "done!"
cd "$xenPath"
echo -e "\nFound the following revisions:\n \e[1;32mXen\e[0m: \e[1;33m$finalVersion\e[0m (\e[1;33m$hash\e[0m)\n \e[1;36mQEMU\e[0m: \e[1;33m$finalQEMUVersion\e[0m (\e[1;33m$qemuHash\e[0m)\n \e[1;36mSeaBIOS\e[0m: \e[1;33m$finalSeaBIOSVersion\e[0m (\e[1;33m$seaBIOSHash\e[0m)\n \e[1;36mOVMF\e[0m: \e[1;33m$ovmfVersion\e[0m (\e[1;33m$ovmfHash\e[0m)\n \e[1;36miPXE\e[0m: \e[1;33m$ipxeVersion\e[0m (\e[1;33m$ipxeHash\e[0m)"
# Set OCaml Version
read -r -p $'\nEnter the corresponding \e[1;33mOCaml\e[0m version for \e[1;32mXen '"$version"$'\e[0m, or press \e[1;34menter\e[0m for the default value of \e[1;32m4_14\e[0m: ' ocamlVersion
ocamlVersion=${ocamlVersion:-"4_14"}
mkdir -p "$branch"/
rm -f "$branch"/default.nix
# Prepare any .patch files that are called by Nix through a path value.
echo -e "\nPlease add any required patches to version \e[1;32m$branch\e[0m in \e[1;34m$branch/\e[0m, and press \e[1;34menter\e[0m when done."
read -r -p $'Remember to follow the naming specification as defined in \e[1;34m./README.md\e[0m.'
echo -e "\nDiscovering patches..."
discoveredXenPatches="$(find "$branch"/ -type f -name "[0-9][0-9][0-9][0-9]-xen-*-$branch.patch" -printf "./%f ")"
discoveredQEMUPatches="$(find "$branch"/ -type f -name "[0-9][0-9][0-9][0-9]-qemu-*-$branch.patch" -printf "./%f ")"
discoveredSeaBIOSPatches="$(find "$branch"/ -type f -name "[0-9][0-9][0-9][0-9]-seabios-*-$branch.patch" -printf "./%f ")"
discoveredOVMFPatches="$(find "$branch"/ -type f -name "[0-9][0-9][0-9][0-9]-ovmf-*-$branch.patch" -printf "./%f ")"
discoveredIPXEPatches="$(find "$branch"/ -type f -name "[0-9][0-9][0-9][0-9]-ipxe-*-$branch.patch" -printf "./%f ")"
discoveredXenPatchesEcho=${discoveredXenPatches:-"\e[1;31mNone found!\e[0m"}
discoveredQEMUPatchesEcho=${discoveredQEMUPatches:-"\e[1;31mNone found!\e[0m"}
discoveredSeaBIOSPatchesEcho=${discoveredSeaBIOSPatches:-"\e[1;31mNone found!\e[0m"}
discoveredOVMFPatchesEcho=${discoveredOVMFPatches:-"\e[1;31mNone found!\e[0m"}
discoveredIPXEPatchesEcho=${discoveredIPXEPatches:-"\e[1;31mNone found!\e[0m"}
echo -e "Found the following patches:\n \e[1;32mXen\e[0m: \e[1;33m$discoveredXenPatchesEcho\e[0m\n \e[1;36mQEMU\e[0m: \e[1;33m$discoveredQEMUPatchesEcho\e[0m\n \e[1;36mSeaBIOS\e[0m: \e[1;33m$discoveredSeaBIOSPatchesEcho\e[0m\n \e[1;36mOVMF\e[0m: \e[1;33m$discoveredOVMFPatchesEcho\e[0m\n \e[1;36miPXE\e[0m: \e[1;33m$discoveredIPXEPatchesEcho\e[0m"
# Prepare patches that are called in ./patches.nix.
defaultPatchListInit=("QUBES_REPRODUCIBLE_BUILDS" "XSA_460" "XSA_461" )
read -r -a defaultPatchList -p $'\nWould you like to override the \e[1;34mupstreamPatches\e[0m list for \e[1;32mXen '"$version"$'\e[0m? If no, press \e[1;34menter\e[0m to use the default patch list: [ \e[1;34m'"${defaultPatchListInit[*]}"$' \e[0m]: '
defaultPatchList=(${defaultPatchList[@]:-${defaultPatchListInit[@]}})
upstreamPatches=${defaultPatchList[*]}
# Write and format default.nix file.
echo -e -n "\nWriting updated \e[1;34mversionDefinition\e[0m..."
cat >"$branch"/default.nix <<EOF
{
lib,
fetchpatch,
callPackage,
ocaml-ng,
...
}@genericDefinition:
let
upstreamPatches = import ../generic/patches.nix {
inherit lib;
inherit fetchpatch;
};
upstreamPatchList = lib.lists.flatten (with upstreamPatches; [
$upstreamPatches
]);
in
callPackage (import ../generic/default.nix {
pname = "xen";
branch = "$branch";
version = "$version";
latest = $latest;
pkg = {
xen = {
rev = "$finalVersion";
hash = "$hash";
patches = [ $discoveredXenPatches ] ++ upstreamPatchList;
};
qemu = {
rev = "$finalQEMUVersion";
hash = "$qemuHash";
patches = [ $discoveredQEMUPatches ];
};
seaBIOS = {
rev = "$finalSeaBIOSVersion";
hash = "$seaBIOSHash";
patches = [ $discoveredSeaBIOSPatches ];
};
ovmf = {
rev = "$ovmfVersion";
hash = "$ovmfHash";
patches = [ $discoveredOVMFPatches ];
};
ipxe = {
rev = "$ipxeVersion";
hash = "$ipxeHash";
patches = [ $discoveredIPXEPatches ];
};
};
}) ({ ocamlPackages = ocaml-ng.ocamlPackages_$ocamlVersion; } // genericDefinition)
EOF
echo done!
echo -n "Formatting..."
nixfmt "$branch"/default.nix
echo done!
echo -e "\n\e[1;32mSuccessfully produced $branch/default.nix.\e[0m"
done
echo -e -n "\nCleaning up..."
rm -rf /tmp/xenUpdateScript
echo done!
+495
View File
@@ -0,0 +1,495 @@
{
lib,
stdenv,
autoPatchelfHook,
cmake,
pkg-config,
testers,
which,
fetchgit,
fetchpatch,
# Xen
acpica-tools,
bison,
bzip2,
dev86,
e2fsprogs,
flex,
libnl,
libuuid,
lzo,
ncurses,
ocamlPackages,
perl,
python3Packages,
systemdMinimal,
xz,
yajl,
zlib,
zstd,
# Optional Components
seabios,
OVMF,
ipxe,
checkpolicy,
binutils-unwrapped,
# Documentation
pandoc,
# Scripts
bridge-utils,
coreutils,
diffutils,
gawk,
gnugrep,
gnused,
inetutils,
iproute2,
iptables,
multipath-tools,
nbd,
openvswitch,
util-linux,
}:
{
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
# Inherit helper functions from lib and builtins.
inherit (builtins) elemAt isAttrs;
inherit (lib.strings)
concatLines
enableFeature
makeSearchPathOutput
optionalString
removeSuffix
versionOlder
;
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.
minSupportedVersion = "4.16";
## Generic Patch Handling ##
upstreamPatches = import ./patches.nix {
inherit lib fetchpatch;
};
upstreamPatchList = flatten (
with upstreamPatches;
[
QUBES_REPRODUCIBLE_BUILDS
XSA_460
XSA_461
XSA_462
]
);
## XSA Patches Description Builder ##
# Simple counter for the number of attrsets (patches) in the patches list after normalisation.
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
# produce the range that will be used in the following builtin.map calls.
availablePatchesToTry = range 0 (numberOfPatches - 1);
# 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
# to remove these junk values, if necessary.
retrievePatchAttributes =
attributeName:
map (x: attrByPath attributeName null (elemAt upstreamPatchList x)) availablePatchesToTry;
# 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
# then used in meta.longDescription, to let users know their Xen is patched against
# known vulnerabilities, as the package version isn't always the best indicator.
#
# Produces something like this: (one string for each XSA)
# * [Xen Security Advisory #1](https://xenbits.xenproject.org/xsa/advisory-1.html): **Title for XSA.**
# >Description of issue in XSA
#Extra lines
#are not indented,
#but markdown should be
#fine with it.
# Fixes:
# * [CVE-1999-00001](https://www.cve.org/CVERecord?id=CVE-1999-00001)
# * [CVE-1999-00002](https://www.cve.org/CVERecord?id=CVE-1999-00002)
# * [CVE-1999-00003](https://www.cve.org/CVERecord?id=CVE-1999-00003)
writeAdvisoryDescription =
if (remove null (retrievePatchAttributes [ "xsa" ]) != [ ]) then
zipListsWith (a: b: a + b)
(zipListsWith (a: b: a + "**" + b + ".**\n >")
(zipListsWith (a: b: "* [Xen Security Advisory #" + a + "](" + b + "): ")
(remove null (retrievePatchAttributes [ "xsa" ]))
(
remove null (retrievePatchAttributes [
"meta"
"homepage"
])
)
)
(
remove null (retrievePatchAttributes [
"meta"
"description"
])
)
)
(
remove null (retrievePatchAttributes [
"meta"
"longDescription"
])
)
else
[ ];
## Binutils Override ##
# Originally, there were two versions of binutils being used: the standard one and
# this patched one. Unfortunately, that required patches to the Xen Makefiles, and
# quickly became too complex to maintain. The new solution is to simply build this
# efi-binutils derivation and use it for the whole build process, except if
# enableEFI is disabled; it'll then use `binutils`.
efiBinutils = binutils-unwrapped.overrideAttrs (oldAttrs: {
name = "efi-binutils";
configureFlags = oldAttrs.configureFlags ++ [ "--enable-targets=x86_64-pep" ];
doInstallCheck = false; # We get a spurious failure otherwise, due to a host/target mismatch.
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
stdenv.mkDerivation (finalAttrs: {
inherit pname version;
# TODO: Split $out in $bin for binaries and $lib for libraries.
# TODO: Python package to be in separate output/package.
outputs = [
"out"
"man"
"doc"
"dev"
"boot"
];
# Main Xen source.
src = fetchgit {
url = "https://xenbits.xenproject.org/git-http/xen.git";
inherit rev hash;
};
patches = optionals useDefaultPatchList upstreamPatchList ++ patches;
nativeBuildInputs = [
autoPatchelfHook
bison
cmake
flex
pandoc
pkg-config
python3Packages.setuptools
];
buildInputs = [
# Xen
acpica-tools
bzip2
dev86
e2fsprogs.dev
libnl
libuuid
lzo
ncurses
perl
python3Packages.python
xz
yajl
zlib
zstd
# oxenstored
ocamlPackages.findlib
ocamlPackages.ocaml
# Python Fixes
python3Packages.wrapPython
] ++ optional withFlask checkpolicy ++ optional (versionOlder version "4.19") systemdMinimal;
configureFlags = [
"--enable-systemd"
"--disable-qemu-traditional"
"--with-system-qemu"
(if withSeaBIOS then "--with-system-seabios=${seabios}/share/seabios" else "--disable-seabios")
(if withOVMF then "--with-system-ovmf=${OVMF.firmware}" else "--disable-ovmf")
(if withIPXE then "--with-system-ipxe=${ipxe}" else "--disable-ipxe")
(enableFeature withFlask "xsmpolicy")
];
makeFlags =
[
"SUBSYSTEMS=${toString finalAttrs.buildFlags}"
"PREFIX=$(out)"
"BASH_COMPLETION_DIR=$(PREFIX)/share/bash-completion/completions"
"XEN_WHOAMI=${pname}"
"XEN_DOMAIN=${vendor}"
"GIT=${coreutils}/bin/false"
"WGET=${coreutils}/bin/false"
]
++ optionals withEFI [
"EFI_VENDOR=${vendor}"
"INSTALL_EFI_STRIP=1"
"LD=${getExe efiBinutils}" # See the comment in the efiBinutils definition above.
]
# These flags set the CONFIG_* options in /boot/xen.config
# and define if the default policy file is built. However,
# the Flask binaries always get compiled by default.
++ optionals withFlask [
"XSM_ENABLE=y"
"FLASK_ENABLE=y"
];
buildFlags = [
"xen"
"tools"
"docs"
];
enableParallelBuilding = true;
env.NIX_CFLAGS_COMPILE = toString [
"-Wno-error=maybe-uninitialized"
"-Wno-error=array-bounds"
];
dontUseCmakeConfigure = true;
# Remove in-tree QEMU sources, we don't need them in any circumstance.
prePatch = "rm --recursive --force tools/qemu-xen tools/qemu-xen-traditional";
postPatch =
# The following patch forces Xen to install xen.efi on $out/boot
# instead of $out/boot/efi/efi/nixos, as the latter directory
# would otherwise need to be created manually. This also creates
# a more consistent output for downstreams who override the
# vendor attribute above.
''
substituteInPlace xen/Makefile \
--replace-fail "\$(D)\$(EFI_MOUNTPOINT)/efi/\$(EFI_VENDOR)/\$(T)-\$(XEN_FULLVERSION).efi" \
"\$(D)\$(BOOT_DIR)/\$(T)-\$(XEN_FULLVERSION).efi"
''
# The following patch fixes the call to /bin/mkdir on the
# launch_xenstore.sh helper script.
+ ''
substituteInPlace tools/hotplug/Linux/launch-xenstore.in \
--replace-fail "/bin/mkdir" "${coreutils}/bin/mkdir"
''
# The following expression fixes the paths called by Xen's systemd
# units, so we can use them in the NixOS module.
+ ''
substituteInPlace \
tools/hotplug/Linux/systemd/{xen-init-dom0,xen-qemu-dom0-disk-backend,xenconsoled,xendomains,xenstored}.service.in \
--replace-fail /bin/grep ${gnugrep}/bin/grep
substituteInPlace \
tools/hotplug/Linux/systemd/{xen-qemu-dom0-disk-backend,xenconsoled}.service.in \
--replace-fail "/bin/mkdir" "${coreutils}/bin/mkdir"
'';
installPhase = ''
runHook preInstall
mkdir --parents $out $out/share $boot
cp -prvd dist/install/nix/store/*/* $out/
cp -prvd dist/install/etc $out
cp -prvd dist/install/boot $boot
runHook postInstall
'';
postInstall =
# Wrap xencov_split, xenmon and xentrace_format.
''
wrapPythonPrograms
''
# We also need to wrap pygrub, which lies in $out/libexec/xen/bin.
+ ''
wrapPythonProgramsIn "$out/libexec/xen/bin" "$out $pythonPath"
''
# Fix shebangs in Xen's various scripts.
#TODO: Remove any and all usage of `sed` and replace these complicated magic runes with readable code.
+ ''
shopt -s extglob
for i in $out/etc/xen/scripts/!(*.sh); do
sed --in-place "2s@^@export PATH=$out/bin:${scriptEnvPath}\n@" $i
done
'';
postFixup =
''
addAutoPatchelfSearchPath $out/lib
autoPatchelf $out/libexec/xen/bin
''
# Flask is particularly hard to disable. Even after
# setting the make flags to `n`, it still gets compiled.
# If withFlask is disabled, delete the extra binaries.
+ optionalString (!withFlask) ''
rm -f $out/bin/flask-*
'';
passthru = {
efi =
if withEFI then "boot/xen-${version}.efi" else throw "This Xen was compiled without an EFI binary.";
flaskPolicy =
if withFlask then
"boot/xenpolicy-${version}"
else
throw "This Xen was compiled without FLASK support.";
# This test suite is very simple, as Xen's userspace
# utilities require the hypervisor to be booted.
tests = {
pkg-config = testers.hasPkgConfigModules {
package = finalAttrs.finalPackage;
moduleNames = [
"xencall"
"xencontrol"
"xendevicemodel"
"xenevtchn"
"xenforeignmemory"
"xengnttab"
"xenguest"
"xenhypfs"
"xenlight"
"xenstat"
"xenstore"
"xentoolcore"
"xentoollog"
"xenvchan"
"xlutil"
];
};
};
};
meta = {
inherit branch;
description = "Type-1 hypervisor intended for embedded and hyperscale use cases";
longDescription =
''
The Xen Project Hypervisor is a virtualisation technology defined as a *type-1
hypervisor*, which allows multiple virtual machines, known as domains, to run
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**.
Use with the `qemu_xen` package.
''
# Then, if any of the optional with* components are being built, add the "Includes:" string.
+ optionalString (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.
+ 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."
+ 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."
+ 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."
)
# 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.
+ optionalString (writeAdvisoryDescription != [ ]) (
"\n\nThis Xen Project Hypervisor (${version}) has been patched against the following known security vulnerabilities:\n"
+ removeSuffix "\n" (concatLines writeAdvisoryDescription)
);
homepage = "https://xenproject.org/";
downloadPage = "https://downloads.xenproject.org/release/xen/${version}/";
changelog = "https://wiki.xenproject.org/wiki/Xen_Project_${branch}_Release_Notes";
license = [
# Documentation.
cc-by-40
# Most of Xen is licensed under the GPL v2.0.
gpl2Only
# Xen Libraries and the `xl` command-line utility.
lgpl21Only
# Development headers in $dev/include.
mit
];
maintainers = 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";
mainProgram = "xl";
#TODO: Migrate meta.platforms to the new lib.systems.inspect.patterns.* format.
platforms = linux;
badPlatforms = aarch64;
} // meta;
})
@@ -6,6 +6,9 @@
{ lib, fetchpatch }:
let
inherit (builtins) concatStringsSep;
inherit (lib.strings) optionalString concatMapStrings;
xsaPatch =
{
id,
@@ -16,8 +19,7 @@ let
cve ? null,
}:
(fetchpatch {
name =
"XSA-" + id + lib.strings.optionalString (cve != null) ("-" + builtins.concatStringsSep "+" cve);
name = "XSA-" + id + optionalString (cve != null) ("-" + concatStringsSep "+" cve);
url = "https://xenbits.xen.org/xsa/xsa${id}.patch";
inherit hash;
passthru = {
@@ -37,9 +39,7 @@ let
" _No CVE was assigned to this XSA._"
else
" Fixes:${
lib.strings.concatMapStrings (
x: "\n * [" + x + "](https://www.cve.org/CVERecord?id=" + x + ")"
) cve
concatMapStrings (x: "\n * [" + x + "](https://www.cve.org/CVERecord?id=" + x + ")") cve
}"
);
homepage = "https://xenbits.xenproject.org/xsa/advisory-${id}.html";
+3 -3
View File
@@ -19,7 +19,7 @@
libkvmi,
xenSupport ? true,
xen-slim,
xen,
}:
let
@@ -58,7 +58,7 @@ stdenv.mkDerivation {
json_c
libvirt
]
++ lib.optionals xenSupport [ xen-slim ]
++ lib.optionals xenSupport [ xen ]
++ lib.optionals (!legacyKVM) [ libkvmi ]
++ lib.optionals withVMIFS [ fuse ];
@@ -71,7 +71,7 @@ stdenv.mkDerivation {
postFixup = lib.optionalString xenSupport ''
libvmi="$lib/lib/libvmi.so.${libVersion}"
oldrpath=$(patchelf --print-rpath "$libvmi")
patchelf --set-rpath "$oldrpath:${lib.makeLibraryPath [ xen-slim ]}" "$libvmi"
patchelf --set-rpath "$oldrpath:${lib.makeLibraryPath [ xen ]}" "$libvmi"
'';
passthru = {
+1
View File
@@ -0,0 +1 @@
{ qemu }: qemu.override { xenSupport = true; }
+3 -3
View File
@@ -4,7 +4,7 @@
rustPlatform,
llvmPackages,
pkg-config,
xen-slim,
xen,
}:
rustPlatform.buildRustPackage rec {
pname = "xen-guest-agent";
@@ -25,7 +25,7 @@ rustPlatform.buildRustPackage rec {
pkg-config
];
buildInputs = [ xen-slim ];
buildInputs = [ xen ];
postInstall =
# Install the sample systemd service.
@@ -38,7 +38,7 @@ rustPlatform.buildRustPackage rec {
postFixup =
# Add the Xen libraries in the runpath so the guest agent can find libxenstore.
"patchelf $out/bin/xen-guest-agent --add-rpath ${xen-slim.out}/lib";
"patchelf $out/bin/xen-guest-agent --add-rpath ${xen}/lib";
meta = {
description = "Xen agent running in Linux/BSDs (POSIX) VMs";
+133
View File
@@ -0,0 +1,133 @@
<p align="center">
<a href="https://xenproject.org/">
<picture>
<source
media="(prefers-color-scheme: light)"
srcset="https://downloads.xenproject.org/Branding/Logos/Green+Black/xen_project_logo_dualcolor_2000x832.png">
<source
media="(prefers-color-scheme: dark)"
srcset="https://xenproject.org/wp-content/uploads/sites/79/2018/09/logo_xenproject.png">
<img
src="https://downloads.xenproject.org/Branding/Logos/Green+Black/xen_project_logo_dualcolor_2000x832.png"
width="512px"
alt="Xen Project Logo">
</picture>
</a>
</p>
# Xen Project Hypervisor <a href="https://xenproject.org/"><img src="https://downloads.xenproject.org/Branding/Mascots/Xen-Fu-Panda-2000px.png" width="48px" align="top" alt="Xen Fu Panda"></a>
This directory begins the [Xen Project Hypervisor](https://xenproject.org/) build process.
Some other notable packages that compose the Xen Project Ecosystem include:
- `ocamlPackages.xenstore`: Mirage's `oxenstore` implementation.
- `ocamlPackages.vchan`: Mirage's `xen-vchan` implementation.
- `ocamlPackages.xenstore-tool`: XAPI's `oxenstore` utilities.
- `xen-guest-agent`: Guest drivers for UNIX domUs.
- `win-pvdrivers`: Guest drivers for Windows domUs.
- `xtf`: The Xen Test Framework.
## Updating
### Manually
1. [Update](https://xenbits.xenproject.org/gitweb/) the `package.nix` file for
the latest branch of Xen.
- Do not forget to set the `branch`, `version`, and `latest` attributes.
- The revisions are preferably commit hashes, but tag names are acceptable
as well.
1. Make sure it builds.
1. Use the NixOS module to test if dom0 boots successfully on the new version.
1. Make sure the `meta` attributes evaluate to something that makes sense. The
following one-line command is useful for testing this:
```console
echo -e "\033[1m$(nix eval .#xen.meta.description --raw 2> /dev/null)\033[0m\n\n$(nix eval .#xen.meta.longDescription --raw 2> /dev/null)"
```
1. Run `xtf --all --host` as root when booted into the Xen update, and make
sure no important tests fail.
1. Clean up your changes and commit them, making sure to follow the
[Nixpkgs Contribution Guidelines](../../../../CONTRIBUTING.md).
1. Open a PR and await a review from the current maintainers.
## Features
### Generic Builder
`buildXenPackage` is a helpful utility capable of building Xen when passed
certain attributes. The `package.nix` file on this directory includes all
important attributes for building a Xen package with Nix. Downstreams can
pin their Xen revision or include extra patches if the default Xen package
does not meet their needs.
### EFI
Building `xen.efi` requires an `ld` with PE support.[^2]
We use a `makeFlag` to override the `$LD` environment variable to point to our
patched `efiBinutils`. For more information, see the comment in `pkgs/build-support/xen/default.nix`.
> [!TIP]
> If you are certain you will not be running Xen in an x86 EFI environment, disable
the `withEFI` flag with an [override](https://nixos.org/manual/nixpkgs/stable/#chap-overrides)
to save you the need to compile `efiBinutils`.
## Security
We aim to support the **latest** version of Xen at any given time.
See the [Xen Support Matrix](https://xenbits.xen.org/docs/unstable/support-matrix.html)
for a list of versions. As soon as a version is no longer the newest, it should
be removed from Nixpkgs (`master`). If you need earlier versions of Xen, consider
building your own Xen by following the instructions in the **Generic Builder**
section.
> [!CAUTION]
> Pull requests that introduce XSA patches
should have the `1.severity: security` label.
### Maintainers
Xen is a particularly complex piece of software, so we are always looking for new
maintainers. Help out by [making and triaging issues](https://github.com/NixOS/nixpkgs/issues/new/choose),
[sending build fixes and improvements through PRs](https://github.com/NixOS/nixpkgs/compare),
updating the branches, and [patching security flaws](https://xenbits.xenproject.org/xsa/).
We are also looking for testers, particularly those who can test Xen on AArch64
machines. Open issues for any build failures or runtime errors you find!
## Tests
So far, we only have had one simple automated test that checks for
the correct `pkg-config` output files.
Due to Xen's nature as a type-1 hypervisor, it is not a trivial matter to design
new tests, as even basic functionality requires a machine booted in a dom0
kernel. For this reason, most testing done with this package must be done
manually in a NixOS machine with `virtualisation.xen.enable` set to `true`.
Another unfortunate thing is that none of the Xen commands have a `--version`
flag. This means that `testers.testVersion` cannot ascertain the Xen version.
The only way to verify that you have indeed built the correct version is to
boot into the freshly built Xen kernel and run `xl info`.
<p align="center">
<a href="https://xenproject.org/">
<img
src="https://downloads.xenproject.org/Branding/Mascots/Xen%20Big%20Panda%204242x3129.png"
width="96px"
alt="Xen Fu Panda">
</a>
</p>
[^1]: We also produce fake `git`, `wget` and `hostname` binaries that do nothing,
to prevent the build from failing because Xen cannot fetch the sources that
were already fetched by Nix.
[^2]: From the [Xen Documentation](https://xenbits.xenproject.org/docs/unstable/misc/efi.html):
> For x86, building `xen.efi` requires `gcc` 4.5.x or above (4.6.x or newer
recommended, as 4.5.x was probably never really tested for this purpose)
and `binutils` 2.22 or newer. Additionally, the `binutils` build must be
configured to include support for the x86_64-pep emulation (i.e.
`--enable-targets=x86_64-pep` or an option of equivalent effect should be
passed to the configure script).
+11
View File
@@ -0,0 +1,11 @@
{
buildXenPackage,
python3Packages,
}:
buildXenPackage.override { inherit python3Packages; } {
pname = "xen";
version = "4.19.0";
rev = "026c9fa29716b0ff0f8b7c687908e71ba29cf239";
hash = "sha256-Q6x+2fZ4ITBz6sKICI0NHGx773Rc919cl+wzI89UY+Q=";
}
+6
View File
@@ -1705,6 +1705,12 @@ mapAliases {
xcodebuild6 = throw "'xcodebuild6' has been renamed to/replaced by 'xcodebuild'"; # Added 2023-12-10
xdg_utils = xdg-utils; # Added 2021-02-01
xen-light = throw "'xen-light' has been renamed to/replaced by 'xen-slim'"; # Added 2024-06-30
xen-slim = throw "'xen-slim' has been renamed to 'xen'. The old Xen package with built-in components no longer exists"; # Added 2024-10-05
xen_4_16 = throw "While Xen 4.16 was still security-supported when it was removed from Nixpkgs, it would have reached its End of Life a couple of days after NixOS 24.11 released. To avoid shipping an insecure version of Xen, the Xen Project Hypervisor Maintenance Team decided to delete the derivation entirely"; # Added 2024-10-05
xen_4_17 = throw "Due to technical challenges involving building older versions of Xen with newer dependencies, the Xen Project Hypervisor Maintenance Team decided to switch to a latest-only support cycle. As Xen 4.17 would have been the 'n-2' version, it was removed"; # Added 2024-10-05
xen_4_18 = throw "Due to technical challenges involving building older versions of Xen with newer dependencies, the Xen Project Hypervisor Maintenance Team decided to switch to a latest-only support cycle. As Xen 4.18 would have been the 'n-1' version, it was removed"; # Added 2024-10-05
xen_4_19 = throw "Use 'xen' instead"; # Added 2024-10-05
xenPackages = throw "The attributes in the xenPackages set have been promoted to the top-level. (xenPackages.xen_4_19 -> xen)";
xineLib = xine-lib; # Added 2021-04-27
xineUI = xine-ui; # Added 2021-04-27
xmlada = gnatPackages.xmlada; # Added 2024-02-25
+1 -11
View File
@@ -26400,13 +26400,6 @@ with pkgs;
glusterfsSupport = lib.meta.availableOn stdenv.hostPlatform glusterfs && lib.meta.availableOn stdenv.hostPlatform libuuid;
});
# See `xenPackages` source for explanations.
# Building with `xen` instead of `xen-slim` is possible, but makes no sense.
qemu_xen_4_19 = lowPrio (qemu.override { hostCpuTargets = [ "i386-softmmu" ]; xenSupport = true; xen = xenPackages.xen_4_19-slim; });
qemu_xen_4_18 = lowPrio (qemu.override { hostCpuTargets = [ "i386-softmmu" ]; xenSupport = true; xen = xenPackages.xen_4_18-slim; });
qemu_xen_4_17 = lowPrio (qemu.override { hostCpuTargets = [ "i386-softmmu" ]; xenSupport = true; xen = xenPackages.xen_4_17-slim; });
qemu_xen = qemu_xen_4_19;
qemu_test = lowPrio (qemu.override { hostCpuOnly = true; nixosTestRunner = true; });
quick-lint-js = callPackage ../development/tools/quick-lint-js { };
@@ -33834,10 +33827,7 @@ with pkgs;
xdotool = callPackage ../tools/X11/xdotool { };
xenPackages = recurseIntoAttrs (callPackage ../applications/virtualization/xen/packages.nix {});
xen = xenPackages.xen_4_19;
xen-slim = xenPackages.xen_4_19-slim;
buildXenPackage = callPackage ../build-support/xen { };
xkbset = callPackage ../tools/X11/xkbset { };
+1 -1
View File
@@ -17590,7 +17590,7 @@ self: super: with self; {
inherit (pkgs) graphviz;
};
xen = toPythonModule (pkgs.xen-slim.override {
xen = toPythonModule (pkgs.xen.override {
python3Packages = self;
});