push sheeet
Some checks failed
Periodic Merges (6h) / master → staging-nixos (push) Failing after 12m50s
Periodic Merges (6h) / master → staging-next (push) Failing after 12m54s
Periodic Merges (24h) / merge-base(master,staging) → haskell-updates (push) Failing after 11m54s
Periodic Merges (6h) / staging-next → staging (push) Failing after 12m13s
Periodic Merges (24h) / staging-next-25.05 → staging-25.05 (push) Failing after 13m24s
Periodic Merges (24h) / release-25.05 → staging-next-25.05 (push) Failing after 14m28s

This commit is contained in:
Dark Steveneq
2025-10-09 14:15:47 +02:00
commit 646b892680
49168 changed files with 5897842 additions and 0 deletions

View File

@@ -0,0 +1,13 @@
diff --git a/net/bridge/br_private.h b/net/bridge/br_private.h
index aea3d13..8fcbf81 100644
--- a/net/bridge/br_private.h
+++ b/net/bridge/br_private.h
@@ -39,7 +39,7 @@
#define BR_GROUPFWD_8021AD 0xB801u
/* Path to usermode spanning tree program */
-#define BR_STP_PROG "/sbin/bridge-stp"
+#define BR_STP_PROG "/run/current-system/sw/bin/bridge-stp"
typedef struct bridge_id bridge_id;
typedef struct mac_addr mac_addr;

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,40 @@
{
lib,
stdenv,
buildPackages,
extraMakeFlags ? [ ],
}:
# Absolute paths for compilers avoid any PATH-clobbering issues.
[
#
# We use the unwrapped compiler, because the clang-wrapper doesn't like -target.
"CC=${lib.getExe stdenv.cc.cc}"
# The wrapper for ld.lld breaks linking the kernel. We use the unwrapped linker as workaround. See:
# https://github.com/NixOS/nixpkgs/issues/321667
"LD=${lib.getExe' stdenv.cc.bintools.bintools "${stdenv.cc.targetPrefix}ld"}"
"AR=${lib.getExe' stdenv.cc "${stdenv.cc.targetPrefix}ar"}"
"NM=${lib.getExe' stdenv.cc "${stdenv.cc.targetPrefix}nm"}"
"STRIP=${lib.getExe' stdenv.cc.bintools.bintools "${stdenv.cc.targetPrefix}strip"}"
"OBJCOPY=${lib.getExe' stdenv.cc "${stdenv.cc.targetPrefix}objcopy"}"
"OBJDUMP=${lib.getExe' stdenv.cc "${stdenv.cc.targetPrefix}objdump"}"
"READELF=${lib.getExe' stdenv.cc "${stdenv.cc.targetPrefix}readelf"}"
"HOSTCC=${lib.getExe' buildPackages.stdenv.cc "${buildPackages.stdenv.cc.targetPrefix}cc"}"
"HOSTCXX=${lib.getExe' buildPackages.stdenv.cc "${buildPackages.stdenv.cc.targetPrefix}c++"}"
"HOSTAR=${lib.getExe' buildPackages.stdenv.cc.bintools "${buildPackages.stdenv.cc.targetPrefix}ar"}"
"HOSTLD=${lib.getExe' buildPackages.stdenv.cc.bintools "${buildPackages.stdenv.cc.targetPrefix}ld"}"
"ARCH=${stdenv.hostPlatform.linuxArch}"
"CROSS_COMPILE=${stdenv.cc.targetPrefix}"
]
# Add the built in headers the kernel needs
++ lib.optionals (stdenv.cc.isClang) (
let
clangLib = lib.getLib stdenv.cc.cc;
majorVer = lib.versions.major clangLib.version;
in
[
"CFLAGS_MODULE=-I${clangLib}/lib/clang/${majorVer}/include"
"CFLAGS_KERNEL=-I${clangLib}/lib/clang/${majorVer}/include"
]
)
++ (stdenv.hostPlatform.linux-kernel.makeFlags or [ ])
++ extraMakeFlags

View File

@@ -0,0 +1,11 @@
Export linux-rt (PREEMPT_RT) specific symbols needed by ZFS.
(Regular kernel provides them static inline in linux/preempt.h.)
--- a/kernel/sched/core.c
+++ b/kernel/sched/core.c
@@ -1812 +1812 @@ void migrate_disable(void)
-EXPORT_SYMBOL_GPL(migrate_disable);
+EXPORT_SYMBOL(migrate_disable);
@@ -1843 +1843 @@ void migrate_enable(void)
-EXPORT_SYMBOL_GPL(migrate_enable);
+EXPORT_SYMBOL(migrate_enable);

View File

@@ -0,0 +1,160 @@
# This script runs `make config' to generate a Linux kernel
# configuration file. For each question (i.e. kernel configuration
# option), unless an override is provided, it answers "m" if possible,
# and otherwise uses the default answer (as determined by the default
# config for the architecture). Overrides are read from the file
# $KERNEL_CONFIG, which on each line contains an option name and an
# answer, e.g. "EXT2_FS_POSIX_ACL y". The script warns about ignored
# options in $KERNEL_CONFIG, and barfs if `make config' selects
# another answer for an option than the one provided in
# $KERNEL_CONFIG.
use strict;
use IPC::Open2;
use Cwd;
# exported via nix
my $debug = $ENV{'DEBUG'};
my $autoModules = $ENV{'AUTO_MODULES'};
my $preferBuiltin = $ENV{'PREFER_BUILTIN'};
my $ignoreConfigErrors = $ENV{'ignoreConfigErrors'};
my $buildRoot = $ENV{'BUILD_ROOT'};
my $makeFlags = $ENV{'MAKE_FLAGS'};
$SIG{PIPE} = 'IGNORE';
# Read the answers.
my %answers;
my %requiredAnswers;
open ANSWERS, "<$ENV{KERNEL_CONFIG}" or die "Could not open answer file";
while (<ANSWERS>) {
chomp;
s/#.*//;
if (/^\s*([A-Za-z0-9_]+)(\?)?\s+(.*\S)\s*$/) {
$answers{$1} = $3;
$requiredAnswers{$1} = !(defined $2);
} elsif (!/^\s*$/) {
die "invalid config line: $_";
}
}
close ANSWERS;
sub runConfig {
# Run `make config'.
#
# We have to pass through the target toolchain, because `make config` checks them for versions. This is
# required to get clang LTO working, among other things.
my $pid = open2(\*IN, \*OUT,
"make -C $ENV{SRC} O=$buildRoot config"
. " SHELL=bash ARCH=$ENV{ARCH} CROSS_COMPILE=$ENV{CROSS_COMPILE}"
. " $makeFlags");
# Parse the output, look for questions and then send an
# appropriate answer.
my $line = ""; my $s;
my %choices = ();
my ($prevQuestion, $prevName);
while (!eof IN) {
read IN, $s, 1 or next;
$line .= $s;
#print STDERR "LINE: $line\n";
if ($s eq "\n") {
print STDERR "GOT: $line" if $debug;
# Remember choice alternatives ("> 1. bla (FOO)" or " 2. bla (BAR) (NEW)").
if ($line =~ /^\s*>?\s*(\d+)\.\s+.*?\(([A-Za-z0-9_]+)\)(?:\s+\(NEW\))?\s*$/) {
$choices{$2} = $1;
} else {
# The list of choices has ended without us being
# asked. This happens for options where only one value
# is valid, for instance. The results can foul up
# later options, so forget about it.
%choices = ();
}
$line = "";
}
elsif ($line =~ /###$/) {
# The config program is waiting for an answer.
# Is this a regular question? ("bla bla (OPTION_NAME) [Y/n/m/...] ")
if ($line =~ /(.*) \(([A-Za-z0-9_]+)\) \[(.*)\].*###$/) {
my $question = $1; my $name = $2; my $alts = $3;
my $answer = "";
# Build everything as a module if possible.
$answer = "m" if $autoModules && $alts =~ qr{\A(\w/)+m/(\w/)*\?\z} && !($preferBuiltin && $alts =~ /Y/);
$answer = $answers{$name} if defined $answers{$name};
print STDERR "QUESTION: $question, NAME: $name, ALTS: $alts, ANSWER: $answer\n" if $debug;
print OUT "$answer\n";
die "repeated question: $question" if $prevQuestion && $prevQuestion eq $question && $name eq $prevName;
$prevQuestion = $question;
$prevName = $name;
}
# Is this a choice? ("choice[1-N]: ")
elsif ($line =~ /choice\[(.*)\]: ###$/) {
my $answer = "";
foreach my $name (keys %choices) {
$answer = $choices{$name} if ($answers{$name} || "") eq "y";
}
print STDERR "CHOICE: $1, ANSWER: $answer\n" if $debug;
print OUT "$answer\n" if $1 =~ /-/;
}
# Some questions lack the option name ("bla bla [Y/n/m/...] ").
elsif ($line =~ /(.*) \[(.*)\] ###$/) {
print OUT "\n";
}
else {
warn "don't know how to answer this question: $line\n";
print OUT "\n";
}
$line = "";
%choices = ();
}
}
close IN;
waitpid $pid, 0;
}
# Run `make config' several times to converge on the desired result.
# (Some options may only become available after other options are
# set in a previous run.)
runConfig;
runConfig;
# Read the final .config file and check that our answers are in
# there. `make config' often overrides answers if later questions
# cause options to be selected.
my %config;
open CONFIG, "<$buildRoot/.config" or die "Could not read .config";
while (<CONFIG>) {
chomp;
if (/^CONFIG_([A-Za-z0-9_]+)="(.*)"$/) {
# String options have double quotes, e.g. 'CONFIG_NLS_DEFAULT="utf8"' and allow escaping.
($config{$1} = $2) =~ s/\\([\\"])/$1/g;
} elsif (/^CONFIG_([A-Za-z0-9_]+)=(.*)$/) {
$config{$1} = $2;
} elsif (/^# CONFIG_([A-Za-z0-9_]+) is not set$/) {
$config{$1} = "n";
}
}
close CONFIG;
my $ret = 0;
foreach my $name (sort (keys %answers)) {
my $f = $requiredAnswers{$name} && $ignoreConfigErrors ne "1"
? sub { warn "error: " . $_[0]; $ret = -1; } : sub { warn "warning: " . $_[0]; };
&$f("unused option: $name\n") unless defined $config{$name};
&$f("option not set correctly: $name (wanted '$answers{$name}', got '$config{$name}')\n")
if $config{$name} && $config{$name} ne $answers{$name};
}
exit $ret;

View File

@@ -0,0 +1,416 @@
{
buildPackages,
pkgsBuildBuild,
callPackage,
perl,
bison ? null,
flex ? null,
gmp ? null,
libmpc ? null,
mpfr ? null,
pahole,
lib,
stdenv,
rustc-unwrapped,
rustPlatform,
rust-bindgen-unwrapped,
# testing
emptyFile,
nixos,
nixosTests,
}@args':
let
overridableKernel = lib.makeOverridable (
# The kernel source tarball.
{
src,
# The kernel version.
version,
# Allows overriding the default defconfig
defconfig ? null,
# Legacy overrides to the intermediate kernel config, as string
extraConfig ? "",
# Additional make flags passed to kbuild
extraMakeFlags ? [ ],
# enables the options in ./common-config.nix and lib/systems/platform.nix;
# if `false` then only `structuredExtraConfig` is used
enableCommonConfig ? true
, # kernel intermediate config overrides, as a set
structuredExtraConfig ? { },
# The version number used for the module directory
# If unspecified, this is determined automatically from the version.
modDirVersion ? null,
# An attribute set whose attributes express the availability of
# certain features in this kernel. E.g. `{ia32Emulation = true;}'
# indicates a kernel that provides Intel wireless support. Used in
# NixOS to implement kernel-specific behaviour.
features ? { },
# Custom seed used for CONFIG_GCC_PLUGIN_RANDSTRUCT if enabled. This is
# automatically extended with extra per-version and per-config values.
randstructSeed ? "",
# A list of patches to apply to the kernel. Each element of this list
# should be an attribute set {name, patch} where `name' is a
# symbolic name and `patch' is the actual patch. The patch may
# optionally be compressed with gzip or bzip2.
kernelPatches ? [ ],
ignoreConfigErrors ?
!lib.elem stdenv.hostPlatform.linux-kernel.name [
"aarch64-multiplatform"
"pc"
],
extraMeta ? { },
extraPassthru ? { },
isLTS ? false,
isZen ? false,
isLibre ? false,
isHardened ? false,
# easy overrides to stdenv.hostPlatform.linux-kernel members
autoModules ? stdenv.hostPlatform.linux-kernel.autoModules,
preferBuiltin ? stdenv.hostPlatform.linux-kernel.preferBuiltin or false,
kernelArch ? stdenv.hostPlatform.linuxArch,
kernelTests ? { },
stdenv ? args'.stdenv,
buildPackages ? args'.buildPackages,
pkgsBuildBuild ? args'.pkgsBuildBuild,
...
}@args:
# Note: this package is used for bootstrapping fetchurl, and thus
# cannot use fetchpatch! All mutable patches (generated by GitHub or
# cgit) that are needed here should be included directly in Nixpkgs as
# files.
let
# Dirty hack to make sure that `version` & `src` have
# `<nixpkgs/pkgs/os-specific/linux/kernel/linux-x.y.nix>` as position
# when using `builtins.unsafeGetAttrPos`.
#
# This is to make sure that ofborg actually detects changes in the kernel derivation
# and pings all maintainers.
#
# For further context, see https://github.com/NixOS/nixpkgs/pull/143113#issuecomment-953319957
basicArgs = removeAttrs args (
lib.filter (
x:
!(builtins.elem x [
"version"
"pname"
"src"
])
) (lib.attrNames args)
);
# Combine the `features' attribute sets of all the kernel patches.
kernelFeatures = lib.foldr (x: y: (x.features or { }) // y) (
{
efiBootStub = true;
netfilterRPFilter = true;
ia32Emulation = true;
}
// features
) kernelPatches;
commonStructuredConfig = import ./common-config.nix {
inherit lib stdenv version;
rustAvailable = lib.meta.availableOn stdenv.hostPlatform rustc-unwrapped;
features = kernelFeatures; # Ensure we know of all extra patches, etc.
};
intermediateNixConfig =
configfile.moduleStructuredConfig.intermediateNixConfig
# extra config in legacy string format
+ extraConfig
# need the 'or ""' at the end in case enableCommonConfig = true and extraConfig is not present
+ lib.optionalString enableCommonConfig stdenv.hostPlatform.linux-kernel.extraConfig or "";
structuredConfigFromPatches = map (
{
structuredExtraConfig ? { },
...
}@args:
if args ? extraStructuredConfig then
throw ''
Passing `extraStructuredConfig` to the Linux kernel (e.g.
via `boot.kernelPatches` in NixOS) is not supported anymore. Use
`structuredExtraConfig` instead.
''
else
{
settings = structuredExtraConfig;
}
) kernelPatches;
# appends kernel patches extraConfig
kernelConfigFun =
baseConfigStr:
let
configFromPatches = map (
{
extraConfig ? "",
...
}:
extraConfig
) kernelPatches;
in
lib.concatStringsSep "\n" ([ baseConfigStr ] ++ configFromPatches);
withRust = ((configfile.moduleStructuredConfig.settings.RUST or { }).tristate or null) == "y";
configfile = stdenv.mkDerivation {
inherit
ignoreConfigErrors
autoModules
preferBuiltin
kernelArch
extraMakeFlags
;
pname = "linux-config";
inherit version;
generateConfig = ./generate-config.pl;
kernelConfig = kernelConfigFun intermediateNixConfig;
passAsFile = [ "kernelConfig" ];
depsBuildBuild = [ buildPackages.stdenv.cc ];
nativeBuildInputs = [
perl
gmp
libmpc
mpfr
bison
flex
]
++ lib.optional (lib.versionAtLeast version "5.2") pahole
++ lib.optionals withRust [
rust-bindgen-unwrapped
rustc-unwrapped
];
RUST_LIB_SRC = lib.optionalString withRust rustPlatform.rustLibSrc;
platformName = stdenv.hostPlatform.linux-kernel.name;
# e.g. "defconfig"
kernelBaseConfig =
if defconfig != null then defconfig else stdenv.hostPlatform.linux-kernel.baseConfig;
makeFlags = import ./common-flags.nix {
inherit
lib
stdenv
buildPackages
extraMakeFlags
;
};
postPatch = kernel.postPatch + ''
# Patch kconfig to print "###" after every question so that
# generate-config.pl from the generic builder can answer them.
sed -e '/fflush(stdout);/i\printf("###");' -i scripts/kconfig/conf.c
'';
preUnpack = kernel.preUnpack or "";
inherit (kernel) src patches;
buildPhase = ''
export buildRoot="''${buildRoot:-build}"
# Get a basic config file for later refinement with $generateConfig.
make $makeFlags \
-C . O="$buildRoot" $kernelBaseConfig \
ARCH=$kernelArch CROSS_COMPILE=${stdenv.cc.targetPrefix} \
$makeFlags
# Create the config file.
echo "generating kernel configuration..."
ln -s "$kernelConfigPath" "$buildRoot/kernel-config"
DEBUG=1 ARCH=$kernelArch CROSS_COMPILE=${stdenv.cc.targetPrefix} \
KERNEL_CONFIG="$buildRoot/kernel-config" AUTO_MODULES=$autoModules \
PREFER_BUILTIN=$preferBuiltin BUILD_ROOT="$buildRoot" SRC=. MAKE_FLAGS="$makeFlags" \
perl -w $generateConfig
''
+ lib.optionalString stdenv.cc.isClang ''
if ! grep -Fq CONFIG_CC_IS_CLANG=y $buildRoot/.config; then
echo "Kernel config didn't recognize the clang compiler?"
exit 1
fi
''
+ lib.optionalString stdenv.cc.bintools.isLLVM ''
if ! grep -Fq CONFIG_LD_IS_LLD=y $buildRoot/.config; then
echo "Kernel config didn't recognize the LLVM linker?"
exit 1
fi
''
+ lib.optionalString withRust ''
if ! grep -Fq CONFIG_RUST_IS_AVAILABLE=y $buildRoot/.config; then
echo "Kernel config didn't find Rust toolchain?"
exit 1
fi
'';
installPhase = "mv $buildRoot/.config $out";
enableParallelBuilding = true;
passthru = rec {
module = import ../../../../nixos/modules/system/boot/kernel_config.nix;
# used also in apache
# { modules = [ { options = res.options; config = svc.config or svc; } ];
# check = false;
# The result is a set of two attributes
moduleStructuredConfig =
(lib.evalModules {
modules = [
module
]
++ lib.optionals enableCommonConfig [
{
settings = commonStructuredConfig;
_file = "pkgs/os-specific/linux/kernel/common-config.nix";
}
]
++ [
{
settings = structuredExtraConfig;
_file = "structuredExtraConfig";
}
]
++ structuredConfigFromPatches;
}).config;
structuredConfig = moduleStructuredConfig.settings;
};
}; # end of configfile derivation
kernel = (callPackage ./manual-config.nix { inherit lib stdenv buildPackages; }) (
basicArgs
// {
inherit
kernelPatches
randstructSeed
extraMakeFlags
extraMeta
configfile
modDirVersion
;
pos = builtins.unsafeGetAttrPos "version" args;
config = {
CONFIG_MODULES = "y";
CONFIG_FW_LOADER = "y";
CONFIG_RUST = if withRust then "y" else "n";
};
}
);
in
kernel.overrideAttrs (
finalAttrs: previousAttrs: {
passthru =
previousAttrs.passthru or { }
// extraPassthru
// basicArgs
// {
features = kernelFeatures;
inherit
commonStructuredConfig
structuredExtraConfig
extraMakeFlags
isLTS
isZen
isHardened
isLibre
;
isXen = lib.warn "The isXen attribute is deprecated. All Nixpkgs kernels that support it now have Xen enabled." true;
# Adds dependencies needed to edit the config:
# nix-shell '<nixpkgs>' -A linux.configEnv --command 'make nconfig'
configEnv = finalAttrs.finalPackage.overrideAttrs (previousAttrs: {
depsBuildBuild =
previousAttrs.depsBuildBuild or [ ]
++ (with pkgsBuildBuild; [
pkg-config
ncurses
]);
});
tests =
let
overridableKernel = finalAttrs.finalPackage // {
override =
args:
lib.warn (
"override is stubbed for NixOS kernel tests, not applying changes these arguments: "
+ toString (lib.attrNames (lib.toFunction args { }))
) overridableKernel;
};
/*
Certain arguments must be evaluated lazily; so that only the output(s) depend on them.
Original reproducer / simplified use case:
*/
versionDoesNotDependOnPatchesEtcNixOS =
builtins.seq
(nixos (
{ config, pkgs, ... }:
{
boot.kernelPatches = [
(builtins.seq config.boot.kernelPackages.kernel.version { patch = pkgs.emptyFile; })
];
}
)).config.boot.kernelPackages.kernel.outPath
emptyFile;
versionDoesNotDependOnPatchesEtc =
builtins.seq
(import ./generic.nix args' (
args
// (
let
explain = attrName: ''
The ${attrName} attribute must be able to access the kernel.version attribute without an infinite recursion.
That means that the kernel attrset (attrNames) and the kernel.version attribute must not depend on the ${attrName} argument.
The fact that this exception is raised shows that such a dependency does exist.
This is a problem for the configurability of ${attrName} in version-aware logic such as that in NixOS.
Strictness can creep in through optional attributes, or assertions and warnings that run as part of code that shouldn't access what is checked.
'';
in
{
kernelPatches = throw (explain "kernelPatches");
structuredExtraConfig = throw (explain "structuredExtraConfig");
modDirVersion = throw (explain "modDirVersion");
}
)
)).version
emptyFile;
in
{
inherit versionDoesNotDependOnPatchesEtc;
testsForKernel = nixosTests.kernel-generic.passthru.testsForKernel overridableKernel;
# Disabled by default, because the infinite recursion is hard to understand. The other test's error is better and produces a shorter trace.
# inherit versionDoesNotDependOnPatchesEtcNixOS;
}
// kernelTests;
};
}
)
);
in
overridableKernel

