guix-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [PATCH] Add SELinux policy for guix-daemon.


From: Catonano
Subject: Re: [PATCH] Add SELinux policy for guix-daemon.
Date: Tue, 13 Feb 2018 16:30:44 +0100



2018-01-25 17:17 GMT+01:00 Ricardo Wurmus <address@hidden>:
Hi Guix,

attached is a patch that adds an SELinux policy for the guix-daemon.
The policy defines the guix_daemon_t domain and specifies what labels
may be accessed and how by processes running in that domain.

These file labels are defined:

* guix_daemon_conf_t
  for Guix configuration files (in localstatedir and sysconfdir)
* guix_daemon_exec_t
  for executables spawned by the daemon (which are allowed to run in the
  guix_daemon_t domain)
* guix_daemon_socket_t
  for the daemon socket file
* guix_profiles_t
  for the contents of the profiles directory

The “filecon” statements near the bottom of the file specify which
labels are to be used for what file names.

I tested this with “guix build --no-grafts --check hello”, “guix build
samtools”, “guix gc -C 1k”, and “guix package -p ~/foo -i hello”;
no operations were blocked by SELinux.

If you want to test this on Fedora, set SELinux to permissive, and make
sure to configure Guix properly (i.e. set localstatedir, prefix, and
sysconfdir).  Then install the policy with “sudo semodule -i
etc/guix-daemon.cil”.  Then relabel the filesystem (at least /gnu,
$localstatedir, $sysconfdir, and $prefix) with something like this:

    sudo restorecon -R /gnu $localstatedir $sysconfdir $prefix

This will take a very long time (a couple of hours).

Restart the daemon.  Check that it now runs in the guix_daemon_t
context:

    ps -Zax | grep /bin/guix-daemon

This should return something like this

   system_u:system_r:guix_daemon.guix_daemon_t:s0 14886 ? Ss   0:00 /root/.guix-profile/bin/guix-daemon --build-users-group=guix-builder

Check the audit log for violations:

   sudo tail -f /var/log/audit/audit.log | grep x-daemon

And then use Guix:

   guix build --no-grafts --check hello

The audit log shouldn’t show you any complaints.  At this point you
could probably switch to enforcing mode, but I haven’t tested this
myself for no particular reason.

Open issues:

* guix_daemon_socket_t isn’t actually used.  All of the socket
  operations that I observed involve contexts that don’t have anything
  to do with guix_daemon_socket_t.  It doesn’t hurt to have this unused
  label, but I would have preferred to define socket rules for only this
  label.  Oh well.

* “guix gc” cannot access arbitrary links to profiles.  By design, the
  file label of the destination of a symlink is independent of the file
  label of the link itself.  Although all profiles under $localstatedir
  are labelled, the links to these profiles inherit the label of the
  directory they are in.  For links in the user’s home directory this
  will be “user_home_t” (for which I’ve added a rule).  But for links
  from root’s home directory, or /tmp, or the HTTP server’s working
  directory … this won’t work.  “guix gc” would be prevented from
  reading and following these links.

* I don’t know if the daemon’s TCP listen feature still works.  I didn’t
  test it and assume that it would require extra rules, because SELinux
  treats network sockets differently from files.

* Is this all correct?  I don’t know!  I only just learned about the
  SELinux Common Intermediate Language (CIL), and the documentation is
  very sparse, so I have no idea if I did something stupid.  It seems
  fine to me, but I must admit that I find it a bit uncomfortable to see
  so many access types in the rules.

* I allowed type transitions from init_t to guix_daemon_t via
  guix_daemon_exec_t, but also from guix_store_content_t to
  guix_daemon_t via guix_daemon_exec_t.  Type transitions are necessary
  to get from an allowed entry point to a domain.  On Fedora “init_t” is
  the domain in which processes are that are spawned by the init
  system.  With the first type transition I permit these processes to
  transition to the guix_daemon_t domain when the executables are
  labeled as guix_daemon_exec_t (such as the daemon executable itself,
  and all the helpers it spawns).

  This much is obvious.  But the second type transition is less obvious.
  It is needed to make sure that we can enter the guix_daemon_t domain
  even when running the daemon from an executable in the store (which
  will be running in the “guix_store_content_t” domain).  Thinking of
  this, I wonder if maybe that’s actually a mistake and shouldn’t be
  permitted.

* A possible problem is that I assign all files with a name matching
  “/gnu/store/.+-(guix-.+|profile)/bin/guix-daemon” the label
  “guix_daemon_exec_t”; this means that *any* file with that name in any
  profile would be permitted to run in the guix_daemon_t domain.  This
  is not ideal.  An attacker could build a package that provides this
  executable and convince a user to install and run it, which lifts it
  into the guix_daemon_t domain.  At that point SELinux could not
  prevent it from accessing files that are allowed for processes in that
  domain (such as the actual daemon).

  This makes me wonder if we could do better by generating a much more
  restrictive policy at installation time, so that only the *exact* file
  name of the currently installed guix-daemon executable would be
  labelled with guix_daemon_exec_t, instead of using a regular
  _expression_ like that.  This means that root would have to
  install/upgrade the policy at installation time whenever the Guix
  package that provides the effectively running guix-daemon executable
  is upgraded.  Food for thought.

