~ruther/guix-local

587fd2dad49d8af3f31d06e29ff43c986d6f35c4 — Noé Lopez 2 months ago 9a78e76
etc: Add AppArmor profile for the daemon.

* .gitignore: Add etc/apparmor.d/tunables/guix.
* Makefile.am (nodist_apparmor_profile_DATA)
(nodist_apparmor_profile_tunables_DATA): Define it.
* configure.ac: Generate etc/apparmor.d/tunables/guix. Add
--with-apparmor-profile-dir option.
* etc/apparmor.d/guix-daemon: New file.
* etc/apparmor.d/tunables/guix.in: New file.
* doc/guix.texi: Document AppArmor profiles.
* gnu/packages/package-management.scm (guix): Add future changes commented.

Change-Id: Iac7df9d642383cc46a2d450c3badef31199ab041
Signed-off-by: Rutherther <rutherther@ditigal.xyz>
M .gitignore => .gitignore +1 -0
@@ 68,6 68,7 @@
/doc/stamp-vti
/doc/version.texi
/doc/version-*.texi
/etc/apparmor.d/tunables/guix
/etc/committer.scm
/etc/gnu-store.mount
/etc/guix-daemon.cil

M Makefile.am => Makefile.am +7 -0
@@ 746,6 746,13 @@ dist_fishcompletion_DATA = etc/completion/fish/guix.fish
# SELinux policy
nodist_selinux_policy_DATA = etc/guix-daemon.cil

# AppArmor profiles.
nodist_apparmor_profile_DATA =	\
  etc/apparmor.d/guix-daemon

nodist_apparmor_profile_tunables_DATA = \
  etc/apparmor.d/tunables/guix

EXTRA_DIST +=						\
  .dir-locals.el					\
  .guix-authorizations					\

M configure.ac => configure.ac +10 -0
@@ 81,6 81,15 @@ AC_ARG_WITH([selinux-policy-dir],
  [selinux_policydir='${datadir}/selinux/'])
AC_SUBST([selinux_policydir])

AC_ARG_WITH([apparmor-profile-dir],
  AS_HELP_STRING([--with-apparmor-profile-dir=DIR],
    [name of the AppArmor profile directory]),
  [apparmor_profiledir="$withval"],
  [apparmor_profiledir='${sysconfdir}/apparmor.d'])
AC_SUBST([apparmor_profiledir])
apparmor_profile_tunablesdir='${apparmor_profiledir}/tunables'
AC_SUBST([apparmor_profile_tunablesdir])

dnl Better be verbose.
AC_MSG_CHECKING([for the store directory])
AC_MSG_RESULT([$storedir])


@@ 308,6 317,7 @@ AC_CONFIG_FILES([Makefile
                 po/guix/Makefile.in
                 po/packages/Makefile.in
                 etc/guix-daemon.cil
                 etc/apparmor.d/tunables/guix
                 guix/config.scm])

AC_CONFIG_FILES([etc/committer.scm], [chmod +x etc/committer.scm])

M doc/guix.texi => doc/guix.texi +41 -0
@@ 146,6 146,7 @@ Copyright @copyright{} 2025 Artur Wroblewski@*
Copyright @copyright{} 2025 Edouard Klein@*
Copyright @copyright{} 2025 Rodion Goritskov@*
Copyright @copyright{} 2025 dan@*
Copyright @copyright{} 2025 Noé Lopez@*

Permission is granted to copy, distribute and/or modify this document
under the terms of the GNU Free Documentation License, Version 1.3 or


@@ 919,6 920,7 @@ pre-built binaries.
* Build Environment Setup::     Preparing the isolated build environment.
* Daemon Offload Setup::        Offloading builds to remote machines.
* SELinux Support::             Using an SELinux policy for the daemon.
* AppArmor Support::            Using an AppArmor profile for the daemon.
@end menu

@node Build Environment Setup


@@ 1097,6 1099,8 @@ systemctl daemon-reload
systemctl start guix-daemon
@end example

If your system has AppArmor enabled, @pxref{AppArmor Support}.

@quotation Warning
The commands above assume that @command{guix pull} was run for the root
user.  You can check whether this is the case by running this command:


@@ 1526,6 1530,43 @@ installation time whenever the Guix package that provides the
effectively running @code{guix-daemon} executable is upgraded.
@end enumerate

@node AppArmor Support
@subsection AppArmor Support

@cindex AppArmor

Guix includes an AppArmor profile for the build daemon in
@file{etc/apparmor.d/guix-daemon} that can be installed on systems with
strict AppArmor policies to allow it to run unprivileged
(@pxref{Build Environment Setup}).  Indeed, the unprivileged daemon makes
use of Linux user namespaces but these are disallowed
without an AppArmor policy on some systems like Ubuntu.

To know if this applies to you, check if the
@code{kernel.apparmor_restrict_unprivileged_userns} kernel parameter is
enabled.

