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: Ricardo Wurmus
Subject: Re: [PATCH] Add SELinux policy for guix-daemon.
Date: Fri, 26 Jan 2018 15:47:07 +0100
User-agent: mu4e 1.0-alpha3; emacs 25.3.1

Hi,

Catonano <address@hidden> writes:

> I' m not sure I understand: is this meant to allow Guix to run in foreign
> distros like Fedora ?
>
> Or is this meant to have SELinux running inside the GuixSD environment ?

On GuixSD we don’t have a base policy yet, so it would not work on
GuixSD.  The base policy specifies a bunch of things that this
guix-daemon policy relies on, such as the type “init_t” and the
assumption that processes spawned by the init system are executed in
this domain.

> I might be interested in runnig Guix on my Fedora installation.

It should be useful for that purpose.  I have a Fedora workstation at
work and I developed and tested the policy on it.  I haven’t yet had the
time to switch to “enforcing” mode, which would block any operation that
is not explicitly permitted by the policy, so I suggest starting with
“permissive” mode and using it for a while.  After some time you can
then analyse the audit logs to see if the daemon misbehaved according to
the policy.

> Also, Ricardo, I remember you posted a link to an introduction to SELinux
> for human beings, some months ago.

Yeah, it was the SELinux Coloring Book by Red Hat:

   https://people.redhat.com/duffy/selinux/selinux-coloring-book_A4-Stapled.pdf

But I *really* don’t recommend it for learning SELinux.  Half of the
book doesn’t even apply to common SELinux installations, and the bit
that *does* apply really isn’t thorough enough.  All I took away from it
was that a dog shouldn’t eat cat food (and that’s enforced by an angry
penguin).

The lack of *good* documentation for SELinux is very frustrating.

Here’s a high level overview: the goal is to ensure that processes only
have a set of permissions to do exactly what they were designed to do,
and nothing more.  A common example is an HTTP server.  It should be
allowed to publish *some* files and not others.  A misbehaving HTTP
server process should be prevented from publishing files that I didn’t
label as publishable (like my private home directory or /etc/passwd).

Traditionally, the only way to achieve this was to let the server
process run under a separate user identity and change the ownership of
files that are allowed to be published.  To that end the server process
would be started as root and then drop privileges by becoming that
separate user.  This assumes that software is bug free, though.  What if
the server process has a bug that allows an attacker to run code as
root, though?  In that case it could publish *any* file – or it could
delete or overwrite files.

So the idea behind SELinux is that the kernel should watch all access
attempts to all resources and only allow specific operations.  This way
a rogue server process is automatically prevented from, say, publishing
the system passwords.

A system admin informs the kernel about what operations are permitted
through rules in a so-called policy.  These rules look something like
this (in the SELinux Common Intermediate Language):

    (allow guix_daemon_t
           user_home_t
           (dir (search)))

This says: a process of type “guix_daemon_t” is permitted to perform a
“search” action on a “dir(ectory)”, if that directory has the label/type
“user_home_t”.  These types are defined by policy developers; they are
completely arbitrary.

There are two things in this example that have types: processes and
files.  Files get their types by labeling.  Looking at the policy for
guix-daemon you see things like this:

    (filecon "/gnu/store(/.+)?"
             any (unconfined_u object_r guix_store_content_t (low low)))

This is an instruction to label anything (“any”) matching the given
regular expression with the type “guix_store_content_t” (ignore the
“unconfined_u” and “object_r”, and also the “low”).  By running
“restorecon” recursively on the file system, all files will get labels
according to instructions like that.

How about processes?  How do they get their types?  (In other words: how
does a process enter a certain domain?)  They start out in a certain
domain and then may transition to other domains.  That’s specified by
transition rules like this one:

    (typetransition init_t guix_daemon_exec_t
                    process guix_daemon_t)

This says that a process in the domain “init_t” may transition to domain
“guix_daemon_t” if the file that spawns the process has the label
“guix_daemon_exec_t”.  Again, “init_t” is an arbitrary name for a type,
which in the case of Fedora is specified in some other policy that I
simply take for granted.  On Fedora, all processes that are spawned by
the init system are in the domain “init_t”, so when the daemon is
started via SystemD it’s in “init_t” and then transitions to
“guix_daemon_t” because the executable file “guix-daemon” is labeled
“guix_daemon_exec_t”.

Getting back to the rule above: it says that a process in the
“guix_daemon_t” domain may perform a “search” on a “dir” if that
directory has the label “user_home_t”.  If that’s the only rule, then
that’s the only permitted action for such a process.

At some point I’d like to build a base policy for GuixSD, which defines
a couple of basic types, label rules, and type transitions.  The hardest
part in designing a policy is finding good names for types and figuring
out how types should be allowed to transition.  In the case of Guix this
is all made more difficult because applications don’t share the same
root-controlled global namespace (such as /usr, or /bin).  But the core
idea is the same: make explicit what *type* of files there are and what
type of processes should be granted access to files of these types.

--
Ricardo



reply via email to

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