View File

@@ -0,0 +1,325 @@
-----BEGIN PGP PUBLIC KEY BLOCK-----
Version: GnuPG v2
mQINBE64OEUBEADPS1v+zoCdKA6zyfUtVIaBoIwMhCibqurXi30tVoC9LgM6W1ve
HwPFukWq7DAS0mZUPE3mSV63JFLaTy0bY/6GO1D4wLdWZx4ppH7XKNCvKCbsi70k
UozFykNVf+83WEskuF1oYzXlF3aB5suz2IWJl7ey1EXgIpehwQaTJUA5JIWYFp9A
566LRNJefYMzUR33xc4dRKj6Etg0xdLVq7/vZoo8HpLCBGNWiP0AKqFWEwTg0xQL
7nsJA5tfJJdwAJvrzjpFsvb63PKG6waAtdHhON4q7E2Udak9fz2tRjxA5l9l2zXk
aqsysUzkxPhNjwMENoQ04KZg4aT+ZhhBzTowSWLp3KV2uaZ66kdPUO3s+/1bPp5/
N/IlykaUwyL773iYOZ5dOY/9hIuX/zssihcrGEMW6yIyZR5uKhzYdaM9ExTXP637
UccgNS9/pskPGPx/xK23NDCfeHzL9YHS5KokA2wb/b9hqpwvLaeblbMl2pt79F1R
ac+rZlrRyX3NvlTQP4hqM9Ei2YBAU7QFDJEjH8pVIceL7grxi1Ju1iD5QiSK+je5
Jj5EAikfwSeAttSzsqNvaXJHfABrv5mkkVt1z3icP3HIHTYnG+uj+t8kvW+o9/1i
pD6e6LUh4w5v1aY9kaK/M3+eBH59yNYI99crPUKUBVfW4gv4DBUJAQTWRQARAQAB
tDVMZXZlbnRlIFBvbHlhayAoYW50aHJheHgpIDxsZXZlbnRlQGxldmVudGVwb2x5
YWsubmV0PokCQQQTAQIAKwIbAwYLCQgHAwIGFQgCCQoLBBYCAwECHgECF4ACGQEF
AlSXU9QFCQfATw8ACgkQ/BtUfI2BcsjPbxAAs+UR/bJz/HeYTpPy+HnKwDJgI9GP
AZlNvp+QSIhOTtKCYkQ/Iu+5scY5J0Qyv0pcJW5Rxjx+l7KGovw84jzVznnYsJoy
UQ5H3Ev9T2xW1nrZT3abJ7j6ZIck+Q+WFHu5Plsq6doSXOXmJNoehvT3BVolvc6w
S1+CAoyA5Wm1yfocZgVOvWPWQaa1T4XA7OwxFWrvNWEZwAzTSjkGHkwmji+DxdBd
RPam9+qm/rcN1IJTu6xJPr38a9LydWonsUpTR2Qn7Bo4EJp8yHJLaiLEMV/Nmgrr
1orBYw/OzDzhbdMl+2zzwEBLUMPABdgnPM6ZCZ5PWyWnCU4jsBGyVd0IC5xEu3Eg
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
a6MNZO/+vKN4UTlgjpjxZon+/yK8bsmT/VNie5hzqZim6tfztl3rpJ9jPUeLgr5x
oGePYV02inapzNHdWFHk0L9zR/3KKfJ3IRJwUXp00Eya28hEepIvdxgLYcN1UqVn
VuFuMY8zYSl/VXtPxySCLENJHxvdtClMZXZlbnRlIFBvbHlhayA8bGV2ZW50ZUBs
ZXZlbnRlcG9seWFrLmRlPokCPgQTAQIAKAIbAwYLCQgHAwIGFQgCCQoLBBYCAwEC
HgECF4AFAlSXU9oFCQfATw8ACgkQ/BtUfI2BcsiPxw//X2xUctIrd1O7UOk7LHBX
/xI7xXoWQcA7l/1XMuZhM8yC8yIoAgvFrWBP1a29I0P3/yigkQXs+eTDTdvb0QP2
q72q7Azt852v5u8+dHzoOXDpbo+4lfX+0OBDWimwJuChD8LQH7b7jO0oqWIV0AzM
vegFJVp3cDbyqw08lBz3xZ79A9JtBeewf6PLpXKjEVS8bEAZjZKjsjAY+5ShtJAf
PsD8r353dmkaHgC5Aji74ijZeY3PUCvGVVCGeN9isLnRpTEn7qUvN2DfHJU4w6aw
sXu7m7zidISo6dQLUzo54dHKWPGFy6INNkzXPOgrlbYnjt7v0Ou21/R6HrhdmsSw
lt7GALJcgAUxrcT/ljB3SZhSB0BdH0DXPcUziEdfhgMhhrXYpMjwH2XFBD1MLusW
GaVDbpPrSoEnmPVePcDUonDHePcuLjfOl13mOER1Kf6WFapOCa+4HCLakfKcPnGY
eyfD7Dbz3/046MmfQ8/Iyf8ipFXN6tI2WkRKj8uq9IFYrX3yoCBxZJN837DM3Grq
h48/T3pYU1f9LiekxbsgXmcHoGNdXX5+EsuO+QILZPttlG5QLuqFdJHei77uvW+B
4u8mgzi1Zhh0hRLm4K6UaJ/fBJ87BZSHShPKI9PI073U1O/CcYXnb8cdPLu3UgSQ
FM/bxT70TSYKI01Dt4KXRfWIRgQQEQIABgUCTrg/KAAKCRC+dA9BPyK7GT9FAJ47
X5+0dQaOFkfy3WnMgX3AmIXJYQCfR4XL47rZ9a66jWaD0IbcXMK4oE2JAj4EEwEC
ACgFAk64PJ4CGwMFCQIchwAGCwkIBwMCBhUIAgkKCwQWAgMBAh4BAheAAAoJEPwb
VHyNgXLI2U8QAJGKPv1gWLn7P1KeHVsKkfRf+zgdsoY4mF3bUjX/03z1h1OKp+S7
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
kekzzVjVTZxOgZE=
=yRuG
-----END PGP PUBLIC KEY BLOCK-----

