Re: [PATCH v2 0/7] Smack namespace

Casey Schaufler
2015-05-27T01:04:43Z

On 5/25/2015 5:32 AM, Lukasz Pawelczyk wrote:
> Hello,
>
> Some time ago I sent a Smack namespace documentation and a preliminary
> LSM namespace for RFC. I've been suggested that there shouldn't be a
> separate LSM namespace and that it should live within user namespace.
> And this version does. This is a complete set of patches required for
> Smack namespace.
>
> This was designed with a collaboration of Smack maintainer Casey
> Schaufler.
>
> Smack namespace have been implemented using user namespace hooks added
> by one of the patches. To put some context to it I paste here a
> documentation on what Smack namespace wants to achieve.
>
> LSM hooks themselves are documented in the security.h file inside the
> patch.
>
> The patches are based on:
> https://github.com/cschaufler/smack-next/tree/smack-for-4.2-stacked
>
> The tree with them is avaiable here:
> https://github.com/Havner/smack-namespace/tree/smack-namespace-for-4.2-stacked-v2
>
> Changes from v1:
> - "kernel/exit.c: make sure current's nsproxy != NULL while checking
> caps" patch has been dropped
> - fixed the title of the user_ns operations patch
>
>
> ===================================================================
>
> --- What is a Smack namespace ---
>
> Smack namespace was developed to make it possible for Smack to work
> nicely with Linux containers where there is a full operating system
> with its own init inside the namespace. Such a system working with
> Smack expects to have at least partially working SMACK_MAC_ADMIN to be
> able to change labels of processes and files. This is required to be
> able to securely start applications under the control of Smack and
> manage their access rights.
>
> It was implemented using new LSM hooks added to the user namespace
> that were developed together with Smack namespace.
>
>
> --- Design ideas ---
>
> "Smack namespace" is rather "Smack labels namespace" as not the whole
> MAC is namespaced, only the labels. There is a great analogy between
> Smack labels namespace and the user namespace part that remaps UIDs.
>
> The idea is to create a map of labels for a namespace so the namespace
> is only allowed to use those labels. Smack rules are always the same
> as in the init namespace (limited only by what labels are mapped) and
> cannot be manipulated from the child namespace. The map is actually
> only for labels' names. The underlying structures for labels remain
> the same. The filesystem also stores the "unmapped" labels from the
> init namespace.
>
> Let's say we have those labels in the init namespace:
> label1
> label2
> label3
>
> and those rules:
> label1 label2 rwx
> label1 label3 rwx
> label2 label3 rwx
>
> We create a map for a namespace:
> label1 -> mapped1
> label2 -> mapped2
>
> This means that 'label3' is completely invisible in the namespace. As if
> it didn't exist. All the rules that include it are ignored.
>
> Effectively in the namespace we have only one rule:
> mapped1 mapped2 rwx
>
> Which in reality is:
> label1 label2 rwx
>
> All requests to access an object with a 'label3' will be denied. If it
> ever comes to a situation where 'label3' would have to be printed
> (e.g. reading an exec or mmap label from a file to which we have
> access) then huh sign '?' will be printed instead.
>
> All the operations in the namespace on the remaining labels will have
> to be performed using their mapped names. Things like changing own
> process's label, changing filesystem label. Labels will also be
> printed with their mapped names.
>
> You cannot import new labels in a namespace. Every operation that
> would do so in an init namespace will return an error in the child
> namespace. You cannot assign an unmapped or not existing label to an
> object. You can only operate on labels that have been explicitly
> mapped.
>
>
> --- Capabilities ---
>
> Enabling Smack related capabilities (CAP_MAC_ADMIN and
> CAP_MAC_OVERRIDE) is main goal of Smack namespace, so it can work
> properly in the container. And those capabilities do work to some
> extent. In several places where capabilities are checked compatibility
> with Smack namespace has been introduced. Capabilities are of course
> limited to operate only on mapped labels.
>
> CAP_MAC_OVERRIDE works fully, will allow you to ignore Smack access
> rules, but only between objects that have labels mapped. So in the
> example above having this CAP will allow e.g. label2 to write to
> label1, but will not allow any access to label3.
>
> With CAP_MAC_ADMIN the following operations has been allowed inside
> the namespace:
> - setting and removing xattr on files, including the security.* ones
> - setting process's own label (/proc/self/attr/current)
> - mounting in a privileged Smack mode, which means one can specify
> additional mount options like: smackfsdef, smackfsfloor etc.
>
> Again this is also allowed only on the mapped labels. Labels on the
> filesystem will be stored in unmapped form so they are preserved
> through reboots.
>
> Such a namespace construct allows e.g. systemd (with Smack support)
> working in a container to assign labels properly to daemons and other
> processes.
>
>
> --- Usage ---
>
> Smack namespace is written using LSM hooks inside user namespace. That
> means it's connected to it.
>
> To create a new Smack namespace you need to unshare() user namespace
> as usual. If that is all you do though, than there is no difference to
> what is now. To activate the Smack namespace you need to fill the
> labels' map. It is in a file /proc/$PID/smack_map.
>
> By default the map is empty and Smack namespaces are inactive (labels
> are taken directly from a parent namespace). It also means that the
> Smack capabilities will be inactive. After you fill the map it starts
> to take effect in the namespace and Smack capabilities (only on mapped
> labels) start to work.
>
> Due to the way Smack works only CAP_MAC_ADMIN from the parent
> namespace (init_user_ns for now, see the "Current limitations" below)
> is allowed to fill the map. That means that an unprivileged user is
> still allowed to create the user namespace but it will not be able to
> fill the labels' map (activate Smack namespace). An administrator
> intervention is required.
>
> The attr_map write format is:
> unmapped_label mapped_label
>
> When reading the file it shows an active map for a namespace the
> process in question is in in the format:
> unmapped_label -> mapped_label
>
> If the smack_map file is empty it means the namespace is not mapped
> and Smack namespace is inactive (no mappings, MAC related capabilities
> behave as they did before, meaning they are active only in
> init_user_ns). For init_user_ns the map will always be empty.
>
> Writing to the map file is not disabled after the first write as it is
> in uid_map. For Smack we have no means to map ranges of labels, hence
> it can really be advantageous to be able to expand the map later
> on. But you can only add to the map. You cannot remove already mapped
> labels. You cannot change the already existing mappings. Also mappings
> has to be 1-1. All requests to create a map where either the unmapped
> or the mapped label already exists in the map will be denied.
>
> setns() with Smack namespace active has an additional check that the
> label of a process that is calling setns() has to be already mapped in
> the target Smack namespace for the call to succeed.
>
>
> --- Special labels ---
>
> Smack is using some special labels that have built-in rules. Things
> like floor '_', dash '^', star '*', etc. Those labels are not
> automatically mapped to the namespace. Moreover, you can choose to map
> a different label from the init namespace to behave e.g. like floor
> inside the namespace.
>
> Let's say we have no rules and those labels in the init namespace:
> _
> floor_to_be
> label
>
> Both 'label' and 'floor_to_be' can read objects with '_'. But they
> have no access rights to each other.
>
> Now let's create a map like this:
> _ ordinary_label
> floor_to_be _
> label mapped
>
> Right now label 'mapped' can read label '_' which means that
> effectively inside this namespace label 'label' has gained read access
> to the 'floor_to_be'. The label 'ordinary_label' is exactly it, an
> ordinary label that the built-in rules no longer apply to inside the
> namespace.
>
> To sum up, special labels in the namespace behave the same as in the
> init namespace. Not the original special labels though, but the ones
> we map to specials. This is the only case where a namespace can have
> access rights the init namespace does not have (like the 'label' to
> 'floor_to_be' in the example above).
>
> Of course mappings like these are perfectly legal:
> _ _
> * *
> ^ ^
>
>
> --- Current limitations ---
>
> The Smack namespace is not hierarchical yet. It is currently not
> possible to fill a smack_map of a nested user namespace (you can still
> create nested user namespace, it will just inherit its parent's map
> and won't have active Smack capabilities). When hierarchy will be
> implemented the process creating another namespace will be allowed to
> map only labels that it has permission to itself (those that it has in
> its own map).
>
> Special files inside the virtual smackfs needs to be reviewed whether
> it's beneficial to have some of their functionality namespaced as well
> (e.g. onlycap, syslog. ambient, etc). This would increase
> CAP_MAC_ADMIN privileges inside the namespace.
>
>
> Lukasz Pawelczyk (7):
> user_ns: 3 new hooks for user namespace operations
> smack: extend capability functions and fix 2 checks
> smack: abstraction layer for 2 common Smack operations
> smack: misc cleanups in preparation for a namespace patch
> smack: namespace groundwork
> smack: namespace implementation
> smack: documentation for the Smack namespace
>
> Documentation/security/00-INDEX | 2 +
> Documentation/security/Smack-namespace.txt | 231 +++++++++++++
> MAINTAINERS | 1 +
> fs/proc/base.c | 57 +++
> include/linux/lsm_hooks.h | 28 ++
> include/linux/security.h | 23 ++
> include/linux/user_namespace.h | 9 +
> kernel/user.c | 3 +
> kernel/user_namespace.c | 18 +
> security/security.c | 28 ++
> security/smack/Kconfig | 12 +
> security/smack/Makefile | 1 +
> security/smack/smack.h | 187 +++++++++-
> security/smack/smack_access.c | 191 ++++++++--
> security/smack/smack_lsm.c | 536 ++++++++++++++++++++---------
> security/smack/smack_ns.c | 471 +++++++++++++++++++++++++
> security/smack/smackfs.c | 154 +++++----
> 17 files changed, 1702 insertions(+), 250 deletions(-)
> create mode 100644 Documentation/security/Smack-namespace.txt
> create mode 100644 security/smack/smack_ns.c
>

I have reviewed these patches (again!) and don't have
any issues. I see that Mr. Smalley has some insightful
suggestions, and once those are addressed I think that
we should be lined up to sell it to the infrastructure.