On Wed, 2017-06-21 at 14:19 -0700, Bill D wrote:
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?
Sorry, I should have suggested using another type for /opt/foo.
semanage fcontext -d "/opt/foo(/.*)?"
semanage fcontext -a -t user_home_dir_t -r s0:c1 "/opt/foo(/.*)?"
restorecon -RF /opt/foo