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(a)lists.fedoraproject.org
To unsubscribe send an email to selinux-leave(a)lists.fedoraproject.org