View File

@@ -0,0 +1,113 @@
# Based on recommendations from:
# http://kernsec.org/wiki/index.php/Kernel_Self_Protection_Project#Recommended_settings
# https://wiki.gentoo.org/wiki/Hardened/Hardened_Kernel_Project
#
# Dangerous features that can be permanently (for the boot session) disabled at
# boot via sysctl or kernel cmdline are left enabled here, for improved
# flexibility.
#
# See also <nixos/modules/profiles/hardened.nix>
{
stdenv,
lib,
version,
}:
with lib.kernel;
with (lib.kernel.whenHelpers version);
assert (lib.versionAtLeast version "4.9");
{
# Mark LSM hooks read-only after init. SECURITY_WRITABLE_HOOKS n
# conflicts with SECURITY_SELINUX_DISABLE y; disabling the latter
# implicitly marks LSM hooks read-only after init.
#
# SELinux can only be disabled at boot via selinux=0
#
# We set SECURITY_WRITABLE_HOOKS n primarily for documentation purposes; the
# config builder fails to detect that it has indeed been unset.
SECURITY_SELINUX_DISABLE = whenOlder "6.4" no; # On 6.4: error: unused option: SECURITY_SELINUX_DISABLE
SECURITY_WRITABLE_HOOKS = option no;
# Perform additional validation of commonly targeted structures.
DEBUG_CREDENTIALS = whenOlder "6.6" yes;
DEBUG_NOTIFIERS = yes;
DEBUG_PI_LIST = whenOlder "5.2" yes; # doesn't BUG()
DEBUG_PLIST = whenAtLeast "5.2" yes;
DEBUG_SG = yes;
DEBUG_VIRTUAL = yes;
SCHED_STACK_END_CHECK = yes;
REFCOUNT_FULL = whenOlder "5.4.208" yes;
# tell EFI to wipe memory during reset
# https://lwn.net/Articles/730006/
RESET_ATTACK_MITIGATION = yes;
# restricts loading of line disciplines via TIOCSETD ioctl to CAP_SYS_MODULE
CONFIG_LDISC_AUTOLOAD = option no;
# Wipe higher-level memory allocations on free() with page_poison=1
PAGE_POISONING_NO_SANITY = whenOlder "5.11" yes;
PAGE_POISONING_ZERO = whenOlder "5.11" yes;
# Enable init_on_free by default
INIT_ON_FREE_DEFAULT_ON = whenAtLeast "5.3" yes;
# Wipe all caller-used registers on exit from a function
ZERO_CALL_USED_REGS = whenAtLeast "5.15" yes;
# Enable the SafeSetId LSM
SECURITY_SAFESETID = whenAtLeast "5.1" yes;
# Reboot devices immediately if kernel experiences an Oops.
PANIC_TIMEOUT = freeform "-1";
GCC_PLUGINS = yes; # Enable gcc plugin options
GCC_PLUGIN_STRUCTLEAK = option yes; # A port of the PaX structleak plugin
GCC_PLUGIN_STRUCTLEAK_BYREF_ALL = option yes; # Also cover structs passed by address
GCC_PLUGIN_STACKLEAK = whenAtLeast "4.20" yes; # A port of the PaX stackleak plugin
GCC_PLUGIN_RANDSTRUCT = whenOlder "5.19" yes; # A port of the PaX randstruct plugin
GCC_PLUGIN_RANDSTRUCT_PERFORMANCE = whenOlder "5.19" yes;
# Runtime undefined behaviour checks
# https://www.kernel.org/doc/html/latest/dev-tools/ubsan.html
# https://developers.redhat.com/blog/2014/10/16/gcc-undefined-behavior-sanitizer-ubsan
UBSAN = yes;
UBSAN_TRAP = whenAtLeast "5.7" yes;
UBSAN_BOUNDS = whenAtLeast "5.7" yes;
UBSAN_SANITIZE_ALL = whenOlder "6.9" yes;
UBSAN_LOCAL_BOUNDS = option yes; # clang only
CFI_CLANG = option yes; # clang only Control Flow Integrity since 6.1
# Disable various dangerous settings
ACPI_CUSTOM_METHOD = whenOlder "6.9" no; # Allows writing directly to physical memory
PROC_KCORE = no; # Exposes kernel text image layout
INET_DIAG = no; # Has been used for heap based attacks in the past
# INET_DIAG=n causes the following options to not exist anymore, but since they are defined in common-config.nix,
# make them optional
INET_DIAG_DESTROY = option no;
INET_RAW_DIAG = option no;
INET_TCP_DIAG = option no;
INET_UDP_DIAG = option no;
INET_MPTCP_DIAG = option no;
# Use -fstack-protector-strong (gcc 4.9+) for best stack canary coverage.
CC_STACKPROTECTOR_REGULAR = lib.mkForce (whenOlder "4.18" no);
CC_STACKPROTECTOR_STRONG = whenOlder "4.18" yes;
# CONFIG_DEVMEM=n causes these to not exist anymore.
STRICT_DEVMEM = option no;
IO_STRICT_DEVMEM = option no;
# stricter IOMMU TLB invalidation
IOMMU_DEFAULT_DMA_STRICT = option yes;
IOMMU_DEFAULT_DMA_LAZY = option no;
# not needed for less than a decade old glibc versions
LEGACY_VSYSCALL_NONE = lib.mkIf stdenv.hostPlatform.isx86 yes;
}

View File

@@ -0,0 +1,12 @@
{
"6.12": {
"patch": {
"extra": "-hardened1",
"name": "linux-hardened-v6.12.43-hardened1.patch",
"sha256": "10hp4718agz7bj4wnis7g1c8ahnwn5917a5v88y9iwawrjm9148v",
"url": "https://github.com/anthraxx/linux-hardened/releases/download/v6.12.43-hardened1/linux-hardened-v6.12.43-hardened1.patch"
},
"sha256": "1vmxywg11z946i806sg7rk7jr9px87spmwwbzjxpps2nsjybpjqg",
"version": "6.12.43"
}
}

View File

@@ -0,0 +1,301 @@
#! /usr/bin/env nix-shell
#! nix-shell -i python -p "python3.withPackages (ps: [ps.pygithub ps.packaging])" git gnupg
# This is automatically called by ../update.sh.
from __future__ import annotations
import json
import os
import re
import subprocess
import sys
from dataclasses import dataclass
from pathlib import Path
from tempfile import TemporaryDirectory
from typing import (
Dict,
Iterator,
List,
Optional,
Sequence,
Tuple,
TypedDict,
Union,
)
from github import Github
from github.GitRelease import GitRelease
from packaging.version import parse as parse_version, Version
VersionComponent = Union[int, str]
Version = List[VersionComponent]
PatchData = TypedDict("PatchData", {"name": str, "url": str, "sha256": str, "extra": str})
Patch = TypedDict("Patch", {
"patch": PatchData,
"version": str,
"sha256": str,
})
def read_min_kernel_branch() -> List[str]:
with open(NIXPKGS_KERNEL_PATH / "kernels-org.json") as f:
return list(parse_version(sorted(json.load(f).keys())[0]).release)
@dataclass
class ReleaseInfo:
version: Version
release: GitRelease
HERE = Path(__file__).resolve().parent
NIXPKGS_KERNEL_PATH = HERE.parent
NIXPKGS_PATH = HERE.parents[4]
HARDENED_GITHUB_REPO = "anthraxx/linux-hardened"
HARDENED_TRUSTED_KEY = HERE / "anthraxx.asc"
HARDENED_PATCHES_PATH = HERE / "patches.json"
MIN_KERNEL_VERSION: Version = read_min_kernel_branch()
def run(*args: Union[str, Path]) -> subprocess.CompletedProcess[bytes]:
try:
return subprocess.run(
args,
check=True,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
encoding="utf-8",
)
except subprocess.CalledProcessError as err:
print(
f"error: `{err.cmd}` failed unexpectedly\n"
f"status code: {err.returncode}\n"
f"stdout:\n{err.stdout.strip()}\n"
f"stderr:\n{err.stderr.strip()}",
file=sys.stderr,
)
sys.exit(1)
def nix_prefetch_url(url: str) -> Tuple[str, Path]:
output = run("nix-prefetch-url", "--print-path", url).stdout
sha256, path = output.strip().split("\n")
return sha256, Path(path)
def verify_openpgp_signature(
*, name: str, trusted_key: Path, sig_path: Path, data_path: Path,
) -> bool:
with TemporaryDirectory(suffix=".nixpkgs-gnupg-home") as gnupg_home_str:
gnupg_home = Path(gnupg_home_str)
run("gpg", "--homedir", gnupg_home, "--import", trusted_key)
keyring = gnupg_home / "pubring.kbx"
try:
subprocess.run(
("gpgv", "--keyring", keyring, sig_path, data_path),
check=True,
stderr=subprocess.PIPE,
encoding="utf-8",
)
return True
except subprocess.CalledProcessError as err:
print(
f"error: signature for {name} failed to verify!",
file=sys.stderr,
)
print(err.stderr, file=sys.stderr, end="")
return False
def fetch_patch(*, name: str, release_info: ReleaseInfo) -> Optional[Patch]:
release = release_info.release
extra = f'-{release_info.version[-1]}'
def find_asset(filename: str) -> str:
try:
it: Iterator[str] = (
asset.browser_download_url
for asset in release.get_assets()
if asset.name == filename
)
return next(it)
except StopIteration:
raise KeyError(filename)
patch_filename = f"{name}.patch"
try:
patch_url = find_asset(patch_filename)
sig_url = find_asset(patch_filename + ".sig")
except KeyError:
print(f"error: {patch_filename}{{,.sig}} not present", file=sys.stderr)
return None
sha256, patch_path = nix_prefetch_url(patch_url)
_, sig_path = nix_prefetch_url(sig_url)
sig_ok = verify_openpgp_signature(
name=name,
trusted_key=HARDENED_TRUSTED_KEY,
sig_path=sig_path,
data_path=patch_path,
)
if not sig_ok:
return None
kernel_ver = re.sub(r"v?(.*)(-hardened[\d]+)$", r'\1', release_info.release.tag_name)
major = kernel_ver.split('.')[0]
sha256_kernel, _ = nix_prefetch_url(f"mirror://kernel/linux/kernel/v{major}.x/linux-{kernel_ver}.tar.xz")
return Patch(
patch=PatchData(name=patch_filename, url=patch_url, sha256=sha256, extra=extra),
version=kernel_ver,
sha256=sha256_kernel
)
def normalize_kernel_version(version_str: str) -> list[str|int]:
# There have been two variants v6.10[..] and 6.10[..], drop the v
version_str_without_v = version_str[1:] if not version_str[0].isdigit() else version_str
version: list[str|int] = []
for component in re.split(r'\.|\-', version_str_without_v):
try:
version.append(int(component))
except ValueError:
version.append(component)
return version
def version_string(version: Version) -> str:
return ".".join(str(component) for component in version)
def major_kernel_version_key(kernel_version: list[int|str]) -> str:
return version_string(kernel_version[:-1])
def commit_patches(*, kernel_key: Version, message: str) -> None:
new_patches_path = HARDENED_PATCHES_PATH.with_suffix(".new")
with open(new_patches_path, "w") as new_patches_file:
json.dump(patch_json, new_patches_file, indent=4, sort_keys=True)
new_patches_file.write("\n")
os.rename(new_patches_path, HARDENED_PATCHES_PATH)
message = f"linux/hardened/patches/{kernel_key}: {message}"
print(message)
if os.environ.get("COMMIT"):
run(
"git",
"-C",
NIXPKGS_PATH,
"commit",
f"--message={message}",
HARDENED_PATCHES_PATH,
)
# Load the existing patches.
with open(HARDENED_PATCHES_PATH) as patches_file:
patch_json = json.load(patches_file)
patch_versions = set([parse_version(k) for k in patch_json.keys()])
with open(NIXPKGS_KERNEL_PATH / "kernels-org.json") as kernel_versions_json:
kernel_versions = json.load(kernel_versions_json)
kernels = {
parse_version(version): meta
for version, meta in kernel_versions.items()
if version != "testing"
}
latest_lts = sorted(ver for ver, meta in kernels.items() if meta.get("lts", False))[-1]
keys = sorted(kernels.keys())
latest_release = keys[-1]
fallback = keys[-2]
g = Github(os.environ.get("GITHUB_TOKEN"))
repo = g.get_repo(HARDENED_GITHUB_REPO)
failures = False
all_candidates = set([latest_lts, latest_release, fallback])
kernels_to_package = {}
for release in repo.get_releases()[:30]:
version = normalize_kernel_version(release.tag_name)
# needs to look like e.g. 5.6.3-hardened1
if len(version) < 4:
continue
if not (isinstance(version[-2], int)):
continue
kernel_version = version[:-1]
kernel_key = parse_version(major_kernel_version_key(kernel_version))
if kernel_key not in all_candidates:
continue
try:
found = kernels_to_package[kernel_key]
if found.version > version:
continue
except KeyError:
pass
kernels_to_package[kernel_key] = ReleaseInfo(version=version, release=release)
if latest_release in kernels_to_package:
if fallback != latest_lts:
del kernels_to_package[fallback]
kernel_versions = set([latest_lts, latest_release])
else:
kernel_versions = set([latest_lts, fallback])
# Remove patches for unpackaged kernel versions.
removals = False
for kernel_key in sorted(patch_versions - kernels_to_package.keys()):
del patch_json[str(kernel_key)]
removals = True
commit_patches(kernel_key=kernel_key, message="remove")
# Update hardened-patches.json for each release.
for kernel_key in sorted(kernels_to_package.keys()):
release_info = kernels_to_package[kernel_key]
release = release_info.release
version = release_info.version
version_str = release.tag_name
name = f"linux-hardened-{version_str}"
old_version: Optional[list[int|str]] = None
old_version_str: Optional[str] = None
update: bool
try:
old_filename = patch_json[str(kernel_key)]["patch"]["name"]
old_version_str = old_filename.replace("linux-hardened-", "").replace(
".patch", ""
)
old_version = normalize_kernel_version(old_version_str)
update = old_version < version
except KeyError:
update = True
if update:
patch = fetch_patch(name=name, release_info=release_info)
if patch is None:
failures = True
else:
if str(kernel_key) in patch_json:
message = f"{old_version_str} -> {version_str}"
else:
message = f"init at {version_str}"
patch_json[str(kernel_key)] = patch
commit_patches(kernel_key=kernel_key, message=message)
if removals:
print("Hardened kernels were removed. Don't forget to remove their attributes!")
if failures:
sys.exit(1)

