Re: Enforcing directory access control using categories

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

 



On 06/21/2017 11:26 AM, Stephen Smalley wrote:

On Wed, 2017-06-21 at 10:12 -0700, Bill D wrote:
On 06/21/2017 09:23 AM, Stephen Smalley wrote:

On Wed, 2017-06-21 at 08:58 -0700, Bill D wrote:
Hello,

Is it possible to enforce directory read/write/execute control
using
categories?

For example, using a category, I would like Linux users assigned
to
that
category to have read/write/execute rights to directory /opt/foo.

Other Linux users that do not have that category assigned should
not
have read/write/execute access to /opt/foo

I know this can be done with normal DAC procedures using groups
and/or
file permission tools such as chmod and chown.

And I also know that it can done with SELinux TE (i.e create an
SELinux
security policy)

But can it be done by using just categories?
Yes, that is how sandbox, libvirt, docker, and other tools isolate
sandboxes, VMs, containers, etc.  And Android uses it for user
isolation and potentially app isolation in the future.  Categories
are
suitable when your primary goal is isolation.

In Fedora, you would need to mark the user domains as MCS
constrained
since that is no longer the default.  Depending on your particular
goals, you might need to revise the MCS constraints, but they may
be
sufficient as is.
Thank you for the information.  I am using RHEL 6.9 and CentOS 6.9.

Any pointers on how to mark the user domains as MCS constrained and
how
to view the existing MCS constraints for verification?
Didn't Philip Seeley provide instructions for using categories in the
earlier discussion of controlling execution of Java JAR files?

Yes, I got that.


Looks like RHEL6 defined mcs_untrusted_proc(), while modern Fedora
defines mcs_constrained() (in
/usr/share/selinux/devel/include/kernel/mcs.if). So, if you wanted to
just use user_t for the users, you would do something like:

# Make user_t MCS constrained.
$ cat mcsconstrained.te
require {
	type user_t;
}
# NB: use mcs_constrained() if on Fedora or RHEL 7.
mcs_untrusted_proc(user_t)

# Build and install the above policy module.
$ make -f /usr/share/selinux/devel/Makefile mcsconstrained.pp
$ semodule -i mcsconstrained.pp

# Define a SELinux user that is authorized only for category 0.
$ semanage user -a -R user_r -rs0:c0 c0user_u

# Define a SELinux user that is authorized only for category 1.
$ semanage user -a -R user_r -rs0:c1 c1user_u

# Add a user with category 0 access.
$ useradd -Z c0user_u jack

# Add a user with category 1 access.
$ useradd -Z c1user_u mary

# Restrict /opt/foo to category 1 users.
$ semanage fcontext -a -t usr_t -r s0:c1 "/opt/foo(/.*)?"
$ restorecon -RF /opt/foo

Then login as jack and see if you can access /opt/foo, and ditto for
mary.

I suspect you are better off testing to confirm correct operation than
trying to read the constraints, but if you really want them, you can
see a version disassembled from binary policy via seinfo --constrain,
or can just download the .src.rpm for selinux-policy and extract the
mcs file from it.  Looks like RHEL6 did not yet support attribute
preservation in constraints, and still displayed them in postfix form,
so the seinfo --constrain output isn't very human-friendly (it has
since improved).

I have tried your steps without success.  Here is what I did:

$ cat /etc/redhat-release
Red Hat Enterprise Linux Server release 6.9 (Santiago)

# create the folder foo and a bash script
$ mkdir -p /opt/foo
$ echo 'echo hello' > /opt/foo/bar.sh
$ chmod -R 770 /opt/foo
$ chown -R admin:admin /opt/foo
$ chcon -u system_u /opt/foo
$ chcon -u system_u /opt/foo/bar.sh
$ ls -aldtZ /opt/foo/ /opt/foo/bar.sh
drwxrwx---. admin admin system_u:object_r:usr_t:SystemLow /opt/foo/
-rwxrwx---. admin admin system_u:object_r:usr_t:SystemLow /opt/foo/bar.sh

$ getenforce
Enforcing

$ setenforce 0

$ getenforce
Permissive

$ vi /etc/selinux/targeted/setrans.conf

$ cat /etc/selinux/targeted/setrans.conf
#
# Multi-Category Security translation table for SELinux
#
# Uncomment the following to disable translation libary
# disable=1
#
# Objects can be categorized with 0-1023 categories defined by the admin.
# Objects can be in more than one category at a time.
# Categories are stored in the system as c0-c1023.  Users can use this
# table to translate the categories into a more meaningful output.
# Examples:
# s0:c0=CompanyConfidential
# s0:c1=PatientRecord
# s0:c2=Unclassified
# s0:c3=TopSecret
# s0:c1,c3=CompanyConfidentialRedHat
s0:c0=CompanyConfidential
s0:c1=PatientRecord
s0=SystemLow
s0-s0:c0.c1023=SystemLow-SystemHigh
s0:c0.c1023=SystemHigh

$ service mcstrans restart
Stopping mcstransd:                                        [  OK  ]
Starting mcstransd:                                        [  OK  ]

$ chcat -L
s0:c0                          CompanyConfidential
s0:c1                          PatientRecord
s0                             SystemLow
s0-s0:c0.c1023                 SystemLow-SystemHigh
s0:c0.c1023                    SystemHigh

$ cat mcsconstrained.te
module mymcsmodule 1.0;

require {
    type user_t;
}
# NB: use mcs_constrained() if on Fedora or RHEL 7.
mcs_untrusted_proc(user_t)