@subsubsection Installing the AppArmor profile
@cindex AppArmor, profile installation

@quotation Note
The @code{guix-install.sh} binary installation script offers to perform
the steps below for you (@pxref{Binary Installation}).
@end quotation

Run these commands as root to install the profile:

@example
export apparmor_sources=/var/guix/profiles/per-user/root/current-guix/etc/apparmor.d
cp -f -t /etc/apparmor.d/tunables "$apparmor_sources/tunables/guix"
cp -f -t /etc/apparmor.d "$apparmor_sources/guix-daemon"
cp -f -t /etc/apparmor.d "$apparmor_sources/guix"
apparmor_parser -r /etc/apparmor.d/guix-daemon
apparmor_parser -r /etc/apparmor.d/guix
@end example

After this, the build daemon will be able to function correctly.

@node Invoking guix-daemon
@section Invoking @command{guix-daemon}
@cindex @command{guix-daemon}

A etc/apparmor.d/guix-daemon => etc/apparmor.d/guix-daemon +88 -0
@@ 0,0 1,88 @@
abi <abi/4.0>,

include <tunables/global>
include <tunables/guix>

profile guix-daemon @{guix_storedir}/*-{guix-daemon,guix}-*/bin/guix-daemon flags=(enforce,attach_disconnected.path=/disconnected) {
  include <abstractions/base>

  userns,
  signal,
  capability sys_admin,
  capability net_admin,
  capability sys_chroot,
  capability setgid,
  capability chown,
  network dgram,
  umount,
  mount,
  pivot_root,
  # Paths inside build chroot
  /real-root/ w,
  / w,

  @{guix_localstatedir}/guix/** rwk,
  /var/log/guix/** w,
  owner @{PROC}/@{pid}/{fd/,environ} r,
  owner @{PROC}/@{pid}/oom_score_adj w,
  owner @{PROC}/@{pid}/uid_map rw,
  owner @{PROC}/@{pid}/gid_map rw,
  owner @{PROC}/@{pid}/setgroups w,
  @{guix_storedir}/ r,
  @{guix_storedir}/** rwlmk,
  @{guix_storedir}/*/bin/guile cx -> guix-builder,
  @{guix_storedir}/*-guix-command cx -> guix-helper,
  @{guix_storedir}/*-guix-*/bin/guix cx -> guix-helper,
  @{etc_rw}/nsswitch.conf r,
  @{etc_rw}/passwd r,
  @{etc_rw}/group r,
  owner /tmp/** rwl,
  owner /var/tmp/** rwl,

  /usr/bin/newgidmap Ux,

  # Site-specific additions and overrides. See local/README for details.
  include if exists <local/guix-daemon>

  profile guix-builder flags=(enforce,attach_disconnected.path=/disconnected) {
    include <abstractions/base>

    signal (receive),

    @{guix_storedir}/** rwlmkux,

    owner /tmp/** rw,

    @{PROC}/@{pid}/fd/ r,

    /disconnected/** rw,
  }

  # This is for any time guix is called by the daemon as a helper:
  # - guix download
  # - guix discover
  # - guix gc --list-busy
  # - probably more?
  profile guix-helper flags=(enforce,attach_disconnected.path=/disconnected) {
    include <abstractions/base>
    include <abstractions/nameservice>

    signal (receive),
    ptrace (read) peer=guix-daemon,

    /disconnected/run/dbus/system_bus_socket rw,
    dbus (send, receive),
    @{guix_localstatedir}/guix/discover/ rw,
    @{guix_localstatedir}/guix/discover/* rw,

    @{guix_localstatedir}/guix/substitute/ rw,
    @{guix_localstatedir}/guix/substitute/** rwk,

    @{guix_sysconfdir}/guix/** r,

    @{guix_storedir}/** rwlmix,

    @{PROC}/ r,
    owner @{PROC}/@{pid}/{fd/,environ} r,
  }
}

A etc/apparmor.d/tunables/guix.in => etc/apparmor.d/tunables/guix.in +5 -0
@@ 0,0 1,5 @@
@{guix_storedir} = @storedir@
@{guix_sysconfdir} = @guix_sysconfdir@
@{guix_localstatedir} = @guix_localstatedir@

include if exists <tunables/guix.d>
\ No newline at end of file

M gnu/packages/package-management.scm => gnu/packages/package-management.scm +4 -0
@@ 234,6 234,10 @@
                            (string-append "--with-bash-completion-dir="
                                           (assoc-ref %outputs "out")
                                           "/etc/bash_completion.d")
                            ;; TODO: Uncomment after guix is updated.
                            ;; (string-append "--with-apparmor-profile-dir="
                            ;;                (assoc-ref %outputs "out")
                            ;;                "/etc/apparmor.d")

                            ;; Set 'DOT_USER_PROGRAM' to the empty string so
                            ;; we don't keep a reference to Graphviz, whose