View File

@@ -0,0 +1,58 @@
{
lib,
stdenv,
graphviz,
imagemagick,
linux_latest,
makeFontsConf,
perl,
python3,
which,
}:
stdenv.mkDerivation {
pname = "linux-kernel-latest-htmldocs";
inherit (linux_latest) version src;
postPatch = ''
patchShebangs \
Documentation/sphinx/parse-headers.pl \
scripts/{get_abi.pl,get_feat.pl,kernel-doc,sphinx-pre-install} \
tools/net/ynl/pyynl/ynl_gen_rst.py
'';
FONTCONFIG_FILE = makeFontsConf {
fontDirectories = [ ];
};
nativeBuildInputs = [
graphviz
imagemagick
perl
python3.pkgs.sphinx
python3.pkgs.sphinx-rtd-theme
python3.pkgs.pyyaml
which
];
preBuild = ''
export XDG_CACHE_HOME="$(mktemp -d)"
'';
makeFlags = [ "htmldocs" ];
installPhase = ''
mkdir -p $out/share/doc
mv Documentation/output $out/share/doc/linux-doc
cp -r Documentation/* $out/share/doc/linux-doc/
'';
meta = {
description = "Linux kernel html documentation";
homepage = "https://www.kernel.org/doc/htmldocs/";
platforms = lib.platforms.linux;
inherit (linux_latest.meta) license;
maintainers = with lib.maintainers; [ sigmanificient ];
};
}

View File

@@ -0,0 +1,47 @@
{
"testing": {
"version": "6.17-rc7",
"hash": "sha256:11bjz14ncfbnz3h9a4vk71av664xrx1kh28i22w7yg6g46hifq65",
"lts": false
},
"6.1": {
"version": "6.1.155",
"hash": "sha256:0wsw99h2jsrcx9fff59nqjx66l40vywj8qi3j6yvqpq8xsp8g4y2",
"lts": true
},
"5.15": {
"version": "5.15.194",
"hash": "sha256:0zi6ihvjmaf940arnc7jjvdqrjf3cvkc9mqc8n24dz85vam6z39l",
"lts": true
},
"5.10": {
"version": "5.10.245",
"hash": "sha256:17wxs8i8vd5ivv99ra0sri3wmkw5c22wsaw8nf1xcvys2kmpa7hk",
"lts": true
},
"5.4": {
"version": "5.4.300",
"hash": "sha256:0nl1l689d4jq2l39v816yy7z5lzc5dvv8aqn85xlv4najc022jcr",
"lts": true
},
"6.6": {
"version": "6.6.110",
"hash": "sha256:07gv37ralrhf709plqj1hzk1adwilh6znmay6agpbf23anphvwhv",
"lts": true
},
"6.12": {
"version": "6.12.51",
"hash": "sha256:08bj3b6a6jwvrpjl5sxvmzwwnc00clq98rjwb61fznd7khaasm9d",
"lts": true
},
"6.16": {
"version": "6.16.11",
"hash": "sha256:0yxsinhly689327jbvwm2nfr6cx7ynj9sd87a9var1rx8l64yc2z",
"lts": false
},
"6.17": {
"version": "6.17.1",
"hash": "sha256:182d9xf7j0n4cn61rsqs87al9xc83rawri8p3yk246a984zvwgd5",
"lts": false
}
}

View File

@@ -0,0 +1,106 @@
{
stdenv,
lib,
fetchFromGitHub,
buildLinux,
rpiVersion,
...
}@args:
let
# NOTE: raspberrypifw & raspberryPiWirelessFirmware should be updated with this
modDirVersion = "6.12.47";
tag = "stable_20250916";
hash = "sha256-HG8Oc04V2t54l0SOn4gKmNJWQUrZfjWusgKcWvx74H0==";
in
lib.overrideDerivation
(buildLinux (
args
// {
version = "${modDirVersion}-${tag}";
inherit modDirVersion;
pname = "linux-rpi";
src = fetchFromGitHub {
owner = "raspberrypi";
repo = "linux";
inherit tag hash;
};
defconfig =
{
"1" = "bcmrpi_defconfig";
"2" = "bcm2709_defconfig";
"3" = if stdenv.hostPlatform.isAarch64 then "bcm2711_defconfig" else "bcm2709_defconfig";
"4" = "bcm2711_defconfig";
}
.${toString rpiVersion};
features = {
efiBootStub = false;
}
// (args.features or { });
isLTS = true;
extraMeta =
if (rpiVersion < 3) then
{
platforms = with lib.platforms; lib.intersectLists arm linux;
hydraPlatforms = [ ];
}
else
{
platforms = with lib.platforms; lib.intersectLists (arm ++ aarch64) linux;
hydraPlatforms = [ "aarch64-linux" ];
};
ignoreConfigErrors = true;
}
// (args.argsOverride or { })
))
(oldAttrs: {
postConfigure = ''
# The v7 defconfig has this set to '-v7' which screws up our modDirVersion.
sed -i $buildRoot/.config -e 's/^CONFIG_LOCALVERSION=.*/CONFIG_LOCALVERSION=""/'
sed -i $buildRoot/include/config/auto.conf -e 's/^CONFIG_LOCALVERSION=.*/CONFIG_LOCALVERSION=""/'
'';
# Make copies of the DTBs named after the upstream names so that U-Boot finds them.
# This is ugly as heck, but I don't know a better solution so far.
postFixup = ''
dtbDir=${if stdenv.hostPlatform.isAarch64 then "$out/dtbs/broadcom" else "$out/dtbs"}
rm $dtbDir/bcm283*.dtb
copyDTB() {
cp -v "$dtbDir/$1" "$dtbDir/$2"
}
''
+ lib.optionalString (lib.elem stdenv.hostPlatform.system [ "armv6l-linux" ]) ''
copyDTB bcm2708-rpi-zero-w.dtb bcm2835-rpi-zero.dtb
copyDTB bcm2708-rpi-zero-w.dtb bcm2835-rpi-zero-w.dtb
copyDTB bcm2708-rpi-b.dtb bcm2835-rpi-a.dtb
copyDTB bcm2708-rpi-b.dtb bcm2835-rpi-b.dtb
copyDTB bcm2708-rpi-b.dtb bcm2835-rpi-b-rev2.dtb
copyDTB bcm2708-rpi-b-plus.dtb bcm2835-rpi-a-plus.dtb
copyDTB bcm2708-rpi-b-plus.dtb bcm2835-rpi-b-plus.dtb
copyDTB bcm2708-rpi-b-plus.dtb bcm2835-rpi-zero.dtb
copyDTB bcm2708-rpi-cm.dtb bcm2835-rpi-cm.dtb
''
+ lib.optionalString (lib.elem stdenv.hostPlatform.system [ "armv7l-linux" ]) ''
copyDTB bcm2709-rpi-2-b.dtb bcm2836-rpi-2-b.dtb
''
+
lib.optionalString
(lib.elem stdenv.hostPlatform.system [
"armv7l-linux"
"aarch64-linux"
])
''
copyDTB bcm2710-rpi-zero-2.dtb bcm2837-rpi-zero-2.dtb
copyDTB bcm2710-rpi-zero-2-w.dtb bcm2837-rpi-zero-2-w.dtb
copyDTB bcm2710-rpi-3-b.dtb bcm2837-rpi-3-b.dtb
copyDTB bcm2710-rpi-3-b-plus.dtb bcm2837-rpi-3-a-plus.dtb
copyDTB bcm2710-rpi-3-b-plus.dtb bcm2837-rpi-3-b-plus.dtb
copyDTB bcm2710-rpi-cm3.dtb bcm2837-rpi-cm3.dtb
copyDTB bcm2711-rpi-4-b.dtb bcm2838-rpi-4-b.dtb
'';
})

View File

@@ -0,0 +1,62 @@
{
lib,
buildLinux,
fetchurl,
kernelPatches ? [ ],
structuredExtraConfig ? { },
extraMeta ? { },
argsOverride ? { },
...
}@args:
let
version = "5.10.240-rt134"; # updated by ./update-rt.sh
branch = lib.versions.majorMinor version;
kversion = builtins.elemAt (lib.splitString "-" version) 0;
in
buildLinux (
args
// {
inherit version;
pname = "linux-rt";
# modDirVersion needs a patch number, change X.Y-rtZ to X.Y.0-rtZ.
modDirVersion = lib.versions.pad 3 version;
src = fetchurl {
url = "mirror://kernel/linux/kernel/v5.x/linux-${kversion}.tar.xz";
sha256 = "04sdcf4aqsqchii38anzmk9f9x65wv8q1x3m9dandmi6fabw724d";
};
kernelPatches =
let
rt-patch = {
name = "rt";
patch = fetchurl {
url = "mirror://kernel/linux/kernel/projects/rt/${branch}/older/patch-${version}.patch.xz";
sha256 = "0f2wq6w0707qn798a9lk7r31mfmdll6xwnxq8fy86574gl08ah79";
};
};
in
[ rt-patch ] ++ kernelPatches;
isLTS = true;
structuredExtraConfig =
with lib.kernel;
{
PREEMPT_RT = yes;
# Fix error: unused option: PREEMPT_RT.
EXPERT = yes; # PREEMPT_RT depends on it (in kernel/Kconfig.preempt)
# Fix error: option not set correctly: PREEMPT_VOLUNTARY (wanted 'y', got 'n').
PREEMPT_VOLUNTARY = lib.mkForce no; # PREEMPT_RT deselects it.
# Fix error: unused option: RT_GROUP_SCHED.
RT_GROUP_SCHED = lib.mkForce (option no); # Removed by sched-disable-rt-group-sched-on-rt.patch.
}
// structuredExtraConfig;
extraMeta = extraMeta // {
inherit branch;
};
}
// argsOverride
)

View File

@@ -0,0 +1,67 @@
{
lib,
buildLinux,
fetchurl,
kernelPatches ? [ ],
structuredExtraConfig ? { },
extraMeta ? { },
argsOverride ? { },
...
}@args:
let
version = "5.15.189-rt87"; # updated by ./update-rt.sh
branch = lib.versions.majorMinor version;
kversion = builtins.elemAt (lib.splitString "-" version) 0;
in
buildLinux (
args
// {
inherit version;
pname = "linux-rt";
# modDirVersion needs a patch number, change X.Y-rtZ to X.Y.0-rtZ.
modDirVersion =
if (builtins.match "[^.]*[.][^.]*-.*" version) == null then
version
else
lib.replaceStrings [ "-" ] [ ".0-" ] version;
src = fetchurl {
url = "mirror://kernel/linux/kernel/v5.x/linux-${kversion}.tar.xz";
sha256 = "1hshd26ahn6dbw6jnqi0v5afpk672w7p09mk7iri93i7hxdh5l73";
};
kernelPatches =
let
rt-patch = {
name = "rt";
patch = fetchurl {
url = "mirror://kernel/linux/kernel/projects/rt/${branch}/older/patch-${version}.patch.xz";
sha256 = "151vznvdcdmjsjsz3b4hfxw1v2jyigrh34k2qyxk3fkqg999fx9w";
};
};
in
[ rt-patch ] ++ kernelPatches;
structuredExtraConfig =
with lib.kernel;
{
PREEMPT_RT = yes;
# Fix error: unused option: PREEMPT_RT.
EXPERT = yes; # PREEMPT_RT depends on it (in kernel/Kconfig.preempt)
# Fix error: option not set correctly: PREEMPT_VOLUNTARY (wanted 'y', got 'n').
PREEMPT_VOLUNTARY = lib.mkForce no; # PREEMPT_RT deselects it.
# Fix error: unused option: RT_GROUP_SCHED.
RT_GROUP_SCHED = lib.mkForce (option no); # Removed by sched-disable-rt-group-sched-on-rt.patch.
}
// structuredExtraConfig;
isLTS = true;
extraMeta = extraMeta // {
inherit branch;
};
}
// argsOverride
)

View File

@@ -0,0 +1,60 @@
{
lib,
buildLinux,
fetchurl,
kernelPatches ? [ ],
structuredExtraConfig ? { },
extraMeta ? { },
argsOverride ? { },
...
}@args:
let
version = "5.4.296-rt100"; # updated by ./update-rt.sh
branch = lib.versions.majorMinor version;
kversion = builtins.elemAt (lib.splitString "-" version) 0;
in
buildLinux (
args
// {
inherit version;
pname = "linux-rt";
src = fetchurl {
url = "mirror://kernel/linux/kernel/v5.x/linux-${kversion}.tar.xz";
sha256 = "0fm73yqzbzclh2achcj8arpg428d412k2wgmlfmyy6xzb1762qrx";
};
kernelPatches =
let
rt-patch = {
name = "rt";
patch = fetchurl {
url = "mirror://kernel/linux/kernel/projects/rt/${branch}/older/patch-${version}.patch.xz";
sha256 = "0ggmgkhmnvx4xxb3smfdcafqr9m3qdyc40xp3h7586p4n3wwpw9d";
};
};
in
[ rt-patch ] ++ kernelPatches;
structuredExtraConfig =
with lib.kernel;
{
PREEMPT_RT = yes;
# Fix error: unused option: PREEMPT_RT.
EXPERT = yes; # PREEMPT_RT depends on it (in kernel/Kconfig.preempt)
# Fix error: option not set correctly: PREEMPT_VOLUNTARY (wanted 'y', got 'n').
PREEMPT_VOLUNTARY = lib.mkForce no; # PREEMPT_RT deselects it.
# Fix error: unused option: RT_GROUP_SCHED.
RT_GROUP_SCHED = lib.mkForce (option no); # Removed by sched-disable-rt-group-sched-on-rt.patch.
}
// structuredExtraConfig;
isLTS = true;
extraMeta = extraMeta // {
inherit branch;
};
}
// argsOverride
)

