]> Git — Sourcephile - sourcephile-nix.git/blob - nixpkgs/patches/apparmor.diff
nix: update to latest nixpkgs
[sourcephile-nix.git] / nixpkgs / patches / apparmor.diff
1 diff --git a/maintainers/maintainer-list.nix b/maintainers/maintainer-list.nix
2 index b166e7bf01f..c059c2bb002 100644
3 --- a/maintainers/maintainer-list.nix
4 +++ b/maintainers/maintainer-list.nix
5 @@ -4657,7 +4657,7 @@
6 name = "Julien Dehos";
7 };
8 julm = {
9 - email = "julm+nix@sourcephile.fr";
10 + email = "julm+nixpkgs@sourcephile.fr";
11 github = "ju1m";
12 githubId = 21160136;
13 name = "Julien Moutinho";
14 diff --git a/nixos/doc/manual/release-notes/rl-2105.xml b/nixos/doc/manual/release-notes/rl-2105.xml
15 index 6dd14d6051e..f485eb114cc 100644
16 --- a/nixos/doc/manual/release-notes/rl-2105.xml
17 +++ b/nixos/doc/manual/release-notes/rl-2105.xml
18 @@ -662,6 +662,24 @@ self: super:
19 The option's description was incorrect regarding ownership management and has been simplified greatly.
20 </para>
21 </listitem>
22 + <listitem>
23 + <para>
24 + The <literal>security.apparmor</literal> module,
25 + for the <link xlink:href="https://gitlab.com/apparmor/apparmor/-/wikis/Documentation">AppArmor</link>
26 + Mandatory Access Control system,
27 + has been substantialy improved along with related tools,
28 + so that module maintainers can now more easily write AppArmor profiles for NixOS.
29 + The most notable change on the user-side is the new option <xref linkend="opt-security.apparmor.policies"/>,
30 + replacing the previous <literal>profiles</literal> option
31 + to provide a way to disable a profile
32 + and to select whether to confine in enforce mode (default)
33 + or in complain mode (see <literal>journalctl -b --grep apparmor</literal>).
34 + Before enabling this module, either directly
35 + or by importing <literal>&lt;nixpkgs/nixos/modules/profiles/hardened.nix&gt;</literal>,
36 + please be sure to read the documentation of <link linkend="opt-security.apparmor.enable">security.apparmor.enable</link>,
37 + and especially the part about <xref linkend="opt-security.apparmor.killUnconfinedConfinables"/>.
38 + </para>
39 + </listitem>
40 <listitem>
41 <para>
42 The GNOME desktop manager once again installs <package>gnome3.epiphany</package> by default.
43 diff --git a/nixos/modules/config/fonts/fontconfig.nix b/nixos/modules/config/fonts/fontconfig.nix
44 index 6e7b8c4b88a..72827c5abaa 100644
45 --- a/nixos/modules/config/fonts/fontconfig.nix
46 +++ b/nixos/modules/config/fonts/fontconfig.nix
47 @@ -448,6 +448,40 @@ in
48 (mkIf cfg.enable {
49 environment.systemPackages = [ pkgs.fontconfig ];
50 environment.etc.fonts.source = "${fontconfigEtc}/etc/fonts/";
51 + security.apparmor.includes."abstractions/fonts" = ''
52 + # fonts.conf
53 + r ${pkg.out}/etc/fonts/fonts.conf,
54 +
55 + # fontconfig default config files
56 + r ${pkg.out}/etc/fonts/conf.d/*.conf,
57 +
58 + # 00-nixos-cache.conf
59 + r ${cacheConf},
60 +
61 + # 10-nixos-rendering.conf
62 + r ${renderConf},
63 +
64 + # 50-user.conf
65 + ${optionalString cfg.includeUserConf ''
66 + r ${pkg.out}/etc/fonts/conf.d.bak/50-user.conf,
67 + ''}
68 +
69 + # local.conf (indirect priority 51)
70 + ${optionalString (cfg.localConf != "") ''
71 + r ${localConf},
72 + ''}
73 +
74 + # 52-nixos-default-fonts.conf
75 + r ${defaultFontsConf},
76 +
77 + # 53-no-bitmaps.conf
78 + r ${rejectBitmaps},
79 +
80 + ${optionalString (!cfg.allowType1) ''
81 + # 53-nixos-reject-type1.conf
82 + r ${rejectType1},
83 + ''}
84 + '';
85 })
86 (mkIf cfg.enable {
87 fonts.fontconfig.confPackages = [ confPkg ];
88 diff --git a/nixos/modules/config/malloc.nix b/nixos/modules/config/malloc.nix
89 index a3eb55d8a42..fc35993b5a8 100644
90 --- a/nixos/modules/config/malloc.nix
91 +++ b/nixos/modules/config/malloc.nix
92 @@ -87,5 +87,12 @@ in
93 environment.etc."ld-nix.so.preload".text = ''
94 ${providerLibPath}
95 '';
96 + security.apparmor.includes = {
97 + "abstractions/base" = ''
98 + r /etc/ld-nix.so.preload,
99 + r ${config.environment.etc."ld-nix.so.preload".source},
100 + mr ${providerLibPath},
101 + '';
102 + };
103 };
104 }
105 diff --git a/nixos/modules/module-list.nix b/nixos/modules/module-list.nix
106 index 3055459e781..d9cc86fcd4e 100644
107 --- a/nixos/modules/module-list.nix
108 +++ b/nixos/modules/module-list.nix
109 @@ -199,7 +199,6 @@
110 ./rename.nix
111 ./security/acme.nix
112 ./security/apparmor.nix
113 - ./security/apparmor-suid.nix
114 ./security/audit.nix
115 ./security/auditd.nix
116 ./security/ca.nix
117 diff --git a/nixos/modules/security/apparmor-suid.nix b/nixos/modules/security/apparmor-suid.nix
118 deleted file mode 100644
119 index 6c479e070e2..00000000000
120 --- a/nixos/modules/security/apparmor-suid.nix
121 +++ /dev/null
122 @@ -1,49 +0,0 @@
123 -{ config, lib, pkgs, ... }:
124 -let
125 - cfg = config.security.apparmor;
126 -in
127 -with lib;
128 -{
129 - imports = [
130 - (mkRenamedOptionModule [ "security" "virtualization" "flushL1DataCache" ] [ "security" "virtualisation" "flushL1DataCache" ])
131 - ];
132 -
133 - options.security.apparmor.confineSUIDApplications = mkOption {
134 - type = types.bool;
135 - default = true;
136 - description = ''
137 - Install AppArmor profiles for commonly-used SUID application
138 - to mitigate potential privilege escalation attacks due to bugs
139 - in such applications.
140 -
141 - Currently available profiles: ping
142 - '';
143 - };
144 -
145 - config = mkIf (cfg.confineSUIDApplications) {
146 - security.apparmor.profiles = [ (pkgs.writeText "ping" ''
147 - #include <tunables/global>
148 - /run/wrappers/bin/ping {
149 - #include <abstractions/base>
150 - #include <abstractions/consoles>
151 - #include <abstractions/nameservice>
152 -
153 - capability net_raw,
154 - capability setuid,
155 - network inet raw,
156 -
157 - ${pkgs.stdenv.cc.libc.out}/lib/*.so mr,
158 - ${pkgs.libcap.lib}/lib/libcap.so* mr,
159 - ${pkgs.attr.out}/lib/libattr.so* mr,
160 -
161 - ${pkgs.iputils}/bin/ping mixr,
162 -
163 - #/etc/modules.conf r,
164 -
165 - ## Site-specific additions and overrides. See local/README for details.
166 - ##include <local/bin.ping>
167 - }
168 - '') ];
169 - };
170 -
171 -}
172 diff --git a/nixos/modules/security/apparmor.nix b/nixos/modules/security/apparmor.nix
173 index cfc65b347bc..dfa695b81bb 100644
174 --- a/nixos/modules/security/apparmor.nix
175 +++ b/nixos/modules/security/apparmor.nix
176 @@ -1,59 +1,207 @@
177 { config, lib, pkgs, ... }:
178
179 let
180 - inherit (lib) mkIf mkOption types concatMapStrings;
181 + inherit (builtins) attrNames head map match readFile;
182 + inherit (lib) types;
183 + inherit (config.environment) etc;
184 cfg = config.security.apparmor;
185 + mkDisableOption = name: lib.mkEnableOption name // {
186 + default = true;
187 + example = false;
188 + };
189 + enabledPolicies = lib.filterAttrs (n: p: p.enable) cfg.policies;
190 in
191
192 {
193 - options = {
194 - security.apparmor = {
195 - enable = mkOption {
196 - type = types.bool;
197 - default = false;
198 - description = "Enable the AppArmor Mandatory Access Control system.";
199 - };
200 - profiles = mkOption {
201 - type = types.listOf types.path;
202 - default = [];
203 - description = "List of files containing AppArmor profiles.";
204 - };
205 - packages = mkOption {
206 - type = types.listOf types.package;
207 - default = [];
208 - description = "List of packages to be added to apparmor's include path";
209 - };
210 - };
211 - };
212 + imports = [
213 + (lib.mkRenamedOptionModule [ "security" "virtualization" "flushL1DataCache" ] [ "security" "virtualisation" "flushL1DataCache" ])
214 + (lib.mkRemovedOptionModule [ "security" "apparmor" "confineSUIDApplications" ] "Please use the new options: `security.apparmor.policies.<policy>.enable'.")
215 + (lib.mkRemovedOptionModule [ "security" "apparmor" "profiles" ] "Please use the new option: `security.apparmor.policies'.")
216 + apparmor/includes.nix
217 + apparmor/profiles.nix
218 + ];
219
220 - config = mkIf cfg.enable {
221 - environment.systemPackages = [ pkgs.apparmor-utils ];
222 + options = {
223 + security.apparmor = {
224 + enable = lib.mkEnableOption ''the AppArmor Mandatory Access Control system.
225
226 - boot.kernelParams = [ "apparmor=1" "security=apparmor" ];
227 + If you're enabling this module on a running system,
228 + note that a reboot will be required to activate AppArmor in the kernel.
229
230 - systemd.services.apparmor = let
231 - paths = concatMapStrings (s: " -I ${s}/etc/apparmor.d")
232 - ([ pkgs.apparmor-profiles ] ++ cfg.packages);
233 - in {
234 - after = [ "local-fs.target" ];
235 - before = [ "sysinit.target" ];
236 - wantedBy = [ "multi-user.target" ];
237 - unitConfig = {
238 - DefaultDependencies = "no";
239 - };
240 - serviceConfig = {
241 - Type = "oneshot";
242 - RemainAfterExit = "yes";
243 - ExecStart = map (p:
244 - ''${pkgs.apparmor-parser}/bin/apparmor_parser -rKv ${paths} "${p}"''
245 - ) cfg.profiles;
246 - ExecStop = map (p:
247 - ''${pkgs.apparmor-parser}/bin/apparmor_parser -Rv "${p}"''
248 - ) cfg.profiles;
249 - ExecReload = map (p:
250 - ''${pkgs.apparmor-parser}/bin/apparmor_parser --reload ${paths} "${p}"''
251 - ) cfg.profiles;
252 - };
253 - };
254 - };
255 + Also, beware that enabling this module will by default
256 + try to kill unconfined but confinable running processes,
257 + in order to obtain a confinement matching what is declared in the NixOS configuration.
258 + This will happen when upgrading to a NixOS revision
259 + introducing an AppArmor profile for the executable of a running process.
260 + This is because enabling an AppArmor profile for an executable
261 + can only confine new or already confined processes of that executable,
262 + but leaves already running processes unconfined.
263 + Set <link linkend="opt-security.apparmor.killUnconfinedConfinables">killUnconfinedConfinables</link>
264 + to <literal>false</literal> if you prefer to leave those processes running'';
265 + policies = lib.mkOption {
266 + description = ''
267 + AppArmor policies.
268 + '';
269 + type = types.attrsOf (types.submodule ({ name, config, ... }: {
270 + options = {
271 + enable = mkDisableOption "loading of the profile into the kernel";
272 + enforce = mkDisableOption "enforcing of the policy or only complain in the logs";
273 + profile = lib.mkOption {
274 + description = "The policy of the profile.";
275 + type = types.lines;
276 + apply = pkgs.writeText name;
277 + };
278 + };
279 + }));
280 + default = {};
281 + };
282 + includes = lib.mkOption {
283 + type = types.attrsOf types.lines;
284 + default = {};
285 + description = ''
286 + List of paths to be added to AppArmor's searched paths
287 + when resolving <literal>include</literal> directives.
288 + '';
289 + apply = lib.mapAttrs pkgs.writeText;
290 + };
291 + packages = lib.mkOption {
292 + type = types.listOf types.package;
293 + default = [];
294 + description = "List of packages to be added to AppArmor's include path";
295 + };
296 + enableCache = lib.mkEnableOption ''caching of AppArmor policies
297 + in <literal>/var/cache/apparmor/</literal>.
298 +
299 + Beware that AppArmor policies almost always contain Nix store paths,
300 + and thus produce at each change of these paths
301 + a new cached version accumulating in the cache'';
302 + killUnconfinedConfinables = mkDisableOption ''killing of processes
303 + which have an AppArmor profile enabled
304 + (in <link linkend="opt-security.apparmor.policies">policies</link>)
305 + but are not confined (because AppArmor can only confine new processes).
306 + Beware that due to a current limitation of AppArmor,
307 + only profiles with exact paths (and no name) can enable such kills'';
308 + };
309 + };
310 +
311 + config = lib.mkIf cfg.enable {
312 + assertions = map (policy:
313 + { assertion = match ".*/.*" policy == null;
314 + message = "`security.apparmor.policies.\"${policy}\"' must not contain a slash.";
315 + # Because, for instance, aa-remove-unknown uses profiles_names_list() in rc.apparmor.functions
316 + # which does not recurse into sub-directories.
317 + }
318 + ) (attrNames cfg.policies);
319 +
320 + environment.systemPackages = [
321 + pkgs.apparmor-utils
322 + pkgs.apparmor-bin-utils
323 + ];
324 + environment.etc."apparmor.d".source = pkgs.linkFarm "apparmor.d" (
325 + # It's important to put only enabledPolicies here and not all cfg.policies
326 + # because aa-remove-unknown reads profiles from all /etc/apparmor.d/*
327 + lib.mapAttrsToList (name: p: {inherit name; path=p.profile;}) enabledPolicies ++
328 + lib.mapAttrsToList (name: path: {inherit name path;}) cfg.includes
329 + );
330 + environment.etc."apparmor/parser.conf".text = ''
331 + ${if cfg.enableCache then "write-cache" else "skip-cache"}
332 + cache-loc /var/cache/apparmor
333 + Include /etc/apparmor.d
334 + '' +
335 + lib.concatMapStrings (p: "Include ${p}/etc/apparmor.d\n") cfg.packages;
336 + # For aa-logprof
337 + environment.etc."apparmor/apparmor.conf".text = ''
338 + '';
339 + # For aa-logprof
340 + environment.etc."apparmor/severity.db".source = pkgs.apparmor-utils + "/etc/apparmor/severity.db";
341 + environment.etc."apparmor/logprof.conf".source = pkgs.runCommand "logprof.conf" {
342 + header = ''
343 + [settings]
344 + # /etc/apparmor.d/ is read-only on NixOS
345 + profiledir = /var/cache/apparmor/logprof
346 + inactive_profiledir = /etc/apparmor.d/disable
347 + # Use: journalctl -b --since today --grep audit: | aa-logprof
348 + logfiles = /dev/stdin
349 +
350 + parser = ${pkgs.apparmor-parser}/bin/apparmor_parser
351 + ldd = ${pkgs.glibc.bin}/bin/ldd
352 + logger = ${pkgs.utillinux}/bin/logger
353 +
354 + # customize how file ownership permissions are presented
355 + # 0 - off
356 + # 1 - default of what ever mode the log reported
357 + # 2 - force the new permissions to be user
358 + # 3 - force all perms on the rule to be user
359 + default_owner_prompt = 1
360 +
361 + custom_includes = /etc/apparmor.d ${lib.concatMapStringsSep " " (p: "${p}/etc/apparmor.d") cfg.packages}
362 +
363 + [qualifiers]
364 + ${pkgs.runtimeShell} = icnu
365 + ${pkgs.bashInteractive}/bin/sh = icnu
366 + ${pkgs.bashInteractive}/bin/bash = icnu
367 + '';
368 + footer = "${pkgs.apparmor-utils}/etc/apparmor/logprof.conf";
369 + passAsFile = [ "header" ];
370 + } ''
371 + cp $headerPath $out
372 + sed '1,/\[qualifiers\]/d' $footer >> $out
373 + '';
374 +
375 + boot.kernelParams = [ "apparmor=1" "security=apparmor" ];
376 +
377 + systemd.services.apparmor = {
378 + after = [
379 + "local-fs.target"
380 + "systemd-journald-audit.socket"
381 + ];
382 + before = [ "sysinit.target" ];
383 + wantedBy = [ "multi-user.target" ];
384 + unitConfig = {
385 + Description="Load AppArmor policies";
386 + DefaultDependencies = "no";
387 + ConditionSecurity = "apparmor";
388 + };
389 + # Reloading instead of restarting enables to load new AppArmor profiles
390 + # without necessarily restarting all services which have Requires=apparmor.service
391 + reloadIfChanged = true;
392 + restartTriggers = [
393 + etc."apparmor/parser.conf".source
394 + etc."apparmor.d".source
395 + ];
396 + serviceConfig = let
397 + killUnconfinedConfinables = pkgs.writeShellScript "apparmor-kill" ''
398 + set -eu
399 + ${pkgs.apparmor-bin-utils}/bin/aa-status --json |
400 + ${pkgs.jq}/bin/jq --raw-output '.processes | .[] | .[] | select (.status == "unconfined") | .pid' |
401 + xargs --verbose --no-run-if-empty --delimiter='\n' \
402 + kill
403 + '';
404 + commonOpts = p: "--verbose --show-cache ${lib.optionalString (!p.enforce) "--complain "}${p.profile}";
405 + in {
406 + Type = "oneshot";
407 + RemainAfterExit = "yes";
408 + ExecStartPre = "${pkgs.apparmor-utils}/bin/aa-teardown";
409 + ExecStart = lib.mapAttrsToList (n: p: "${pkgs.apparmor-parser}/bin/apparmor_parser --add ${commonOpts p}") enabledPolicies;
410 + ExecStartPost = lib.optional cfg.killUnconfinedConfinables killUnconfinedConfinables;
411 + ExecReload =
412 + # Add or replace into the kernel profiles in enabledPolicies
413 + # (because AppArmor can do that without stopping the processes already confined).
414 + lib.mapAttrsToList (n: p: "${pkgs.apparmor-parser}/bin/apparmor_parser --replace ${commonOpts p}") enabledPolicies ++
415 + # Remove from the kernel any profile whose name is not
416 + # one of the names within the content of the profiles in enabledPolicies
417 + # (indirectly read from /etc/apparmor.d/*, without recursing into sub-directory).
418 + # Note that this does not remove profiles dynamically generated by libvirt.
419 + [ "${pkgs.apparmor-utils}/bin/aa-remove-unknown" ] ++
420 + # Optionaly kill the processes which are unconfined but now have a profile loaded
421 + # (because AppArmor can only start to confine new processes).
422 + lib.optional cfg.killUnconfinedConfinables killUnconfinedConfinables;
423 + ExecStop = "${pkgs.apparmor-utils}/bin/aa-teardown";
424 + CacheDirectory = [ "apparmor" "apparmor/logprof" ];
425 + CacheDirectoryMode = "0700";
426 + };
427 + };
428 + };
429 +
430 + meta.maintainers = with lib.maintainers; [ julm ];
431 }
432 diff --git a/nixos/modules/security/apparmor/includes.nix b/nixos/modules/security/apparmor/includes.nix
433 new file mode 100644
434 index 00000000000..498d7e77650
435 --- /dev/null
436 +++ b/nixos/modules/security/apparmor/includes.nix
437 @@ -0,0 +1,301 @@
438 +{ config, lib, pkgs, ... }:
439 +let
440 + inherit (builtins) attrNames hasAttr isAttrs;
441 + inherit (lib) getLib;
442 + inherit (config.environment) etc;
443 + etcRule = arg:
444 + let go = {path ? null, mode ? "r", trail ? ""}:
445 + lib.optionalString (hasAttr path etc)
446 + "${mode} ${config.environment.etc.${path}.source}${trail},";
447 + in if isAttrs arg
448 + then go arg
449 + else go {path=arg;};
450 +in
451 +{
452 +# FIXME: most of the etcRule calls below have been
453 +# written systematically by converting from apparmor-profiles's profiles
454 +# without testing nor deep understanding of their uses,
455 +# and thus may need more rules or can have less rules;
456 +# this remains to be determined case by case,
457 +# some may even be completely useless.
458 +config.security.apparmor.includes = {
459 + # This one is included by <tunables/global>
460 + # which is usualy included before any profile.
461 + "abstractions/tunables/alias" = ''
462 + alias /bin -> /run/current-system/sw/bin,
463 + alias /lib/modules -> /run/current-system/kernel/lib/modules,
464 + alias /sbin -> /run/current-system/sw/sbin,
465 + alias /usr -> /run/current-system/sw,
466 + '';
467 + "abstractions/audio" = ''
468 + include "${pkgs.apparmor-profiles}/etc/apparmor.d/abstractions/audio"
469 + ${etcRule "asound.conf"}
470 + ${etcRule "esound/esd.conf"}
471 + ${etcRule "libao.conf"}
472 + ${etcRule {path="pulse"; trail="/";}}
473 + ${etcRule {path="pulse"; trail="/**";}}
474 + ${etcRule {path="sound"; trail="/";}}
475 + ${etcRule {path="sound"; trail="/**";}}
476 + ${etcRule {path="alsa/conf.d"; trail="/";}}
477 + ${etcRule {path="alsa/conf.d"; trail="/*";}}
478 + ${etcRule "openal/alsoft.conf"}
479 + ${etcRule "wildmidi/wildmidi.conf"}
480 + '';
481 + "abstractions/authentication" = ''
482 + include "${pkgs.apparmor-profiles}/etc/apparmor.d/abstractions/authentication"
483 + # Defined in security.pam
484 + include <abstractions/pam>
485 + ${etcRule "nologin"}
486 + ${etcRule "securetty"}
487 + ${etcRule {path="security"; trail="/*";}}
488 + ${etcRule "shadow"}
489 + ${etcRule "gshadow"}
490 + ${etcRule "pwdb.conf"}
491 + ${etcRule "default/passwd"}
492 + ${etcRule "login.defs"}
493 + '';
494 + "abstractions/base" = ''
495 + include "${pkgs.apparmor-profiles}/etc/apparmor.d/abstractions/base"
496 + r ${pkgs.stdenv.cc.libc}/share/locale/**,
497 + r ${pkgs.stdenv.cc.libc}/share/locale.alias,
498 + ${lib.optionalString (pkgs.glibcLocales != null) "r ${pkgs.glibcLocales}/lib/locale/locale-archive,"}
499 + ${etcRule "localtime"}
500 + r ${pkgs.tzdata}/share/zoneinfo/**,
501 + r ${pkgs.stdenv.cc.libc}/share/i18n/**,
502 + '';
503 + "abstractions/bash" = ''
504 + include "${pkgs.apparmor-profiles}/etc/apparmor.d/abstractions/bash"
505 + # system-wide bash configuration
506 + ${etcRule "profile.dos"}
507 + ${etcRule "profile"}
508 + ${etcRule "profile.d"}
509 + ${etcRule {path="profile.d"; trail="/*";}}
510 + ${etcRule "bashrc"}
511 + ${etcRule "bash.bashrc"}
512 + ${etcRule "bash.bashrc.local"}
513 + ${etcRule "bash_completion"}
514 + ${etcRule "bash_completion.d"}
515 + ${etcRule {path="bash_completion.d"; trail="/*";}}
516 + # bash relies on system-wide readline configuration
517 + ${etcRule "inputrc"}
518 + # bash inspects filesystems at startup
519 + # and /etc/mtab is linked to /proc/mounts
520 + @{PROC}/mounts
521 +
522 + # run out of /etc/bash.bashrc
523 + ${etcRule "DIR_COLORS"}
524 + '';
525 + "abstractions/cups-client" = ''
526 + include "${pkgs.apparmor-profiles}/etc/apparmor.d/abstractions/cpus-client"
527 + ${etcRule "cups/cups-client.conf"}
528 + '';
529 + "abstractions/consoles" = ''
530 + include "${pkgs.apparmor-profiles}/etc/apparmor.d/abstractions/consoles"
531 + '';
532 + "abstractions/dbus-session-strict" = ''
533 + include "${pkgs.apparmor-profiles}/etc/apparmor.d/abstractions/dbus-session-strict"
534 + ${etcRule "machine-id"}
535 + '';
536 + "abstractions/dconf" = ''
537 + include "${pkgs.apparmor-profiles}/etc/apparmor.d/abstractions/dconf"
538 + ${etcRule {path="dconf"; trail="/**";}}
539 + '';
540 + "abstractions/dri-common" = ''
541 + include "${pkgs.apparmor-profiles}/etc/apparmor.d/abstractions/dri-common"
542 + ${etcRule "drirc"}
543 + '';
544 + # The config.fonts.fontconfig NixOS module adds many files to /etc/fonts/
545 + # by symlinking them but without exporting them outside of its NixOS module,
546 + # those are therefore added there to this "abstractions/fonts".
547 + "abstractions/fonts" = ''
548 + include "${pkgs.apparmor-profiles}/etc/apparmor.d/abstractions/fonts"
549 + ${etcRule {path="fonts"; trail="/**";}}
550 + '';
551 + "abstractions/gnome" = ''
552 + include "${pkgs.apparmor-profiles}/etc/apparmor.d/abstractions/gnome"
553 + ${etcRule {path="gnome"; trail="/gtkrc*";}}
554 + ${etcRule {path="gtk"; trail="/*";}}
555 + ${etcRule {path="gtk-2.0"; trail="/*";}}
556 + ${etcRule {path="gtk-3.0"; trail="/*";}}
557 + ${etcRule "orbitrc"}
558 + include <abstractions/fonts>
559 + ${etcRule {path="pango"; trail="/*";}}
560 + ${etcRule {path="/etc/gnome-vfs-2.0"; trail="/modules/";}}
561 + ${etcRule {path="/etc/gnome-vfs-2.0"; trail="/modules/*";}}
562 + ${etcRule "papersize"}
563 + ${etcRule {path="cups"; trail="/lpoptions";}}
564 + ${etcRule {path="gnome"; trail="/defaults.list";}}
565 + ${etcRule {path="xdg"; trail="/{,*-}mimeapps.list";}}
566 + ${etcRule "xdg/mimeapps.list"}
567 + '';
568 + "abstractions/kde" = ''
569 + include "${pkgs.apparmor-profiles}/etc/apparmor.d/abstractions/kde"
570 + ${etcRule {path="qt3"; trail="/kstylerc";}}
571 + ${etcRule {path="qt3"; trail="/qt_plugins_3.3rc";}}
572 + ${etcRule {path="qt3"; trail="/qtrc";}}
573 + ${etcRule "kderc"}
574 + ${etcRule {path="kde3"; trail="/*";}}
575 + ${etcRule "kde4rc"}
576 + ${etcRule {path="xdg"; trail="/kdeglobals";}}
577 + ${etcRule {path="xdg"; trail="/Trolltech.conf";}}
578 + '';
579 + "abstractions/kerberosclient" = ''
580 + include "${pkgs.apparmor-profiles}/etc/apparmor.d/abstractions/kerberosclient"
581 + ${etcRule {path="krb5.keytab"; mode="rk";}}
582 + ${etcRule "krb5.conf"}
583 + ${etcRule "krb5.conf.d"}
584 + ${etcRule {path="krb5.conf.d"; trail="/*";}}
585 +
586 + # config files found via strings on libs
587 + ${etcRule "krb.conf"}
588 + ${etcRule "krb.realms"}
589 + ${etcRule "srvtab"}
590 + '';
591 + "abstractions/ldapclient" = ''
592 + include "${pkgs.apparmor-profiles}/etc/apparmor.d/abstractions/ldapclient"
593 + ${etcRule "ldap.conf"}
594 + ${etcRule "ldap.secret"}
595 + ${etcRule {path="openldap"; trail="/*";}}
596 + ${etcRule {path="openldap"; trail="/cacerts/*";}}
597 + ${etcRule {path="sasl2"; trail="/*";}}
598 + '';
599 + "abstractions/likewise" = ''
600 + include "${pkgs.apparmor-profiles}/etc/apparmor.d/abstractions/likewise"
601 + '';
602 + "abstractions/mdns" = ''
603 + include "${pkgs.apparmor-profiles}/etc/apparmor.d/abstractions/mdns"
604 + ${etcRule "nss_mdns.conf"}
605 + '';
606 + "abstractions/nameservice" = ''
607 + include "${pkgs.apparmor-profiles}/etc/apparmor.d/abstractions/nameservice"
608 +
609 + # Many programs wish to perform nameservice-like operations, such as
610 + # looking up users by name or id, groups by name or id, hosts by name
611 + # or IP, etc. These operations may be performed through files, dns,
612 + # NIS, NIS+, LDAP, hesiod, wins, etc. Allow them all here.
613 + ${etcRule "group"}
614 + ${etcRule "host.conf"}
615 + ${etcRule "hosts"}
616 + ${etcRule "nsswitch.conf"}
617 + ${etcRule "gai.conf"}
618 + ${etcRule "passwd"}
619 + ${etcRule "protocols"}
620 +
621 + # libtirpc (used for NIS/YP login) needs this
622 + ${etcRule "netconfig"}
623 +
624 + ${etcRule "resolv.conf"}
625 +
626 + ${etcRule {path="samba"; trail="/lmhosts";}}
627 + ${etcRule "services"}
628 +
629 + ${etcRule "default/nss"}
630 +
631 + # libnl-3-200 via libnss-gw-name
632 + ${etcRule {path="libnl"; trail="/classid";}}
633 + ${etcRule {path="libnl-3"; trail="/classid";}}
634 +
635 + mr ${getLib pkgs.nss}/lib/libnss_*.so*,
636 + mr ${getLib pkgs.nss}/lib64/libnss_*.so*,
637 + '';
638 + "abstractions/nis" = ''
639 + include "${pkgs.apparmor-profiles}/etc/apparmor.d/abstractions/nis"
640 + '';
641 + "abstractions/nvidia" = ''
642 + include "${pkgs.apparmor-profiles}/etc/apparmor.d/abstractions/nvidia"
643 + ${etcRule "vdpau_wrapper.cfg"}
644 + '';
645 + "abstractions/opencl-common" = ''
646 + include "${pkgs.apparmor-profiles}/etc/apparmor.d/abstractions/opencl-common"
647 + ${etcRule {path="OpenCL"; trail="/**";}}
648 + '';
649 + "abstractions/opencl-mesa" = ''
650 + include "${pkgs.apparmor-profiles}/etc/apparmor.d/abstractions/opencl-mesa"
651 + ${etcRule "default/drirc"}
652 + '';
653 + "abstractions/openssl" = ''
654 + include "${pkgs.apparmor-profiles}/etc/apparmor.d/abstractions/openssl"
655 + ${etcRule {path="ssl"; trail="/openssl.cnf";}}
656 + '';
657 + "abstractions/p11-kit" = ''
658 + include "${pkgs.apparmor-profiles}/etc/apparmor.d/abstractions/p11-kit"
659 + ${etcRule {path="pkcs11"; trail="/";}}
660 + ${etcRule {path="pkcs11"; trail="/pkcs11.conf";}}
661 + ${etcRule {path="pkcs11"; trail="/modules/";}}
662 + ${etcRule {path="pkcs11"; trail="/modules/*";}}
663 + '';
664 + "abstractions/perl" = ''
665 + include "${pkgs.apparmor-profiles}/etc/apparmor.d/abstractions/perl"
666 + ${etcRule {path="perl"; trail="/**";}}
667 + '';
668 + "abstractions/php" = ''
669 + include "${pkgs.apparmor-profiles}/etc/apparmor.d/abstractions/php"
670 + ${etcRule {path="php"; trail="/**/";}}
671 + ${etcRule {path="php5"; trail="/**/";}}
672 + ${etcRule {path="php7"; trail="/**/";}}
673 + ${etcRule {path="php"; trail="/**.ini";}}
674 + ${etcRule {path="php5"; trail="/**.ini";}}
675 + ${etcRule {path="php7"; trail="/**.ini";}}
676 + '';
677 + "abstractions/postfix-common" = ''
678 + include "${pkgs.apparmor-profiles}/etc/apparmor.d/abstractions/postfix-common"
679 + ${etcRule "mailname"}
680 + ${etcRule {path="postfix"; trail="/*.cf";}}
681 + ${etcRule "postfix/main.cf"}
682 + ${etcRule "postfix/master.cf"}
683 + '';
684 + "abstractions/python" = ''
685 + include "${pkgs.apparmor-profiles}/etc/apparmor.d/abstractions/python"
686 + '';
687 + "abstractions/qt5" = ''
688 + include "${pkgs.apparmor-profiles}/etc/apparmor.d/abstractions/qt5"
689 + ${etcRule {path="xdg"; trail="/QtProject/qtlogging.ini";}}
690 + ${etcRule {path="xdg/QtProject"; trail="/qtlogging.ini";}}
691 + ${etcRule "xdg/QtProject/qtlogging.ini"}
692 + '';
693 + "abstractions/samba" = ''
694 + include "${pkgs.apparmor-profiles}/etc/apparmor.d/abstractions/samba"
695 + ${etcRule {path="samba"; trail="/*";}}
696 + '';
697 + "abstractions/ssl_certs" = ''
698 + include "${pkgs.apparmor-profiles}/etc/apparmor.d/abstractions/ssl_certs"
699 + ${etcRule "ssl/certs/ca-certificates.crt"}
700 + ${etcRule "ssl/certs/ca-bundle.crt"}
701 + ${etcRule "pki/tls/certs/ca-bundle.crt"}
702 +
703 + ${etcRule {path="ssl/trust"; trail="/";}}
704 + ${etcRule {path="ssl/trust"; trail="/*";}}
705 + ${etcRule {path="ssl/trust/anchors"; trail="/";}}
706 + ${etcRule {path="ssl/trust/anchors"; trail="/**";}}
707 + ${etcRule {path="pki/trust"; trail="/";}}
708 + ${etcRule {path="pki/trust"; trail="/*";}}
709 + ${etcRule {path="pki/trust/anchors"; trail="/";}}
710 + ${etcRule {path="pki/trust/anchors"; trail="/**";}}
711 +
712 + # security.acme NixOS module
713 + r /var/lib/acme/*/cert.pem,
714 + r /var/lib/acme/*/chain.pem,
715 + r /var/lib/acme/*/fullchain.pem,
716 + '';
717 + "abstractions/ssl_keys" = ''
718 + # security.acme NixOS module
719 + r /var/lib/acme/*/full.pem,
720 + r /var/lib/acme/*/key.pem,
721 + '';
722 + "abstractions/vulkan" = ''
723 + include "${pkgs.apparmor-profiles}/etc/apparmor.d/abstractions/vulkan"
724 + ${etcRule {path="vulkan/icd.d"; trail="/";}}
725 + ${etcRule {path="vulkan/icd.d"; trail="/*.json";}}
726 + '';
727 + "abstractions/winbind" = ''
728 + include "${pkgs.apparmor-profiles}/etc/apparmor.d/abstractions/winbind"
729 + ${etcRule {path="samba"; trail="/smb.conf";}}
730 + ${etcRule {path="samba"; trail="/dhcp.conf";}}
731 + '';
732 + "abstractions/X" = ''
733 + include "${pkgs.apparmor-profiles}/etc/apparmor.d/abstractions/X"
734 + ${etcRule {path="X11/cursors"; trail="/";}}
735 + ${etcRule {path="X11/cursors"; trail="/**";}}
736 + '';
737 +};
738 +}
739 diff --git a/nixos/modules/security/apparmor/profiles.nix b/nixos/modules/security/apparmor/profiles.nix
740 new file mode 100644
741 index 00000000000..8eb630b5a48
742 --- /dev/null
743 +++ b/nixos/modules/security/apparmor/profiles.nix
744 @@ -0,0 +1,11 @@
745 +{ config, lib, pkgs, ... }:
746 +let apparmor = config.security.apparmor; in
747 +{
748 +config.security.apparmor.packages = [ pkgs.apparmor-profiles ];
749 +config.security.apparmor.policies."bin.ping".profile = lib.mkIf apparmor.policies."bin.ping".enable ''
750 + include "${pkgs.iputils.apparmor}/bin.ping"
751 + include "${pkgs.inetutils.apparmor}/bin.ping"
752 + # Note that including those two profiles in the same profile
753 + # would not work if the second one were to re-include <tunables/global>.
754 +'';
755 +}
756 diff --git a/nixos/modules/security/pam.nix b/nixos/modules/security/pam.nix
757 index 103cf205012..8216c03795a 100644
758 --- a/nixos/modules/security/pam.nix
759 +++ b/nixos/modules/security/pam.nix
760 @@ -895,6 +895,61 @@ in
761 runuser-l = { rootOK = true; unixAuth = false; };
762 };
763
764 + security.apparmor.includes."abstractions/pam" = let
765 + isEnabled = test: fold or false (map test (attrValues config.security.pam.services));
766 + in ''
767 + ${lib.concatMapStringsSep "\n"
768 + (name: "r ${config.environment.etc."pam.d/${name}".source},")
769 + (attrNames config.security.pam.services)}
770 + mr ${getLib pkgs.pam}/lib/security/pam_filter/*,
771 + mr ${getLib pkgs.pam}/lib/security/pam_*.so,
772 + r ${getLib pkgs.pam}/lib/security/,
773 + ${optionalString use_ldap
774 + "mr ${pam_ldap}/lib/security/pam_ldap.so,"}
775 + ${optionalString config.services.sssd.enable
776 + "mr ${pkgs.sssd}/lib/security/pam_sss.so,"}
777 + ${optionalString config.krb5.enable ''
778 + mr ${pam_krb5}/lib/security/pam_krb5.so,
779 + mr ${pam_ccreds}/lib/security/pam_ccreds.so,
780 + ''}
781 + ${optionalString (isEnabled (cfg: cfg.googleOsLoginAccountVerification)) ''
782 + mr ${pkgs.google-compute-engine-oslogin}/lib/pam_oslogin_login.so,
783 + mr ${pkgs.google-compute-engine-oslogin}/lib/pam_oslogin_admin.so,
784 + ''}
785 + ${optionalString (isEnabled (cfg: cfg.googleOsLoginAuthentication))
786 + "mr ${pkgs.google-compute-engine-oslogin}/lib/pam_oslogin_login.so,"}
787 + ${optionalString (config.security.pam.enableSSHAgentAuth && isEnabled (cfg: cfg.sshAgentAuth))
788 + "mr ${pkgs.pam_ssh_agent_auth}/libexec/pam_ssh_agent_auth.so,"}
789 + ${optionalString (isEnabled (cfg: cfg.fprintAuth))
790 + "mr ${pkgs.fprintd}/lib/security/pam_fprintd.so,"}
791 + ${optionalString (isEnabled (cfg: cfg.u2fAuth))
792 + "mr ${pkgs.pam_u2f}/lib/security/pam_u2f.so,"}
793 + ${optionalString (isEnabled (cfg: cfg.usbAuth))
794 + "mr ${pkgs.pam_usb}/lib/security/pam_usb.so,"}
795 + ${optionalString (isEnabled (cfg: cfg.oathAuth))
796 + "mr ${pkgs.oathToolkit}/lib/security/pam_oath.so,"}
797 + ${optionalString (isEnabled (cfg: cfg.yubicoAuth))
798 + "mr ${pkgs.yubico-pam}/lib/security/pam_yubico.so,"}
799 + ${optionalString (isEnabled (cfg: cfg.duoSecurity.enable))
800 + "mr ${pkgs.duo-unix}/lib/security/pam_duo.so,"}
801 + ${optionalString (isEnabled (cfg: cfg.otpwAuth))
802 + "mr ${pkgs.otpw}/lib/security/pam_otpw.so,"}
803 + ${optionalString config.security.pam.enableEcryptfs
804 + "mr ${pkgs.ecryptfs}/lib/security/pam_ecryptfs.so,"}
805 + ${optionalString (isEnabled (cfg: cfg.pamMount))
806 + "mr ${pkgs.pam_mount}/lib/security/pam_mount.so,"}
807 + ${optionalString (isEnabled (cfg: cfg.enableGnomeKeyring))
808 + "mr ${pkgs.gnome3.gnome-keyring}/lib/security/pam_gnome_keyring.so,"}
809 + ${optionalString (isEnabled (cfg: cfg.startSession))
810 + "mr ${pkgs.systemd}/lib/security/pam_systemd.so,"}
811 + ${optionalString (isEnabled (cfg: cfg.enableAppArmor) && config.security.apparmor.enable)
812 + "mr ${pkgs.apparmor-pam}/lib/security/pam_apparmor.so,"}
813 + ${optionalString (isEnabled (cfg: cfg.enableKwallet))
814 + "mr ${pkgs.plasma5.kwallet-pam}/lib/security/pam_kwallet5.so,"}
815 + ${optionalString config.virtualisation.lxc.lxcfs.enable
816 + "mr ${pkgs.lxc}/lib/security/pam_cgfs.so"}
817 + '';
818 +
819 };
820
821 }
822 diff --git a/nixos/modules/security/wrappers/default.nix b/nixos/modules/security/wrappers/default.nix
823 index 3cbf22fea7a..1e65f451515 100644
824 --- a/nixos/modules/security/wrappers/default.nix
825 +++ b/nixos/modules/security/wrappers/default.nix
826 @@ -171,6 +171,14 @@ in
827 export PATH="${wrapperDir}:$PATH"
828 '';
829
830 + security.apparmor.includes."nixos/security.wrappers" = ''
831 + include "${pkgs.apparmorRulesFromClosure { name="security.wrappers"; } [
832 + securityWrapper
833 + pkgs.stdenv.cc.cc
834 + pkgs.stdenv.cc.libc
835 + ]}"
836 + '';
837 +
838 ###### setcap activation script
839 system.activationScripts.wrappers =
840 lib.stringAfter [ "specialfs" "users" ]
841 diff --git a/nixos/modules/services/torrent/transmission.nix b/nixos/modules/services/torrent/transmission.nix
842 index 7bec073e26f..779924a65a8 100644
843 --- a/nixos/modules/services/torrent/transmission.nix
844 +++ b/nixos/modules/services/torrent/transmission.nix
845 @@ -5,17 +5,22 @@ with lib;
846 let
847 cfg = config.services.transmission;
848 inherit (config.environment) etc;
849 - apparmor = config.security.apparmor.enable;
850 + apparmor = config.security.apparmor;
851 rootDir = "/run/transmission";
852 - homeDir = "/var/lib/transmission";
853 settingsDir = ".config/transmission-daemon";
854 downloadsDir = "Downloads";
855 incompleteDir = ".incomplete";
856 watchDir = "watchdir";
857 - # TODO: switch to configGen.json once RFC0042 is implemented
858 - settingsFile = pkgs.writeText "settings.json" (builtins.toJSON cfg.settings);
859 + settingsFormat = pkgs.formats.json {};
860 + settingsFile = settingsFormat.generate "settings.json" cfg.settings;
861 in
862 {
863 + imports = [
864 + (mkRenamedOptionModule ["services" "transmission" "port"]
865 + ["services" "transmission" "settings" "rpc-port"])
866 + (mkAliasOptionModule ["services" "transmission" "openFirewall"]
867 + ["services" "transmission" "openPeerPorts"])
868 + ];
869 options = {
870 services.transmission = {
871 enable = mkEnableOption ''the headless Transmission BitTorrent daemon.
872 @@ -24,48 +29,141 @@ in
873 transmission-remote, the WebUI (http://127.0.0.1:9091/ by default),
874 or other clients like stig or tremc.
875
876 - Torrents are downloaded to ${homeDir}/${downloadsDir} by default and are
877 + Torrents are downloaded to <xref linkend="opt-services.transmission.home"/>/${downloadsDir} by default and are
878 accessible to users in the "transmission" group'';
879
880 - settings = mkOption rec {
881 - # TODO: switch to types.config.json as prescribed by RFC0042 once it's implemented
882 - type = types.attrs;
883 - apply = recursiveUpdate default;
884 - default =
885 - {
886 - download-dir = "${cfg.home}/${downloadsDir}";
887 - incomplete-dir = "${cfg.home}/${incompleteDir}";
888 - incomplete-dir-enabled = true;
889 - watch-dir = "${cfg.home}/${watchDir}";
890 - watch-dir-enabled = false;
891 - message-level = 1;
892 - peer-port = 51413;
893 - peer-port-random-high = 65535;
894 - peer-port-random-low = 49152;
895 - peer-port-random-on-start = false;
896 - rpc-bind-address = "127.0.0.1";
897 - rpc-port = 9091;
898 - script-torrent-done-enabled = false;
899 - script-torrent-done-filename = "";
900 - umask = 2; # 0o002 in decimal as expected by Transmission
901 - utp-enabled = true;
902 - };
903 - example =
904 - {
905 - download-dir = "/srv/torrents/";
906 - incomplete-dir = "/srv/torrents/.incomplete/";
907 - incomplete-dir-enabled = true;
908 - rpc-whitelist = "127.0.0.1,192.168.*.*";
909 - };
910 + settings = mkOption {
911 description = ''
912 - Attribute set whose fields overwrites fields in
913 + Settings whose options overwrite fields in
914 <literal>.config/transmission-daemon/settings.json</literal>
915 - (each time the service starts). String values must be quoted, integer and
916 - boolean values must not.
917 + (each time the service starts).
918
919 See <link xlink:href="https://github.com/transmission/transmission/wiki/Editing-Configuration-Files">Transmission's Wiki</link>
920 - for documentation.
921 + for documentation of settings not explicitely covered by this module.
922 '';
923 + default = {};
924 + type = types.submodule {
925 + freeformType = settingsFormat.type;
926 + options.download-dir = mkOption {
927 + type = types.path;
928 + default = "${cfg.home}/${downloadsDir}";
929 + description = "Directory where to download torrents.";
930 + };
931 + options.incomplete-dir = mkOption {
932 + type = types.path;
933 + default = "${cfg.home}/${incompleteDir}";
934 + description = ''
935 + When enabled with
936 + services.transmission.home
937 + <xref linkend="opt-services.transmission.settings.incomplete-dir-enabled"/>,
938 + new torrents will download the files to this directory.
939 + When complete, the files will be moved to download-dir
940 + <xref linkend="opt-services.transmission.settings.download-dir"/>.
941 + '';
942 + };
943 + options.incomplete-dir-enabled = mkOption {
944 + type = types.bool;
945 + default = true;
946 + description = "";
947 + };
948 + options.message-level = mkOption {
949 + type = types.ints.between 0 2;
950 + default = 2;
951 + description = "Set verbosity of transmission messages.";
952 + };
953 + options.peer-port = mkOption {
954 + type = types.port;
955 + default = 51413;
956 + description = "The peer port to listen for incoming connections.";
957 + };
958 + options.peer-port-random-high = mkOption {
959 + type = types.port;
960 + default = 65535;
961 + description = ''
962 + The maximum peer port to listen to for incoming connections
963 + when <xref linkend="opt-services.transmission.settings.peer-port-random-on-start"/> is enabled.
964 + '';
965 + };
966 + options.peer-port-random-low = mkOption {
967 + type = types.port;
968 + default = 65535;
969 + description = ''
970 + The minimal peer port to listen to for incoming connections
971 + when <xref linkend="opt-services.transmission.settings.peer-port-random-on-start"/> is enabled.
972 + '';
973 + };
974 + options.peer-port-random-on-start = mkOption {
975 + type = types.bool;
976 + default = false;
977 + description = "Randomize the peer port.";
978 + };
979 + options.rpc-bind-address = mkOption {
980 + type = types.str;
981 + default = "127.0.0.1";
982 + example = "0.0.0.0";
983 + description = ''
984 + Where to listen for RPC connections.
985 + Use \"0.0.0.0\" to listen on all interfaces.
986 + '';
987 + };
988 + options.rpc-port = mkOption {
989 + type = types.port;
990 + default = 9091;
991 + description = "The RPC port to listen to.";
992 + };
993 + options.script-torrent-done-enabled = mkOption {
994 + type = types.bool;
995 + default = false;
996 + description = ''
997 + Whether to run
998 + <xref linkend="opt-services.transmission.settings.script-torrent-done-filename"/>
999 + at torrent completion.
1000 + '';
1001 + };
1002 + options.script-torrent-done-filename = mkOption {
1003 + type = types.nullOr types.path;
1004 + default = null;
1005 + description = "Executable to be run at torrent completion.";
1006 + };
1007 + options.umask = mkOption {
1008 + type = types.int;
1009 + default = 2;
1010 + description = ''
1011 + Sets transmission's file mode creation mask.
1012 + See the umask(2) manpage for more information.
1013 + Users who want their saved torrents to be world-writable
1014 + may want to set this value to 0.
1015 + Bear in mind that the json markup language only accepts numbers in base 10,
1016 + so the standard umask(2) octal notation "022" is written in settings.json as 18.
1017 + '';
1018 + };
1019 + options.utp-enabled = mkOption {
1020 + type = types.bool;
1021 + default = true;
1022 + description = ''
1023 + Whether to enable <link xlink:href="http://en.wikipedia.org/wiki/Micro_Transport_Protocol">Micro Transport Protocol (µTP)</link>.
1024 + '';
1025 + };
1026 + options.watch-dir = mkOption {
1027 + type = types.path;
1028 + default = "${cfg.home}/${watchDir}";
1029 + description = "Watch a directory for torrent files and add them to transmission.";
1030 + };
1031 + options.watch-dir-enabled = mkOption {
1032 + type = types.bool;
1033 + default = false;
1034 + description = ''Whether to enable the
1035 + <xref linkend="opt-services.transmission.settings.watch-dir"/>.
1036 + '';
1037 + };
1038 + options.trash-original-torrent-files = mkOption {
1039 + type = types.bool;
1040 + default = false;
1041 + description = ''Whether to delete torrents added from the
1042 + <xref linkend="opt-services.transmission.settings.watch-dir"/>.
1043 + '';
1044 + };
1045 + };
1046 };
1047
1048 downloadDirPermissions = mkOption {
1049 @@ -74,31 +172,22 @@ in
1050 example = "775";
1051 description = ''
1052 The permissions set by <literal>systemd.activationScripts.transmission-daemon</literal>
1053 - on the directories <link linkend="opt-services.transmission.settings">settings.download-dir</link>
1054 - and <link linkend="opt-services.transmission.settings">settings.incomplete-dir</link>.
1055 + on the directories <xref linkend="opt-services.transmission.settings.download-dir"/>
1056 + and <xref linkend="opt-services.transmission.settings.incomplete-dir"/>.
1057 Note that you may also want to change
1058 - <link linkend="opt-services.transmission.settings">settings.umask</link>.
1059 - '';
1060 - };
1061 -
1062 - port = mkOption {
1063 - type = types.port;
1064 - description = ''
1065 - TCP port number to run the RPC/web interface.
1066 -
1067 - If instead you want to change the peer port,
1068 - use <link linkend="opt-services.transmission.settings">settings.peer-port</link>
1069 - or <link linkend="opt-services.transmission.settings">settings.peer-port-random-on-start</link>.
1070 + <xref linkend="opt-services.transmission.settings.umask"/>.
1071 '';
1072 };
1073
1074 home = mkOption {
1075 type = types.path;
1076 - default = homeDir;
1077 + default = "/var/lib/transmission";
1078 description = ''
1079 The directory where Transmission will create <literal>${settingsDir}</literal>.
1080 - as well as <literal>${downloadsDir}/</literal> unless <link linkend="opt-services.transmission.settings">settings.download-dir</link> is changed,
1081 - and <literal>${incompleteDir}/</literal> unless <link linkend="opt-services.transmission.settings">settings.incomplete-dir</link> is changed.
1082 + as well as <literal>${downloadsDir}/</literal> unless
1083 + <xref linkend="opt-services.transmission.settings.download-dir"/> is changed,
1084 + and <literal>${incompleteDir}/</literal> unless
1085 + <xref linkend="opt-services.transmission.settings.incomplete-dir"/> is changed.
1086 '';
1087 };
1088
1089 @@ -119,19 +208,22 @@ in
1090 description = ''
1091 Path to a JSON file to be merged with the settings.
1092 Useful to merge a file which is better kept out of the Nix store
1093 - because it contains sensible data like <link linkend="opt-services.transmission.settings">settings.rpc-password</link>.
1094 + because it contains sensible data like
1095 + <xref linkend="opt-services.transmission.settings.rpc-password"/>.
1096 '';
1097 default = "/dev/null";
1098 example = "/var/lib/secrets/transmission/settings.json";
1099 };
1100
1101 - openFirewall = mkEnableOption "opening of the peer port(s) in the firewall";
1102 + openPeerPorts = mkEnableOption "opening of the peer port(s) in the firewall";
1103 +
1104 + openRPCPort = mkEnableOption "opening of the RPC port in the firewall";
1105
1106 performanceNetParameters = mkEnableOption ''tweaking of kernel parameters
1107 to open many more connections at the same time.
1108
1109 Note that you may also want to increase
1110 - <link linkend="opt-services.transmission.settings">settings.peer-limit-global</link>.
1111 + <xref linkend="opt-services.transmission.settings.peer-limit-global"/>.
1112 And be aware that these settings are quite aggressive
1113 and might not suite your regular desktop use.
1114 For instance, SSH sessions may time out more easily'';
1115 @@ -152,40 +244,14 @@ in
1116 install -d -m '${cfg.downloadDirPermissions}' -o '${cfg.user}' -g '${cfg.group}' '${cfg.settings.download-dir}'
1117 '' + optionalString cfg.settings.incomplete-dir-enabled ''
1118 install -d -m '${cfg.downloadDirPermissions}' -o '${cfg.user}' -g '${cfg.group}' '${cfg.settings.incomplete-dir}'
1119 + '' + optionalString cfg.settings.watch-dir-enabled ''
1120 + install -d -m '${cfg.downloadDirPermissions}' -o '${cfg.user}' -g '${cfg.group}' '${cfg.settings.watch-dir}'
1121 '';
1122
1123 - assertions = [
1124 - { assertion = builtins.match "^/.*" cfg.home != null;
1125 - message = "`services.transmission.home' must be an absolute path.";
1126 - }
1127 - { assertion = types.path.check cfg.settings.download-dir;
1128 - message = "`services.transmission.settings.download-dir' must be an absolute path.";
1129 - }
1130 - { assertion = types.path.check cfg.settings.incomplete-dir;
1131 - message = "`services.transmission.settings.incomplete-dir' must be an absolute path.";
1132 - }
1133 - { assertion = types.path.check cfg.settings.watch-dir;
1134 - message = "`services.transmission.settings.watch-dir' must be an absolute path.";
1135 - }
1136 - { assertion = cfg.settings.script-torrent-done-filename == "" || types.path.check cfg.settings.script-torrent-done-filename;
1137 - message = "`services.transmission.settings.script-torrent-done-filename' must be an absolute path.";
1138 - }
1139 - { assertion = types.port.check cfg.settings.rpc-port;
1140 - message = "${toString cfg.settings.rpc-port} is not a valid port number for `services.transmission.settings.rpc-port`.";
1141 - }
1142 - # In case both port and settings.rpc-port are explicitely defined: they must be the same.
1143 - { assertion = !options.services.transmission.port.isDefined || cfg.port == cfg.settings.rpc-port;
1144 - message = "`services.transmission.port' is not equal to `services.transmission.settings.rpc-port'";
1145 - }
1146 - ];
1147 -
1148 - services.transmission.settings =
1149 - optionalAttrs options.services.transmission.port.isDefined { rpc-port = cfg.port; };
1150 -
1151 systemd.services.transmission = {
1152 description = "Transmission BitTorrent Service";
1153 - after = [ "network.target" ] ++ optional apparmor "apparmor.service";
1154 - requires = optional apparmor "apparmor.service";
1155 + after = [ "network.target" ] ++ optional apparmor.enable "apparmor.service";
1156 + requires = optional apparmor.enable "apparmor.service";
1157 wantedBy = [ "multi-user.target" ];
1158 environment.CURL_CA_BUNDLE = etc."ssl/certs/ca-certificates.crt".source;
1159
1160 @@ -226,11 +292,9 @@ in
1161 cfg.settings.download-dir
1162 ] ++
1163 optional cfg.settings.incomplete-dir-enabled
1164 - cfg.settings.incomplete-dir
1165 - ++
1166 - optional cfg.settings.watch-dir-enabled
1167 - cfg.settings.watch-dir
1168 - ;
1169 + cfg.settings.incomplete-dir ++
1170 + optional (cfg.settings.watch-dir-enabled && cfg.settings.trash-original-torrent-files)
1171 + cfg.settings.watch-dir;
1172 BindReadOnlyPaths = [
1173 # No confinement done of /nix/store here like in systemd-confinement.nix,
1174 # an AppArmor profile is provided to get a confinement based upon paths and rights.
1175 @@ -239,8 +303,10 @@ in
1176 "/run"
1177 ] ++
1178 optional (cfg.settings.script-torrent-done-enabled &&
1179 - cfg.settings.script-torrent-done-filename != "")
1180 - cfg.settings.script-torrent-done-filename;
1181 + cfg.settings.script-torrent-done-filename != null)
1182 + cfg.settings.script-torrent-done-filename ++
1183 + optional (cfg.settings.watch-dir-enabled && !cfg.settings.trash-original-torrent-files)
1184 + cfg.settings.watch-dir;
1185 # The following options are only for optimizing:
1186 # systemd-analyze security transmission
1187 AmbientCapabilities = "";
1188 @@ -307,25 +373,28 @@ in
1189 };
1190 });
1191
1192 - networking.firewall = mkIf cfg.openFirewall (
1193 - if cfg.settings.peer-port-random-on-start
1194 - then
1195 - { allowedTCPPortRanges =
1196 - [ { from = cfg.settings.peer-port-random-low;
1197 - to = cfg.settings.peer-port-random-high;
1198 - }
1199 - ];
1200 - allowedUDPPortRanges =
1201 - [ { from = cfg.settings.peer-port-random-low;
1202 - to = cfg.settings.peer-port-random-high;
1203 - }
1204 - ];
1205 - }
1206 - else
1207 - { allowedTCPPorts = [ cfg.settings.peer-port ];
1208 - allowedUDPPorts = [ cfg.settings.peer-port ];
1209 - }
1210 - );
1211 + networking.firewall = mkMerge [
1212 + (mkIf cfg.openPeerPorts (
1213 + if cfg.settings.peer-port-random-on-start
1214 + then
1215 + { allowedTCPPortRanges =
1216 + [ { from = cfg.settings.peer-port-random-low;
1217 + to = cfg.settings.peer-port-random-high;
1218 + }
1219 + ];
1220 + allowedUDPPortRanges =
1221 + [ { from = cfg.settings.peer-port-random-low;
1222 + to = cfg.settings.peer-port-random-high;
1223 + }
1224 + ];
1225 + }
1226 + else
1227 + { allowedTCPPorts = [ cfg.settings.peer-port ];
1228 + allowedUDPPorts = [ cfg.settings.peer-port ];
1229 + }
1230 + ))
1231 + (mkIf cfg.openRPCPort { allowedTCPPorts = [ cfg.settings.rpc-port ]; })
1232 + ];
1233
1234 boot.kernel.sysctl = mkMerge [
1235 # Transmission uses a single UDP socket in order to implement multiple uTP sockets,
1236 @@ -340,113 +409,57 @@ in
1237 # Increase the number of available source (local) TCP and UDP ports to 49151.
1238 # Usual default is 32768 60999, ie. 28231 ports.
1239 # Find out your current usage with: ss -s
1240 - "net.ipv4.ip_local_port_range" = "16384 65535";
1241 + "net.ipv4.ip_local_port_range" = mkDefault "16384 65535";
1242 # Timeout faster generic TCP states.
1243 # Usual default is 600.
1244 # Find out your current usage with: watch -n 1 netstat -nptuo
1245 - "net.netfilter.nf_conntrack_generic_timeout" = 60;
1246 + "net.netfilter.nf_conntrack_generic_timeout" = mkDefault 60;
1247 # Timeout faster established but inactive connections.
1248 # Usual default is 432000.
1249 - "net.netfilter.nf_conntrack_tcp_timeout_established" = 600;
1250 + "net.netfilter.nf_conntrack_tcp_timeout_established" = mkDefault 600;
1251 # Clear immediately TCP states after timeout.
1252 # Usual default is 120.
1253 - "net.netfilter.nf_conntrack_tcp_timeout_time_wait" = 1;
1254 + "net.netfilter.nf_conntrack_tcp_timeout_time_wait" = mkDefault 1;
1255 # Increase the number of trackable connections.
1256 # Usual default is 262144.
1257 # Find out your current usage with: conntrack -C
1258 - "net.netfilter.nf_conntrack_max" = 1048576;
1259 + "net.netfilter.nf_conntrack_max" = mkDefault 1048576;
1260 })
1261 ];
1262
1263 - security.apparmor.profiles = mkIf apparmor [
1264 - (pkgs.writeText "apparmor-transmission-daemon" ''
1265 - include <tunables/global>
1266 + security.apparmor.policies."bin.transmission-daemon".profile = ''
1267 + include "${pkgs.transmission.apparmor}/bin.transmission-daemon"
1268 + '';
1269 + security.apparmor.includes."local/bin.transmission-daemon" = ''
1270 + r ${config.systemd.services.transmission.environment.CURL_CA_BUNDLE},
1271
1272 - ${pkgs.transmission}/bin/transmission-daemon {
1273 - include <abstractions/base>
1274 - include <abstractions/nameservice>
1275 + owner rw ${cfg.home}/${settingsDir}/**,
1276 + rw ${cfg.settings.download-dir}/**,
1277 + ${optionalString cfg.settings.incomplete-dir-enabled ''
1278 + rw ${cfg.settings.incomplete-dir}/**,
1279 + ''}
1280 + ${optionalString cfg.settings.watch-dir-enabled ''
1281 + r${optionalString cfg.settings.trash-original-torrent-files "w"} ${cfg.settings.watch-dir}/**,
1282 + ''}
1283 + profile dirs {
1284 + rw ${cfg.settings.download-dir}/**,
1285 + ${optionalString cfg.settings.incomplete-dir-enabled ''
1286 + rw ${cfg.settings.incomplete-dir}/**,
1287 + ''}
1288 + ${optionalString cfg.settings.watch-dir-enabled ''
1289 + r${optionalString cfg.settings.trash-original-torrent-files "w"} ${cfg.settings.watch-dir}/**,
1290 + ''}
1291 + }
1292
1293 - # NOTE: https://github.com/NixOS/nixpkgs/pull/93457
1294 - # will remove the need for these by fixing <abstractions/base>
1295 - r ${etc."hosts".source},
1296 - r /etc/ld-nix.so.preload,
1297 - ${lib.optionalString (builtins.hasAttr "ld-nix.so.preload" etc) ''
1298 - r ${etc."ld-nix.so.preload".source},
1299 - ${concatMapStrings (p: optionalString (p != "") ("mr ${p},\n"))
1300 - (splitString "\n" config.environment.etc."ld-nix.so.preload".text)}
1301 - ''}
1302 - r ${etc."ssl/certs/ca-certificates.crt".source},
1303 - r ${pkgs.tzdata}/share/zoneinfo/**,
1304 - r ${pkgs.stdenv.cc.libc}/share/i18n/**,
1305 - r ${pkgs.stdenv.cc.libc}/share/locale/**,
1306 -
1307 - mr ${getLib pkgs.stdenv.cc.cc}/lib/*.so*,
1308 - mr ${getLib pkgs.stdenv.cc.libc}/lib/*.so*,
1309 - mr ${getLib pkgs.attr}/lib/libattr*.so*,
1310 - mr ${getLib pkgs.c-ares}/lib/libcares*.so*,
1311 - mr ${getLib pkgs.curl}/lib/libcurl*.so*,
1312 - mr ${getLib pkgs.keyutils}/lib/libkeyutils*.so*,
1313 - mr ${getLib pkgs.libcap}/lib/libcap*.so*,
1314 - mr ${getLib pkgs.libevent}/lib/libevent*.so*,
1315 - mr ${getLib pkgs.libgcrypt}/lib/libgcrypt*.so*,
1316 - mr ${getLib pkgs.libgpgerror}/lib/libgpg-error*.so*,
1317 - mr ${getLib pkgs.libkrb5}/lib/lib*.so*,
1318 - mr ${getLib pkgs.libssh2}/lib/libssh2*.so*,
1319 - mr ${getLib pkgs.lz4}/lib/liblz4*.so*,
1320 - mr ${getLib pkgs.nghttp2}/lib/libnghttp2*.so*,
1321 - mr ${getLib pkgs.openssl}/lib/libcrypto*.so*,
1322 - mr ${getLib pkgs.openssl}/lib/libssl*.so*,
1323 - mr ${getLib pkgs.systemd}/lib/libsystemd*.so*,
1324 - mr ${getLib pkgs.util-linuxMinimal.out}/lib/libblkid.so*,
1325 - mr ${getLib pkgs.util-linuxMinimal.out}/lib/libmount.so*,
1326 - mr ${getLib pkgs.util-linuxMinimal.out}/lib/libuuid.so*,
1327 - mr ${getLib pkgs.xz}/lib/liblzma*.so*,
1328 - mr ${getLib pkgs.zlib}/lib/libz*.so*,
1329 -
1330 - r @{PROC}/sys/kernel/random/uuid,
1331 - r @{PROC}/sys/vm/overcommit_memory,
1332 - # @{pid} is not a kernel variable yet but a regexp
1333 - #r @{PROC}/@{pid}/environ,
1334 - r @{PROC}/@{pid}/mounts,
1335 - rwk /tmp/tr_session_id_*,
1336 - r /run/systemd/resolve/stub-resolv.conf,
1337 -
1338 - r ${pkgs.openssl.out}/etc/**,
1339 - r ${config.systemd.services.transmission.environment.CURL_CA_BUNDLE},
1340 - r ${pkgs.transmission}/share/transmission/**,
1341 -
1342 - owner rw ${cfg.home}/${settingsDir}/**,
1343 - rw ${cfg.settings.download-dir}/**,
1344 - ${optionalString cfg.settings.incomplete-dir-enabled ''
1345 - rw ${cfg.settings.incomplete-dir}/**,
1346 - ''}
1347 - ${optionalString cfg.settings.watch-dir-enabled ''
1348 - rw ${cfg.settings.watch-dir}/**,
1349 - ''}
1350 - profile dirs {
1351 - rw ${cfg.settings.download-dir}/**,
1352 - ${optionalString cfg.settings.incomplete-dir-enabled ''
1353 - rw ${cfg.settings.incomplete-dir}/**,
1354 - ''}
1355 - ${optionalString cfg.settings.watch-dir-enabled ''
1356 - rw ${cfg.settings.watch-dir}/**,
1357 - ''}
1358 - }
1359 -
1360 - ${optionalString (cfg.settings.script-torrent-done-enabled &&
1361 - cfg.settings.script-torrent-done-filename != "") ''
1362 - # Stack transmission_directories profile on top of
1363 - # any existing profile for script-torrent-done-filename
1364 - # FIXME: to be tested as I'm not sure it works well with NoNewPrivileges=
1365 - # https://gitlab.com/apparmor/apparmor/-/wikis/AppArmorStacking#seccomp-and-no_new_privs
1366 - px ${cfg.settings.script-torrent-done-filename} -> &@{dirs},
1367 - ''}
1368 -
1369 - # FIXME: enable customizing using https://github.com/NixOS/nixpkgs/pull/93457
1370 - # include <local/transmission-daemon>
1371 - }
1372 - '')
1373 - ];
1374 + ${optionalString (cfg.settings.script-torrent-done-enabled &&
1375 + cfg.settings.script-torrent-done-filename != null) ''
1376 + # Stack transmission_directories profile on top of
1377 + # any existing profile for script-torrent-done-filename
1378 + # FIXME: to be tested as I'm not sure it works well with NoNewPrivileges=
1379 + # https://gitlab.com/apparmor/apparmor/-/wikis/AppArmorStacking#seccomp-and-no_new_privs
1380 + px ${cfg.settings.script-torrent-done-filename} -> &@{dirs},
1381 + ''}
1382 + '';
1383 };
1384
1385 meta.maintainers = with lib.maintainers; [ julm ];
1386 diff --git a/nixos/modules/tasks/network-interfaces.nix b/nixos/modules/tasks/network-interfaces.nix
1387 index f730ec82bdf..3bfb59a8848 100644
1388 --- a/nixos/modules/tasks/network-interfaces.nix
1389 +++ b/nixos/modules/tasks/network-interfaces.nix
1390 @@ -1111,6 +1111,21 @@ in
1391 } else {
1392 ping.source = "${pkgs.iputils.out}/bin/ping";
1393 };
1394 + security.apparmor.policies."bin.ping".profile = lib.mkIf config.security.apparmor.policies."bin.ping".enable (lib.mkAfter ''
1395 + /run/wrappers/bin/ping {
1396 + include <abstractions/base>
1397 + include <nixos/security.wrappers>
1398 + rpx /run/wrappers/wrappers.*/ping,
1399 + }
1400 + /run/wrappers/wrappers.*/ping {
1401 + include <abstractions/base>
1402 + include <nixos/security.wrappers>
1403 + r /run/wrappers/wrappers.*/ping.real,
1404 + mrpx ${config.security.wrappers.ping.source},
1405 + capability net_raw,
1406 + capability setpcap,
1407 + }
1408 + '');
1409
1410 # Set the host and domain names in the activation script. Don't
1411 # clear it if it's not configured in the NixOS configuration,
1412 diff --git a/nixos/modules/virtualisation/lxc.nix b/nixos/modules/virtualisation/lxc.nix
1413 index f484d5ee59a..0f8b22a45df 100644
1414 --- a/nixos/modules/virtualisation/lxc.nix
1415 +++ b/nixos/modules/virtualisation/lxc.nix
1416 @@ -74,9 +74,13 @@ in
1417 systemd.tmpfiles.rules = [ "d /var/lib/lxc/rootfs 0755 root root -" ];
1418
1419 security.apparmor.packages = [ pkgs.lxc ];
1420 - security.apparmor.profiles = [
1421 - "${pkgs.lxc}/etc/apparmor.d/lxc-containers"
1422 - "${pkgs.lxc}/etc/apparmor.d/usr.bin.lxc-start"
1423 - ];
1424 + security.apparmor.policies = {
1425 + "bin.lxc-start".profile = ''
1426 + include ${pkgs.lxc}/etc/apparmor.d/usr.bin.lxc-start
1427 + '';
1428 + "lxc-containers".profile = ''
1429 + include ${pkgs.lxc}/etc/apparmor.d/lxc-containers
1430 + '';
1431 + };
1432 };
1433 }
1434 diff --git a/nixos/modules/virtualisation/lxd.nix b/nixos/modules/virtualisation/lxd.nix
1435 index 4b2adf4cc69..335dc67673f 100644
1436 --- a/nixos/modules/virtualisation/lxd.nix
1437 +++ b/nixos/modules/virtualisation/lxd.nix
1438 @@ -83,11 +83,15 @@ in {
1439
1440 security.apparmor = {
1441 enable = true;
1442 - profiles = [
1443 - "${cfg.lxcPackage}/etc/apparmor.d/usr.bin.lxc-start"
1444 - "${cfg.lxcPackage}/etc/apparmor.d/lxc-containers"
1445 - ];
1446 packages = [ cfg.lxcPackage ];
1447 + policies = {
1448 + "bin.lxc-start".profile = ''
1449 + include ${cfg.lxcPackage}/etc/apparmor.d/usr.bin.lxc-start
1450 + '';
1451 + "lxc-containers".profile = ''
1452 + include ${cfg.lxcPackage}/etc/apparmor.d/lxc-containers
1453 + '';
1454 + };
1455 };
1456
1457 # TODO: remove once LXD gets proper support for cgroupsv2
1458 diff --git a/pkgs/applications/networking/p2p/transmission/default.nix b/pkgs/applications/networking/p2p/transmission/default.nix
1459 index 8cc674b1ea7..bf09c4be1db 100644
1460 --- a/pkgs/applications/networking/p2p/transmission/default.nix
1461 +++ b/pkgs/applications/networking/p2p/transmission/default.nix
1462 @@ -20,6 +20,7 @@
1463 , enableSystemd ? stdenv.isLinux
1464 , enableDaemon ? true
1465 , enableCli ? true
1466 +, apparmorRulesFromClosure
1467 }:
1468
1469 let
1470 @@ -37,6 +38,8 @@ in stdenv.mkDerivation {
1471 fetchSubmodules = true;
1472 };
1473
1474 + outputs = [ "out" "apparmor" ];
1475 +
1476 cmakeFlags =
1477 let
1478 mkFlag = opt: if opt then "ON" else "OFF";
1479 @@ -72,6 +75,30 @@ in stdenv.mkDerivation {
1480
1481 NIX_LDFLAGS = lib.optionalString stdenv.isDarwin "-framework CoreFoundation";
1482
1483 + postInstall = ''
1484 + install -D -m 644 /dev/stdin $apparmor/bin.transmission-daemon <<EOF
1485 + include <tunables/global>
1486 + $out/bin/transmission-daemon {
1487 + include <abstractions/base>
1488 + include <abstractions/nameservice>
1489 + include <abstractions/ssl_certs>
1490 + include "${apparmorRulesFromClosure { name = "transmission-daemon"; } ([
1491 + curl libevent openssl pcre zlib
1492 + ] ++ lib.optionals enableSystemd [ systemd ]
1493 + ++ lib.optionals stdenv.isLinux [ inotify-tools ]
1494 + )}"
1495 + r @{PROC}/sys/kernel/random/uuid,
1496 + r @{PROC}/sys/vm/overcommit_memory,
1497 + r @{PROC}/@{pid}/environ,
1498 + r @{PROC}/@{pid}/mounts,
1499 + rwk /tmp/tr_session_id_*,
1500 + r /run/systemd/resolve/stub-resolv.conf,
1501 +
1502 + include <local/bin.transmission-daemon>
1503 + }
1504 + EOF
1505 + '';
1506 +
1507 meta = {
1508 description = "A fast, easy and free BitTorrent client";
1509 longDescription = ''
1510 diff --git a/pkgs/os-specific/linux/apparmor/default.nix b/pkgs/os-specific/linux/apparmor/default.nix
1511 index 935b5e65b1f..5ec86c49660 100644
1512 --- a/pkgs/os-specific/linux/apparmor/default.nix
1513 +++ b/pkgs/os-specific/linux/apparmor/default.nix
1514 @@ -10,26 +10,37 @@
1515 , pam
1516 , libnotify
1517 , buildPackages
1518 +, coreutils
1519 +, gnugrep
1520 +, gnused
1521 +, kmod
1522 +, writeShellScript
1523 +, closureInfo
1524 +, runCommand
1525 }:
1526
1527 let
1528 - apparmor-series = "2.13";
1529 - apparmor-patchver = "6";
1530 - apparmor-version = apparmor-series + "." + apparmor-patchver;
1531 + apparmor-version = "3.0.1";
1532
1533 apparmor-meta = component: with lib; {
1534 homepage = "https://apparmor.net/";
1535 description = "A mandatory access control system - ${component}";
1536 license = licenses.gpl2;
1537 - maintainers = with maintainers; [ phreedom thoughtpolice joachifm ];
1538 + maintainers = with maintainers; [ joachifm julm phreedom thoughtpolice ];
1539 platforms = platforms.linux;
1540 };
1541
1542 apparmor-sources = fetchurl {
1543 - url = "https://launchpad.net/apparmor/${apparmor-series}/${apparmor-version}/+download/apparmor-${apparmor-version}.tar.gz";
1544 - sha256 = "13xshy7905d9q9n8d8i0jmdi9m36wr525g4wlsp8k21n7yvvh9j4";
1545 + url = "https://launchpad.net/apparmor/${lib.versions.majorMinor apparmor-version}/${apparmor-version}/+download/apparmor-${apparmor-version}.tar.gz";
1546 + sha256 = "096zbg3v7b51x7f1ly61mzd3iy9alad6sd4lam98j2d6v5ragbcg";
1547 };
1548
1549 + aa-teardown = writeShellScript "aa-teardown" ''
1550 + PATH="${lib.makeBinPath [coreutils gnused gnugrep]}:$PATH"
1551 + . ${apparmor-parser}/lib/apparmor/rc.apparmor.functions
1552 + remove_profiles
1553 + '';
1554 +
1555 prePatchCommon = ''
1556 chmod a+x ./common/list_capabilities.sh ./common/list_af_names.sh
1557 patchShebangs ./common/list_capabilities.sh ./common/list_af_names.sh
1558 @@ -45,12 +56,6 @@ let
1559 name = "0003-Added-missing-typedef-definitions-on-parser.patch";
1560 sha256 = "0yyaqz8jlmn1bm37arggprqz0njb4lhjni2d9c8qfqj0kll0bam0";
1561 })
1562 - (fetchpatch {
1563 - url = "https://git.alpinelinux.org/aports/plain/testing/apparmor/0007-Do-not-build-install-vim-file-with-utils-package.patch?id=74b8427cc21f04e32030d047ae92caa618105b53";
1564 - name = "0007-Do-not-build-install-vim-file-with-utils-package.patch";
1565 - sha256 = "1m4dx901biqgnr4w4wz8a2z9r9dxyw7wv6m6mqglqwf2lxinqmp4";
1566 - })
1567 - # (alpine patches {1,4,5,6,8} are needed for apparmor 2.11, but not 2.12)
1568 ];
1569
1570 # Set to `true` after the next FIXME gets fixed or this gets some
1571 @@ -121,7 +126,11 @@ let
1572 libapparmor.python
1573 ];
1574
1575 - prePatch = prePatchCommon + ''
1576 + prePatch = prePatchCommon +
1577 + # Do not build vim file
1578 + lib.optionalString stdenv.hostPlatform.isMusl ''
1579 + sed -i ./utils/Makefile -e "/\<vim\>/d"
1580 + '' + ''
1581 substituteInPlace ./utils/apparmor/easyprof.py --replace "/sbin/apparmor_parser" "${apparmor-parser}/bin/apparmor_parser"
1582 substituteInPlace ./utils/apparmor/aa.py --replace "/sbin/apparmor_parser" "${apparmor-parser}/bin/apparmor_parser"
1583 substituteInPlace ./utils/logprof.conf --replace "/sbin/apparmor_parser" "${apparmor-parser}/bin/apparmor_parser"
1584 @@ -132,7 +141,8 @@ let
1585 installFlags = [ "DESTDIR=$(out)" "BINDIR=$(out)/bin" "VIM_INSTALL_PATH=$(out)/share" "PYPREFIX=" ];
1586
1587 postInstall = ''
1588 - for prog in aa-audit aa-autodep aa-cleanprof aa-complain aa-disable aa-enforce aa-genprof aa-logprof aa-mergeprof aa-status aa-unconfined ; do
1589 + sed -i $out/bin/aa-unconfined -e "/my_env\['PATH'\]/d"
1590 + for prog in aa-audit aa-autodep aa-cleanprof aa-complain aa-disable aa-enforce aa-genprof aa-logprof aa-mergeprof aa-unconfined ; do
1591 wrapProgram $out/bin/$prog --prefix PYTHONPATH : "$out/lib/${python.libPrefix}/site-packages:$PYTHONPATH"
1592 done
1593
1594 @@ -140,6 +150,13 @@ let
1595 # aa-notify checks its name and does not work named ".aa-notify-wrapped"
1596 mv $out/bin/aa-notify $out/bin/aa-notify-wrapped
1597 makeWrapper ${perl}/bin/perl $out/bin/aa-notify --set PERL5LIB ${libapparmor}/${perl.libPrefix} --add-flags $out/bin/aa-notify-wrapped
1598 +
1599 + substituteInPlace $out/bin/aa-remove-unknown \
1600 + --replace "/lib/apparmor/rc.apparmor.functions" "${apparmor-parser}/lib/apparmor/rc.apparmor.functions"
1601 + wrapProgram $out/bin/aa-remove-unknown \
1602 + --prefix PATH : ${lib.makeBinPath [gawk]}
1603 +
1604 + ln -s ${aa-teardown} $out/bin/aa-teardown
1605 '';
1606
1607 inherit doCheck;
1608 @@ -167,7 +184,7 @@ let
1609 prePatch = prePatchCommon;
1610 postPatch = "cd ./binutils";
1611 makeFlags = [ "LANGS=" "USE_SYSTEM=1" ];
1612 - installFlags = [ "DESTDIR=$(out)" "BINDIR=$(out)/bin" ];
1613 + installFlags = [ "DESTDIR=$(out)" "BINDIR=$(out)/bin" "SBINDIR=$(out)/bin" ];
1614
1615 inherit doCheck;
1616
1617 @@ -188,6 +205,9 @@ let
1618 substituteInPlace ./parser/Makefile --replace "/usr/include/linux/capability.h" "${linuxHeaders}/include/linux/capability.h"
1619 ## techdoc.pdf still doesn't build ...
1620 substituteInPlace ./parser/Makefile --replace "manpages htmlmanpages pdf" "manpages htmlmanpages"
1621 + substituteInPlace parser/rc.apparmor.functions \
1622 + --replace "/sbin/apparmor_parser" "$out/bin/apparmor_parser"
1623 + sed -i parser/rc.apparmor.functions -e '2i . ${./fix-rc.apparmor.functions.sh}'
1624 '';
1625 inherit patches;
1626 postPatch = "cd ./parser";
1627 @@ -249,8 +269,35 @@ let
1628 meta = apparmor-meta "kernel patches";
1629 };
1630
1631 + # Generate generic AppArmor rules in a file,
1632 + # from the closure of given rootPaths.
1633 + # To be included in an AppArmor profile like so:
1634 + # include "$(apparmorRulesFromClosure {} [pkgs.hello]}"
1635 + apparmorRulesFromClosure =
1636 + { # The store path of the derivation is given in $path
1637 + additionalRules ? []
1638 + # TODO: factorize here some other common paths
1639 + # that may emerge from use cases.
1640 + , baseRules ? [
1641 + "r $path"
1642 + "r $path/etc/**"
1643 + "r $path/share/**"
1644 + # Note that not all libraries are prefixed with "lib",
1645 + # eg. glibc-2.30/lib/ld-2.30.so
1646 + "mr $path/lib/**.so*"
1647 + # eg. glibc-2.30/lib/gconv/gconv-modules
1648 + "r $path/lib/**"
1649 + ]
1650 + , name ? ""
1651 + }: rootPaths: runCommand
1652 + ( "apparmor-closure-rules"
1653 + + lib.optionalString (name != "") "-${name}") {} ''
1654 + touch $out
1655 + while read -r path
1656 + do printf >>$out "%s,\n" ${lib.concatMapStringsSep " " (x: "\"${x}\"") (baseRules ++ additionalRules)}
1657 + done <${closureInfo {inherit rootPaths;}}/store-paths
1658 + '';
1659 in
1660 -
1661 {
1662 inherit
1663 libapparmor
1664 @@ -259,5 +306,6 @@ in
1665 apparmor-parser
1666 apparmor-pam
1667 apparmor-profiles
1668 - apparmor-kernel-patches;
1669 + apparmor-kernel-patches
1670 + apparmorRulesFromClosure;
1671 }
1672 diff --git a/pkgs/os-specific/linux/apparmor/fix-rc.apparmor.functions.sh b/pkgs/os-specific/linux/apparmor/fix-rc.apparmor.functions.sh
1673 new file mode 100644
1674 index 00000000000..ebc1baaa92d
1675 --- /dev/null
1676 +++ b/pkgs/os-specific/linux/apparmor/fix-rc.apparmor.functions.sh
1677 @@ -0,0 +1,32 @@
1678 +aa_action() {
1679 + STRING=$1
1680 + shift
1681 + $*
1682 + rc=$?
1683 + if [ $rc -eq 0 ] ; then
1684 + aa_log_success_msg $"$STRING "
1685 + else
1686 + aa_log_failure_msg $"$STRING "
1687 + fi
1688 + return $rc
1689 +}
1690 +
1691 +aa_log_success_msg() {
1692 + [ -n "$1" ] && echo -n $1
1693 + echo ": done."
1694 +}
1695 +
1696 +aa_log_warning_msg() {
1697 + [ -n "$1" ] && echo -n $1
1698 + echo ": Warning."
1699 +}
1700 +
1701 +aa_log_failure_msg() {
1702 + [ -n "$1" ] && echo -n $1
1703 + echo ": Failed."
1704 +}
1705 +
1706 +aa_log_skipped_msg() {
1707 + [ -n "$1" ] && echo -n $1
1708 + echo ": Skipped."
1709 +}
1710 diff --git a/pkgs/os-specific/linux/iputils/default.nix b/pkgs/os-specific/linux/iputils/default.nix
1711 index 56942d6d420..122a9ca1b7b 100644
1712 --- a/pkgs/os-specific/linux/iputils/default.nix
1713 +++ b/pkgs/os-specific/linux/iputils/default.nix
1714 @@ -1,6 +1,7 @@
1715 { lib, stdenv, fetchFromGitHub
1716 , meson, ninja, pkg-config, gettext, libxslt, docbook_xsl_ns
1717 , libcap, libidn2
1718 +, apparmorRulesFromClosure
1719 }:
1720
1721 let
1722 @@ -20,6 +21,8 @@ in stdenv.mkDerivation rec {
1723 sha256 = "08j2hfgnfh31vv9rn1ml7090j2lsvm9wdpdz13rz60rmyzrx9dq3";
1724 };
1725
1726 + outputs = ["out" "apparmor"];
1727 +
1728 mesonFlags = [
1729 "-DBUILD_RARPD=true"
1730 "-DBUILD_TRACEROUTE6=true"
1731 @@ -34,6 +37,25 @@ in stdenv.mkDerivation rec {
1732 nativeBuildInputs = [ meson ninja pkg-config gettext libxslt.bin docbook_xsl_ns ];
1733 buildInputs = [ libcap ]
1734 ++ lib.optional (!stdenv.hostPlatform.isMusl) libidn2;
1735 + postInstall = ''
1736 + install -D -m 644 /dev/stdin $apparmor/bin.ping <<EOF
1737 + include <tunables/global>
1738 + $out/bin/ping {
1739 + include <abstractions/base>
1740 + include <abstractions/consoles>
1741 + include <abstractions/nameservice>
1742 + include "${apparmorRulesFromClosure { name = "ping"; }
1743 + ([libcap] ++ lib.optional (!stdenv.hostPlatform.isMusl) libidn2)}"
1744 + include <local/bin.ping>
1745 + capability net_raw,
1746 + network inet raw,
1747 + network inet6 raw,
1748 + mr $out/bin/ping,
1749 + r $out/share/locale/**,
1750 + r @{PROC}/@{pid}/environ,
1751 + }
1752 + EOF
1753 + '';
1754
1755 meta = with lib; {
1756 description = "A set of small useful utilities for Linux networking";
1757 diff --git a/pkgs/tools/networking/inetutils/default.nix b/pkgs/tools/networking/inetutils/default.nix
1758 index 1290ec2bdb1..fe5a0d91585 100644
1759 --- a/pkgs/tools/networking/inetutils/default.nix
1760 +++ b/pkgs/tools/networking/inetutils/default.nix
1761 @@ -1,4 +1,6 @@
1762 -{ stdenv, lib, fetchurl, ncurses, perl, help2man }:
1763 +{ stdenv, lib, fetchurl, ncurses, perl, help2man
1764 +, apparmorRulesFromClosure
1765 +}:
1766
1767 stdenv.mkDerivation rec {
1768 name = "inetutils-1.9.4";
1769 @@ -8,6 +10,8 @@ stdenv.mkDerivation rec {
1770 sha256 = "05n65k4ixl85dc6rxc51b1b732gnmm8xnqi424dy9f1nz7ppb3xy";
1771 };
1772
1773 + outputs = ["out" "apparmor"];
1774 +
1775 patches = [
1776 ./whois-Update-Canadian-TLD-server.patch
1777 ./service-name.patch
1778 @@ -41,6 +45,22 @@ stdenv.mkDerivation rec {
1779
1780 installFlags = [ "SUIDMODE=" ];
1781
1782 + postInstall = ''
1783 + install -D -m 644 /dev/stdin $apparmor/bin.ping <<EOF
1784 + $out/bin/ping {
1785 + include <abstractions/base>
1786 + include <abstractions/consoles>
1787 + include <abstractions/nameservice>
1788 + include "${apparmorRulesFromClosure { name = "ping"; } [stdenv.cc.libc]}"
1789 + include <local/bin.ping>
1790 + capability net_raw,
1791 + network inet raw,
1792 + network inet6 raw,
1793 + mr $out/bin/ping,
1794 + }
1795 + EOF
1796 + '';
1797 +
1798 meta = with lib; {
1799 description = "Collection of common network programs";
1800
1801 diff --git a/pkgs/top-level/all-packages.nix b/pkgs/top-level/all-packages.nix
1802 index bc5c1b88046..b3fee4ce167 100644
1803 --- a/pkgs/top-level/all-packages.nix
1804 +++ b/pkgs/top-level/all-packages.nix
1805 @@ -18758,7 +18758,7 @@ in
1806
1807 inherit (callPackages ../os-specific/linux/apparmor { python = python3; })
1808 libapparmor apparmor-utils apparmor-bin-utils apparmor-parser apparmor-pam
1809 - apparmor-profiles apparmor-kernel-patches;
1810 + apparmor-profiles apparmor-kernel-patches apparmorRulesFromClosure;
1811
1812 aseq2json = callPackage ../os-specific/linux/aseq2json {};
1813