On 06/22/2017 08:26 AM, Stephen Smalley wrote:
On Thu, 2017-06-22 at 08:17 -0700, Bill D wrote:
On 06/22/2017 07:56 AM, Stephen Smalley wrote:
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
Thanks. That resolves the issue of not being able to write to
/opt/foo
but it now blocks executing /opt/foo/bar.sh as follows:
$ id
uid=503(mary) gid=503(mary) groups=503(mary),501(admin)
context=c1user_u:user_r:user_t:PatientRecord
$ /opt/foo/bar.sh
-bash: /opt/foo/bar.sh: Permission denied
And here are the file permissions for /opt/foo/bar.sh
# id
uid=0(root) gid=0(root) groups=0(root)
context=unconfined_u:unconfined_r:unconfined_t:SystemLow-SystemHigh
# ls -aldtZ /opt/foo/bar.sh
-rwxrwx---. admin admin
system_u:object_r:user_home_dir_t:PatientRecord
/opt/foo/bar.sh
And here is the denial:
type=AVC msg=audit(1498144073.846:204627): avc: denied { execute }
for pid=15033 comm="bash" name="bar.sh" dev=dm-5 ino=3801090
scontext=c1user_u:user_r:user_t:s0:c1
tcontext=system_u:object_r:user_home_dir_t:s0:c1 tclass=file
type=SYSCALL msg=audit(1498144073.846:204627): arch=c000003e
syscall=59
success=no exit=-13 a0=21bf870 a1=21b2f50 a2=21be210 a3=10 items=1
ppid=14879 pid=15033 auid=503 uid=503 gid=503 euid=503 suid=503
fsuid=503 egid=503 sgid=503 fsgid=503 tty=pts1 ses=155 comm="bash"
exe="/bin/bash" subj=c1user_u:user_r:user_t:s0:c1 key=(null)
type=CWD msg=audit(1498144073.846:204627): cwd="/home/mary"
type=PATH msg=audit(1498144073.846:204627): item=0
name="/opt/foo/bar.sh" inode=3801090 dev=fd:05 mode=0100770 ouid=501
ogid=501 rdev=00:00 obj=system_u:object_r:user_home_dir_t:s0:c1
nametype=NORMAL
Sigh, if at first you don't succeed,
semanage fcontext -m -t user_home_t -r s0:c1 "/opt/foo(/.*)?"
restorecon -RF /opt/foo
That worked! Thanks!
Regards,
Bill
_______________________________________________
selinux mailing list -- selinux@xxxxxxxxxxxxxxxxxxxxxxx
To unsubscribe send an email to selinux-leave@xxxxxxxxxxxxxxxxxxxxxxx