Search This Blog

Friday, 2 September 2016

A look at an SELinux error message



As a fan of the SELinux security framework that runs as part of Linux, I thought it would be a good idea to improve my skillset in this area, and go beyond the basics.

Part of that is research, subscribing to SELinux mailing lists, playing with test setups and, of course, reading what others are saying via Google searches.

One, whilst going off at a tangent to my goal, sparked my interest as all the posts I saw didn't have the answer. It was this type of error:

libsemanage.validate_handler: MLS range s0-s1:c1,c3 for Unix user XXX exceeds allowed range s0:c1,c3-s1:c1,c3 for SELinux user XXX
libsemanage.validate_handler: seuser mapping [XXX -> (XXX, s0-s1:c1,c3)] is invalid
libsemanage.dbase_llist_iterate: could not iterate over records

For example here, just search for libsemanage.validate_handler.

The answer should be straightforward, and relies on the fact that SELinux enforces mandatory access controls; aka stop you doing stupid or bad things (or at least what policy states are stupid/bad things), plus the tools stop stupid/bad configurations (again, at least what the developers state are such).

We can look at three types of user concept here. First, we have the traditional UNIX user as defined in /etc/passwd or your favourite password backend. Secondly, we have the concept of an SELinux user, which is more akin to a class or UNIX group. Finally, we have mappings which map the UNIX user to the SELinux user, which themselves (can) specify ranges.

SELinux users are managed by semanage user, whilst the mappings are managed by semanage login.

If we map a UNIX user to a SELinux user, we are stating that the UNIX user has a particular range of clearances to access and do stuff on the machine. However, when we set up the mapping we can further constrain the user, but cannot (shouldn't be able to) grant more than the base SELinux user they are mapped to.

So, here's an example on one of my test boxes.

The test box is running the mls policy and is using poly-instantiated directories of /tmp /var/tmp and $HOME based on the context (i.e. we can only see a home area or temp area commensurate to our current level.

First, lets create an SELinux user of devuser_u which has the standard user role of user_r:

[root@centos-7-2-t1 ~]# semanage user -a -R user_r -r s0-s1:c1,c3 devuser_u
[root@centos-7-2-t1 ~]# semanage user -l

                Labelling  MLS/       MLS/                         
SELinux User    Prefix     MCS Level  MCS Range            SELinux Roles

devuser_u       user       s0         s0-s1:c1,c3          user_r

Now  let's create a user that is of that type:

[root@centos-7-2-t1 ~]# useradd -m -Z devuser_u dev1
[root@centos-7-2-t1 ~]# semanage login -l

Login Name           SELinux User         MLS/MCS Range        Service

__default__          user_u               s0                   *
dev1                 devuser_u            s0-s1:c1,c3          *

Now lets say that we wish for the user to be able to access a new category (compartment) of c8. We may state that we do this with the mapping, but as this user is an SELinux user of devuser_u this isn't going to work:

[root@centos-7-2-t1 ~]# semanage login -m -r s0-s1:c1,c3,c8 dev1
libsemanage.validate_handler: MLS range s0-s1:c1,c3,c8 for Unix user dev1 exceeds allowed range s0-s1:c1,c3 for SELinux user devuser_u
libsemanage.validate_handler: seuser mapping [dev1 -> (devuser_u, s0-s1:c1,c3,c8)] is invalid
libsemanage.dbase_llist_iterate: could not iterate over records
ValueError: Could not commit semanage transaction

Instead we either need to create a new SELinux user (and map the unix user to it) or modify the existing one. So, lets modify the existing one so that it includes this new category:

[root@centos-7-2-t1 ~]# semanage user -m -r s0-s1:c1,c3,c8 devuser_u
[root@centos-7-2-t1 ~]# semanage user -l

                Labelling  MLS/       MLS/                          
SELinux User    Prefix     MCS Level  MCS Range            SELinux Roles

devuser_u       user       s0         s0-s1:c1,c3,c8       user_r

Cool, that worked. Note that this does not update the individual mappings.

[root@centos-7-2-t1 ~]# semanage login -l

Login Name           SELinux User         MLS/MCS Range        Service

__default__          user_u               s0                   *
dev1                 devuser_u            s0-s1:c1,c3          *

So, lets do that.

[root@centos-7-2-t1 ~]# semanage login -m -r s0-s1:c1,c3,c8 dev1
[root@centos-7-2-t1 ~]# semanage login -l

Login Name           SELinux User         MLS/MCS Range        Service

__default__          user_u               s0                   *
dev1                 devuser_u            s0-s1:c1,c3,c8       *

So now all is well.

Providing the MLS/MCS range of the SELinux user is a superset of the range an individual user has, then you shouldn't have a problem.

A side note, I have found it is occasionally possible to sometimes modify the SELinux user to no longer be a superset; but then all other modifications against that user breaks until you fix it (i.e. make it a superset, then clear the categories or sensitivities you wish to remove from the member UNIX user mappings, then update the SELinux user); a bug perhaps.