nix-required-mounts: guest and host paths may differ

This commit is contained in:
Someone Serge 2023-11-11 14:02:54 +00:00
parent 7418e4fefd
commit 5560f6a514
5 changed files with 52 additions and 16 deletions

View File

@ -5,16 +5,23 @@ let
package = pkgs.nix-required-mounts;
overridenPackage = package.override { inherit (cfg) allowedPatterns; };
Mount = with lib; types.submodule {
options.host = mkOption { type = types.str; description = "Host path to mount"; };
options.guest = mkOption {
type = types.str;
description = "Location in the sandbox to mount the host path at";
};
};
Pattern = with lib.types;
submodule ({ config, name, ... }: {
types.submodule ({ config, name, ... }: {
options.onFeatures = lib.mkOption {
type = listOf str;
type = listOf types.str;
description =
"Which requiredSystemFeatures should trigger relaxation of the sandbox";
default = [ name ];
};
options.paths = lib.mkOption {
type = listOf path;
type = listOf (oneOf [ path Mount ]);
description =
"A list of glob patterns, indicating which paths to expose to the sandbox";
};

View File

@ -19,10 +19,19 @@ in
programs.nix-required-mounts.enable = true;
programs.nix-required-mounts.allowedPatterns.supported-feature = {
onFeatures = [ "supported-feature" ];
paths = [ "/supported-feature-files" ];
paths = [
"/supported-feature-files"
{
host = "/usr/lib/imaginary-fhs-drivers";
guest = "/run/opengl-driver/lib";
}
];
};
users.users.person.isNormalUser = true;
virtualisation.fileSystems."/supported-feature-files".fsType = "tmpfs";
systemd.tmpfiles.rules = [
"d /supported-feature-files 0755 person users -"
"f /usr/lib/imaginary-fhs-drivers/libcuda.so 0444 root root -"
];
};
testScript = ''
import shlex

View File

@ -4,9 +4,13 @@ pkgs.runCommandNoCC "${feature}-present"
{
requiredSystemFeatures = [ feature ];
} ''
if [[ -e /${feature}-files ]]; then
touch $out
else
if [[ ! -e /${feature}-files ]]; then
echo "The host declares ${feature} support, but doesn't expose /${feature}-files" >&2
exit 1
fi
if [[ ! -f /run/opengl-driver/lib/libcuda.so ]] ; then
echo "The host declares ${feature} support, but it the hook fails to handle the hostPath != guestPath cases" >&2
exit 1
fi
touch $out
''

View File

@ -8,12 +8,20 @@ from argparse import ArgumentParser
from itertools import chain
from pathlib import Path
from sys import stderr
from typing import Dict, List, TypedDict
from typing import Dict, List, Tuple, TypeAlias, TypedDict
Glob: TypeAlias = str
PathString: TypeAlias = str
class Mount(TypedDict):
host: PathString
guest: PathString
class Pattern(TypedDict):
onFeatures: List[str]
paths: List[str] # List of glob patterns
paths: List[Glob | Mount]
class HookConfig(TypedDict):
@ -106,12 +114,21 @@ def entrypoint():
features = get_strings(drv_env, "requiredSystemFeatures")
features = list(filter(known_features.__contains__, features))
patterns = list(
patterns: List[PathString | Mount] = list(
chain.from_iterable(allowed_patterns[f]["paths"] for f in features)
) # noqa: E501
roots = sorted(
set(Path(path) for pattern in patterns for path in glob.glob(pattern))
# TODO: Would it make sense to preserve the original order instead?
roots: List[Tuple[PathString, PathString]] = sorted(
set(
mnt
for pattern in patterns
for mnt in (
((path, path) for path in glob.glob(pattern))
if isinstance(pattern, PathString)
else [(pattern["guest"], pattern["host"])]
)
)
)
# the pre-build-hook command
@ -121,8 +138,7 @@ def entrypoint():
print("extra-sandbox-paths")
# arguments, one per line
for p in roots:
guest_path, host_path = p, p
for guest_path, host_path in roots:
print(f"{guest_path}={host_path}")
# terminated by an empty line

View File

@ -3,7 +3,7 @@
, allowedPatterns ? rec {
# This config is just an example.
# When the hook observes either of the following requiredSystemFeatures:
nvidia-gpu.onFeatures = [ "gpu" "opengl" "vulkan" "cuda" ];
nvidia-gpu.onFeatures = [ "gpu" "nvidia-gpu" "opengl" "cuda" ];
# It exposes these paths in the sandbox:
nvidia-gpu.paths = [
# Note that mounting /run/opengl-driver/lib actually isn't sufficient,