Skip to content

Commit c64639b

Browse files
committedFeb 18, 2018
nixos/binfmt: Initial binfmt_msc support.
1 parent 6952a2b commit c64639b

File tree

2 files changed

+140
-0
lines changed

2 files changed

+140
-0
lines changed
 

‎nixos/modules/module-list.nix

+1
Original file line numberDiff line numberDiff line change
@@ -694,6 +694,7 @@
694694
./services/x11/xserver.nix
695695
./system/activation/activation-script.nix
696696
./system/activation/top-level.nix
697+
./system/boot/binfmt.nix
697698
./system/boot/coredump.nix
698699
./system/boot/emergency-mode.nix
699700
./system/boot/grow-partition.nix

‎nixos/modules/system/boot/binfmt.nix

+139
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,139 @@
1+
{ config, lib, ... }:
2+
let
3+
inherit (lib) mkOption types optionalString;
4+
5+
cfg = config.boot.binfmtMiscRegistrations;
6+
7+
makeBinfmtLine = name: { recognitionType, offset, magicOrExtension
8+
, mask, preserveArgvZero, openBinary
9+
, matchCredentials, fixBinary, ...
10+
}: let
11+
type = if recognitionType == "magic" then "M" else "E";
12+
offset' = toString offset;
13+
mask' = toString mask;
14+
interpreter = "/run/binfmt/${name}";
15+
flags = if !(matchCredentials -> openBinary)
16+
then throw "boot.binfmtMiscRegistrations.${name}: you can't specify openBinary = false when matchCredentials = true."
17+
else optionalString preserveArgvZero "P" +
18+
optionalString (openBinary && !matchCredentials) "O" +
19+
optionalString matchCredentials "C" +
20+
optionalString fixBinary "F";
21+
in ":${name}:${type}:${offset'}:${magicOrExtension}:${mask'}:${interpreter}:${flags}";
22+
23+
binfmtFile = builtins.toFile "binfmt_nixos.conf"
24+
(lib.concatStringsSep "\n" (lib.mapAttrsToList makeBinfmtLine cfg));
25+
26+
activationSnippet = name: { interpreter, ... }:
27+
"ln -sf ${interpreter} /run/binfmt/${name}";
28+
activationScript = ''
29+
mkdir -p -m 0755 /run/binfmt
30+
${lib.concatStringsSep "\n" (lib.mapAttrsToList activationSnippet cfg)}
31+
'';
32+
in {
33+
options = {
34+
boot.binfmtMiscRegistrations = mkOption {
35+
default = {};
36+
37+
description = ''
38+
Extra binary formats to register with the kernel.
39+
See https://www.kernel.org/doc/html/latest/admin-guide/binfmt-misc.html for more details.
40+
'';
41+
42+
type = types.attrsOf (types.submodule ({ config, ... }: {
43+
options = {
44+
recognitionType = mkOption {
45+
default = "magic";
46+
description = "Whether to recognize executables by magic number or extension.";
47+
type = types.enum [ "magic" "extension" ];
48+
};
49+
50+
offset = mkOption {
51+
default = null;
52+
description = "The byte offset of the magic number used for recognition.";
53+
type = types.nullOr types.int;
54+
};
55+
56+
magicOrExtension = mkOption {
57+
description = "The magic number or extension to match on.";
58+
type = types.str;
59+
};
60+
61+
mask = mkOption {
62+
default = null;
63+
description =
64+
"A mask to be ANDed with the byte sequence of the file before matching";
65+
type = types.nullOr types.str;
66+
};
67+
68+
interpreter = mkOption {
69+
description = ''
70+
The interpreter to invoke to run the program.
71+
72+
Note that the actual registration will point to
73+
/run/binfmt/''${name}, so the kernel interpreter length
74+
limit doesn't apply.
75+
'';
76+
type = types.path;
77+
};
78+
79+
preserveArgvZero = mkOption {
80+
default = false;
81+
description = ''
82+
Whether to pass the original argv[0] to the interpreter.
83+
84+
See the description of the 'P' flag in the kernel docs
85+
for more details;
86+
'';
87+
type = types.bool;
88+
};
89+
90+
openBinary = mkOption {
91+
default = config.matchCredentials;
92+
description = ''
93+
Whether to pass the binary to the interpreter as an open
94+
file descriptor, instead of a path.
95+
'';
96+
type = types.bool;
97+
};
98+
99+
matchCredentials = mkOption {
100+
default = false;
101+
description = ''
102+
Whether to launch with the credentials and security
103+
token of the binary, not the interpreter (e.g. setuid
104+
bit).
105+
106+
See the description of the 'C' flag in the kernel docs
107+
for more details.
108+
109+
Implies/requires openBinary = true.
110+
'';
111+
type = types.bool;
112+
};
113+
114+
fixBinary = mkOption {
115+
default = false;
116+
description = ''
117+
Whether to open the interpreter file as soon as the
118+
registration is loaded, rather than waiting for a
119+
relevant file to be invoked.
120+
121+
See the description of the 'F' flag in the kernel docs
122+
for more details.
123+
'';
124+
type = types.bool;
125+
};
126+
};
127+
}));
128+
};
129+
};
130+
131+
config = lib.mkIf (cfg != {}) {
132+
environment.etc."binfmt.d/nixos.conf".source = binfmtFile;
133+
system.activationScripts.binfmt = activationScript;
134+
systemd.additionalUpstreamSystemUnits =
135+
[ "proc-sys-fs-binfmt_misc.automount"
136+
"proc-sys-fs-binfmt_misc.mount"
137+
];
138+
};
139+
}

2 commit comments

Comments
 (2)

dtzWill commented on Feb 18, 2018

@dtzWill
Member

Awesome, thanks!

bgamari commented on Feb 25, 2018

@bgamari
Contributor

Indeed, thanks!

Please sign in to comment.