View File

@@ -0,0 +1,67 @@
{
lib,
buildLinux,
fetchurl,
kernelPatches ? [ ],
structuredExtraConfig ? { },
extraMeta ? { },
argsOverride ? { },
...
}@args:
let
version = "6.1.146-rt53"; # updated by ./update-rt.sh
branch = lib.versions.majorMinor version;
kversion = builtins.elemAt (lib.splitString "-" version) 0;
in
buildLinux (
args
// {
inherit version;
pname = "linux-rt";
# modDirVersion needs a patch number, change X.Y-rtZ to X.Y.0-rtZ.
modDirVersion =
if (builtins.match "[^.]*[.][^.]*-.*" version) == null then
version
else
lib.replaceStrings [ "-" ] [ ".0-" ] version;
src = fetchurl {
url = "mirror://kernel/linux/kernel/v6.x/linux-${kversion}.tar.xz";
sha256 = "117gyi8zym09z2qarnv02i7v23v8596nqvllid07aydlcpihl9pv";
};
kernelPatches =
let
rt-patch = {
name = "rt";
patch = fetchurl {
url = "mirror://kernel/linux/kernel/projects/rt/${branch}/older/patch-${version}.patch.xz";
sha256 = "1kz416nc8hd2pi87l9k496r2lig07dbapyh701lq81rilbzx9nmc";
};
};
in
[ rt-patch ] ++ kernelPatches;
structuredExtraConfig =
with lib.kernel;
{
PREEMPT_RT = yes;
# Fix error: unused option: PREEMPT_RT.
EXPERT = yes; # PREEMPT_RT depends on it (in kernel/Kconfig.preempt)
# Fix error: option not set correctly: PREEMPT_VOLUNTARY (wanted 'y', got 'n').
PREEMPT_VOLUNTARY = lib.mkForce no; # PREEMPT_RT deselects it.
# Fix error: unused option: RT_GROUP_SCHED.
RT_GROUP_SCHED = lib.mkForce (option no); # Removed by sched-disable-rt-group-sched-on-rt.patch.
}
// structuredExtraConfig;
extraMeta = extraMeta // {
inherit branch;
};
isLTS = true;
}
// argsOverride
)

View File

@@ -0,0 +1,67 @@
{
lib,
buildLinux,
fetchurl,
kernelPatches ? [ ],
structuredExtraConfig ? { },
extraMeta ? { },
argsOverride ? { },
...
}@args:
let
version = "6.6.101-rt59"; # updated by ./update-rt.sh
branch = lib.versions.majorMinor version;
kversion = builtins.elemAt (lib.splitString "-" version) 0;
in
buildLinux (
args
// {
inherit version;
pname = "linux-rt";
# modDirVersion needs a patch number, change X.Y-rtZ to X.Y.0-rtZ.
modDirVersion =
if (builtins.match "[^.]*[.][^.]*-.*" version) == null then
version
else
lib.replaceStrings [ "-" ] [ ".0-" ] version;
src = fetchurl {
url = "mirror://kernel/linux/kernel/v6.x/linux-${kversion}.tar.xz";
sha256 = "1h71zbqlsxcafrk218s0rip9rdrj0fzqvsl81ndqnlrnjy3g4kwc";
};
kernelPatches =
let
rt-patch = {
name = "rt";
patch = fetchurl {
url = "mirror://kernel/linux/kernel/projects/rt/${branch}/older/patch-${version}.patch.xz";
sha256 = "0w71nl8s0npcz6x3qavl5j3vcqwd5wcqx4dj5ck2qs7bzv9kbrwb";
};
};
in
[ rt-patch ] ++ kernelPatches;
structuredExtraConfig =
with lib.kernel;
{
PREEMPT_RT = yes;
# Fix error: unused option: PREEMPT_RT.
EXPERT = yes; # PREEMPT_RT depends on it (in kernel/Kconfig.preempt)
# Fix error: option not set correctly: PREEMPT_VOLUNTARY (wanted 'y', got 'n').
PREEMPT_VOLUNTARY = lib.mkForce no; # PREEMPT_RT deselects it.
# Fix error: unused option: RT_GROUP_SCHED.
RT_GROUP_SCHED = lib.mkForce (option no); # Removed by sched-disable-rt-group-sched-on-rt.patch.
}
// structuredExtraConfig;
extraMeta = extraMeta // {
inherit branch;
};
isLTS = true;
}
// argsOverride
)

View File

@@ -0,0 +1,42 @@
let
allKernels = builtins.fromJSON (builtins.readFile ./kernels-org.json);
in
{
branch,
lib,
fetchurl,
fetchzip,
buildLinux,
...
}@args:
let
thisKernel = allKernels.${branch};
inherit (thisKernel) version;
src =
# testing kernels are a special case because they don't have tarballs on the CDN
if branch == "testing" then
fetchzip {
url = "https://git.kernel.org/torvalds/t/linux-${version}.tar.gz";
inherit (thisKernel) hash;
}
else
fetchurl {
url = "mirror://kernel/linux/kernel/v${lib.versions.major version}.x/linux-${version}.tar.xz";
inherit (thisKernel) hash;
};
args' =
(removeAttrs args [ "branch" ])
// {
inherit src version;
isLTS = thisKernel.lts;
modDirVersion = lib.versions.pad 3 version;
extraMeta.branch = branch;
}
// (args.argsOverride or { });
in
buildLinux args'

View File

