summary refs log tree commit diff
path: root/nixos/lib
diff options
context:
space:
mode:
authorpennae <github@quasiparticle.net>2022-01-09 08:46:55 +0100
committerpennae <github@quasiparticle.net>2022-03-12 00:48:52 +0100
commit40a35299fa30421de85a56f084f6c59d05ea883e (patch)
tree563048cbb3cb7b4fdc870e1e3406b1738d0ec43a /nixos/lib
parent74f542c42e5bca4f74f53cf7054c8a93d4736f51 (diff)
downloadnixpkgs-40a35299fa30421de85a56f084f6c59d05ea883e.tar
nixpkgs-40a35299fa30421de85a56f084f6c59d05ea883e.tar.gz
nixpkgs-40a35299fa30421de85a56f084f6c59d05ea883e.tar.bz2
nixpkgs-40a35299fa30421de85a56f084f6c59d05ea883e.tar.lz
nixpkgs-40a35299fa30421de85a56f084f6c59d05ea883e.tar.xz
nixpkgs-40a35299fa30421de85a56f084f6c59d05ea883e.tar.zst
nixpkgs-40a35299fa30421de85a56f084f6c59d05ea883e.zip
nixos: add functions and documentation for escaping systemd Exec* directives
it's really easy to accidentally write the wrong systemd Exec* directive, ones
that works most of the time but fails when users include systemd metacharacters
in arguments that are interpolated into an Exec* directive. add a few functions
analogous to escapeShellArg{,s} and some documentation on how and when to use them.
Diffstat (limited to 'nixos/lib')
-rw-r--r--nixos/lib/utils.nix20
1 files changed, 20 insertions, 0 deletions
diff --git a/nixos/lib/utils.nix b/nixos/lib/utils.nix
index bbebf8ba35a..29135024195 100644
--- a/nixos/lib/utils.nix
+++ b/nixos/lib/utils.nix
@@ -45,6 +45,26 @@ rec {
    replaceChars ["/" "-" " "] ["-" "\\x2d" "\\x20"]
    (removePrefix "/" s);
 
+  # Quotes an argument for use in Exec* service lines.
+  # systemd accepts "-quoted strings with escape sequences, toJSON produces
+  # a subset of these.
+  # Additionally we escape % to disallow expansion of % specifiers. Any lone ;
+  # in the input will be turned it ";" and thus lose its special meaning.
+  # Every $ is escaped to $$, this makes it unnecessary to disable environment
+  # substitution for the directive.
+  escapeSystemdExecArg = arg:
+    let
+      s = if builtins.isPath arg then "${arg}"
+        else if builtins.isString arg then arg
+        else if builtins.isInt arg || builtins.isFloat arg then toString arg
+        else throw "escapeSystemdExecArg only allows strings, paths and numbers";
+    in
+      replaceChars [ "%" "$" ] [ "%%" "$$" ] (builtins.toJSON s);
+
+  # Quotes a list of arguments into a single string for use in a Exec*
+  # line.
+  escapeSystemdExecArgs = concatMapStringsSep " " escapeSystemdExecArg;
+
   # Returns a system path for a given shell package
   toShellPath = shell:
     if types.shellPackage.check shell then