networkmanager/modemmanager: ship separate packages for the daemon and CLI tools

they require fundamentally different sandboxing approaches. the daemon *can't* always use bwrap if it wants to run as non-root. meanwhile the CLI tools would mostly *prefer* to run under bwrap.

in the long term i'll maybe upstream the systemd sandboxing into nixpkgs, where there looks to be desire for it
This commit is contained in:
Colin 2024-05-31 23:23:49 +00:00
parent a380bd04c4
commit 539d9e45a2
10 changed files with 67 additions and 8 deletions

View File

@ -78,6 +78,7 @@
./megapixels.nix
./mepo.nix
./mimeo
./mmcli.nix
./modemmanager.nix
./mopidy.nix
./mpv
@ -89,6 +90,7 @@
./nheko.nix
./nicotine-plus.nix
./nix-index.nix
./nmcli.nix
./notejot.nix
./ntfy-sh.nix
./objdump.nix

View File

@ -0,0 +1,8 @@
{ pkgs, ... }:
{
sane.programs.mmcli = {
packageUnwrapped = pkgs.modemmanager-split.mmcli;
# TODO: sandbox
};
}

View File

@ -4,7 +4,7 @@ let
in
{
sane.programs.modemmanager = {
packageUnwrapped = pkgs.modemmanager.overrideAttrs (upstream: {
packageUnwrapped = pkgs.modemmanager-split.daemon.overrideAttrs (upstream: {
postInstall = (upstream.postInstall or "") + ''
sed 's/"root"/"networkmanager"/g' $out/share/dbus-1/system.d/org.freedesktop.ModemManager1.conf \
> $out/share/dbus-1/system.d/networkmanager-org.freedesktop.ModemManager1.conf
@ -13,7 +13,14 @@ in
# mmcli needs /run/current-system/sw/share/dbus-1 files to function
enableFor.system = lib.mkIf (builtins.any (en: en) (builtins.attrValues cfg.enableFor.user)) true;
sandbox.method = "bwrap"; #< landlock also works
suggestedPrograms = [ "mmcli" ];
# bwrap sandboxing works, but requires the real user to be root.
# landlock sandboxing works, and allows the real user to be someone else (like `networkmanager`).
# non-root is very important, because of how many things in e.g. /dev are r/w based on uid=0.
# TODO: have the services run as `networkmanager` user
sandbox.method = "bwrap";
# sandbox.method = "landlock";
sandbox.wrapperType = "inplace"; #< .pc files, GIR files with absolute paths,
sandbox.net = "all"; #< needed for modem bringup
# sandbox.isolatePids = false;

View File

@ -12,7 +12,7 @@ in
config = lib.mkMerge [
{
sane.programs.networkmanager = {
packageUnwrapped = pkgs.networkmanager.overrideAttrs (upstream: {
packageUnwrapped = pkgs.networkmanager-split.daemon.overrideAttrs (upstream: {
# postPatch = (upstream.postPatch or "") + ''
# substituteInPlace src/{core/org.freedesktop.NetworkManager,nm-dispatcher/nm-dispatcher}.conf --replace-fail \
# 'user="root"' 'user="networkmanager"'
@ -23,14 +23,13 @@ in
sed 's/"root"/"networkmanager"/g' $out/share/dbus-1/system.d/$f \
> $out/share/dbus-1/system.d/networkmanager-$f
done
'';
postFixup = (upstream.postFixup or "") + ''
# remove unused services to prevent any unexpected interactions
rm $out/etc/systemd/system/{nm-cloud-setup.service,nm-cloud-setup.timer,nm-priv-helper.service}
'';
});
suggestedPrograms = [ "wpa_supplicant" ];
suggestedPrograms = [ "nmcli" "wpa_supplicant" ];
enableFor.system = lib.mkIf (builtins.any (en: en) (builtins.attrValues cfg.enableFor.user)) true;
# this contains both the NetworkManager service and the NetworkManager-dispatcher service

View File

@ -0,0 +1,7 @@
{ pkgs, ... }:
{
sane.programs.nmcli = {
packageUnwrapped = pkgs.networkmanager-split.nmcli;
# TODO: sandbox
};
}

View File

@ -2,5 +2,5 @@
static-nix-shell.mkPython3Bin {
pname = "eg25-control";
srcRoot = ./.;
pkgs = [ "curl" "modemmanager" ];
pkgs = [ "curl" "modemmanager-split.mmcli" ];
}

View File

@ -1,5 +1,5 @@
#!/usr/bin/env nix-shell
#!nix-shell -i python3 -p "python3.withPackages (ps: [ ])" -p curl -p modemmanager
#!nix-shell -i python3 -p "python3.withPackages (ps: [ ])" -p curl -p modemmanager-split.mmcli
# this script should run after ModemManager.service is started.
# typical invocation is `eg25-control --power-on --enable-gps`.

View File

@ -0,0 +1,17 @@
{ deepLinkIntoOwnPackage
, modemmanager
}:
(deepLinkIntoOwnPackage modemmanager).overrideAttrs (base: {
outputs = [ "out" "daemon" "mmcli" ];
postFixup = ''
moveToOutput "" "$daemon"
for f in bin/mmcli man/man1/mmcli.1.gz share/bash-completion/completions/mmcli; do
moveToOutput "$f" "$mmcli"
done
# ensure non-empty default output so the build doesn't fail
mkdir "$out"
'';
meta = base.meta // {
outputsToInstall = [ ];
};
})

View File

@ -0,0 +1,17 @@
{ deepLinkIntoOwnPackage
, networkmanager
}:
(deepLinkIntoOwnPackage networkmanager).overrideAttrs (base: {
outputs = [ "out" "daemon" "nmcli" ];
postFixup = ''
moveToOutput "" "$daemon"
for f in bin/{nmcli,nmtui,nmtui-connect,nmtui-edit,nmtui-hostname} share/bash-completion/completions/nmcli; do
moveToOutput "$f" "$nmcli"
done
# ensure non-empty default output so the build doesn't fail
mkdir "$out"
'';
meta = base.meta // {
outputsToInstall = [ ];
};
})

View File

@ -59,7 +59,9 @@ let
linux-postmarketos = callPackage ./additional/linux-postmarketos { };
mcg = callPackage ./additional/mcg { };
megapixels-next = callPackage ./additional/megapixels-next { };
modemmanager-split = callPackage ./additional/modemmanager-split { };
mx-sanebot = callPackage ./additional/mx-sanebot { };
networkmanager-split = callPackage ./additional/networkmanager-split { };
peerswap = callPackage ./additional/peerswap { };
phog = callPackage ./additional/phog { };
pipeline = callPackage ./additional/pipeline { };