@@ -0,0 +1,607 @@
{
lib,
stdenv,
buildPackages,
bc,
bison,
flex,
perl,
rsync,
gmp,
libmpc,
mpfr,
openssl,
cpio,
elfutils,
hexdump,
zstd,
python3Minimal,
zlib,
pahole,
kmod,
ubootTools,
fetchpatch,
rustc-unwrapped,
rust-bindgen-unwrapped,
rustPlatform,
}:
let
lib_ = lib;
stdenv_ = stdenv;
readConfig =
configfile:
let
matchLine =
line:
let
match = lib.match "(CONFIG_[^=]+)=([ym])" line;
in
lib.optional (match != null) {
name = lib.elemAt match 0;
value = lib.elemAt match 1;
};
in
lib.listToAttrs (lib.concatMap matchLine (lib.splitString "\n" (builtins.readFile configfile)));
in
lib.makeOverridable (
{
# The kernel version
version,
# The kernel pname (should be set for variants)
pname ? "linux",
# Position of the Linux build expression
pos ? null,
# Additional kernel make flags
extraMakeFlags ? [ ],
# The name of the kernel module directory
# Needs to be X.Y.Z[-extra], so pad with zeros if needed.
modDirVersion ? null, # derive from version
# The kernel source (tarball, git checkout, etc.)
src,
# a list of { name=..., patch=..., extraConfig=...} patches
kernelPatches ? [ ],
# The kernel .config file
configfile,
# Manually specified nixexpr representing the config
# If unspecified, this will be autodetected from the .config
config ? lib.optionalAttrs (builtins.isPath configfile || allowImportFromDerivation) (
readConfig configfile
),
# Custom seed used for CONFIG_GCC_PLUGIN_RANDSTRUCT if enabled. This is
# automatically extended with extra per-version and per-config values.
randstructSeed ? "",
# Extra meta attributes
extraMeta ? { },
# for module compatibility
isZen ? false,
isLibre ? false,
isHardened ? false,
# Whether to utilize the controversial import-from-derivation feature to parse the config
allowImportFromDerivation ? false,
# ignored
features ? null,
lib ? lib_,
stdenv ? stdenv_,
}:
let
# Provide defaults. Note that we support `null` so that callers don't need to use optionalAttrs,
# which can lead to unnecessary strictness and infinite recursions.
modDirVersion_ = if modDirVersion == null then lib.versions.pad 3 version else modDirVersion;
in
let
# Shadow the un-defaulted parameter; don't want null.
modDirVersion = modDirVersion_;
inherit (lib)
hasAttr
getAttr
optional
optionals
optionalString
optionalAttrs
maintainers
teams
platforms
;
drvAttrs =
config_: kernelConf: kernelPatches: configfile:
let
# Folding in `ubootTools` in the default nativeBuildInputs is problematic, as
# it makes updating U-Boot cumbersome, since it will go above the current
# threshold of rebuilds
#
# To prevent these needless rounds of staging for U-Boot builds, we can
# limit the inclusion of ubootTools to target platforms where uImage *may*
# be produced.
#
# This command lists those (kernel-named) platforms:
# .../linux $ grep -l uImage ./arch/*/Makefile | cut -d'/' -f3 | sort
#
# This is still a guesstimation, but since none of our cached platforms
# coincide in that list, this gives us "perfect" decoupling here.
linuxPlatformsUsingUImage = [
"arc"
"arm"
"csky"
"mips"
"powerpc"
"sh"
"sparc"
"xtensa"
];
needsUbootTools = lib.elem stdenv.hostPlatform.linuxArch linuxPlatformsUsingUImage;
config =
let
attrName = attr: "CONFIG_" + attr;
in
{
isSet = attr: hasAttr (attrName attr) config;
getValue = attr: if config.isSet attr then getAttr (attrName attr) config else null;
isYes = attr: (config.getValue attr) == "y";
isNo = attr: (config.getValue attr) == "n";
isModule = attr: (config.getValue attr) == "m";
isEnabled = attr: (config.isModule attr) || (config.isYes attr);
isDisabled = attr: (!(config.isSet attr)) || (config.isNo attr);
}
// config_;
isModular = config.isYes "MODULES";
withRust = config.isYes "RUST";
buildDTBs = kernelConf.DTB or false;
# Dependencies that are required to build kernel modules
moduleBuildDependencies = [
pahole
perl
elfutils
# module makefiles often run uname commands to find out the kernel version
(buildPackages.deterministic-uname.override { inherit modDirVersion; })
]
++ optional (lib.versionAtLeast version "5.13") zstd
++ optionals withRust [
rustc-unwrapped
rust-bindgen-unwrapped
];
in
(optionalAttrs isModular {
outputs = [
"out"
"dev"
"modules"
];
})
// {
__structuredAttrs = true;
passthru = rec {
inherit
version
modDirVersion
config
kernelPatches
configfile
moduleBuildDependencies
stdenv
;
inherit
isZen
isHardened
isLibre
withRust
;
isXen = lib.warn "The isXen attribute is deprecated. All Nixpkgs kernels that support it now have Xen enabled." true;
baseVersion = lib.head (lib.splitString "-rc" version);
kernelOlder = lib.versionOlder baseVersion;
kernelAtLeast = lib.versionAtLeast baseVersion;
};
inherit src;
depsBuildBuild = [ buildPackages.stdenv.cc ];
nativeBuildInputs = [
bison
flex
perl
bc
openssl
rsync
gmp
libmpc
mpfr
elfutils
zstd
python3Minimal
kmod
hexdump
]
++ optional needsUbootTools ubootTools
++ optionals (lib.versionAtLeast version "5.2") [
cpio
pahole
zlib
]
++ optionals withRust [
rustc-unwrapped
rust-bindgen-unwrapped
];
env = {
RUST_LIB_SRC = lib.optionalString withRust rustPlatform.rustLibSrc;
# avoid leaking Rust source file names into the final binary, which adds
# a false dependency on rust-lib-src on targets with uncompressed kernels
KRUSTFLAGS = lib.optionalString withRust "--remap-path-prefix ${rustPlatform.rustLibSrc}=/";
};
patches =
# kernelPatches can contain config changes and no actual patch
lib.filter (p: p != null) (map (p: p.patch) kernelPatches)
# Required for deterministic builds along with some postPatch magic.
++ optional (lib.versionOlder version "5.19") ./randstruct-provide-seed.patch
++ optional (lib.versionAtLeast version "5.19") ./randstruct-provide-seed-5.19.patch
# Linux 5.12 marked certain PowerPC-only symbols as GPL, which breaks
# OpenZFS; this was fixed in Linux 5.19 so we backport the fix
# https://github.com/openzfs/zfs/pull/13367
++
optional
(
lib.versionAtLeast version "5.12" && lib.versionOlder version "5.19" && stdenv.hostPlatform.isPower
)
(fetchpatch {
url = "https://git.kernel.org/pub/scm/linux/kernel/git/powerpc/linux.git/patch/?id=d9e5c3e9e75162f845880535957b7fd0b4637d23";
hash = "sha256-bBOyJcP6jUvozFJU0SPTOf3cmnTQ6ZZ4PlHjiniHXLU=";
});
postPatch = ''
# Ensure that depmod gets resolved through PATH
sed -i Makefile -e 's|= /sbin/depmod|= depmod|'
# Some linux-hardened patches now remove certain files in the scripts directory, so the file may not exist.
[[ -f scripts/ld-version.sh ]] && patchShebangs scripts/ld-version.sh
# Set randstruct seed to a deterministic but diversified value. Note:
# we could have instead patched gen-random-seed.sh to take input from
# the buildFlags, but that would require also patching the kernel's
# toplevel Makefile to add a variable export. This would be likely to
# cause future patch conflicts.
for file in scripts/gen-randstruct-seed.sh scripts/gcc-plugins/gen-random-seed.sh; do
if [ -f "$file" ]; then
substituteInPlace "$file" \
--replace NIXOS_RANDSTRUCT_SEED \
$(echo ${randstructSeed}${src} ${placeholder "configfile"} | sha256sum | cut -d ' ' -f 1 | tr -d '\n')
break
fi
done
patchShebangs scripts
# also patch arch-specific install scripts
for i in $(find arch -name install.sh); do
patchShebangs "$i"
done
# unset $src because the build system tries to use it and spams a bunch of warnings
# see: https://github.com/torvalds/linux/commit/b1992c3772e69a6fd0e3fc81cd4d2820c8b6eca0
unset src
'';
configurePhase = ''
runHook preConfigure
mkdir build
export buildRoot="$(pwd)/build"
echo "manual-config configurePhase buildRoot=$buildRoot pwd=$PWD"
if [ -f "$buildRoot/.config" ]; then
echo "Could not link $buildRoot/.config : file exists"
exit 1
fi
ln -sv ${configfile} $buildRoot/.config
# reads the existing .config file and prompts the user for options in
# the current kernel source that are not found in the file.
make "''${makeFlags[@]}" oldconfig
runHook postConfigure
make "''${makeFlags[@]}" prepare
actualModDirVersion="$(cat $buildRoot/include/config/kernel.release)"
if [ "$actualModDirVersion" != "${modDirVersion}" ]; then
echo "Error: modDirVersion ${modDirVersion} specified in the Nix expression is wrong, it should be: $actualModDirVersion"
exit 1
fi
buildFlags+=("KBUILD_BUILD_TIMESTAMP=$(date -u -d @$SOURCE_DATE_EPOCH)")
cd $buildRoot
'';
buildFlags = [
"KBUILD_BUILD_VERSION=1-NixOS"
kernelConf.target
"vmlinux" # for "perf" and things like that
"scripts_gdb"
]
++ optional isModular "modules"
++ optionals buildDTBs [
"dtbs"
"DTC_FLAGS=-@"
]
++ extraMakeFlags;
installFlags = [
"INSTALL_PATH=${placeholder "out"}"
]
++ (optional isModular "INSTALL_MOD_PATH=${placeholder "modules"}")
++ optionals buildDTBs [
"dtbs_install"
"INSTALL_DTBS_PATH=${placeholder "out"}/dtbs"
];
preInstall =
let
# All we really need to do here is copy the final image and System.map to $out,
# and use the kernel's modules_install, firmware_install, dtbs_install, etc. targets
# for the rest. Easy, right?
#
# Unfortunately for us, the obvious way of getting the built image path,
# make -s image_name, does not work correctly, because some architectures
# (*cough* aarch64 *cough*) change KBUILD_IMAGE on the fly in their install targets,
# so we end up attempting to install the thing we didn't actually build.
#
# Thankfully, there's a way out that doesn't involve just hardcoding everything.
#
# The kernel has an install target, which runs a pretty simple shell script
# (located at scripts/install.sh or arch/$arch/boot/install.sh, depending on
# which kernel version you're looking at) that tries to do something sensible.
#
# (it would be great to hijack this script immediately, as it has all the
# information we need passed to it and we don't need it to try and be smart,
# but unfortunately, the exact location of the scripts differs between kernel
# versions, and they're seemingly not considered to be public API at all)
#
# One of the ways it tries to discover what "something sensible" actually is
# is by delegating to what's supposed to be a user-provided install script
# located at ~/bin/installkernel.
#
# (the other options are:
# - a distribution-specific script at /sbin/installkernel,
# which we can't really create in the sandbox easily
# - an architecture-specific script at arch/$arch/boot/install.sh,
# which attempts to guess _something_ and usually guesses very wrong)
#
# More specifically, the install script exec's into ~/bin/installkernel, if one
# exists, with the following arguments:
#
# $1: $KERNELRELEASE - full kernel version string
# $2: $KBUILD_IMAGE - the final image path
# $3: System.map - path to System.map file, seemingly hardcoded everywhere
# $4: $INSTALL_PATH - path to the destination directory as specified in installFlags
#
# $2 is exactly what we want, so hijack the script and use the knowledge given to it
# by the makefile overlords for our own nefarious ends.
#
# Note that the makefiles specifically look in ~/bin/installkernel, and
# writeShellScriptBin writes the script to <store path>/bin/installkernel,
# so HOME needs to be set to just the store path.
#
# FIXME: figure out a less roundabout way of doing this.
installkernel = buildPackages.writeShellScriptBin "installkernel" ''
cp -av $2 $4
cp -av $3 $4
'';
in
''
installFlags+=("-j$NIX_BUILD_CORES")
export HOME=${installkernel}
'';
# Some image types need special install targets (e.g. uImage is installed with make uinstall on arm)
installTargets = [
(kernelConf.installTarget or (
if kernelConf.target == "uImage" && stdenv.hostPlatform.linuxArch == "arm" then
"uinstall"
else if
(
kernelConf.target == "zImage"
|| kernelConf.target == "Image.gz"
|| kernelConf.target == "vmlinuz.efi"
)
&& builtins.elem stdenv.hostPlatform.linuxArch [
"arm"
"arm64"
"parisc"
"riscv"
]
then
"zinstall"
else
"install"
)
)
];
# We remove a bunch of stuff that is symlinked from other places to save space,
# which trips the broken symlink check. So, just skip it. We'll know if it explodes.
dontCheckForBrokenSymlinks = true;
postInstall = optionalString isModular ''
mkdir -p $dev
cp vmlinux $dev/
mkdir -p $dev/lib/modules/${modDirVersion}/build/scripts
cp -rL ../scripts/gdb/ $dev/lib/modules/${modDirVersion}/build/scripts
if [ -z "''${dontStrip-}" ]; then
installFlags+=("INSTALL_MOD_STRIP=1")
fi
make modules_install "''${makeFlags[@]}" "''${installFlags[@]}"
unlink $modules/lib/modules/${modDirVersion}/build
mkdir -p $dev/lib/modules/${modDirVersion}/{build,source}
# To save space, exclude a bunch of unneeded stuff when copying.
(cd .. && rsync --archive --prune-empty-dirs \
--exclude='/build/' \
* $dev/lib/modules/${modDirVersion}/source/)
cd $dev/lib/modules/${modDirVersion}/source
cp $buildRoot/{.config,Module.symvers} $dev/lib/modules/${modDirVersion}/build
make modules_prepare "''${makeFlags[@]}" O=$dev/lib/modules/${modDirVersion}/build
# For reproducibility, removes accidental leftovers from a `cc1` call
# from a `try-run` call from the Makefile
rm -f $dev/lib/modules/${modDirVersion}/build/.[0-9]*.d
# Keep some extra files on some arches (powerpc, aarch64)
for f in arch/powerpc/lib/crtsavres.o arch/arm64/kernel/ftrace-mod.o; do
if [ -f "$buildRoot/$f" ]; then
mkdir -p "$(dirname $dev/lib/modules/${modDirVersion}/build/$f)"
cp $buildRoot/$f $dev/lib/modules/${modDirVersion}/build/$f
fi
done
# !!! No documentation on how much of the source tree must be kept
# If/when kernel builds fail due to missing files, you can add
# them here. Note that we may see packages requiring headers
# from drivers/ in the future; it adds 50M to keep all of its
# headers on 3.10 though.
chmod u+w -R ..
buildArchDir="$dev/lib/modules/${modDirVersion}/build/arch"
# Remove unused arches
for d in $(cd arch/; ls); do
if [ -d "$buildArchDir/$d" ]; then continue; fi
if [ -d "$buildArchDir/arm64" ] && [ "$d" = arm ]; then continue; fi
rm -rf arch/$d
done
# Remove all driver-specific code (50M of which is headers)
rm -fR drivers
# Keep all headers
find . -type f -name '*.h' -print0 | xargs -0 -r chmod u-w
# Keep linker scripts (they are required for out-of-tree modules on aarch64)
find . -type f -name '*.lds' -print0 | xargs -0 -r chmod u-w
# Keep root and arch-specific Makefiles
chmod u-w Makefile arch/*/Makefile*
# Keep whole scripts dir
chmod u-w -R scripts
# Delete everything not kept
find . -type f -perm -u=w -print0 | xargs -0 -r rm
# Delete empty directories
find -empty -type d -delete
'';
requiredSystemFeatures = [ "big-parallel" ];
meta = {
# https://github.com/NixOS/nixpkgs/pull/345534#issuecomment-2391238381
broken = withRust && lib.versionOlder version "6.12";
description =
"The Linux kernel"
+ (
if kernelPatches == [ ] then
""
else
" (with patches: " + lib.concatStringsSep ", " (map (x: x.name) kernelPatches) + ")"
);
license = lib.licenses.gpl2Only;
homepage = "https://www.kernel.org/";
maintainers = [ maintainers.thoughtpolice ];
teams = [ teams.linux-kernel ];
platforms = platforms.linux;
badPlatforms =
lib.optionals (lib.versionOlder version "4.15") [
"riscv32-linux"
"riscv64-linux"
]
++ lib.optional (lib.versionOlder version "5.19") "loongarch64-linux";
timeout = 14400; # 4 hours
identifiers.cpeParts = {
part = "o";
vendor = "linux";
product = "linux_kernel";
inherit version;
update = "*";
};
}
// extraMeta;
};
commonMakeFlags = import ./common-flags.nix {
inherit
lib
stdenv
buildPackages
extraMakeFlags
;
};
in
stdenv.mkDerivation (
builtins.foldl' lib.recursiveUpdate { } [
(drvAttrs config stdenv.hostPlatform.linux-kernel kernelPatches configfile)
{
inherit pname version;
enableParallelBuilding = true;
hardeningDisable = [
"bindnow"
"format"
"fortify"
"stackprotector"
"pic"
"pie"
];
makeFlags = [
"O=$(buildRoot)"
# We have a `modules` variable in the environment for our
# split output, but the kernel Makefiles also define their
# own `modules` variable. Their definition wins, but Make
# remembers that the variable was originally from the
# environment and exports it to all the build recipes. This
# breaks the build with an “Argument list too long” error due
# to passing the huge list of every module object file in the
# environment of every process invoked by every build recipe.
#
# We use `--eval` here to undefine the inherited environment
# variable before any Makefiles are read, ensuring that the
# kernels definition creates a new, unexported variable.
"--eval=undefine modules"
]
++ commonMakeFlags;
passthru = { inherit commonMakeFlags; };
karch = stdenv.hostPlatform.linuxArch;
}
(optionalAttrs (pos != null) { inherit pos; })
]
)
)

View File

@@ -0,0 +1,28 @@
{ lib }:
with lib.kernel;
{
# DRM_AMDGPU = yes;
IPV6 = yes;
MPTCP = yes;
IP_MULTIPLE_TABLES = yes;
# Enable advanced path-managers...
MPTCP_PM_ADVANCED = yes;
MPTCP_FULLMESH = yes;
MPTCP_NDIFFPORTS = yes;
# ... but use none by default.
# The default is safer if source policy routing is not setup.
DEFAULT_DUMMY = yes;
DEFAULT_MPTCP_PM.freeform = "default";
# MPTCP scheduler selection.
MPTCP_SCHED_ADVANCED = yes;
DEFAULT_MPTCP_SCHED.freeform = "default";
# Smarter TCP congestion controllers
TCP_CONG_LIA = module;
TCP_CONG_OLIA = module;
TCP_CONG_WVEGAS = module;
TCP_CONG_BALIA = module;
}

View File

@@ -0,0 +1,79 @@
{
lib,
fetchpatch,
fetchurl,
}:
{
ath_regd_optional = rec {
name = "ath_regd_optional";
patch = fetchpatch {
name = name + ".patch";
url = "https://github.com/openwrt/openwrt/raw/ed2015c38617ed6624471e77f27fbb0c58c8c660/package/kernel/mac80211/patches/ath/402-ath_regd_optional.patch";
sha256 = "1ssDXSweHhF+pMZyd6kSrzeW60eb6MO6tlf0il17RC0=";
postFetch = ''
sed -i 's/CPTCFG_/CONFIG_/g' $out
sed -i '/--- a\/local-symbols/,$d' $out
'';
};
};
bridge_stp_helper = {
name = "bridge-stp-helper";
patch = ./bridge-stp-helper.patch;
};
# Reverts the buggy commit causing https://bugzilla.kernel.org/show_bug.cgi?id=217802
dell_xps_regression = {
name = "dell_xps_regression";
patch = fetchpatch {
name = "Revert-101bd907b424-misc-rtsx-judge-ASPM-Mode-to-set.patch";
url = "https://raw.githubusercontent.com/openSUSE/kernel-source/1b02b1528a26f4e9b577e215c114d8c5e773ee10/patches.suse/Revert-101bd907b424-misc-rtsx-judge-ASPM-Mode-to-set.patch";
sha256 = "sha256-RHJdQ4p0msTOVPR+/dYiKuwwEoG9IpIBqT4dc5cJjf8=";
};
};
request_key_helper = {
name = "request-key-helper";
patch = ./request-key-helper.patch;
};
request_key_helper_updated = {
name = "request-key-helper-updated";
patch = ./request-key-helper-updated.patch;
};
hardened =
let
mkPatch =
kernelVersion:
{
version,
sha256,
patch,
}:
let
src = patch;
in
{
name = lib.removeSuffix ".patch" src.name;
patch = fetchurl (lib.filterAttrs (k: v: k != "extra") src);
extra = src.extra;
inherit version sha256;
};
patches = lib.importJSON ./hardened/patches.json;
in
lib.mapAttrs mkPatch patches;
# Adapted for Linux 5.4 from:
# https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=04896832c94aae4842100cafb8d3a73e1bed3a45
rtl8761b_support = {
name = "rtl8761b-support";
patch = ./rtl8761b-support.patch;
};
export-rt-sched-migrate = {
name = "export-rt-sched-migrate";
patch = ./export-rt-sched-migrate.patch;
};
}

View File

@@ -0,0 +1,13 @@
diff --git a/scripts/gen-randstruct-seed.sh b/scripts/gen-randstruct-seed.sh
index 61017b36c464..7bb494dd2e18 100755
--- a/scripts/gen-randstruct-seed.sh
+++ b/scripts/gen-randstruct-seed.sh
@@ -1,7 +1,7 @@
#!/bin/sh
# SPDX-License-Identifier: GPL-2.0
-SEED=$(od -A n -t x8 -N 32 /dev/urandom | tr -d ' \n')
+SEED="NIXOS_RANDSTRUCT_SEED"
echo "$SEED" > "$1"
HASH=$(echo -n "$SEED" | sha256sum | cut -d" " -f1)
echo "#define RANDSTRUCT_HASHED_SEED \"$HASH\"" > "$2"

View File

@@ -0,0 +1,12 @@
diff -ru a/scripts/gcc-plugins/gen-random-seed.sh b/scripts/gcc-plugins/gen-random-seed.sh
--- a/scripts/gcc-plugins/gen-random-seed.sh 2019-01-11 11:50:29.228258920 +0100
+++ b/scripts/gcc-plugins/gen-random-seed.sh 2019-01-11 12:18:33.555902720 +0100
@@ -2,7 +2,7 @@
# SPDX-License-Identifier: GPL-2.0
if [ ! -f "$1" ]; then
- SEED=`od -A n -t x8 -N 32 /dev/urandom | tr -d ' \n'`
+ SEED="NIXOS_RANDSTRUCT_SEED"
echo "const char *randstruct_seed = \"$SEED\";" > "$1"
HASH=`echo -n "$SEED" | sha256sum | cut -d" " -f1 | tr -d ' \n'`
echo "#define RANDSTRUCT_HASHED_SEED \"$HASH\"" > "$2"

View File

@@ -0,0 +1,13 @@
diff --git a/security/keys/request_key.c b/security/keys/request_key.c
index 88172c163953..4da74a1eebb2 100644
--- a/security/keys/request_key.c
+++ b/security/keys/request_key.c
@@ -161,7 +161,7 @@ static int call_sbin_request_key(struct key_construction *cons,
/* set up the argument list */
i = 0;
- argv[i++] = "/sbin/request-key";
+ argv[i++] = "/run/current-system/sw/bin/request-key";
argv[i++] = (char *) op;
argv[i++] = key_str;
argv[i++] = uid_str;

View File

@@ -0,0 +1,13 @@
diff --git a/security/keys/request_key.c b/security/keys/request_key.c
index 957b9e3e1492..5436a0d8b81d 100644
--- a/security/keys/request_key.c
+++ b/security/keys/request_key.c
@@ -114,7 +114,7 @@ static int call_usermodehelper_keys(const char *path, char **argv, char **envp,
*/
static int call_sbin_request_key(struct key *authkey, void *aux)
{
- static char const request_key[] = "/sbin/request-key";
+ static char const request_key[] = "/run/current-system/sw/bin/request-key";
struct request_key_auth *rka = get_request_key_auth(authkey);
const struct cred *cred = current_cred();
key_serial_t prkey, sskey;

View File

@@ -0,0 +1,33 @@
diff --git a/drivers/bluetooth/btrtl.c b/drivers/bluetooth/btrtl.c
index 67f4bc21e7c5..3a9afc905f24 100644
--- a/drivers/bluetooth/btrtl.c
+++ b/drivers/bluetooth/btrtl.c
@@ -130,12 +130,19 @@ static const struct id_table ic_id_table[] = {
.cfg_name = "rtl_bt/rtl8821c_config" },
/* 8761A */
- { IC_MATCH_FL_LMPSUBV, RTL_ROM_LMP_8761A, 0x0,
+ { IC_INFO(RTL_ROM_LMP_8761A, 0xa),
.config_needed = false,
.has_rom_version = true,
.fw_name = "rtl_bt/rtl8761a_fw.bin",
.cfg_name = "rtl_bt/rtl8761a_config" },
+ /* 8761B */
+ { IC_INFO(RTL_ROM_LMP_8761A, 0xb),
+ .config_needed = false,
+ .has_rom_version = true,
+ .fw_name = "rtl_bt/rtl8761b_fw.bin",
+ .cfg_name = "rtl_bt/rtl8761b_config" },
+
/* 8822C with USB interface */
{ IC_INFO(RTL_ROM_LMP_8822B, 0xc),
.config_needed = false,
@@ -251,6 +258,7 @@ static int rtlbt_parse_firmware(struct hci_dev *hdev,
{ RTL_ROM_LMP_8723B, 9 }, /* 8723D */
{ RTL_ROM_LMP_8821A, 10 }, /* 8821C */
{ RTL_ROM_LMP_8822B, 13 }, /* 8822C */
+ { RTL_ROM_LMP_8761A, 14 }, /* 8761B */
};
min_size = sizeof(struct rtl_epatch_header) + sizeof(extension_sig) + 3;

View File

@@ -0,0 +1,167 @@
#!/usr/bin/env nix-shell
#!nix-shell -i python3 -p "python3.withPackages (ps: [ ps.beautifulsoup4 ps.lxml ps.packaging ])"
from functools import cached_property
from itertools import groupby
import json
import os
import pathlib
import subprocess
import sys
import urllib.request
from dataclasses import dataclass
from enum import Enum
from bs4 import BeautifulSoup, NavigableString, Tag
from packaging.version import parse as parse_version, Version
HERE = pathlib.Path(__file__).parent
ROOT = HERE.parent.parent.parent.parent
VERSIONS_FILE = HERE / "kernels-org.json"
class KernelNature(Enum):
MAINLINE = 1
STABLE = 2
LONGTERM = 3
@dataclass
class KernelRelease:
nature: KernelNature
version: str
date: str
link: str
eol: bool = False
@cached_property
def parsed_version(self) -> Version:
return parse_version(self.version)
@cached_property
def branch(self) -> str:
version = self.parsed_version
# This is a testing kernel.
if version.is_prerelease:
return "testing"
else:
return f"{version.major}.{version.minor}"
def parse_release(release: Tag) -> KernelRelease | None:
columns: list[Tag] = list(release.find_all("td"))
try:
nature = KernelNature[columns[0].get_text().rstrip(":").upper()]
except KeyError:
# skip linux-next
return None
version = columns[1].get_text().rstrip(" [EOL]")
date = columns[2].get_text()
link = columns[3].find("a")
if link is not None and isinstance(link, Tag):
link = link.attrs.get("href")
assert link is not None, f"link for kernel {version} is non-existent"
eol = bool(release.find(class_="eolkernel"))
return KernelRelease(
nature=nature,
version=version,
date=date,
link=link,
eol=eol,
)
def get_hash(kernel: KernelRelease):
if kernel.branch == "testing":
args = ["--unpack"]
else:
args = []
hash = (
subprocess.check_output(["nix-prefetch-url", kernel.link] + args)
.decode()
.strip()
)
return f"sha256:{hash}"
def get_oldest_branch(kernels) -> Version:
return min(parse_version(v) for v in kernels.keys() if v != "testing")
def predates_oldest_branch(oldest: Version, to_compare: str) -> bool:
if to_compare == "testing":
return False
return parse_version(to_compare) < oldest
def commit(message):
return subprocess.check_call(["git", "commit", "-m", message, VERSIONS_FILE])
def main():
kernel_org = urllib.request.urlopen("https://kernel.org/")
soup = BeautifulSoup(kernel_org.read().decode(), "lxml")
release_table = soup.find(id="releases")
if not release_table or isinstance(release_table, NavigableString):
print(release_table, file=sys.stderr)
print("Failed to find the release table on https://kernel.org", file=sys.stderr)
sys.exit(1)
releases = release_table.find_all("tr")
parsed_releases = [
parsed for release in releases
if (parsed := parse_release(release)) is not None
]
all_kernels = json.load(VERSIONS_FILE.open())
oldest_branch = get_oldest_branch(all_kernels)
for (branch, kernels) in groupby(parsed_releases, lambda kernel: kernel.branch):
kernel = max(kernels, key=lambda kernel: kernel.parsed_version)
nixpkgs_branch = branch.replace(".", "_")
old_version = all_kernels.get(branch, {}).get("version")
if old_version == kernel.version:
print(f"linux_{nixpkgs_branch}: {kernel.version} is latest, skipping...")
continue
if predates_oldest_branch(oldest_branch, kernel.branch):
print(
f"{kernel.branch} is too old and not supported anymore, skipping...",
file=sys.stderr
)
continue
if old_version is None:
if kernel.eol:
print(
f"{kernel.branch} is EOL, not adding...",
file=sys.stderr
)
continue
message = f"linux_{nixpkgs_branch}: init at {kernel.version}"
else:
message = f"linux_{nixpkgs_branch}: {old_version} -> {kernel.version}"
print(message, file=sys.stderr)
all_kernels[branch] = {
"version": kernel.version,
"hash": get_hash(kernel),
"lts": kernel.nature == KernelNature.LONGTERM,
}
with VERSIONS_FILE.open("w") as fd:
json.dump(all_kernels, fd, indent=4)
fd.write("\n") # makes editorconfig happy
if os.environ.get("COMMIT") == "1":
commit(message)
if __name__ == "__main__":
main()

View File

@@ -0,0 +1,80 @@
#!/usr/bin/env bash
set -euo pipefail
# To update all rt kernels run: ./update-rt.sh
# To update just one ./linux-rt-5.X.nix run: ./update-rt.sh ./linux-rt-5.X.nix
# To add a new kernel branch 5.Y run: ./update-rt.sh ./linux-rt-5.Y.nix
# (with nonexistent .nix file) and update all-packages.nix.
# To commit run with: env COMMIT=1
mirror=https://kernel.org/pub/linux/kernel
main() {
if [ $# -ge 1 ]; then
update-if-needed "$1"
else
update-all-if-needed
fi
}
update-all-if-needed() {
for f in "$(dirname "$0")"/linux-rt-*.nix; do
update-if-needed "$f"
done
}
file-version() {
file="$1" # e.g. ./linux-rt-5.4.nix
if [ -e "$file" ]; then
grep ' version = ' "$file" | grep -o '[0-9].[^"]*'
fi
}
latest-rt-version() {
branch="$1" # e.g. 5.4
curl -sL "$mirror/projects/rt/$branch/sha256sums.asc" |
sed -ne '/.patch.xz/ { s/.*patch-\(.*\).patch.xz/\1/p}' |
grep -v '\-rc' |
sort --version-sort |
tail -n 1
}
update-if-needed() {
file="$1" # e.g. ./linux-rt-5.4.nix (created if does not exist)
branch=$(basename "$file" .nix) # e.g. linux-rt-5.4
branch=${branch#linux-rt-} # e.g. 5.4
cur=$(file-version "$file") # e.g. 5.4.59-rt36 or empty
new=$(latest-rt-version "$branch") # e.g. 5.4.61-rt37
kversion=${new%-*} # e.g. 5.4.61
major=${branch%.*} # e.g 5
nixattr="linux-rt_${branch/./_}"
if [ "$new" = "$cur" ]; then
echo "$nixattr: $cur (up-to-date)"
return
fi
khash=$(nix-prefetch-url "$mirror/v${major}.x/linux-${kversion}.tar.xz")
phash=$(nix-prefetch-url "$mirror/projects/rt/${branch}/older/patch-${new}.patch.xz")
if [ "$cur" ]; then
msg="$nixattr: $cur -> $new"
else
msg="$nixattr: init at $new"
prev=$(ls -v "$(dirname "$0")"/linux-rt-*.nix | tail -1)
cp "$prev" "$file"
cur=$(file-version "$file")
fi
echo "$msg"
sed -i "$file" \
-e "s/$cur/$new/" \
-e "s|kernel/v[0-9]*|kernel/v$major|" \
-e "1,/.patch.xz/ s/sha256 = .*/sha256 = \"$khash\";/" \
-e "1,/.patch.xz/! s/sha256 = .*/sha256 = \"$phash\";/"
if [ "${COMMIT:-}" ]; then
git add "$file"
git commit -m "$msg"
fi
}
return 2>/dev/null || main "$@"

View File

@@ -0,0 +1,98 @@
#!/usr/bin/env nix-shell
#!nix-shell -I nixpkgs=./. -i bash -p bash nix-prefetch curl jq gawk gnused nixfmt
set -euo pipefail
SCRIPT_DIR="$(dirname "${BASH_SOURCE[0]}")"
FILE_PATH="$SCRIPT_DIR/xanmod-kernels.nix"
get_old_version() {
local file_path="$1"
local variant="$2"
grep -A 2 "$variant = {" "$file_path" | grep "version =" | cut -d '"' -f 2
}
VARIANT="${1:-lts}"
OLD_VERSION=${UPDATE_NIX_OLD_VERSION:-$(get_old_version "$FILE_PATH" "$VARIANT")}
RELEASES=$(curl --silent https://gitlab.com/api/v4/projects/xanmod%2Flinux/releases)
# list of URLs. latest first, oldest last
RELEASE_URLS=$(echo "$RELEASES" | jq '.[].assets.links.[0].name')
while IFS= read -r url; do
# Remove trailing slash
url="${url%/}"
# Get variant, version and suffix from url fields:
# 8 9 NF
# | | |
# https://.../<variant>/<version>-<suffix>
release_variant=$(echo "$url" | awk -F'[/-]' '{print $8}')
release_version=$(echo "$url" | awk -F'[/-]' '{print $9}')
# either xanmod1 or xanmod2
suffix=$(echo "$url" | awk -F'[/-]' '{print $NF}')
if [[ "$release_variant" == "$VARIANT" ]]; then
if [[ "$release_version" == "$OLD_VERSION" ]]; then
echo "Xanmod $VARIANT is up-to-date: ${OLD_VERSION}"
exit 0
else
NEW_VERSION="$release_version"
SUFFIX="$suffix"
break
fi
fi
done < <(echo "$RELEASE_URLS" | jq -r)
>&2 echo "Updating Xanmod \"$VARIANT\" from $OLD_VERSION to $NEW_VERSION ($SUFFIX)"
URL="https://gitlab.com/api/v4/projects/xanmod%2Flinux/repository/archive.tar.gz?sha=$NEW_VERSION-$SUFFIX"
HASH="$(nix-prefetch fetchzip --quiet --url "$URL")"
update_variant() {
local file_path="$1"
local variant="$2"
local new_version="$3"
local new_hash="$4"
local suffix="$5"
# ${variant} = { <- range start
# version = ...
# hash = ...
# suffix = ...
# }; <- range end
range_start="^\s*$variant = {"
range_end="^\s*};"
# - Update the version and hash using sed range addresses
# - Remove suffix line, if it exists
sed -i -e "/$range_start/,/$range_end/ {
s|^\s*version = \".*\";| version = \"$new_version\";|;
s|^\s*hash = \".*\";| hash = \"$new_hash\";|;
/^\s*suffix = /d
}" "$file_path"
# Add suffix, if it's different than xanmod1 (the default)
if [[ "$suffix" != "xanmod1" ]]; then
sed -i -e "/$range_start/,/$range_end/ {
s|$range_end| suffix = \"$suffix\";\n };|;
}" "$file_path"
fi
# Apply proper formatting
nixfmt "$file_path"
}
update_variant "$FILE_PATH" "$VARIANT" "$NEW_VERSION" "$HASH" "$SUFFIX"
# Customize commit
# https://github.com/NixOS/nixpkgs/blob/master/pkgs/README.md#supported-features
COMMIT_BODY="
- Changelog: https://dl.xanmod.org/changelog/${NEW_VERSION%.*}/ChangeLog-$NEW_VERSION-xanmod1.gz
- Diff: https://gitlab.com/xanmod/linux/-/compare/$OLD_VERSION-xanmod1..$NEW_VERSION-xanmod1?from_project_id=51590166
"
jq -n --arg commitBody "$COMMIT_BODY" '[$ARGS.named]'

View File

@@ -0,0 +1,122 @@
#! /usr/bin/env nix-shell
#! nix-shell -i python3 -p python3 nix nix-prefetch-git
import fileinput
import json
import os
import sys
import re
import subprocess
from datetime import datetime
from urllib.request import urlopen, Request
def panic(exc):
raise Exception(exc)
DIR = os.path.dirname(os.path.abspath(__file__))
HEADERS = {'Accept': 'application/vnd.github.v3+json'}
def github_api_request(endpoint):
base_url = 'https://api.github.com/'
request = Request(base_url + endpoint, headers=HEADERS)
with urlopen(request) as http_response:
return json.loads(http_response.read().decode('utf-8'))
def get_commit_date(repo, sha):
url = f'https://api.github.com/repos/{repo}/commits/{sha}'
request = Request(url, headers=HEADERS)
with urlopen(request) as http_response:
commit = json.loads(http_response.read().decode())
date = commit['commit']['committer']['date'].rstrip('Z')
date = datetime.fromisoformat(date).date().isoformat()
return 'unstable-' + date
def nix_prefetch_git(url, rev):
"""Prefetches the requested Git revision (incl. submodules) of the given repository URL."""
print(f'nix-prefetch-git {url} {rev}')
out = subprocess.check_output([
'nix-prefetch-git', '--quiet',
'--url', url,
'--rev', rev,
'--fetch-submodules'])
return json.loads(out)['sha256']
def nix_prefetch_url(url, unpack=False):
"""Prefetches the content of the given URL."""
print(f'nix-prefetch-url {url}')
options = ['--type', 'sha256']
if unpack:
options += ['--unpack']
out = subprocess.check_output(['nix-prefetch-url'] + options + [url])
return out.decode('utf-8').rstrip()
def update_file(relpath, variant, version, suffix, sha256):
file_path = os.path.join(DIR, relpath)
with fileinput.FileInput(file_path, inplace=True) as f:
for line in f:
result = line
result = re.sub(
fr'^ version = ".+"; # {variant}',
f' version = "{version}"; # {variant}',
result)
result = re.sub(
fr'^ suffix = ".+"; # {variant}',
f' suffix = "{suffix}"; # {variant}',
result)
result = re.sub(
fr'^ sha256 = ".+"; # {variant}',
f' sha256 = "{sha256}"; # {variant}',
result)
print(result, end='')
def read_file(relpath, variant):
file_path = os.path.join(DIR, relpath)
re_version = re.compile(fr'^\s*version = "(.+)"; # {variant}')
re_suffix = re.compile(fr'^\s*suffix = "(.+)"; # {variant}')
version = None
suffix = None
with fileinput.FileInput(file_path, mode='r') as f:
for line in f:
version_match = re_version.match(line)
if version_match:
version = version_match.group(1)
continue
suffix_match = re_suffix.match(line)
if suffix_match:
suffix = suffix_match.group(1)
continue
if version and suffix:
break
return version, suffix
if __name__ == "__main__":
if len(sys.argv) == 1:
panic("Update variant expected")
variant = sys.argv[1]
if variant not in ("zen", "lqx"):
panic(f"Unexepected variant instead of 'zen' or 'lqx': {sys.argv[1]}")
pattern = re.compile(fr"v(\d+\.\d+\.?\d*)-({variant}\d+)")
zen_tags = github_api_request('repos/zen-kernel/zen-kernel/releases')
for tag in zen_tags:
zen_match = pattern.match(tag['tag_name'])
if zen_match:
zen_tag = zen_match.group(0)
zen_version = zen_match.group(1)
zen_suffix = zen_match.group(2)
break
old_version, old_suffix = read_file('zen-kernels.nix', variant)
if old_version != zen_version or old_suffix != zen_suffix:
zen_hash = nix_prefetch_git('https://github.com/zen-kernel/zen-kernel.git', zen_tag)
update_file('zen-kernels.nix', variant, zen_version, zen_suffix, zen_hash)

View File

@@ -0,0 +1,11 @@
#!/usr/bin/env bash
cd "$(dirname "$(readlink -f "$0")")" || exit
echo "Update linux (mainline)"
COMMIT=1 ./update-mainline.py || echo "update-mainline failed with exit code $?"
echo "Update linux-rt"
COMMIT=1 ./update-rt.sh || echo "update-rt failed with exit code $?"
echo "Update linux-hardened"
COMMIT=1 ./hardened/update.py || echo "update-hardened failed with exit code $?"

View File

@@ -0,0 +1,106 @@
{
lib,
stdenv,
fetchFromGitLab,
buildLinux,
variant,
...
}@args:
let
# These names are how they are designated in https://xanmod.org.
# NOTE: When updating these, please also take a look at the changes done to
# kernel config in the xanmod version commit
variants = {
# ./update-xanmod.sh lts
lts = {
version = "6.12.51";
hash = "sha256-7fIOQ7VctDhueoOnZA8/7Dc7gxAl+vKgO/X5Oa4Z8kE=";
isLTS = true;
};
# ./update-xanmod.sh main
main = {
version = "6.16.11";
hash = "sha256-EZjH22q8JvlbFpab4rdrA24kf+r9heneiwy5YM4WfYk=";
};
};
xanmodKernelFor =
{
version,
suffix ? "xanmod1",
hash,
isLTS ? false,
}:
buildLinux (
args
// rec {
inherit version;
pname = "linux-xanmod";
modDirVersion = lib.versions.pad 3 "${version}-${suffix}";
src = fetchFromGitLab {
owner = "xanmod";
repo = "linux";
rev = modDirVersion;
inherit hash;
};
structuredExtraConfig = with lib.kernel; {
# CPUFreq governor Performance
CPU_FREQ_DEFAULT_GOV_PERFORMANCE = lib.mkOverride 60 yes;
CPU_FREQ_DEFAULT_GOV_SCHEDUTIL = lib.mkOverride 60 no;
# Full preemption
PREEMPT = lib.mkOverride 60 yes;
PREEMPT_VOLUNTARY = lib.mkOverride 60 no;
# Google's BBRv3 TCP congestion Control
TCP_CONG_BBR = yes;
DEFAULT_BBR = yes;
# Preemptive Full Tickless Kernel at 250Hz
HZ = freeform "250";
HZ_250 = yes;
HZ_1000 = no;
# RCU_BOOST and RCU_EXP_KTHREAD
RCU_EXPERT = yes;
RCU_FANOUT = freeform "64";
RCU_FANOUT_LEAF = freeform "16";
RCU_BOOST = yes;
RCU_BOOST_DELAY = freeform "0";
RCU_EXP_KTHREAD = yes;
};
extraPassthru.updateScript = {
command = [
./update-xanmod.sh
variant
];
supportedFeatures = [
"commit"
];
};
inherit isLTS;
extraMeta = {
branch = lib.versions.majorMinor version;
maintainers = with lib.maintainers; [
moni
lovesegfault
atemu
zzzsy
eljamm
];
teams = [ ];
description = "Built with custom settings and new features built to provide a stable, responsive and smooth desktop experience";
broken = stdenv.hostPlatform.isAarch64;
};
}
// (args.argsOverride or { })
);
in
xanmodKernelFor variants.${variant}

View File

@@ -0,0 +1,171 @@
{
lib,
stdenv,
fetchFromGitHub,
buildLinux,
variant,
...
}@args:
let
# Default priority is 100 for common kernel options (see common-config.nix
# file), we need something lower to override them, but we still want users to
# override options if they need using lib.mkForce (that has 50 priority)
mkKernelOverride = lib.mkOverride 90;
# Comments with variant added for update script
variants = {
# ./update-zen.py zen
zen = {
version = "6.17.1"; # zen
suffix = "zen1"; # zen
sha256 = "0610gcmzmvc70nw7n225avf1spahzffc6ajq18ibidra1k5q2msj"; # zen
isLqx = false;
};
# ./update-zen.py lqx
lqx = {
version = "6.16.11"; # lqx
suffix = "lqx1"; # lqx
sha256 = "12azycvaj300gll8adrqcln6qngfx3kr0dz7g91zr40ldf3s4nvg"; # lqx
isLqx = true;
};
};
zenKernelsFor =
{
version,
suffix,
sha256,
isLqx,
}:
buildLinux (
args
// {
inherit version;
pname = "linux-${if isLqx then "lqx" else "zen"}";
modDirVersion = lib.versions.pad 3 "${version}-${suffix}";
isZen = true;
src = fetchFromGitHub {
owner = "zen-kernel";
repo = "zen-kernel";
rev = "v${version}-${suffix}";
inherit sha256;
};
# This is based on the following sources:
# - zen: https://gitlab.archlinux.org/archlinux/packaging/packages/linux-zen/-/blob/main/config
# - lqx: https://github.com/damentz/liquorix-package/blob/6.13/master/linux-liquorix/debian/config/kernelarch-x86/config-arch-64
# - Liquorix features: https://liquorix.net/
# The list below is not exhaustive, so the kernels probably doesn't match
# the upstream, but should bring most of the improvements that will be
# expected by users
structuredExtraConfig =
with lib.kernel;
{
# Zen Interactive tuning
ZEN_INTERACTIVE = yes;
# FQ-Codel Packet Scheduling
NET_SCH_DEFAULT = yes;
DEFAULT_FQ_CODEL = yes;
# Preempt (low-latency)
PREEMPT = mkKernelOverride yes;
PREEMPT_VOLUNTARY = mkKernelOverride no;
# Preemptible tree-based hierarchical RCU
TREE_RCU = yes;
PREEMPT_RCU = yes;
RCU_EXPERT = yes;
TREE_SRCU = yes;
TASKS_RCU_GENERIC = yes;
TASKS_RCU = yes;
TASKS_RUDE_RCU = yes;
TASKS_TRACE_RCU = yes;
RCU_STALL_COMMON = yes;
RCU_NEED_SEGCBLIST = yes;
RCU_FANOUT = freeform "64";
RCU_FANOUT_LEAF = freeform "16";
RCU_BOOST = yes;
RCU_BOOST_DELAY = option (freeform "500");
RCU_NOCB_CPU = yes;
RCU_LAZY = yes;
RCU_DOUBLE_CHECK_CB_TIME = yes;
# BFQ I/O scheduler
IOSCHED_BFQ = mkKernelOverride yes;
# Futex WAIT_MULTIPLE implementation for Wine / Proton Fsync.
FUTEX = yes;
FUTEX_PI = yes;
# NT synchronization primitive emulation
NTSYNC = yes;
# Preemptive Full Tickless Kernel at 1000Hz
HZ = freeform "1000";
HZ_1000 = yes;
}
// lib.optionalAttrs isLqx {
# https://github.com/damentz/liquorix-package/commit/07b176edc002f2a7825ae181613e1f79a3650fd2
CMDLINE_BOOL = yes;
CMDLINE = freeform "audit=0 intel_pstate=disable amd_pstate=disable ";
# Google's BBRv3 TCP congestion Control
TCP_CONG_BBR = yes;
DEFAULT_BBR = yes;
# PDS Process Scheduler
SCHED_ALT = yes;
SCHED_PDS = yes;
# https://github.com/damentz/liquorix-package/commit/a7055b936c0f4edb8f6afd5263fe1d2f8a5cd877
RCU_BOOST = no;
RCU_LAZY = mkKernelOverride no;
# Swap storage is compressed with LZ4 using zswap
ZSWAP_COMPRESSOR_DEFAULT_LZ4 = yes;
ZSWAP_COMPRESSOR_DEFAULT_ZSTD = mkKernelOverride no;
# https://github.com/damentz/liquorix-package/commit/3a82381a4db3452599e2b2a607046a379c72ad27
SLAB_BUCKETS = mkKernelOverride (option no);
# https://github.com/damentz/liquorix-package/commit/ca7efe07abd478f3f4cbe0725a3383fd235aa5be
ENERGY_MODE = mkKernelOverride (option no);
# https://github.com/damentz/liquorix-package/commit/fdc93f5633d22c26f0994fba751a26de0cb51a17
WQ_POWER_EFFICIENT_DEFAULT = mkKernelOverride (option no);
# Fix error: unused option: XXX.
CFS_BANDWIDTH = mkKernelOverride (option no);
PSI = mkKernelOverride (option no);
RT_GROUP_SCHED = mkKernelOverride (option no);
SCHED_AUTOGROUP = mkKernelOverride (option no);
SCHED_CLASS_EXT = mkKernelOverride (option no);
SCHED_CORE = mkKernelOverride (option no);
UCLAMP_TASK = mkKernelOverride (option no);
UCLAMP_TASK_GROUP = mkKernelOverride (option no);
};
extraPassthru.updateScript = [
./update-zen.py
(if isLqx then "lqx" else "zen")
];
extraMeta = {
branch = lib.versions.majorMinor version + "/master";
maintainers = with lib.maintainers; [
thiagokokada
jerrysm64
axertheaxe
];
teams = [ ];
description =
"Built using the best configuration and kernel sources for desktop, multimedia, and gaming workloads."
+ lib.optionalString isLqx " (Same as linux_zen, but less aggressive release schedule and additional extra config)";
broken = stdenv.hostPlatform.isAarch64;
};
}
// (args.argsOverride or { })
);
in
zenKernelsFor variants.${variant}