# Build and install the above policy module.
$ make -f /usr/share/selinux/devel/Makefile mcsconstrained.pp
Compiling targeted mcsconstrained module
/usr/bin/checkmodule: loading policy configuration from tmp/mcsconstrained.tmp
/usr/bin/checkmodule:  policy configuration loaded
/usr/bin/checkmodule: writing binary representation (version 10) to tmp/mcsconstrained.mod
Creating targeted mcsconstrained.pp policy package
rm tmp/mcsconstrained.mod tmp/mcsconstrained.mod.fc

$ semodule -i mcsconstrained.pp

# Define a SELinux user that is authorized only for category 0.
$ semanage user -a -R user_r -rs0:c0 c0user_u

# Define a SELinux user that is authorized only for category 1.
$ semanage user -a -R user_r -rs0:c1 c1user_u

# Add a user with category 0 access.
$ useradd -Z c0user_u jack

# add jack to the admin group
$ usermod -G admin jack

# Add a user with category 1 access.
$ useradd -Z c1user_u mary

# add mary to the admin group
$ usermod -G admin mary

# Restrict /opt/foo to category 1 users.
$ semanage fcontext -a -t usr_t -r s0:c1 "/opt/foo(/.*)?"
$ restorecon -RF /opt/foo

$ ls -aldtZ /opt/foo /opt/foo/bar.sh
drwxrwx---. admin admin system_u:object_r:usr_t:PatientRecord /opt/foo
-rwxrwx---. admin admin system_u:object_r:usr_t:PatientRecord /opt/foo/bar.sh

$ setenforce 1

Now logon as Linux user jack and notice that it is *not* able to write to /opt/foo and can't run /opt/foo/bar.sh which is expected

$ id
uid=502(jack) gid=502(jack) groups=502(jack),501(admin) context=c0user_u:user_r:user_t:CompanyConfidential

$ id -Z
c0user_u:user_r:user_t:CompanyConfidential

$ ls -aldtZ /opt/foo/ /opt/foo/bar.sh
drwxrwx---. admin admin system_u:object_r:usr_t:PatientRecord /opt/foo/
-rwxrwx---. admin admin system_u:object_r:usr_t:PatientRecord /opt/foo/bar.sh

$ touch /opt/foo/bar
touch: cannot touch `/opt/foo/bar': Permission denied

$ /opt/foo/bar.sh
-bash: /opt/foo/bar.sh: Permission denied

Now logon as Linux user mary and notice that it is able to run /opt/foo/bar.sh which is expected.
However, mary is *not* able to write to /opt/foo which is *not* expected

$ id
uid=503(mary) gid=503(mary) groups=503(mary),501(admin) context=c1user_u:user_r:user_t:PatientRecord

$ id -Z
c1user_u:user_r:user_t:PatientRecord

$ ls -aldtZ /opt/foo/ /opt/foo/bar.sh
drwxrwx---. admin admin system_u:object_r:usr_t:PatientRecord /opt/foo/
-rwxrwx---. admin admin system_u:object_r:usr_t:PatientRecord /opt/foo/bar.sh

$ /opt/foo/bar.sh
hello

$ touch /opt/foo/blah
touch: cannot touch `/opt/foo/blah': Permission denied

Following is the denial details in /var/log/audit/audit.log:

type=AVC msg=audit(1498079143.988:16822): avc: denied { write } for pid=10393 comm="touch" name="foo" dev=dm-5 ino=3801089 scontext=c1user_u:user_r:user_t:s0:c1 tcontext=system_u:object_r:usr_t:s0:c1 tclass=dir type=SYSCALL msg=audit(1498079143.988:16822): arch=c000003e syscall=2 success=no exit=-13 a0=7ffda4cab82d a1=941 a2=1b6 a3=7ffda4ca91d0 items=2 ppid=10292 pid=10393 auid=503 uid=503 gid=503 euid=503 suid=503 fsuid=503 egid=503 sgid=503 fsgid=503 tty=pts2 ses=14 comm="touch" exe="/bin/touch" subj=c1user_u:user_r:user_t:s0:c1 key="access"
type=CWD msg=audit(1498079143.988:16822):  cwd="/home/mary"
type=PATH msg=audit(1498079143.988:16822): item=0 name="/opt/foo/" inode=3801089 dev=fd:05 mode=040770 ouid=501 ogid=501 rdev=00:00 obj=system_u:object_r:usr_t:s0:c1 nametype=PARENT type=PATH msg=audit(1498079143.988:16822): item=1 name="/opt/foo/blah" nametype=CREATE

Does it mean that we have to loosen up the access control for the usr_t type such as allowing it to write to directories? It seems like if we did that, then we would be opening up a security hole i.e. regular users can potentially write to the /usr directory?

Best Regards,

Bill
_______________________________________________
selinux mailing list -- selinux@xxxxxxxxxxxxxxxxxxxxxxx
To unsubscribe send an email to selinux-leave@xxxxxxxxxxxxxxxxxxxxxxx
_______________________________________________
selinux mailing list -- selinux@xxxxxxxxxxxxxxxxxxxxxxx
To unsubscribe send an email to selinux-leave@xxxxxxxxxxxxxxxxxxxxxxx




[Index of Archives]     [Fedora Users]     [Fedora Desktop]     [Big List of Linux Books]     [Yosemite News]     [Yosemite Campsites]     [KDE Users]     [Gnome Users]

  Powered by Linux