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 _______________________________________________ selinux mailing list -- selinux@xxxxxxxxxxxxxxxxxxxxxxx To unsubscribe send an email to selinux-leave@xxxxxxxxxxxxxxxxxxxxxxx