Without further ado, here’s the patch:



--
Ricardo



Ok, I followed all these steps

While processing

guix build --no-grafts --check hello

I got some violations, an example follows

SELinux impedisce a .guix-real un accesso write su sock_file /var/guix/daemon-socket/socket.


***** Plugin catchall(100. confidenza) suggerisce**************************

If you believe that .guix-real should be allowed write access on the socket sock_file by default.
Quindi si dovrebbe riportare il problema come bug.
E' possibile generare un modulo di politica locale per consentire questo accesso.
Fai
allow this access for now by executing:
# ausearch -c '.guix-real' --raw | audit2allow -M my-guixreal
# semodule -X 300 -i my-guixreal.pp

Informazioni addizionali:
Contesto della sorgente       unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1
                              023
Contesto target               system_u:object_r:guix_daemon.guix_daemon_conf_t:s
                              0
Oggetti target                /var/guix/daemon-socket/socket [ sock_file ]
Sorgente                      .guix-real
Percorso della sorgente       .guix-real
Porta                         <Sconosciuto>
Host                          localhost.localdomain
Sorgente Pacchetti RPM       
Pacchetti RPM target         
RPM della policy              selinux-policy-3.13.1-283.24.fc27.noarch
Selinux abilitato             True
Tipo di politica              targeted
Modalità Enforcing            Permissive
Host Name                     localhost.localdomain
Piattaforma                   Linux localhost.localdomain
                              4.14.16-300.fc27.x86_64 #1 SMP Wed Jan 31 19:24:27
                              UTC 2018 x86_64 x86_64
Conteggio avvisi              1
Primo visto                   2018-02-13 16:26:40 CET
Ultimo visto                  2018-02-13 16:26:40 CET
ID locale                     795369db-8842-4253-ac70-bfab33d85c47

Messaggi Raw Audit
type=AVC msg=audit(1518535600.232:493): avc:  denied  { write } for  pid=2978 comm=".guix-real" name="socket" dev="dm-0" ino=2754019 scontext=unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023 tcontext=system_u:object_r:guix_daemon.guix_daemon_conf_t:s0 tclass=sock_file permissive=1


Hash: .guix-real,unconfined_t,guix_daemon.guix_daemon_conf_t,sock_file,write



There are some more, it' s just that fetching them in the Gnome GUI is not immediate

But I can publish my /var/log/audit/audit.log file somewhere

Oh wait, i could catch another one right now, here it is




SELinux impedisce a .guix-real un accesso write su sock_file /var/guix/daemon-socket/socket.


***** Plugin catchall(100. confidenza) suggerisce**************************

If you believe that .guix-real should be allowed write access on the socket sock_file by default.
Quindi si dovrebbe riportare il problema come bug.
E' possibile generare un modulo di politica locale per consentire questo accesso.
Fai
allow this access for now by executing:
# ausearch -c '.guix-real' --raw | audit2allow -M my-guixreal
# semodule -X 300 -i my-guixreal.pp

Informazioni addizionali:
Contesto della sorgente       unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1
                              023
Contesto target               system_u:object_r:guix_daemon.guix_daemon_conf_t:s
                              0
Oggetti target                /var/guix/daemon-socket/socket [ sock_file ]
Sorgente                      .guix-real
Percorso della sorgente       .guix-real
Porta                         <Sconosciuto>
Host                          localhost.localdomain
Sorgente Pacchetti RPM       
Pacchetti RPM target         
RPM della policy              selinux-policy-3.13.1-283.24.fc27.noarch
Selinux abilitato             True
Tipo di politica              targeted
Modalità Enforcing            Permissive
Host Name                     localhost.localdomain
Piattaforma                   Linux localhost.localdomain
                              4.14.16-300.fc27.x86_64 #1 SMP Wed Jan 31 19:24:27
                              UTC 2018 x86_64 x86_64
Conteggio avvisi              1
Primo visto                   2018-02-13 16:26:40 CET
Ultimo visto                  2018-02-13 16:26:40 CET
ID locale                     795369db-8842-4253-ac70-bfab33d85c47

Messaggi Raw Audit
type=AVC msg=audit(1518535600.232:493): avc:  denied  { write } for  pid=2978 comm=".guix-real" name="socket" dev="dm-0" ino=2754019 scontext=unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023 tcontext=system_u:object_r:guix_daemon.guix_daemon_conf_t:s0 tclass=sock_file permissive=1


Hash: .guix-real,unconfined_t,guix_daemon.guix_daemon_conf_t,sock_file,write


I' ll keep following this

Thanks
Ciao

reply via email to

[Prev in Thread] Current Thread [Next in Thread]