Compare commits
22
Commits
2.92.2
...
release-2.92
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
7653f109c6 | ||
|
|
16894c7bc5 | ||
|
|
594efc2e56 | ||
|
|
c63eb21e8d | ||
|
|
92cf5ac91b | ||
|
|
88302eaaf4 | ||
|
|
4601564996 | ||
|
|
4015082602 | ||
|
|
a91e28009f | ||
|
|
c698466dc7 | ||
|
|
f10ca0d677 | ||
|
|
8c5e1c8f63 | ||
|
|
fe090a7b9b | ||
|
|
4a3983906f | ||
|
|
bac0d67928 | ||
|
|
22a1d233bb | ||
|
|
4901a6cda9 | ||
|
|
8cbdc36a60 | ||
|
|
56b0b39465 | ||
|
|
438e1839f1 | ||
|
|
99456a0c7e | ||
|
|
1d36dd7596 |
@@ -1,4 +1,61 @@
|
|||||||
# Lix 2.92 "Bombe glacée" (2025-01-18)
|
# Lix 2.92 "Bombe glacée" (2025-01-18)
|
||||||
|
# Lix 2.92.3 (2025-06-30)
|
||||||
|
|
||||||
|
## Fixes
|
||||||
|
- Revert CVE-2025-52992 failed mitigation [fj#883](https://git.lix.systems/lix-project/lix/issues/883) [fj#887](https://git.lix.systems/lix-project/lix/issues/887) [cl/3432](https://gerrit.lix.systems/c/lix/+/3432) [cl/3525](https://gerrit.lix.systems/c/lix/+/3525) [cl/3526](https://gerrit.lix.systems/c/lix/+/3526) [cl/3527](https://gerrit.lix.systems/c/lix/+/3527)
|
||||||
|
|
||||||
|
Following the initial mitigation of **CVE-2025-52992** in `cl/3432`, we
|
||||||
|
received reports of **unexpected deletion of in-use store paths**.
|
||||||
|
|
||||||
|
Upon investigation, we found that the patch did **not correctly cancel all
|
||||||
|
automatic deleters**, resulting in potentially critical path loss during normal
|
||||||
|
operation.
|
||||||
|
|
||||||
|
Given the severity and time-sensitive nature of the situation ([see incident
|
||||||
|
report](https://lix.systems/blog/2025-06-27-lix-critical-bug/)), we evaluated
|
||||||
|
possible options to repair the behavior safely. However, we concluded that a
|
||||||
|
rushed fix would either
|
||||||
|
|
||||||
|
* **Overdelete**, i.e. breaking running systems, or,
|
||||||
|
* **Underdelete**, effectively **reopening CVE-2025-52992** while leaving
|
||||||
|
orphaned paths behind.
|
||||||
|
|
||||||
|
As **CVE-2025-52992 has no known exploit vector**, and correctness is critical
|
||||||
|
in the Lix project, we have **fully reverted the previous mitigations**.
|
||||||
|
|
||||||
|
The affected patches (`cl/3432`) have been rolled back for the time being.
|
||||||
|
|
||||||
|
Moving forward, the Lix team will rework this code path in a **long-term,
|
||||||
|
correctness-first fix** on the main branch. We will explore backporting it to
|
||||||
|
stable channels once its safety is assured.
|
||||||
|
|
||||||
|
We are deeply sorry for the stability incident and the Lix team remain
|
||||||
|
available for assisting you in recovering your systems.
|
||||||
|
|
||||||
|
Many thanks to [Raito Bezarius](https://git.lix.systems/raito) and [eldritch horrors](https://git.lix.systems/pennae) for this.
|
||||||
|
- Fallback to safe temp dir when build-dir is unwritable [fj#876](https://git.lix.systems/lix-project/lix/issues/876) [cl/3503](https://gerrit.lix.systems/c/lix/+/3503)
|
||||||
|
|
||||||
|
Non-daemon builds started failing with a permission error after introducing the `build-dir` option:
|
||||||
|
|
||||||
|
```
|
||||||
|
$ nix build --store ~/scratch nixpkgs#hello --rebuild
|
||||||
|
error: creating directory '/nix/var/nix/builds/nix-build-hello-2.12.2.drv-0': Permission denied
|
||||||
|
```
|
||||||
|
|
||||||
|
This happens because:
|
||||||
|
|
||||||
|
1. These builds are not run via the daemon, which owns `/nix/var/nix/builds`.
|
||||||
|
2. The user lacks permissions for that path.
|
||||||
|
|
||||||
|
We considered making `build-dir` a store-level option and defaulting it to `<chroot-root>/nix/var/nix/builds` for chroot stores, but opted instead for a fallback: if the default fails, Nix now creates a safe build directory under `/tmp`.
|
||||||
|
|
||||||
|
To avoid CVE-2025-52991, the fallback uses an extra path component between `/tmp` and the build dir.
|
||||||
|
|
||||||
|
**Note**: this fallback clutters `/tmp` with build directories that are not cleaned up. To prevent this, explicitly set `build-dir` to a path managed by Lix, even for local workloads.
|
||||||
|
|
||||||
|
Many thanks to [Raito Bezarius](https://git.lix.systems/raito) and [eldritch horrors](https://git.lix.systems/pennae) for this.
|
||||||
|
|
||||||
|
|
||||||
# Lix 2.92.2 (2025-06-23)
|
# Lix 2.92.2 (2025-06-23)
|
||||||
|
|
||||||
## Breaking Changes
|
## Breaking Changes
|
||||||
|
|||||||
+37
-38
@@ -62,38 +62,37 @@ let
|
|||||||
++ autoLayered
|
++ autoLayered
|
||||||
++ extraPkgs;
|
++ extraPkgs;
|
||||||
|
|
||||||
users =
|
users = {
|
||||||
{
|
|
||||||
|
|
||||||
root = {
|
root = {
|
||||||
uid = 0;
|
uid = 0;
|
||||||
shell = "${pkgs.bashInteractive}/bin/bash";
|
shell = "${pkgs.bashInteractive}/bin/bash";
|
||||||
home = "/root";
|
home = "/root";
|
||||||
gid = 0;
|
gid = 0;
|
||||||
groups = [ "root" ];
|
groups = [ "root" ];
|
||||||
description = "System administrator";
|
description = "System administrator";
|
||||||
};
|
};
|
||||||
|
|
||||||
nobody = {
|
nobody = {
|
||||||
uid = 65534;
|
uid = 65534;
|
||||||
shell = "${pkgs.shadow}/bin/nologin";
|
shell = "${pkgs.shadow}/bin/nologin";
|
||||||
home = "/var/empty";
|
home = "/var/empty";
|
||||||
gid = 65534;
|
gid = 65534;
|
||||||
groups = [ "nobody" ];
|
groups = [ "nobody" ];
|
||||||
description = "Unprivileged account (don't use!)";
|
description = "Unprivileged account (don't use!)";
|
||||||
|
};
|
||||||
|
}
|
||||||
|
// lib.listToAttrs (
|
||||||
|
map (n: {
|
||||||
|
name = "nixbld${toString n}";
|
||||||
|
value = {
|
||||||
|
uid = 30000 + n;
|
||||||
|
gid = 30000;
|
||||||
|
groups = [ "nixbld" ];
|
||||||
|
description = "Nix build user ${toString n}";
|
||||||
};
|
};
|
||||||
}
|
}) (lib.lists.range 1 32)
|
||||||
// lib.listToAttrs (
|
);
|
||||||
map (n: {
|
|
||||||
name = "nixbld${toString n}";
|
|
||||||
value = {
|
|
||||||
uid = 30000 + n;
|
|
||||||
gid = 30000;
|
|
||||||
groups = [ "nixbld" ];
|
|
||||||
description = "Nix build user ${toString n}";
|
|
||||||
};
|
|
||||||
}) (lib.lists.range 1 32)
|
|
||||||
);
|
|
||||||
|
|
||||||
groups = {
|
groups = {
|
||||||
root.gid = 0;
|
root.gid = 0;
|
||||||
@@ -193,13 +192,11 @@ let
|
|||||||
in
|
in
|
||||||
''
|
''
|
||||||
{
|
{
|
||||||
${
|
${lib.concatStringsSep "\n" (
|
||||||
lib.concatStringsSep "\n" (
|
builtins.map (output: ''
|
||||||
builtins.map (output: ''
|
${output} = { outPath = "${lib.getOutput output drv}"; };
|
||||||
${output} = { outPath = "${lib.getOutput output drv}"; };
|
'') outputs
|
||||||
'') outputs
|
)}
|
||||||
)
|
|
||||||
}
|
|
||||||
outputs = [ ${lib.concatStringsSep " " (builtins.map (x: "\"${x}\"") outputs)} ];
|
outputs = [ ${lib.concatStringsSep " " (builtins.map (x: "\"${x}\"") outputs)} ];
|
||||||
name = "${drv.name}";
|
name = "${drv.name}";
|
||||||
outPath = "${drv}";
|
outPath = "${drv}";
|
||||||
@@ -361,8 +358,10 @@ let
|
|||||||
"org.opencontainers.image.source" = "https://git.lix.systems/lix-project/lix";
|
"org.opencontainers.image.source" = "https://git.lix.systems/lix-project/lix";
|
||||||
"org.opencontainers.image.vendor" = "Lix project";
|
"org.opencontainers.image.vendor" = "Lix project";
|
||||||
"org.opencontainers.image.version" = pkgs.nix.version;
|
"org.opencontainers.image.version" = pkgs.nix.version;
|
||||||
"org.opencontainers.image.description" = "Minimal Lix container image, with some batteries included.";
|
"org.opencontainers.image.description" =
|
||||||
} // lib.optionalAttrs (lixRevision != null) { "org.opencontainers.image.revision" = lixRevision; };
|
"Minimal Lix container image, with some batteries included.";
|
||||||
|
}
|
||||||
|
// lib.optionalAttrs (lixRevision != null) { "org.opencontainers.image.revision" = lixRevision; };
|
||||||
};
|
};
|
||||||
|
|
||||||
meta = {
|
meta = {
|
||||||
|
|||||||
Generated
+66
-7
@@ -16,6 +16,22 @@
|
|||||||
"type": "github"
|
"type": "github"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"lowdown-src": {
|
||||||
|
"flake": false,
|
||||||
|
"locked": {
|
||||||
|
"lastModified": 1633514407,
|
||||||
|
"narHash": "sha256-Dw32tiMjdK9t3ETl5fzGrutQTzh2rufgZV4A/BbxuD4=",
|
||||||
|
"owner": "kristapsdz",
|
||||||
|
"repo": "lowdown",
|
||||||
|
"rev": "d2c2b44ff6c27b936ec27358a2653caaef8f73b8",
|
||||||
|
"type": "github"
|
||||||
|
},
|
||||||
|
"original": {
|
||||||
|
"owner": "kristapsdz",
|
||||||
|
"repo": "lowdown",
|
||||||
|
"type": "github"
|
||||||
|
}
|
||||||
|
},
|
||||||
"nix2container": {
|
"nix2container": {
|
||||||
"flake": false,
|
"flake": false,
|
||||||
"locked": {
|
"locked": {
|
||||||
@@ -32,18 +48,44 @@
|
|||||||
"type": "github"
|
"type": "github"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"nixpkgs": {
|
"nix_2_18": {
|
||||||
|
"inputs": {
|
||||||
|
"flake-compat": [
|
||||||
|
"flake-compat"
|
||||||
|
],
|
||||||
|
"lowdown-src": "lowdown-src",
|
||||||
|
"nixpkgs": "nixpkgs",
|
||||||
|
"nixpkgs-regression": [
|
||||||
|
"nixpkgs-regression"
|
||||||
|
]
|
||||||
|
},
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1733348545,
|
"lastModified": 1730375271,
|
||||||
"narHash": "sha256-b4JrUmqT0vFNx42aEN9LTWOHomkTKL/ayLopflVf81U=",
|
"narHash": "sha256-RrOFlDGmRXcVRV2p2HqHGqvzGNyWoD0Dado/BNlJ1SI=",
|
||||||
"owner": "NixOS",
|
"owner": "NixOS",
|
||||||
"repo": "nixpkgs",
|
"repo": "nix",
|
||||||
"rev": "9ecb50d2fae8680be74c08bb0a995c5383747f89",
|
"rev": "0f665ff6779454f2117dcc32e44380cda7f45523",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
"owner": "NixOS",
|
"owner": "NixOS",
|
||||||
"ref": "nixos-24.11-small",
|
"ref": "2.18.9",
|
||||||
|
"repo": "nix",
|
||||||
|
"type": "github"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"nixpkgs": {
|
||||||
|
"locked": {
|
||||||
|
"lastModified": 1705033721,
|
||||||
|
"narHash": "sha256-K5eJHmL1/kev6WuqyqqbS1cdNnSidIZ3jeqJ7GbrYnQ=",
|
||||||
|
"owner": "NixOS",
|
||||||
|
"repo": "nixpkgs",
|
||||||
|
"rev": "a1982c92d8980a0114372973cbdfe0a307f1bdea",
|
||||||
|
"type": "github"
|
||||||
|
},
|
||||||
|
"original": {
|
||||||
|
"owner": "NixOS",
|
||||||
|
"ref": "nixos-23.05-small",
|
||||||
"repo": "nixpkgs",
|
"repo": "nixpkgs",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
}
|
}
|
||||||
@@ -64,6 +106,22 @@
|
|||||||
"type": "github"
|
"type": "github"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"nixpkgs_2": {
|
||||||
|
"locked": {
|
||||||
|
"lastModified": 1757198069,
|
||||||
|
"narHash": "sha256-m3VUcOD4rTs8J7S+3dOjWMrAjw6RcITC3XYQ98zhEFs=",
|
||||||
|
"owner": "NixOS",
|
||||||
|
"repo": "nixpkgs",
|
||||||
|
"rev": "0747026fc57ecb9c28901c7f7a2b5dc40e8af43c",
|
||||||
|
"type": "github"
|
||||||
|
},
|
||||||
|
"original": {
|
||||||
|
"owner": "NixOS",
|
||||||
|
"ref": "nixos-25.05-small",
|
||||||
|
"repo": "nixpkgs",
|
||||||
|
"type": "github"
|
||||||
|
}
|
||||||
|
},
|
||||||
"pre-commit-hooks": {
|
"pre-commit-hooks": {
|
||||||
"flake": false,
|
"flake": false,
|
||||||
"locked": {
|
"locked": {
|
||||||
@@ -84,7 +142,8 @@
|
|||||||
"inputs": {
|
"inputs": {
|
||||||
"flake-compat": "flake-compat",
|
"flake-compat": "flake-compat",
|
||||||
"nix2container": "nix2container",
|
"nix2container": "nix2container",
|
||||||
"nixpkgs": "nixpkgs",
|
"nix_2_18": "nix_2_18",
|
||||||
|
"nixpkgs": "nixpkgs_2",
|
||||||
"nixpkgs-regression": "nixpkgs-regression",
|
"nixpkgs-regression": "nixpkgs-regression",
|
||||||
"pre-commit-hooks": "pre-commit-hooks"
|
"pre-commit-hooks": "pre-commit-hooks"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,8 +2,19 @@
|
|||||||
description = "Lix: A modern, delicious implementation of the Nix package manager";
|
description = "Lix: A modern, delicious implementation of the Nix package manager";
|
||||||
|
|
||||||
inputs = {
|
inputs = {
|
||||||
nixpkgs.url = "github:NixOS/nixpkgs/nixos-24.11-small";
|
nixpkgs.url = "github:NixOS/nixpkgs/nixos-25.05-small";
|
||||||
nixpkgs-regression.url = "github:NixOS/nixpkgs/215d4d0fd80ca5163643b03a33fde804a29cc1e2";
|
nixpkgs-regression.url = "github:NixOS/nixpkgs/215d4d0fd80ca5163643b03a33fde804a29cc1e2";
|
||||||
|
|
||||||
|
# Required because Nix 2.18 is not in Nixpkgs ≥ 25.05 anymore.
|
||||||
|
nix_2_18 = {
|
||||||
|
url = "github:NixOS/nix/2.18.9";
|
||||||
|
# NOTE(Raito): this is not possible because patches on libseccomp does not apply anymore on this Nix.
|
||||||
|
# Let's keep the latest known nixpkgs useable with Nix 2.18 for our tests.
|
||||||
|
# inputs.nixpkgs.follows = "nixpkgs";
|
||||||
|
inputs.nixpkgs-regression.follows = "nixpkgs-regression";
|
||||||
|
inputs.flake-compat.follows = "flake-compat";
|
||||||
|
};
|
||||||
|
|
||||||
pre-commit-hooks = {
|
pre-commit-hooks = {
|
||||||
url = "github:cachix/git-hooks.nix";
|
url = "github:cachix/git-hooks.nix";
|
||||||
flake = false;
|
flake = false;
|
||||||
@@ -25,6 +36,7 @@
|
|||||||
nixpkgs-regression,
|
nixpkgs-regression,
|
||||||
pre-commit-hooks,
|
pre-commit-hooks,
|
||||||
nix2container,
|
nix2container,
|
||||||
|
nix_2_18,
|
||||||
flake-compat,
|
flake-compat,
|
||||||
}:
|
}:
|
||||||
|
|
||||||
@@ -159,6 +171,16 @@
|
|||||||
{
|
{
|
||||||
nixStable = prev.nix;
|
nixStable = prev.nix;
|
||||||
|
|
||||||
|
nixVersions = prev.nixVersions // {
|
||||||
|
nix_2_3 = prev.nixVersions.nix_2_3.overrideAttrs (old: {
|
||||||
|
meta = old.meta // {
|
||||||
|
knownVulnerabilities = [ ];
|
||||||
|
};
|
||||||
|
});
|
||||||
|
# Nix 2.18 has been removed from Nixpkgs ≥ 25.05, so we need to reintroduce it ourselves for our tests.
|
||||||
|
nix_2_18 = nix_2_18.outputs.packages.${currentStdenv.hostPlatform.system}.default;
|
||||||
|
};
|
||||||
|
|
||||||
# Forward from the previous stage as we don’t want it to pick the lowdown override
|
# Forward from the previous stage as we don’t want it to pick the lowdown override
|
||||||
nixUnstable = prev.nixUnstable;
|
nixUnstable = prev.nixUnstable;
|
||||||
|
|
||||||
@@ -348,13 +370,16 @@
|
|||||||
in
|
in
|
||||||
pkgs.symlinkJoin {
|
pkgs.symlinkJoin {
|
||||||
name = "nixpkgs-lib-tests";
|
name = "nixpkgs-lib-tests";
|
||||||
paths =
|
paths = [
|
||||||
[ testWithNix ]
|
testWithNix
|
||||||
# NOTE: nixpkgs 24.11 is being ... *creative*, and requires this dance to override
|
]
|
||||||
# the evaluator used for the test. it will break again in the future, don't worry.
|
# NOTE: nixpkgs 25.05 is being ... *creative*, and requires this dance to override
|
||||||
++ lib.optionals pkgs.stdenv.isLinux [
|
# the evaluator used for the test. it will break again in the future, don't worry.
|
||||||
(pkgs.callPackage "${nixpkgs}/ci/eval" { nixVersions.nix_2_24 = nix; }).attrpathsSuperset
|
++ lib.optionals pkgs.stdenv.isLinux [
|
||||||
];
|
((pkgs.callPackage "${nixpkgs}/ci/eval" { inherit nix; }).attrpathsSuperset {
|
||||||
|
evalSystem = system;
|
||||||
|
})
|
||||||
|
];
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
+17
-2
@@ -11,13 +11,28 @@ namespace nix {
|
|||||||
std::string renderMarkdownToTerminal(std::string_view markdown)
|
std::string renderMarkdownToTerminal(std::string_view markdown)
|
||||||
{
|
{
|
||||||
int windowWidth = getWindowSize().second;
|
int windowWidth = getWindowSize().second;
|
||||||
|
size_t lowdown_cols = std::max(windowWidth - 5, 60);
|
||||||
|
|
||||||
struct lowdown_opts opts {
|
struct lowdown_opts opts{
|
||||||
.type = LOWDOWN_TERM,
|
.type = LOWDOWN_TERM,
|
||||||
|
#ifdef LOWDOWN_SEPARATE_TERM_OPTS
|
||||||
|
.term =
|
||||||
|
{
|
||||||
|
.cols = lowdown_cols,
|
||||||
|
.width = 0,
|
||||||
|
.hmargin = 0,
|
||||||
|
.hpadding = 4,
|
||||||
|
.vmargin = 0,
|
||||||
|
.centre = 0,
|
||||||
|
},
|
||||||
|
// maxdepth needs to be part of the ifdefs to match declaration order
|
||||||
.maxdepth = 20,
|
.maxdepth = 20,
|
||||||
.cols = (size_t) std::max(windowWidth - 5, 60),
|
#else
|
||||||
|
.maxdepth = 20,
|
||||||
|
.cols = lowdown_cols,
|
||||||
.hmargin = 0,
|
.hmargin = 0,
|
||||||
.vmargin = 0,
|
.vmargin = 0,
|
||||||
|
#endif /* LOWDOWN_SEPARATE_TERM_OPTS */
|
||||||
.feat = LOWDOWN_COMMONMARK | LOWDOWN_FENCED | LOWDOWN_DEFLIST | LOWDOWN_TABLES,
|
.feat = LOWDOWN_COMMONMARK | LOWDOWN_FENCED | LOWDOWN_DEFLIST | LOWDOWN_TABLES,
|
||||||
.oflags = LOWDOWN_TERM_NOLINK,
|
.oflags = LOWDOWN_TERM_NOLINK,
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -226,7 +226,7 @@ struct ExprAttrs
|
|||||||
AttrDef() { };
|
AttrDef() { };
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
const T & chooseByKind(const T & plain, const T & inherited, const T & inheritedFrom) const
|
T chooseByKind(const T & plain, const T & inherited, const T & inheritedFrom) const
|
||||||
{
|
{
|
||||||
switch (kind) {
|
switch (kind) {
|
||||||
case Kind::Plain:
|
case Kind::Plain:
|
||||||
|
|||||||
@@ -644,10 +644,13 @@ struct nothing : p::nothing<Rule> {
|
|||||||
static_assert(!std::is_base_of_v<semantic, Rule>);
|
static_assert(!std::is_base_of_v<semantic, Rule>);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
template<typename Self, typename OpCtx, typename AttrPathT, typename ExprT>
|
template<typename Self, typename OpCtx, typename AttrPathT, typename ExprT>
|
||||||
struct operator_semantics {
|
struct operator_semantics
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
operator_semantics() = default;
|
||||||
|
friend Self;
|
||||||
|
public:
|
||||||
struct has_attr : grammar::v1::op::has_attr {
|
struct has_attr : grammar::v1::op::has_attr {
|
||||||
AttrPathT path;
|
AttrPathT path;
|
||||||
};
|
};
|
||||||
@@ -730,5 +733,4 @@ struct operator_semantics {
|
|||||||
return popExpr();
|
return popExpr();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -362,9 +362,10 @@ bool LocalDerivationGoal::cleanupDecideWhetherDiskFull()
|
|||||||
if (statvfs(localStore.config().realStoreDir.get().c_str(), &st) == 0 &&
|
if (statvfs(localStore.config().realStoreDir.get().c_str(), &st) == 0 &&
|
||||||
(uint64_t) st.f_bavail * st.f_bsize < required)
|
(uint64_t) st.f_bavail * st.f_bsize < required)
|
||||||
diskFull = true;
|
diskFull = true;
|
||||||
if (statvfs(tmpDir.c_str(), &st) == 0 &&
|
if (statvfs(tmpDirRoot.c_str(), &st) == 0 && (uint64_t) st.f_bavail * st.f_bsize < required)
|
||||||
(uint64_t) st.f_bavail * st.f_bsize < required)
|
{
|
||||||
diskFull = true;
|
diskFull = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@@ -393,13 +394,9 @@ void LocalDerivationGoal::cleanupPostOutputsRegisteredModeCheck()
|
|||||||
|
|
||||||
void LocalDerivationGoal::cleanupPostOutputsRegisteredModeNonCheck()
|
void LocalDerivationGoal::cleanupPostOutputsRegisteredModeNonCheck()
|
||||||
{
|
{
|
||||||
/* In the past, redirected outputs were manually tracked for deletion.
|
/* Delete unused redirected outputs (when doing hash rewriting). */
|
||||||
* Now that we have the scratch outputs cleaner which are a superset of
|
for (auto & i : redirectedOutputs)
|
||||||
* redirected outputs, we just fire all uncancelled automatic deleters now.
|
deletePath(worker.store.Store::toRealPath(i.second));
|
||||||
*
|
|
||||||
* This should clean up any paths that IS NOT registered in the database.
|
|
||||||
*/
|
|
||||||
scratchOutputsCleaner.clear();
|
|
||||||
|
|
||||||
/* Delete the chroot (if we were using one). */
|
/* Delete the chroot (if we were using one). */
|
||||||
autoDelChroot.reset(); /* this runs the destructor */
|
autoDelChroot.reset(); /* this runs the destructor */
|
||||||
@@ -488,24 +485,87 @@ kj::Promise<Outcome<void, Goal::WorkResult>> LocalDerivationGoal::startBuilder()
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
createDirs(settings.buildDir.get());
|
try {
|
||||||
|
auto buildDir = worker.buildDirOverride.value_or(settings.buildDir.get());
|
||||||
|
|
||||||
/* Create a temporary directory where the build will take
|
createDirs(buildDir);
|
||||||
place. */
|
|
||||||
tmpDir = createTempDir(
|
/* Create a temporary directory where the build will take
|
||||||
settings.buildDir.get(),
|
place. */
|
||||||
"nix-build-" + std::string(drvPath.name()),
|
tmpDirRoot =
|
||||||
false,
|
createTempDir(buildDir, "nix-build-" + std::string(drvPath.name()), false, false, 0700);
|
||||||
false,
|
} catch (SysError & e) {
|
||||||
0700
|
/*
|
||||||
);
|
* Fallback to the global tmpdir and create a safe space there
|
||||||
|
* only if it's a permission error.
|
||||||
|
*/
|
||||||
|
if (e.errNo != EACCES) {
|
||||||
|
throw;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto globalTmp = defaultTempDir();
|
||||||
|
createDirs(globalTmp);
|
||||||
|
#if __APPLE__
|
||||||
|
/* macOS filesystem namespacing does not exist, to avoid breaking builds, we need to weaken
|
||||||
|
* the mode bits on the top-level directory. This avoids issues like
|
||||||
|
* https://github.com/NixOS/nix/pull/11031. */
|
||||||
|
constexpr int toplevelDirMode = 0755;
|
||||||
|
#else
|
||||||
|
constexpr int toplevelDirMode = 0700;
|
||||||
|
#endif
|
||||||
|
auto nixBuildsTmp =
|
||||||
|
createTempDir(globalTmp, fmt("nix-builds-%s", geteuid()), false, false, toplevelDirMode);
|
||||||
|
warn(
|
||||||
|
"Failed to use the system-wide build directory '%s', falling back to a temporary "
|
||||||
|
"directory inside '%s'",
|
||||||
|
settings.buildDir.get(),
|
||||||
|
nixBuildsTmp
|
||||||
|
);
|
||||||
|
worker.buildDirOverride = nixBuildsTmp;
|
||||||
|
tmpDirRoot = createTempDir(
|
||||||
|
nixBuildsTmp, "nix-build-" + std::string(drvPath.name()), false, false, 0700
|
||||||
|
);
|
||||||
|
}
|
||||||
/* The TOCTOU between the previous mkdir call and this open call is unavoidable due to
|
/* The TOCTOU between the previous mkdir call and this open call is unavoidable due to
|
||||||
* POSIX semantics.*/
|
* POSIX semantics.*/
|
||||||
tmpDirFd = AutoCloseFD{open(tmpDir.c_str(), O_RDONLY | O_NOFOLLOW | O_DIRECTORY)};
|
tmpDirRootFd = AutoCloseFD{open(tmpDirRoot.c_str(), O_RDONLY | O_NOFOLLOW | O_DIRECTORY)};
|
||||||
|
if (!tmpDirRootFd) {
|
||||||
|
throw SysError("failed to open the build temporary directory descriptor '%1%'", tmpDirRoot);
|
||||||
|
}
|
||||||
|
|
||||||
|
// place the actual build directory in a subdirectory of tmpDirRoot. if
|
||||||
|
// we do not do this a build can `chown 777` its build directory and so
|
||||||
|
// make it accessible to everyone in the system, breaking isolation. we
|
||||||
|
// also need the intermediate level to be inaccessible to others. build
|
||||||
|
// processes must be able to at least traverse to the directory though,
|
||||||
|
// without being able to chmod. this means either mode 0750 or 0710. we
|
||||||
|
// cannot use 0710 because the libarchive we link with is compiled with
|
||||||
|
// an old apple sdk that does not have O_SEARCH, which makes libarchive
|
||||||
|
// try to open tmpDirRoot for *read* and fail because g+r is not set. a
|
||||||
|
// future update to nixpkgs may fix this. until then we do not lose any
|
||||||
|
// security by setting mode 0750 because we use only a single subdir in
|
||||||
|
// tmpDirRoot, so being able to list its parent doesn't break anything.
|
||||||
|
//
|
||||||
|
// use a short name to not increase the path length too much on darwin.
|
||||||
|
// darwin has a severe sockaddr_un path length limitation, so this does
|
||||||
|
// make a difference over more evocative names. we use `b` for `build`.
|
||||||
|
tmpDir = tmpDirRoot + "/b";
|
||||||
|
if (mkdirat(tmpDirRootFd.get(), "b", 0700)) {
|
||||||
|
throw SysError("failed to create the build temporary directory '%1%'", tmpDir);
|
||||||
|
}
|
||||||
|
tmpDirFd = AutoCloseFD{openat(tmpDirRootFd.get(), "b", O_RDONLY | O_NOFOLLOW | O_DIRECTORY)};
|
||||||
if (!tmpDirFd)
|
if (!tmpDirFd)
|
||||||
throw SysError("failed to open the build temporary directory descriptor '%1%'", tmpDir);
|
throw SysError("failed to open the build temporary directory descriptor '%1%'", tmpDir);
|
||||||
|
|
||||||
chownToBuilder(tmpDirFd);
|
chownToBuilder(tmpDirFd);
|
||||||
|
if (buildUser) {
|
||||||
|
if (fchown(tmpDirRootFd.get(), -1, buildUser->getGID()) == -1) {
|
||||||
|
throw SysError("cannot change ownership of '%1%'", tmpDirRoot);
|
||||||
|
}
|
||||||
|
if (fchmod(tmpDirRootFd.get(), 0750) == -1) {
|
||||||
|
throw SysError("cannot change mode of '%1%'", tmpDirRoot);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
for (auto & [outputName, status] : initialOutputs) {
|
for (auto & [outputName, status] : initialOutputs) {
|
||||||
/* Set scratch path we'll actually use during the build.
|
/* Set scratch path we'll actually use during the build.
|
||||||
@@ -536,10 +596,6 @@ kj::Promise<Outcome<void, Goal::WorkResult>> LocalDerivationGoal::startBuilder()
|
|||||||
to use a temporary path */
|
to use a temporary path */
|
||||||
makeFallbackPath(status.known->path);
|
makeFallbackPath(status.known->path);
|
||||||
scratchOutputs.insert_or_assign(outputName, scratchPath);
|
scratchOutputs.insert_or_assign(outputName, scratchPath);
|
||||||
/* Schedule this scratch output path for automatic deletion
|
|
||||||
* if we do not cancel it, e.g. when registering the outputs.
|
|
||||||
*/
|
|
||||||
scratchOutputsCleaner.insert_or_assign(outputName, worker.store.printStorePath(scratchPath));
|
|
||||||
|
|
||||||
/* Substitute output placeholders with the scratch output paths.
|
/* Substitute output placeholders with the scratch output paths.
|
||||||
We'll use during the build. */
|
We'll use during the build. */
|
||||||
@@ -562,6 +618,8 @@ kj::Promise<Outcome<void, Goal::WorkResult>> LocalDerivationGoal::startBuilder()
|
|||||||
std::string h2 { scratchPath.hashPart() };
|
std::string h2 { scratchPath.hashPart() };
|
||||||
inputRewrites[h1] = h2;
|
inputRewrites[h1] = h2;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
redirectedOutputs.insert_or_assign(std::move(fixedFinalPath), std::move(scratchPath));
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Construct the environment passed to the builder. */
|
/* Construct the environment passed to the builder. */
|
||||||
@@ -1864,6 +1922,8 @@ void LocalDerivationGoal::runChild()
|
|||||||
|
|
||||||
if (getEnv("_NIX_TEST_NO_SANDBOX") != "1") {
|
if (getEnv("_NIX_TEST_NO_SANDBOX") != "1") {
|
||||||
Strings sandboxArgs;
|
Strings sandboxArgs;
|
||||||
|
sandboxArgs.push_back("_NIX_BUILD_TOP");
|
||||||
|
sandboxArgs.push_back(tmpDir);
|
||||||
sandboxArgs.push_back("_GLOBAL_TMP_DIR");
|
sandboxArgs.push_back("_GLOBAL_TMP_DIR");
|
||||||
sandboxArgs.push_back(globalTmpDir);
|
sandboxArgs.push_back(globalTmpDir);
|
||||||
if (allowLocalNetworking) {
|
if (allowLocalNetworking) {
|
||||||
@@ -2403,9 +2463,7 @@ SingleDrvOutputs LocalDerivationGoal::registerOutputs()
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Don't register anything, since we already have the
|
/* Don't register anything, since we already have the
|
||||||
previous versions which we're comparing.
|
previous versions which we're comparing. */
|
||||||
NOTE: this means that the `.check` path will be automatically deleted.
|
|
||||||
*/
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2429,13 +2487,8 @@ SingleDrvOutputs LocalDerivationGoal::registerOutputs()
|
|||||||
/* If it's a CA path, register it right away. This is necessary if it
|
/* If it's a CA path, register it right away. This is necessary if it
|
||||||
isn't statically known so that we can safely unlock the path before
|
isn't statically known so that we can safely unlock the path before
|
||||||
the next iteration */
|
the next iteration */
|
||||||
if (newInfo.ca) {
|
if (newInfo.ca)
|
||||||
localStore.registerValidPaths({{newInfo.path, newInfo}});
|
localStore.registerValidPaths({{newInfo.path, newInfo}});
|
||||||
/* Cancel automatic deletion of that output if it was a scratch output. */
|
|
||||||
if (auto cleaner = scratchOutputsCleaner.extract(outputName)) {
|
|
||||||
cleaner.mapped().cancel();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
infos.emplace(outputName, std::move(newInfo));
|
infos.emplace(outputName, std::move(newInfo));
|
||||||
}
|
}
|
||||||
@@ -2475,13 +2528,6 @@ SingleDrvOutputs LocalDerivationGoal::registerOutputs()
|
|||||||
infos2.insert_or_assign(newInfo.path, newInfo);
|
infos2.insert_or_assign(newInfo.path, newInfo);
|
||||||
}
|
}
|
||||||
localStore.registerValidPaths(infos2);
|
localStore.registerValidPaths(infos2);
|
||||||
|
|
||||||
/* Cancel automatic deletion of that output if it was a scratch output that we just registered. */
|
|
||||||
for (auto & [outputName, _ ] : infos) {
|
|
||||||
if (auto cleaner = scratchOutputsCleaner.extract(outputName)) {
|
|
||||||
cleaner.mapped().cancel();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* In case of a fixed-output derivation hash mismatch, throw an
|
/* In case of a fixed-output derivation hash mismatch, throw an
|
||||||
@@ -2515,13 +2561,6 @@ SingleDrvOutputs LocalDerivationGoal::registerOutputs()
|
|||||||
builtOutputs.emplace(outputName, thisRealisation);
|
builtOutputs.emplace(outputName, thisRealisation);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* NOTE: At this point, all outputs MAY NOT have been registered.
|
|
||||||
* Therefore, there may remains auto-deleters pending in the cleaner list (`scratchOutputsCleaner`).
|
|
||||||
*
|
|
||||||
* They will be finally deleted but we have no way to assert they all have been, e.g.
|
|
||||||
* `assert(scratchOutputsCleaner.size() == 0)` cannot be written.
|
|
||||||
*/
|
|
||||||
|
|
||||||
return builtOutputs;
|
return builtOutputs;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2713,16 +2752,16 @@ void LocalDerivationGoal::checkOutputs(const std::map<std::string, ValidPathInfo
|
|||||||
|
|
||||||
void LocalDerivationGoal::deleteTmpDir(bool force)
|
void LocalDerivationGoal::deleteTmpDir(bool force)
|
||||||
{
|
{
|
||||||
if (tmpDir != "") {
|
if (tmpDirRoot != "") {
|
||||||
/* Don't keep temporary directories for builtins because they
|
/* Don't keep temporary directories for builtins because they
|
||||||
might have privileged stuff (like a copy of netrc). */
|
might have privileged stuff (like a copy of netrc). */
|
||||||
if (settings.keepFailed && !force && !drv->isBuiltin()) {
|
if (settings.keepFailed && !force && !drv->isBuiltin()) {
|
||||||
printError("note: keeping build directory '%s'", tmpDir);
|
printError("note: keeping build directory '%s'", tmpDirRoot);
|
||||||
chmod(tmpDir.c_str(), 0755);
|
chmod(tmpDirRoot.c_str(), 0755);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
deletePath(tmpDir);
|
deletePath(tmpDirRoot);
|
||||||
tmpDir = "";
|
tmpDirRoot = "";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -29,12 +29,12 @@ struct LocalDerivationGoal : public DerivationGoal
|
|||||||
/**
|
/**
|
||||||
* The temporary directory.
|
* The temporary directory.
|
||||||
*/
|
*/
|
||||||
Path tmpDir;
|
Path tmpDirRoot, tmpDir;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The temporary directory file descriptor
|
* The temporary directory file descriptor
|
||||||
*/
|
*/
|
||||||
AutoCloseFD tmpDirFd;
|
AutoCloseFD tmpDirRootFd, tmpDirFd;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The path of the temporary directory in the sandbox.
|
* The path of the temporary directory in the sandbox.
|
||||||
@@ -107,6 +107,8 @@ struct LocalDerivationGoal : public DerivationGoal
|
|||||||
* Hash rewriting.
|
* Hash rewriting.
|
||||||
*/
|
*/
|
||||||
StringMap inputRewrites, outputRewrites;
|
StringMap inputRewrites, outputRewrites;
|
||||||
|
typedef map<StorePath, StorePath> RedirectedOutputs;
|
||||||
|
RedirectedOutputs redirectedOutputs;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The outputs paths used during the build.
|
* The outputs paths used during the build.
|
||||||
@@ -123,19 +125,6 @@ struct LocalDerivationGoal : public DerivationGoal
|
|||||||
* self-references.
|
* self-references.
|
||||||
*/
|
*/
|
||||||
OutputPathMap scratchOutputs;
|
OutputPathMap scratchOutputs;
|
||||||
/**
|
|
||||||
* Output paths used during the build are scheduled for
|
|
||||||
* automatic cleanup unless they have been successfully built.
|
|
||||||
*
|
|
||||||
* `registerOutputs` take care of cancelling the cleanups
|
|
||||||
* and clearing this vector.
|
|
||||||
*
|
|
||||||
* `startBuilder` take care of filling this vector
|
|
||||||
* as `scratchOutputs` gets filled.
|
|
||||||
*
|
|
||||||
* This is a map from output names to automatic delete handles.
|
|
||||||
*/
|
|
||||||
std::map<std::string, AutoDelete> scratchOutputsCleaner;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Path registration info from the previous round, if we're
|
* Path registration info from the previous round, if we're
|
||||||
|
|||||||
@@ -26,12 +26,14 @@ R""(
|
|||||||
; Allow getpwuid.
|
; Allow getpwuid.
|
||||||
(allow mach-lookup (global-name "com.apple.system.opendirectoryd.libinfo"))
|
(allow mach-lookup (global-name "com.apple.system.opendirectoryd.libinfo"))
|
||||||
|
|
||||||
; Access to /tmp.
|
; Access to /tmp and the build directory.
|
||||||
; The network-outbound/network-inbound ones are for unix domain sockets, which
|
; The network-outbound/network-inbound ones are for unix domain sockets, which
|
||||||
; we allow access to in TMPDIR (but if we allow them more broadly, you could in
|
; we allow access to in TMPDIR (but if we allow them more broadly, you could in
|
||||||
; theory escape the sandbox)
|
; theory escape the sandbox)
|
||||||
(allow file* process-exec network-outbound network-inbound
|
(allow file* process-exec network-outbound network-inbound
|
||||||
(literal "/tmp") (subpath TMPDIR))
|
(literal "/tmp")
|
||||||
|
(subpath TMPDIR)
|
||||||
|
(subpath (param "_NIX_BUILD_TOP")))
|
||||||
|
|
||||||
; Some packages like to read the system version.
|
; Some packages like to read the system version.
|
||||||
(allow file-read*
|
(allow file-read*
|
||||||
|
|||||||
@@ -193,6 +193,7 @@ public:
|
|||||||
Store & evalStore;
|
Store & evalStore;
|
||||||
kj::AsyncIoContext & aio;
|
kj::AsyncIoContext & aio;
|
||||||
AsyncSemaphore substitutions, localBuilds;
|
AsyncSemaphore substitutions, localBuilds;
|
||||||
|
std::optional<Path> buildDirOverride;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
kj::TaskSet children;
|
kj::TaskSet children;
|
||||||
|
|||||||
@@ -45,8 +45,15 @@ std::string SecretKey::signDetached(std::string_view data) const
|
|||||||
{
|
{
|
||||||
unsigned char sig[crypto_sign_BYTES];
|
unsigned char sig[crypto_sign_BYTES];
|
||||||
unsigned long long sigLen;
|
unsigned long long sigLen;
|
||||||
crypto_sign_detached(sig, &sigLen, charptr_cast<const unsigned char *>(data.data()), data.size(),
|
crypto_sign_detached(
|
||||||
charptr_cast<const unsigned char *>(key.data()));
|
sig,
|
||||||
|
&sigLen,
|
||||||
|
// the following is not a string function so no null termination issues are possible here.
|
||||||
|
// NOLINTNEXTLINE(bugprone-suspicious-stringview-data-usage)
|
||||||
|
charptr_cast<const unsigned char *>(data.data()),
|
||||||
|
data.size(),
|
||||||
|
charptr_cast<const unsigned char *>(key.data())
|
||||||
|
);
|
||||||
return name + ":" + base64Encode(std::string(reinterpret_cast<char *>(sig), sigLen));
|
return name + ":" + base64Encode(std::string(reinterpret_cast<char *>(sig), sigLen));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -146,7 +146,7 @@ SQLiteStmt::Use::~Use()
|
|||||||
SQLiteStmt::Use & SQLiteStmt::Use::operator () (std::string_view value, bool notNull)
|
SQLiteStmt::Use & SQLiteStmt::Use::operator () (std::string_view value, bool notNull)
|
||||||
{
|
{
|
||||||
if (notNull) {
|
if (notNull) {
|
||||||
if (sqlite3_bind_text(stmt, curArg++, value.data(), -1, SQLITE_TRANSIENT) != SQLITE_OK)
|
if (sqlite3_bind_text(stmt, curArg++, value.data(), value.length(), SQLITE_TRANSIENT) != SQLITE_OK)
|
||||||
SQLiteError::throw_(stmt.db, "binding argument");
|
SQLiteError::throw_(stmt.db, "binding argument");
|
||||||
} else
|
} else
|
||||||
bind();
|
bind();
|
||||||
|
|||||||
@@ -259,6 +259,7 @@ struct BrotliCompressionSink : ChunkedCompressionSink
|
|||||||
|
|
||||||
void writeInternal(std::string_view data) override
|
void writeInternal(std::string_view data) override
|
||||||
{
|
{
|
||||||
|
// NOLINTNEXTLINE(bugprone-suspicious-stringview-data-usage)
|
||||||
auto next_in = charptr_cast<const uint8_t *>(data.data());
|
auto next_in = charptr_cast<const uint8_t *>(data.data());
|
||||||
size_t avail_in = data.size();
|
size_t avail_in = data.size();
|
||||||
uint8_t * next_out = outbuf;
|
uint8_t * next_out = outbuf;
|
||||||
|
|||||||
@@ -518,7 +518,7 @@ static void _deletePath(const Path & path, uint64_t & bytesFreed)
|
|||||||
throw SysError("opening directory '%1%'", path);
|
throw SysError("opening directory '%1%'", path);
|
||||||
}
|
}
|
||||||
|
|
||||||
_deletePath(dirfd.get(), baseNameOf(path).data(), bytesFreed);
|
_deletePath(dirfd.get(), std::string(baseNameOf(path)), bytesFreed);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -38,6 +38,6 @@ const nlohmann::json & ensureType(
|
|||||||
nlohmann::json(expectedType).type_name(),
|
nlohmann::json(expectedType).type_name(),
|
||||||
value.type_name());
|
value.type_name());
|
||||||
|
|
||||||
return value;
|
return value; // NOLINT(bugprone-return-const-ref-from-parameter)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -253,12 +253,12 @@ extern Verbosity verbosity;
|
|||||||
* level. Note that this has to be implemented as a macro to ensure that the
|
* level. Note that this has to be implemented as a macro to ensure that the
|
||||||
* arguments are evaluated lazily.
|
* arguments are evaluated lazily.
|
||||||
*/
|
*/
|
||||||
#define printMsgUsing(loggerParam, level, args...) \
|
#define printMsgUsing(loggerParam, level, args...) \
|
||||||
do { \
|
do { \
|
||||||
auto __lvl = level; \
|
auto _lix_logger_print_lvl = level; \
|
||||||
if (__lvl <= nix::verbosity) { \
|
if (_lix_logger_print_lvl <= nix::verbosity) { \
|
||||||
loggerParam->log(__lvl, fmt(args)); \
|
loggerParam->log(_lix_logger_print_lvl, fmt(args)); \
|
||||||
} \
|
} \
|
||||||
} while (0)
|
} while (0)
|
||||||
#define printMsg(level, args...) printMsgUsing(logger, level, args)
|
#define printMsg(level, args...) printMsgUsing(logger, level, args)
|
||||||
|
|
||||||
|
|||||||
@@ -53,7 +53,7 @@ void RefScanSink::operator () (std::string_view data)
|
|||||||
previous fragment and the start of the current fragment. */
|
previous fragment and the start of the current fragment. */
|
||||||
auto s = tail;
|
auto s = tail;
|
||||||
auto tailLen = std::min(data.size(), refLength);
|
auto tailLen = std::min(data.size(), refLength);
|
||||||
s.append(data.data(), tailLen);
|
s.append(data.data(), tailLen); // NOLINT(bugprone-suspicious-stringview-data-usage)
|
||||||
search(s, hashes, seen);
|
search(s, hashes, seen);
|
||||||
|
|
||||||
search(data, hashes, seen);
|
search(data, hashes, seen);
|
||||||
|
|||||||
+10
-4
@@ -68,13 +68,19 @@ typename T::mapped_type * get(T & map, const typename T::key_type & key)
|
|||||||
/**
|
/**
|
||||||
* Get a value for the specified key from an associate container, or a default value if the key isn't present.
|
* Get a value for the specified key from an associate container, or a default value if the key isn't present.
|
||||||
*/
|
*/
|
||||||
template <class T>
|
template<class T>
|
||||||
const typename T::mapped_type & getOr(T & map,
|
const typename T::mapped_type & getOr(
|
||||||
|
T & map [[clang::lifetimebound]],
|
||||||
const typename T::key_type & key,
|
const typename T::key_type & key,
|
||||||
const typename T::mapped_type & defaultValue)
|
const typename T::mapped_type & defaultValue [[clang::lifetimebound]]
|
||||||
|
)
|
||||||
{
|
{
|
||||||
auto i = map.find(key);
|
auto i = map.find(key);
|
||||||
if (i == map.end()) return defaultValue;
|
if (i == map.end()) {
|
||||||
|
/* FIXME(Raito): `[[clang::lifetimebound]]` has no effect on `defaultValue` warning. */
|
||||||
|
// NOLINTNEXTLINE(bugprone-return-const-ref-from-parameter)
|
||||||
|
return defaultValue;
|
||||||
|
}
|
||||||
return i->second;
|
return i->second;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -331,6 +331,11 @@ editline = dependency('libeditline', 'editline', version : '>=1.14', required :
|
|||||||
|
|
||||||
lowdown = dependency('lowdown', version : '>=0.9.0', required : true, include_type : 'system')
|
lowdown = dependency('lowdown', version : '>=0.9.0', required : true, include_type : 'system')
|
||||||
|
|
||||||
|
# TODO(sterni): drop the corresponding #ifdef after NixOS 25.05 is EOL which still distributes lowdown < 1.4.0
|
||||||
|
if lowdown.version().version_compare('>= 1.4.0')
|
||||||
|
add_project_arguments('-DLOWDOWN_SEPARATE_TERM_OPTS', language: 'cpp')
|
||||||
|
endif
|
||||||
|
|
||||||
# HACK(Qyriad): rapidcheck's pkg-config doesn't include the libs lol
|
# HACK(Qyriad): rapidcheck's pkg-config doesn't include the libs lol
|
||||||
# Note: technically we 'check' for rapidcheck twice, for the internal-api-docs handling above,
|
# Note: technically we 'check' for rapidcheck twice, for the internal-api-docs handling above,
|
||||||
# but Meson will cache the result of the first one, and the required : arguments are different.
|
# but Meson will cache the result of the first one, and the required : arguments are different.
|
||||||
|
|||||||
+2
-1
@@ -39,7 +39,8 @@ stdenv.mkDerivation rec {
|
|||||||
propagatedBuildInputs = [
|
propagatedBuildInputs = [
|
||||||
openssl
|
openssl
|
||||||
zlib
|
zlib
|
||||||
] ++ lib.optional (stdenv.cc.isClang && stdenv.targetPlatform.isStatic) empty-libgcc_eh;
|
]
|
||||||
|
++ lib.optional (stdenv.cc.isClang && stdenv.targetPlatform.isStatic) empty-libgcc_eh;
|
||||||
|
|
||||||
# FIXME: separate the binaries from the stuff that user systems actually use
|
# FIXME: separate the binaries from the stuff that user systems actually use
|
||||||
# This runs into a terrible UX issue in Lix and I just don't want to debug it
|
# This runs into a terrible UX issue in Lix and I just don't want to debug it
|
||||||
|
|||||||
@@ -1,106 +0,0 @@
|
|||||||
From d0f2a5bc2300b96b2434c7838184c1dfd6a639f5 Mon Sep 17 00:00:00 2001
|
|
||||||
From: Rebecca Turner <rbt@sent.as>
|
|
||||||
Date: Sun, 8 Sep 2024 15:42:42 -0700
|
|
||||||
Subject: [PATCH 1/2] Recognize Meta+Left and Meta+Right
|
|
||||||
|
|
||||||
Recognize `Alt-Left` and `Alt-Right` for navigating by words in more
|
|
||||||
terminals/shells/platforms.
|
|
||||||
|
|
||||||
I'm not sure exactly where to find canonical documentation for these
|
|
||||||
codes, but this seems to match what my terminal produces (macOS + iTerm2
|
|
||||||
+ Fish + Tmux).
|
|
||||||
|
|
||||||
It might also be nice to have some more support for editing the bindings
|
|
||||||
for these characters; sequences of more than one character are not
|
|
||||||
supported by `el_bind_key` and similar.
|
|
||||||
|
|
||||||
Originally from: https://github.com/troglobit/editline/pull/70
|
|
||||||
This patch is applied upstream: https://gerrit.lix.systems/c/lix/+/1883
|
|
||||||
|
|
||||||
---
|
|
||||||
src/editline.c | 29 +++++++++++++++++++++++++++--
|
|
||||||
1 file changed, 27 insertions(+), 2 deletions(-)
|
|
||||||
|
|
||||||
diff --git a/src/editline.c b/src/editline.c
|
|
||||||
index 5ec9afb..d1cfbbc 100644
|
|
||||||
--- a/src/editline.c
|
|
||||||
+++ b/src/editline.c
|
|
||||||
@@ -1034,6 +1034,30 @@ static el_status_t meta(void)
|
|
||||||
return CSeof;
|
|
||||||
|
|
||||||
#ifdef CONFIG_ANSI_ARROWS
|
|
||||||
+ /* See: https://en.wikipedia.org/wiki/ANSI_escape_code */
|
|
||||||
+ /* Recognize ANSI escapes for `Meta+Left` and `Meta+Right`. */
|
|
||||||
+ if (c == '\e') {
|
|
||||||
+ switch (tty_get()) {
|
|
||||||
+ case '[':
|
|
||||||
+ {
|
|
||||||
+ switch (tty_get()) {
|
|
||||||
+ /* \e\e[C = Meta+Left */
|
|
||||||
+ case 'C': return fd_word();
|
|
||||||
+ /* \e\e[D = Meta+Right */
|
|
||||||
+ case 'D': return bk_word();
|
|
||||||
+ default:
|
|
||||||
+ break;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ return el_ring_bell();
|
|
||||||
+ }
|
|
||||||
+ default:
|
|
||||||
+ break;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ return el_ring_bell();
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
/* Also include VT-100 arrows. */
|
|
||||||
if (c == '[' || c == 'O') {
|
|
||||||
switch (tty_get()) {
|
|
||||||
@@ -1043,6 +1067,7 @@ static el_status_t meta(void)
|
|
||||||
char seq[4] = { 0 };
|
|
||||||
seq[0] = tty_get();
|
|
||||||
|
|
||||||
+ /* \e[1~ */
|
|
||||||
if (seq[0] == '~')
|
|
||||||
return beg_line(); /* Home */
|
|
||||||
|
|
||||||
@@ -1050,9 +1075,9 @@ static el_status_t meta(void)
|
|
||||||
seq[c] = tty_get();
|
|
||||||
|
|
||||||
if (!strncmp(seq, ";5C", 3))
|
|
||||||
- return fd_word(); /* Ctrl+Right */
|
|
||||||
+ return fd_word(); /* \e[1;5C = Ctrl+Right */
|
|
||||||
if (!strncmp(seq, ";5D", 3))
|
|
||||||
- return bk_word(); /* Ctrl+Left */
|
|
||||||
+ return bk_word(); /* \e[1;5D = Ctrl+Left */
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
From 4c4455353a0a88bee09d5f27c28f81f747682fed Mon Sep 17 00:00:00 2001
|
|
||||||
From: Rebecca Turner <rbt@sent.as>
|
|
||||||
Date: Mon, 9 Sep 2024 09:44:44 -0700
|
|
||||||
Subject: [PATCH 2/2] Add support for \e[1;3C and \e[1;3D
|
|
||||||
|
|
||||||
---
|
|
||||||
src/editline.c | 6 ++++--
|
|
||||||
1 file changed, 4 insertions(+), 2 deletions(-)
|
|
||||||
|
|
||||||
diff --git a/src/editline.c b/src/editline.c
|
|
||||||
index d1cfbbc..350b5cb 100644
|
|
||||||
--- a/src/editline.c
|
|
||||||
+++ b/src/editline.c
|
|
||||||
@@ -1074,9 +1074,11 @@ static el_status_t meta(void)
|
|
||||||
for (c = 1; c < 3; c++)
|
|
||||||
seq[c] = tty_get();
|
|
||||||
|
|
||||||
- if (!strncmp(seq, ";5C", 3))
|
|
||||||
+ if (!strncmp(seq, ";5C", 3)
|
|
||||||
+ || !strncmp(seq, ";3C", 3))
|
|
||||||
return fd_word(); /* \e[1;5C = Ctrl+Right */
|
|
||||||
- if (!strncmp(seq, ";5D", 3))
|
|
||||||
+ if (!strncmp(seq, ";5D", 3)
|
|
||||||
+ || !strncmp(seq, ";3D", 3))
|
|
||||||
return bk_word(); /* \e[1;5D = Ctrl+Left */
|
|
||||||
|
|
||||||
break;
|
|
||||||
+84
-91
@@ -86,14 +86,6 @@
|
|||||||
boehmgc-nix = boehmgc.override { enableLargeConfig = true; };
|
boehmgc-nix = boehmgc.override { enableLargeConfig = true; };
|
||||||
|
|
||||||
editline-lix = editline.overrideAttrs (prev: {
|
editline-lix = editline.overrideAttrs (prev: {
|
||||||
patches = (prev.patches or [ ]) ++ [
|
|
||||||
# Recognize `Alt-Left` and `Alt-Right` for navigating by words in more
|
|
||||||
# terminals/shells/platforms.
|
|
||||||
#
|
|
||||||
# See: https://github.com/troglobit/editline/pull/70
|
|
||||||
./nix-support/editline.patch
|
|
||||||
];
|
|
||||||
|
|
||||||
configureFlags = (prev.configureFlags or [ ]) ++ [
|
configureFlags = (prev.configureFlags or [ ]) ++ [
|
||||||
# Enable SIGSTOP (Ctrl-Z) behavior.
|
# Enable SIGSTOP (Ctrl-Z) behavior.
|
||||||
(lib.enableFeature true "sigstop")
|
(lib.enableFeature true "sigstop")
|
||||||
@@ -186,6 +178,8 @@ assert (lintInsteadOfBuild -> lix-clang-tidy != null);
|
|||||||
stdenv.mkDerivation (finalAttrs: {
|
stdenv.mkDerivation (finalAttrs: {
|
||||||
inherit pname version;
|
inherit pname version;
|
||||||
|
|
||||||
|
__structuredAttrs = true;
|
||||||
|
|
||||||
src = fileset.toSource {
|
src = fileset.toSource {
|
||||||
root = ./.;
|
root = ./.;
|
||||||
fileset = fileset.intersection baseFiles (
|
fileset = fileset.intersection baseFiles (
|
||||||
@@ -206,14 +200,13 @@ stdenv.mkDerivation (finalAttrs: {
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
VERSION_SUFFIX = versionSuffix;
|
outputs = [
|
||||||
|
"out"
|
||||||
outputs =
|
]
|
||||||
[ "out" ]
|
++ lib.optionals (!finalAttrs.dontBuild) [
|
||||||
++ lib.optionals (!finalAttrs.dontBuild) [
|
"dev"
|
||||||
"dev"
|
"doc"
|
||||||
"doc"
|
];
|
||||||
];
|
|
||||||
|
|
||||||
dontBuild = lintInsteadOfBuild;
|
dontBuild = lintInsteadOfBuild;
|
||||||
|
|
||||||
@@ -249,81 +242,79 @@ stdenv.mkDerivation (finalAttrs: {
|
|||||||
# We only include CMake so that Meson can locate toml11, which only ships CMake dependency metadata.
|
# We only include CMake so that Meson can locate toml11, which only ships CMake dependency metadata.
|
||||||
dontUseCmakeConfigure = true;
|
dontUseCmakeConfigure = true;
|
||||||
|
|
||||||
nativeBuildInputs =
|
nativeBuildInputs = [
|
||||||
[
|
# python3.withPackages does not splice properly, see https://github.com/NixOS/nixpkgs/issues/305858
|
||||||
# python3.withPackages does not splice properly, see https://github.com/NixOS/nixpkgs/issues/305858
|
(python3.pythonOnBuildForHost.withPackages (p: [
|
||||||
(python3.pythonOnBuildForHost.withPackages (p: [
|
p.pytest
|
||||||
p.pytest
|
p.pytest-xdist
|
||||||
p.pytest-xdist
|
p.python-frontmatter
|
||||||
p.python-frontmatter
|
]))
|
||||||
]))
|
meson
|
||||||
meson
|
ninja
|
||||||
ninja
|
cmake
|
||||||
cmake
|
rustc
|
||||||
rustc
|
capnproto-lix
|
||||||
capnproto-lix
|
]
|
||||||
]
|
++ [
|
||||||
++ [
|
(lib.getBin lowdown-unsandboxed)
|
||||||
(lib.getBin lowdown-unsandboxed)
|
mdbook
|
||||||
mdbook
|
mdbook-linkcheck
|
||||||
mdbook-linkcheck
|
]
|
||||||
]
|
++ [
|
||||||
++ [
|
pkg-config
|
||||||
pkg-config
|
|
||||||
|
|
||||||
# Tests
|
# Tests
|
||||||
git
|
git
|
||||||
mercurial
|
mercurial
|
||||||
jq
|
jq
|
||||||
lsof
|
lsof
|
||||||
]
|
]
|
||||||
++ lib.optional hostPlatform.isLinux util-linuxMinimal
|
++ lib.optional hostPlatform.isLinux util-linuxMinimal
|
||||||
++ lib.optional (!officialRelease && buildUnreleasedNotes) build-release-notes
|
++ lib.optional (!officialRelease && buildUnreleasedNotes) build-release-notes
|
||||||
++ lib.optional internalApiDocs doxygen
|
++ lib.optional internalApiDocs doxygen
|
||||||
++ lib.optionals lintInsteadOfBuild [
|
++ lib.optionals lintInsteadOfBuild [
|
||||||
# required for a wrapped clang-tidy
|
# required for a wrapped clang-tidy
|
||||||
llvmPackages.clang-tools
|
llvmPackages.clang-tools
|
||||||
# load-bearing order (just as below); the actual stdenv wrapped clang
|
# load-bearing order (just as below); the actual stdenv wrapped clang
|
||||||
# needs to precede the unwrapped clang in PATH such that calling `clang`
|
# needs to precede the unwrapped clang in PATH such that calling `clang`
|
||||||
# can compile things.
|
# can compile things.
|
||||||
stdenv.cc
|
stdenv.cc
|
||||||
# required for run-clang-tidy
|
# required for run-clang-tidy
|
||||||
llvmPackages.clang-unwrapped
|
llvmPackages.clang-unwrapped
|
||||||
];
|
];
|
||||||
|
|
||||||
buildInputs =
|
buildInputs = [
|
||||||
[
|
curl
|
||||||
curl
|
bzip2
|
||||||
bzip2
|
xz
|
||||||
xz
|
brotli
|
||||||
brotli
|
editline-lix
|
||||||
editline-lix
|
openssl
|
||||||
openssl
|
sqlite
|
||||||
sqlite
|
libarchive
|
||||||
libarchive
|
boost
|
||||||
boost
|
lowdown
|
||||||
lowdown
|
libsodium
|
||||||
libsodium
|
toml11
|
||||||
toml11
|
pegtl
|
||||||
pegtl
|
capnproto-lix
|
||||||
capnproto-lix
|
]
|
||||||
]
|
++ lib.optionals hostPlatform.isLinux [
|
||||||
++ lib.optionals hostPlatform.isLinux [
|
libseccomp
|
||||||
libseccomp
|
busybox-sandbox-shell
|
||||||
busybox-sandbox-shell
|
passt-lix
|
||||||
passt-lix
|
]
|
||||||
]
|
++ lib.optionals (
|
||||||
++ lib.optionals (
|
stdenv.hostPlatform.isDarwin && lib.versionOlder stdenv.hostPlatform.darwinSdkVersion "11.0"
|
||||||
stdenv.hostPlatform.isDarwin && lib.versionOlder stdenv.hostPlatform.darwinSdkVersion "11.0"
|
) [ apple-sdk_11 ]
|
||||||
) [ apple-sdk_11 ]
|
++ lib.optional internalApiDocs rapidcheck
|
||||||
++ lib.optional internalApiDocs rapidcheck
|
++ lib.optional hostPlatform.isx86_64 libcpuid
|
||||||
++ lib.optional hostPlatform.isx86_64 libcpuid
|
# There have been issues building these dependencies
|
||||||
# There have been issues building these dependencies
|
++ lib.optional (hostPlatform.canExecute buildPlatform) aws-sdk-cpp-nix
|
||||||
++ lib.optional (hostPlatform.canExecute buildPlatform) aws-sdk-cpp-nix
|
++ lib.optionals (finalAttrs.dontBuild) maybePropagatedInputs
|
||||||
++ lib.optionals (finalAttrs.dontBuild) maybePropagatedInputs
|
# I am so sorry. This is because checkInputs are required to pass
|
||||||
# I am so sorry. This is because checkInputs are required to pass
|
# configure, but we don't actually want to *run* the checks here.
|
||||||
# configure, but we don't actually want to *run* the checks here.
|
++ lib.optionals lintInsteadOfBuild finalAttrs.checkInputs;
|
||||||
++ lib.optionals lintInsteadOfBuild finalAttrs.checkInputs;
|
|
||||||
|
|
||||||
checkInputs = [
|
checkInputs = [
|
||||||
gtest
|
gtest
|
||||||
@@ -334,9 +325,9 @@ stdenv.mkDerivation (finalAttrs: {
|
|||||||
|
|
||||||
disallowedReferences = [ boost ];
|
disallowedReferences = [ boost ];
|
||||||
|
|
||||||
# Needed for Meson to find Boost.
|
|
||||||
# https://github.com/NixOS/nixpkgs/issues/86131.
|
|
||||||
env = {
|
env = {
|
||||||
|
# Needed for Meson to find Boost.
|
||||||
|
# https://github.com/NixOS/nixpkgs/issues/86131.
|
||||||
BOOST_INCLUDEDIR = "${lib.getDev boost}/include";
|
BOOST_INCLUDEDIR = "${lib.getDev boost}/include";
|
||||||
BOOST_LIBRARYDIR = "${lib.getLib boost}/lib";
|
BOOST_LIBRARYDIR = "${lib.getLib boost}/lib";
|
||||||
|
|
||||||
@@ -344,6 +335,8 @@ stdenv.mkDerivation (finalAttrs: {
|
|||||||
# Turns out the Nix-generated Cargo dependencies are named the same as they
|
# Turns out the Nix-generated Cargo dependencies are named the same as they
|
||||||
# would be in a Cargo registry cache.
|
# would be in a Cargo registry cache.
|
||||||
MESON_PACKAGE_CACHE_DIR = finalAttrs.cargoDeps;
|
MESON_PACKAGE_CACHE_DIR = finalAttrs.cargoDeps;
|
||||||
|
|
||||||
|
VERSION_SUFFIX = versionSuffix;
|
||||||
};
|
};
|
||||||
|
|
||||||
cargoDeps = rustPlatform.importCargoLock { lockFile = ./Cargo.lock; };
|
cargoDeps = rustPlatform.importCargoLock { lockFile = ./Cargo.lock; };
|
||||||
|
|||||||
+12
-13
@@ -35,19 +35,18 @@ perl.pkgs.toPerlModule (
|
|||||||
ninja
|
ninja
|
||||||
];
|
];
|
||||||
|
|
||||||
buildInputs =
|
buildInputs = [
|
||||||
[
|
nix
|
||||||
nix
|
curl
|
||||||
curl
|
bzip2
|
||||||
bzip2
|
xz
|
||||||
xz
|
perl
|
||||||
perl
|
boost
|
||||||
boost
|
perlPackages.DBI
|
||||||
perlPackages.DBI
|
perlPackages.DBDSQLite
|
||||||
perlPackages.DBDSQLite
|
]
|
||||||
]
|
++ lib.optional (stdenv.isLinux || stdenv.isDarwin) libsodium
|
||||||
++ lib.optional (stdenv.isLinux || stdenv.isDarwin) libsodium
|
++ lib.optional stdenv.isDarwin darwin.apple_sdk.frameworks.Security;
|
||||||
++ lib.optional stdenv.isDarwin darwin.apple_sdk.frameworks.Security;
|
|
||||||
|
|
||||||
# Nixpkgs' Meson hook likes to set this to "plain".
|
# Nixpkgs' Meson hook likes to set this to "plain".
|
||||||
mesonBuildType = "debugoptimized";
|
mesonBuildType = "debugoptimized";
|
||||||
|
|||||||
+1
-4
@@ -19,10 +19,7 @@ endif
|
|||||||
|
|
||||||
cxx = meson.get_compiler('cpp')
|
cxx = meson.get_compiler('cpp')
|
||||||
|
|
||||||
# Really version 5.8.0, but Perl's version string is of the form
|
perl = find_program('perl')
|
||||||
# "This is perl 5, version 38, subversion 2", for 5.38.2, so as far
|
|
||||||
# as Meson is concerned, the version of Perl we need is 8 or greater.
|
|
||||||
perl = find_program('perl', version : '>=8')
|
|
||||||
|
|
||||||
# "compiler to convert Perl XS code into C code"
|
# "compiler to convert Perl XS code into C code"
|
||||||
xsubpp = find_program('xsubpp')
|
xsubpp = find_program('xsubpp')
|
||||||
|
|||||||
@@ -80,4 +80,4 @@ out="$(nix-build 2>&1 failing.nix \
|
|||||||
[[ "$out" =~ .*"note: keeping build directory".* ]]
|
[[ "$out" =~ .*"note: keeping build directory".* ]]
|
||||||
|
|
||||||
build_dir="$(grep "note: keeping build" <<< "$out" | sed -E "s/^(.*)note: keeping build directory '(.*)'(.*)$/\2/")"
|
build_dir="$(grep "note: keeping build" <<< "$out" | sed -E "s/^(.*)note: keeping build directory '(.*)'(.*)$/\2/")"
|
||||||
[[ "foo" = $(<"$build_dir"/bar) ]]
|
[[ "foo" = $(<"$build_dir"/b/bar) ]]
|
||||||
|
|||||||
@@ -174,3 +174,28 @@ test "$(<<<"$out" grep -E '^error:' | wc -l)" = 3
|
|||||||
<<<"$out" grepQuiet -E "error: 2 dependencies of derivation '.*-x4\\.drv' failed to build"
|
<<<"$out" grepQuiet -E "error: 2 dependencies of derivation '.*-x4\\.drv' failed to build"
|
||||||
<<<"$out" grepQuiet -vE "hash mismatch in fixed-output derivation '.*-x3\\.drv'"
|
<<<"$out" grepQuiet -vE "hash mismatch in fixed-output derivation '.*-x3\\.drv'"
|
||||||
<<<"$out" grepQuiet -vE "hash mismatch in fixed-output derivation '.*-x2\\.drv'"
|
<<<"$out" grepQuiet -vE "hash mismatch in fixed-output derivation '.*-x2\\.drv'"
|
||||||
|
|
||||||
|
# Ensure when if the system build dir is inaccessible, we can still build things
|
||||||
|
BUILD_DIR=$(mktemp -d)
|
||||||
|
chmod 0000 "$BUILD_DIR"
|
||||||
|
nix --build-dir "$BUILD_DIR" build -E 'with import ./config.nix; mkDerivation { name = "test"; buildCommand = "echo rawr > $out"; }' --impure --no-link
|
||||||
|
|
||||||
|
# ensure that the build directory parent is not world-accessible
|
||||||
|
chmod 0755 "$BUILD_DIR"
|
||||||
|
FIFO="$BUILD_DIR/fifo"
|
||||||
|
mkfifo "$FIFO"
|
||||||
|
(
|
||||||
|
echo > "$FIFO"
|
||||||
|
trap 'echo > "$FIFO"' EXIT
|
||||||
|
mode=$(stat -c %a $BUILD_DIR/b/*)
|
||||||
|
[ "$mode" = "700" -o "$mode" = "710" ]
|
||||||
|
) &
|
||||||
|
nix build --build-dir "$BUILD_DIR/b" -E '
|
||||||
|
with import ./config.nix; mkDerivation {
|
||||||
|
name = "test";
|
||||||
|
buildCommand = "cat '"$FIFO"'; cat '"$FIFO"' > $out";
|
||||||
|
}' \
|
||||||
|
--extra-sandbox-paths "$FIFO" \
|
||||||
|
--impure \
|
||||||
|
--no-link
|
||||||
|
wait
|
||||||
|
|||||||
@@ -45,7 +45,7 @@ test_custom_build_dir() {
|
|||||||
[ "$status" = "100" ]
|
[ "$status" = "100" ]
|
||||||
[[ 1 == "$(count "$customBuildDir/nix-build-"*)" ]]
|
[[ 1 == "$(count "$customBuildDir/nix-build-"*)" ]]
|
||||||
local buildDir="$customBuildDir/nix-build-"*
|
local buildDir="$customBuildDir/nix-build-"*
|
||||||
grep $checkBuildId $buildDir/checkBuildId
|
grep $checkBuildId $buildDir/b/checkBuildId
|
||||||
}
|
}
|
||||||
test_custom_build_dir
|
test_custom_build_dir
|
||||||
|
|
||||||
|
|||||||
@@ -1,12 +1,11 @@
|
|||||||
nix-repl> 1 + 1
|
nix-repl> 1 + 1
|
||||||
2
|
2
|
||||||
|
|
||||||
nix-repl> :doc builtins.head
|
nix-repl> :doc builtins.add
|
||||||
Synopsis: builtins.head list
|
Synopsis: builtins.add e1 e2
|
||||||
|
|
||||||
|
Return the sum of the numbers e1 and e2.
|
||||||
|
|
||||||
Return the first element of a list; abort evaluation if
|
|
||||||
the argument isn’t a list or is an empty list. You can
|
|
||||||
test whether a list is empty by comparing it with [].
|
|
||||||
|
|
||||||
nix-repl> f = a: "" + a
|
nix-repl> f = a: "" + a
|
||||||
|
|
||||||
|
|||||||
@@ -148,9 +148,6 @@ in
|
|||||||
|
|
||||||
symlinkResolvconf = runNixOSTestFor "x86_64-linux" ./symlink-resolvconf.nix;
|
symlinkResolvconf = runNixOSTestFor "x86_64-linux" ./symlink-resolvconf.nix;
|
||||||
|
|
||||||
# Use this test to test things that cannot easily be tested under chroot Nix stores in functional test suite.
|
|
||||||
non-chroot-misc = runNixOSTestFor "x86_64-linux" ./non-chroot-misc;
|
|
||||||
|
|
||||||
noNewPrivilegesInSandbox = runNixOSTestFor "x86_64-linux" ./no-new-privileges/sandbox.nix;
|
noNewPrivilegesInSandbox = runNixOSTestFor "x86_64-linux" ./no-new-privileges/sandbox.nix;
|
||||||
|
|
||||||
noNewPrivilegesOutsideSandbox = runNixOSTestFor "x86_64-linux" ./no-new-privileges/no-sandbox.nix;
|
noNewPrivilegesOutsideSandbox = runNixOSTestFor "x86_64-linux" ./no-new-privileges/no-sandbox.nix;
|
||||||
|
|||||||
@@ -76,7 +76,7 @@ in
|
|||||||
# Fetching from a server with an untrusted cert should fail.
|
# Fetching from a server with an untrusted cert should fail.
|
||||||
err = machine.fail("nix build --no-substitute --expr 'import <nix/fetchurl.nix> { url = \"https://bad/index.html\"; hash = \"sha256-rsBwZF/lPuOzdjBZN2E08FjMM3JHyXit0Xi2zN+wAZ8=\"; }' 2>&1")
|
err = machine.fail("nix build --no-substitute --expr 'import <nix/fetchurl.nix> { url = \"https://bad/index.html\"; hash = \"sha256-rsBwZF/lPuOzdjBZN2E08FjMM3JHyXit0Xi2zN+wAZ8=\"; }' 2>&1")
|
||||||
print(err)
|
print(err)
|
||||||
assert "SSL peer certificate or SSH remote key was not OK" in err
|
assert "SSL certificate problem: self-signed certificate" in err
|
||||||
|
|
||||||
# Fetching from a server with a trusted cert should work via environment variable override.
|
# Fetching from a server with a trusted cert should work via environment variable override.
|
||||||
machine.succeed("NIX_SSL_CERT_FILE=/tmp/cafile.pem nix build --no-substitute --expr 'import <nix/fetchurl.nix> { url = \"https://bad/index.html\"; hash = \"sha256-rsBwZF/lPuOzdjBZN2E08FjMM3JHyXit0Xi2zN+wAZ8=\"; }'")
|
machine.succeed("NIX_SSL_CERT_FILE=/tmp/cafile.pem nix build --no-substitute --expr 'import <nix/fetchurl.nix> { url = \"https://bad/index.html\"; hash = \"sha256-rsBwZF/lPuOzdjBZN2E08FjMM3JHyXit0Xi2zN+wAZ8=\"; }'")
|
||||||
|
|||||||
@@ -45,12 +45,12 @@ in {
|
|||||||
server.wait_for_unit("network-online.target")
|
server.wait_for_unit("network-online.target")
|
||||||
client.wait_for_unit("network-online.target")
|
client.wait_for_unit("network-online.target")
|
||||||
|
|
||||||
client.succeed("mkdir -m 700 /root/.ssh")
|
client.succeed("mkdir -m 700 /root/.ssh || [[ -d /root/.ssh ]]")
|
||||||
client.copy_from_host("key", "/root/.ssh/id_ed25519")
|
client.copy_from_host("key", "/root/.ssh/id_ed25519")
|
||||||
client.succeed("chmod 600 /root/.ssh/id_ed25519")
|
client.succeed("chmod 600 /root/.ssh/id_ed25519")
|
||||||
|
|
||||||
# Install the SSH key on the server.
|
# Install the SSH key on the server.
|
||||||
server.succeed("mkdir -m 700 /root/.ssh")
|
server.succeed("mkdir -m 700 /root/.ssh || [[ -d /root/.ssh ]]")
|
||||||
server.copy_from_host("key.pub", "/root/.ssh/authorized_keys")
|
server.copy_from_host("key.pub", "/root/.ssh/authorized_keys")
|
||||||
server.wait_for_unit("sshd.service")
|
server.wait_for_unit("sshd.service")
|
||||||
client.succeed(f"ssh -o StrictHostKeyChecking=no {server.name} 'echo hello world' >&2")
|
client.succeed(f"ssh -o StrictHostKeyChecking=no {server.name} 'echo hello world' >&2")
|
||||||
|
|||||||
@@ -1,34 +0,0 @@
|
|||||||
{ ... }:
|
|
||||||
# Misc things we want to test inside of a non redirected, non chroot Nix store.
|
|
||||||
let
|
|
||||||
nonAutoCleaningFailingDerivationCode = ''
|
|
||||||
derivation {
|
|
||||||
name = "scratch-failing";
|
|
||||||
system = builtins.currentSystem;
|
|
||||||
builder = "/bin/sh";
|
|
||||||
args = [ (builtins.toFile "builder.sh" "echo bonjour > $out; echo out: $out; false") ];
|
|
||||||
}
|
|
||||||
'';
|
|
||||||
in
|
|
||||||
{
|
|
||||||
name = "non-chroot-sandbox-misc";
|
|
||||||
|
|
||||||
nodes.machine = {
|
|
||||||
};
|
|
||||||
|
|
||||||
testScript = { nodes }: ''
|
|
||||||
import re
|
|
||||||
start_all()
|
|
||||||
|
|
||||||
# You might ask yourself why write such a convoluted thing?
|
|
||||||
# The condition for fooling Nix into NOT cleaning up the output path are non trivial and unclear.
|
|
||||||
# This is one of those: create a derivation, mkdir or touch the $out path, communicate it back.
|
|
||||||
# Even with a sandboxed Lix, you will observe leftovers before 2.93.0. After this version, this test passes.
|
|
||||||
result = machine.fail("""nix-build --substituters "" -E '${nonAutoCleaningFailingDerivationCode}' 2>&1""")
|
|
||||||
match = re.search(r'out: (\S+)', result)
|
|
||||||
assert match is not None, "Did not find Nix store path in the result of the failing build"
|
|
||||||
outpath = match.group(1).strip()
|
|
||||||
print(f"Found Nix store path: {outpath}")
|
|
||||||
machine.fail(f'stat {outpath}')
|
|
||||||
'';
|
|
||||||
}
|
|
||||||
@@ -48,6 +48,7 @@ in
|
|||||||
imports = [ test.config.builders.config ];
|
imports = [ test.config.builders.config ];
|
||||||
services.openssh.enable = true;
|
services.openssh.enable = true;
|
||||||
virtualisation.writableStore = true;
|
virtualisation.writableStore = true;
|
||||||
|
virtualisation.additionalPaths = [ config.system.build.extraUtils ];
|
||||||
nix.settings.sandbox = true;
|
nix.settings.sandbox = true;
|
||||||
nix.settings.substituters = lib.mkForce [ ];
|
nix.settings.substituters = lib.mkForce [ ];
|
||||||
};
|
};
|
||||||
|
|||||||
+2
-2
@@ -1,5 +1,5 @@
|
|||||||
{
|
{
|
||||||
"version": "2.92.2",
|
"version": "2.92.3",
|
||||||
"official_release": true,
|
"official_release": false,
|
||||||
"release_name": "Bombe glacée"
|
"release_name": "Bombe glacée"
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user