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
Regards,
Bill