root@sandbox:~# cat /etc/fstab # /etc/fstab: static file system information. # <file system> <mount point> <type> <options> <dump> <pass> /dev/vda1 /boot ext2 defaults 0 2 /dev/mapper/vg0-root / btrfs defaults 0 1 /dev/mapper/vg0-usr /usr btrfs defaults 0 2 /dev/mapper/vg0-var /var btrfs defaults 0 2 /dev/mapper/vg0-tmp /tmp btrfs defaults 0 2 /dev/mapper/vg0-rhome /root btrfs defaults 0 2 /dev/mapper/vg0-swap none swap sw 0 0
root@sandbox:~# ssh-keygen -l -f /etc/ssh/ssh_host_ecdsa_key 256 f6:9b:ad:dd:93:cb:3d:c2:83:76:45:c3:02:e8:6a:1d root@sandbox (ECDSA)
sed -i 's/wheezy/jessie/g' /etc/apt/sources.list # that's no bloody enterprise aptitude update && aptitude dist-upgrade -VR # let's go testing, it's stable enough aptitude install vim bash-completion deborphan -VR # a little comfort couldn't hurt aptitude install policycoreutils auditd setools selinux-basics -VR # last is just helper scripts, optional vim /etc/network/interfaces # make interfaces static aptitude purge isc-dhcp-client console-setup console-setup-linux kbd iproute module-init-tools $(deborphan)
Create keys for ssh, register them on the server for root: @local$ ssh-keygen -b 521 -t ecdsa -f selinux-test @remote# mkdir /root/.ssh && cat selinux-test.pub > /root/.ssh/authorized_keys2 && chown && chmod
Well, by the end of the day, we assemble and install our core - we want support for the latest version of the policy, the minimum required set of modules, experiment with the PaX and GRSecurity patches (which, by the way, get on well with SELinux, but I’ll probably describe this later). In general, the vanilla kernel is best suited for us at the current stage. Yes, I can hear you a voice from the audience talking about the Debian way - but today the samurai’s way is not limited to such a framework. In this experiment, we still have UID = 0 without restrictions, and we are doing everything we want. So, let's heat up a little Arizona (or local virtual machine): mkdir src && cd src && wget -c http://kernel.org/pub/linux/kernel/v3.0/linux-3.10.18.tar.bz2 && tar jxf linux*tar.bz2 && cd linux* && make menuconfig && make -j$((2* $(grep processor /proc/cpuinfo | wc -l))) deb-pkg && make clean
At the configuration stage, we enable SELinux (yes, this pun is intended!): # if you are lazy to configure yourself, here's my .config, usable on KVM+libvirt wget -O - $aboveimage | dd bs=1 skip=3991 | xzcat
wget http://oss.tresys.com/files/refpolicy/refpolicy-2.20130424.tar.bz2 tar jxf refpolicy-2.20130424.tar.bz2 cp -rp refpolicy custom #all our modifications asroot# mkdir /usr/share/selinux/custom # so we can 'make install' here asroot# mkdir /etc/selinux/custom asroot# chown $USER:$USER /etc/selinux/custom /usr/share/selinux/custom asroot# touch /etc/selinux/custom/setrans.conf && chown $USER:$USER /etc/selinux/custom/setrans.conf # we'll need it later asroot# aptitude install selinux-utils python-selinux policycoreutils checkpolicy # these are for policy build
Next, the package build script: #!/bin/bash # sample deb build for custom selinux policy # harvests policy from local system version='0.0.1' name='selinux-policy-custom' description='Custom MLS SELinux policy' cf="${name}-control" cc="${name}-Copyright" # depends and conflicts shamessly ripped from selinux-policy-mls read -d '' cheader << EOF Section: non-free Priority: optional Homepage: http://selinux/ Standards-Version: 3.9.2 Package: ${name} Version: ${version} Maintainer: secadm_r <here.can+be@your.email> Pre-Depends: Depends: policycoreutils (>= 2.1.0), libpam-modules (>= 0.77-0.se5), python, libselinux1 (>= 2.0.35), libsepol1 (>= 2.1.0) Conflicts: cron (<= 3.0pl1-87.2sel), fcron (<= 2.9.3-3), logrotate (<= 3.7.1-1), procps (<= 1:3.1.15-1), selinux-policy-refpolicy-strict, selinux-policy-refpolicy-targeted, sysvinit (<= 2.86.ds1-1.se1) Architecture: all Copyright: ./selinux-policy-custom-Copyright Description: ${description} EOF read -d '' postinst << "EOF" File: postinst 755 #!/bin/sh -e set -e if [ "$1" = configure ]; then /usr/sbin/semodule -s custom -b /usr/share/selinux/custom/base.pp $(find /usr/share/selinux/custom/ -type f ! -name base.pp | xargs -r -n1 echo -n " -i") fi #DEBHELPER# exit 0 EOF function make_policy() { cd custom make clean rm -rf /usr/share/selinux/custom/* make install cd .. } function make_files() { echo 'SELinux custom policy copyright:TODO' > ${cc} echo -e "$cheader" > ${cf} echo -e "$postinst" >> ${cf} echo -en "\nFiles: " >> ${cf} # our setrans file echo -e " /etc/selinux/custom/setrans.conf /etc/selinux/custom" >> ${cf} # /etc/selinux dir find /etc/selinux/custom -type f ! -name \*LOCK | xargs -r -n1 -If -- sh -c 'echo " f $(dirname f)"' >> ${cf} # /usr/share/selinux/custom dir find /usr/share/selinux/custom -type f | xargs -r -n1 -If -- sh -c 'echo " f $(dirname f)"' >> ${cf} } function cleanup() { rm -f ${cc} ${cf} } function build_deb() { equivs-build ${cf} [ $? -eq 0 ] && cleanup } rm ./${name}*deb # glob is ok make_policy make_files build_deb scp -P 22 -i ~/.ssh/selinux-test selinux*deb root@selinux:/tmp/
The complete reassembly time turned out to be ~ 30 seconds, so the general principle of the script is chosen - “head-on,” which is called, I think, to adapt for assembling rpm work will not be: $ sed '/^#/d;/^$/d' build.conf TYPE = mls NAME = custom DISTRO = debian UNK_PERMS = reject DIRECT_INITRC = n MONOLITHIC = n UBAC = y CUSTOM_BUILDOPT = MLS_SENS = 4 MLS_CATS = 32 MCS_CATS = 32 QUIET = n
The differences from upstream are minimal: MLS is enabled (this means that all the parameters from policy / mls and config / appconfig-mls will be included during the build); included distro-specific debian macros, which is not really necessary; the policy will not load if permissions that are not reflected in the policy are defined in the kernel — what if we have a much newer kernel; Well, I have significantly reduced the number of levels and categories - we will have only 4 levels of secrecy, each with 32 categories. For now, that's enough for us. grep -A5 contrib policy/modules.conf | grep "= module$" | wc -l # total number grep -A5 contrib policy/modules.conf | grep "= module$" | sed 's/ = module//' | xargs -r -n1 -I__n -- sh -c 'sed -i "s/^__n = module$/__n = off/" policy/modules.conf' # kekeke # turn some servicess off too (xserver + postgresql) # turn _on_ logrotate,mta,postfix,ulogd, and whatever you think you need
grep something-something /var/log/audit/audit.log | audit2allow -M mymegamodule semodule -i mymegamodule
then follow it only if you are aware of what you are doing now - this set of commands means that SELinux will resolve everything that (potentially greedy) something-something has asked for access, and even a little more. Moreover, in the case of MLS, this method does not work at all - because in MLS it is not enough to create an allow rule, it is necessary that the access satisfies all the restrictions imposed on tolerances and categories. Such actions are equivalent to frank confession: “Yes, today I don’t want to think at all with my head, it’s easier for me to allow everything.” Do not make a theater out of your system, and do not tune SELinux in this way - it’s like catching all the packages on a firewall and turning them into permissive rules with a script. dpkg -i /tmp/selinux-policy-custom*deb sed -i 's/^SELINUX=.*$/SELINUX=enforcing/;s/^SELINUXTYPE=.*$/SELINUXTYPE=custom/' /etc/selinux/config selinux-activate # if you installed helper package selinux-basics # if not: touch /.autorelabel # add 'selinux=1 security=selinux' to cmdline reboot # let's rock!
The system will reboot, apply contexts as defined in the established policy ( / etc / selinux / custom / contexts / files / * ), reboot again and kindly offer to go.What is SELinux?Nevertheless, it is good if you have reached this point. This is exactly the behavior that we need, and now we will begin to understand why we are not allowed to.
In a nutshell: denied.
cp /var/log/audit/audit.log /root wc -l /root/audit.log 195
The scale of the disaster is small, two hundred lines. It is time to slowly descend from the mountain: type=DAEMON_START msg=audit(1383338997.597:1957): auditd start, ver=2.3.2 format=raw kernel=3.10.17-vm-slnx auid=4294967295 pid =1319 subj=system_u:system_r:auditd_t:s3:c0.c31 res=success
The first line tells us that auditd successfully (res) started, and on behalf of system_u, the role system_r, in the auditd_t domain, and applies to all categories (c0.c31) of our maximum level (s3). According to BLP , this means that information from any level can successfully fall into the clutches of auditd (write up), and it can read from any level (read down). If it is not completely clear, then let us remember who this architecture was designed for and what they meant by recording information - transferring information from the source (who writes) to the recipient (where / to whom it writes). And then everything falls into place - the Top Secret level really cannot write its data to the Secret level (ie, down, down) - they will become compromised, hence " no write down ". About the " read up " hopefully more obvious. Also in the MLS there are additional restrictions, but type=SYSCALL msg=audit(1383338997.620:219): arch=40000003 syscall=102 success=no exit=-13 a0=3 a1=afbe1c10 a2=a779b000 a3=ffffffc8 items=0 ppid=1338 pid=1346 auid=4294967295 uid=0 gid=0 euid=0 suid=0 fsuid=0 egid=0 sgid=0 fsgid=0 ses=4294967295 tty=(none) comm="acpid" exe="/usr/sbin/acpid" subj=system_u:system_r:initrc_t:s0-s3:c0.c31 key=(null)
The second line tells us that the acpid daemon, with all possible maximum regalia (uid = 0 gid = 0 euid = 0 suid = 0 fsuid = 0 egid = 0 sgid = 0 fsgid = 0), root root and bofh sysop using the context initrc_t (started) addressed (type = SYSCALL) to the socket (syscall = 102), and ( suddenly ) was not recognized, not called, and, as a result, sent (success = no exit = -13). Although, this should not be surprising, because we all know that root is not the most important in Linux, there are more important :-) type=AVC msg=audit(1383338997.810:233): avc: denied { search } for pid=1470 comm="restorecond" name="/" dev="tmpfs" ino=376 scontext=system_u:system_r:restorecond_t:s0-s3:c0.c31 tcontext=system_u:object_r:var_run_t:s3:c0.c31 tclass=dir
Well, take the third line from the middle. Logs AVC (Access Vector Cache) is for us the most interesting. The above, for example, says that the established policy does not have a permission rule for the source (scontext) with the above tolerance, working in the restorecond_t domain, to perform a search ({search} and tclass = dir) in the directory with the number inode = 376 with context var_run_t. An illustration of what? Right, no read up. What are you looking for? Find / var / run -inum 376 will answer this question. Just from a similar line, audit2allow will make a resolving rule. root@sandbox:~# ls -laZ /lib/systemd/systemd-udevd -rwxr-xr-x. 1 root root system_u:object_r:bin_t:s0 210380 Sep 23 12:24 /lib/systemd/systemd-udevd @local$ grep systemd-udevd custom/policy/ -R custom/policy/modules/system/udev.fc:/usr/lib/systemd/systemd-udevd -- gen_context(system_u:object_r:udev_exec_t,s0)
In debian / lib, in RefPolicy / usr / lib. Rule: root@sandbox:~# semanage fcontext -m -t udev_exec_t /lib/systemd/systemd-udevd # try to modify /usr/sbin/semanage: File context for /lib/systemd/systemd-udevd is not defined root@sandbox:~# semanage fcontext -a -t udev_exec_t /lib/systemd/systemd-udevd # ok, add root@sandbox:~# grep udev /etc/selinux/custom/contexts/files/file_contexts.local /lib/systemd/systemd-udevd system_u:object_r:udev_exec_t:s0
semanage is one way. Such a change is advisable, but in our case it may not survive the policy update (if we start shipping our /etc/selinux/custom/contexts/files/file_contexts.local ). Another option is to redefine locally, reassemble the policy, roll in (and at the same time set the policy). type=AVC msg=audit(1383338997.860:251): avc: denied { module_request } for pid=1524 comm="sshd" kmod="net-pf-10" scontext=system_u:system_r:sshd_t:s0-s3:c0.c31 tcontext=system_u:system_r:kernel_t:s3:c0.c31 tclass=system
Deciphering the log is simple, but the constant occupation of this over time tires. Throw it in the log, and let the machine work for us: root@sandbox:~# audit2allow -Rev -i /root/log require { type kernel_t; type sshd_t; class system module_request; } #============= sshd_t ============== # audit(1383338997.860:251): # scontext="system_u:system_r:sshd_t:s0-s3:c0.c31" tcontext="system_u:system_r:kernel_t:s3:c0.c31" # class="system" perms="module_request" # comm="sshd" exe="" path="" # message="type=AVC msg=audit(1383338997.860:251): avc: denied { # module_request } for pid=1524 comm="sshd" kmod="net-pf-10" # scontext=system_u:system_r:sshd_t:s0-s3:c0.c31 # tcontext=system_u:system_r:kernel_t:s3:c0.c31 tclass=system " allow sshd_t kernel_t:system module_request;
And here already, we start to think - we ask ourselves simple questions: mkdir policy/modules/local && cd policy/modules/local echo '<summary>Local layer -- differences from reference policy.</summary>' > metadata.xml echo '## <summary>sshd local policy</summary>' > sshd_local.if echo '## no file contexts redefined here' > sshd_local.fc cat > sshd_local.te <<EOF > policy_module(sshd_local, 0.0.1) > ################################################################## > require { > type kernel_t; > type sshd_t; > class system module_request; > } > #============= sshd_t ============== > # dont audit requests for module load > # NOTE: this may hide some denials in the future > dontaudit sshd_t kernel_t:system module_request; > > EOF
As you can see, we changed the rule to dontaudit sshd_t kernel_t: system module_request; - it means to prohibit, and not to write to the log. By the way, if you come across the fact that any functionality does not work, and the log is empty, then most likely this is just a dontaudit rule. Just reassemble the policy without them: semodule -DB , and get ready for the message flow to the log. root@sandbox:/tmp# sesearch --allow -s sshd_t -t kernel_t | grep system root@sandbox:/tmp# sesearch --dontaudit -s sshd_t -t kernel_t | grep system root@sandbox:/tmp# dpkg -i selinux-policy-custom_0.0.1_all.deb (Reading database ... 20371 files and directories currently installed.) Preparing to replace selinux-policy-custom 0.0.1 (using selinux-policy-custom_0.0.1_all.deb) ... Unpacking replacement selinux-policy-custom ... Setting up selinux-policy-custom (0.0.1) ... root@sandbox:/tmp# sesearch --dontaudit -s sshd_t -t kernel_t | grep system dontaudit sshd_t kernel_t : system module_request ; root@sandbox:/tmp# semodule -l | grep sshd_local sshd_local 0.0.1
The rule has appeared, the module is loaded. Complicated? Yah. Long and dreary? Oh yeah. type=AVC msg=audit(1383338997.630:221): avc: denied { sendto } for pid=1351 comm="acpid" path="/dev/log" scontext=system_u:system_r:initrc_t:s0-s3:c0.c31 tcontext=system_u:system_r:syslogd_t:s3:c0.c31 tclass=unix_dgram_socket type=SYSCALL msg=audit(1383338997.630:221): arch=40000003 syscall=102 success=no exit=-13 a0=3 a1=afbe15d0 a2=a779b000 a3=ffffffc8 items=0 ppid=1 pid=1351 auid=4294967295 uid=0 gid=0 euid=0 suid=0 fsuid=0 egid=0 sgid=0 fsgid=0 ses=4294967295 tty=(none) comm="acpid" exe="/usr/sbin/acpid" subj=system_u:system_r:initrc_t:s0-s3:c0.c31 key=(null)
root@sandbox:~# audit2allow -Rev -i /tmp/x require { type syslogd_t; type initrc_t; class unix_dgram_socket sendto; } #============= initrc_t ============== # audit(1383338997.630:221): # scontext="system_u:system_r:initrc_t:s0-s3:c0.c31" tcontext="system_u:system_r:syslogd_t:s3:c0.c31" # class="unix_dgram_socket" perms="sendto" # comm="acpid" exe="" path="" # message="type=AVC msg=audit(1383338997.630:221): avc: denied { sendto } for # pid=1351 comm="acpid" path="/dev/log" # scontext=system_u:system_r:initrc_t:s0-s3:c0.c31 # tcontext=system_u:system_r:syslogd_t:s3:c0.c31 tclass=unix_dgram_socket "#!!!! This avc is a constraint violation. You will need to add an attribute to either the source or target type to make it work. #Constraint rule: # Possible cause source context and target context 'level' differ allow initrc_t syslogd_t:unix_dgram_socket sendto;
root@sandbox:~# sesearch --allow -s initrc_t -t syslogd_t -c unix_dgram_socket Found 2 semantic av rules: allow initrc_t syslogd_t : unix_dgram_socket sendto ; allow unconfined_domain_type domain : unix_dgram_socket { ioctl read write create getattr setattr lock relabelfrom relabelto append bind connect listen accept getopt setopt shutdown recvfrom sendto recv_msg send_msg name_bind } ;
mlsconstrain unix_dgram_socket sendto (( l1 eq l2 ) or (( t1 == mlsnetwriteranged ) and ( l1 dom l2 ) and ( l1 domby h2 )) or (( t1 == mlsnetwritetoclr ) and ( h1 dom l2 ) and ( l1 domby l2 )) or ( t1 == mlsnetwrite ) or ( t2 == mlstrustedobject )); # scontext=system_u:system_r:initrc_t:s0-s3:c0.c31 # tcontext=system_u:system_r:syslogd_t:s3:c0.c31
Total, sendto to the socket (t1 writes to t2) is allowed if: root@sandbox:~# ls -laZ /dev/log srw-rw-rw-. 1 root root system_u:object_r:devlog_t:s3:c0.c31 0 Nov 1 23:06 /dev/log
«WTF?!» — . tcontext~syslogd_t, devlog_t? ps: root@sandbox:~# ps -auxZ | grep [r]syslog system_u:system_r:syslogd_t:s3:c0.c31 root 1338 0.0 0.3 30784 972 ? Ssl Nov01 0:00 /usr/sbin/rsyslogd
: rsyslog, syslogd_t, , , /dev/log; /dev/log devlog_t . , sendto , , . SELinux, Stephen Smalley. , . syslogd_t mlstrustedobject, /proc/`pidof rsyslog`/ mlstrustedobject. , , Fedora . , — , , , , . , : $ grep '' syslogd_local.* syslogd_local.fc:# no file contexts redefined here syslogd_local.if:## <summary>syslogd local policy</summary> syslogd_local.te:policy_module(syslogd_local, 0.0.1) syslogd_local.te:################################################################## syslogd_local.te:require { syslogd_local.te: type syslogd_t; syslogd_local.te:} syslogd_local.te: syslogd_local.te:#============= syslogd_t ============== syslogd_local.te:# mark syslogd_t as mlstrustedobject syslogd_local.te:# this is possible security hole, TODO: get some heavy brain augmentation and investigate syslogd_local.te:mls_trusted_object(syslogd_t);
. modules.conf . root@sandbox:~# sestatus SELinux status: enabled SELinuxfs mount: /sys/fs/selinux SELinux root directory: /etc/selinux Loaded policy name: custom Current mode: enforcing Mode from config file: enforcing Policy MLS status: enabled Policy deny_unknown status: denied Max kernel policy version: 28 root@sandbox:~# cat /var/log/audit/audit.log type=DAEMON_START msg=audit(1383360996.062:2774): auditd start, ver=2.3.2 format=raw kernel=3.10.17-vm-slnx auid=4294967295 pid=1278 subj=system_u:system_r:auditd_t:s3:c0.c31 res=success type=CONFIG_CHANGE msg=audit(1383360996.180:20): audit_backlog_limit=320 old=64 auid=4294967295 ses=4294967295 subj=system_u:system_r:auditctl_t:s0-s3:c0.c31 res=1 type=LOGIN msg=audit(1383361036.430:21): login pid=1568 uid=0 old auid=4294967295 new auid=0 old ses=4294967295 new ses=1 type=LOGIN msg=audit(1383361038.410:22): login pid=1571 uid=0 old auid=4294967295 new auid=0 old ses=4294967295 new ses=2 root@sandbox:~# id -Z root:secadm_r:secadm_t:s0-s3:c0.c31
, , , , , , , -, . . root@sandbox:~# cat /etc/selinux/custom/setrans.conf Domain=Playbox # levels s0=SystemLow s3:c0.c31=SystemHigh s0-s3:c0.c31=SystemLow-SystemHigh s1=Confidential s2=Secret # employee categories s1.c0=Ninjas s1.c1=Pirates s1.c2=Jesuses # secret stuff s2.c0=Aliens s2.c1=BigBrother
Now we set up our web server, as if it were designed exclusively for internal access, i.e. works strictly at the level of s1 (Confidential). It is not necessary for demonstration, but useful for general development. Of course, we will not configure IPSec and packet marking, otherwise no one will see it, we restrict ourselves to the local context. Since we now only have ssh configured on the test machine, let's choose a server that is not described in RefPolicy: /usr/sbin/nginx -- gen_context(system_u:object_r:nginx_exec_t,s1:c0.c2) /etc/init.d/nginx gen_context(system_u:object_r:nginx_initrc_exec_t,s1:c0.c2) /etc/nginx(/.*)? gen_context(system_u:object_r:nginx_etc_t,s1:c0.c2) /var/log/nginx(/.*)? gen_context(system_u:object_r:nginx_var_log_t,s1:c0.c2) /var/run/nginx(/.*)? gen_context(system_u:object_r:nginx_var_run_t,s1:c0.c2) /var/www(/.*)? gen_context(system_u:object_r:nginx_var_www_t,s1:c0.c2) /var/lib/nginx(/.*)? gen_context(system_u:object_r:nginx_var_lib_t,s1:c0.c3)
, , (, , ..), . s1 (Confidential), . , . , , ( newrole -r secadm_r ), premissive ( setenforce 0 ), ( restorecon -RFvv / ), nginx sysadm_r ( run_init /etc/init.d/nginx start ). audit.log , . modname.if, , , «» : template(`web_server_template',` type $1_t, web_server; allow blah blah; # so we can call web_server_template(nginxN) in modname.te ')
modname.if , «» . . , , : root@sandbox:~# cat nginx_local.te policy_module(nginx_local, 0.0.1) ################################################################## type nginx_t; type nginx_exec_t; type nginx_initrc_exec_t; type nginx_etc_t; type nginx_var_log_t; type nginx_var_run_t; type nginx_var_www_t; type nginx_var_lib_t; corecmd_executable_file(nginx_exec_t); init_script_file(nginx_initrc_exec_t) files_type(nginx_etc_t) logging_log_file(nginx_var_log_t) files_pid_file(nginx_var_run_t) files_type(nginx_var_www_t) files_type(nginx_var_lib_t) init_ranged_daemon_domain(nginx_t, nginx_exec_t, s1:c0.c2)
corecommands.if, . — , MLS, , nginx . # /read kernel sysctl values require { type sysctl_kernel_t; class dir { search }; class file { open read }; } allow nginx_t sysctl_kernel_t:dir { search }; allow nginx_t sysctl_kernel_t:file { open read };
socket: # socket bind require { type node_t; type http_port_t; class tcp_socket { name_bind setopt bind create listen node_bind }; class capability { net_bind_service setuid setgid }; } allow nginx_t http_port_t:tcp_socket { name_bind }; allow nginx_t node_t:tcp_socket { node_bind }; allow nginx_t self:tcp_socket { bind create setopt listen }; allow nginx_t self:capability { net_bind_service setuid setgid };
And so on. audit2allow, MLS. require , , , . , - policy_module(nginx_local, 0.0.1) ################################################################## type nginx_t; type nginx_exec_t; type nginx_initrc_exec_t; type nginx_etc_t; type nginx_var_log_t; type nginx_var_run_t; type nginx_var_www_t; type nginx_var_lib_t; corecmd_executable_file(nginx_exec_t); init_script_file(nginx_initrc_exec_t) files_type(nginx_etc_t) logging_log_file(nginx_var_log_t) files_pid_file(nginx_var_run_t) files_type(nginx_var_www_t) files_type(nginx_var_lib_t) init_ranged_daemon_domain(nginx_t, nginx_exec_t, s1:c0.c2) # rules # /sys and /sys/devices/systemcpu/online require { type sysfs_t; class dir { search }; class file { read open }; } allow nginx_t sysfs_t:dir { search }; allow nginx_t sysfs_t:file { read open }; # /read kernel sysctl values require { type sysctl_kernel_t; type sysctl_t; class dir { search }; class file { open read }; } allow nginx_t sysctl_kernel_t:dir { search }; allow nginx_t sysctl_kernel_t:file { open read }; allow nginx_t sysctl_t:dir search; # self configs and symlinks require { type nginx_etc_t; class dir { open read search }; class file { open read getattr }; class lnk_file { read }; } allow nginx_t nginx_etc_t:dir { open read search }; allow nginx_t nginx_etc_t:file { open read getattr }; allow nginx_t nginx_etc_t:lnk_file { read }; # /etc/localtime, /etc/passwc, etc (no pun intended) require { type locale_t; type etc_t; class file { read open getattr }; } allow nginx_t locale_t:file { read open getattr }; allow nginx_t etc_t:file { read open getattr }; # pid file require { type var_run_t; class dir { search write add_name remove_name } ; class file { write read create open unlink }; } allow nginx_t var_run_t: dir { search }; allow nginx_t nginx_var_run_t: file { read write create open unlink }; allow nginx_t nginx_var_run_t: dir { search write add_name remove_name }; # libs require { type var_lib_t; class dir { search getattr }; } allow nginx_t var_lib_t:dir search; allow nginx_t nginx_var_lib_t: dir { search getattr }; # socket bind require { type node_t; type http_port_t; class tcp_socket { name_bind setopt bind create listen node_bind }; class capability { net_bind_service setuid setgid }; } allow nginx_t http_port_t:tcp_socket { name_bind }; allow nginx_t node_t:tcp_socket { node_bind }; allow nginx_t self:tcp_socket { bind create setopt listen }; allow nginx_t self:capability { net_bind_service setuid setgid }; # socket accept require { class tcp_socket { read write accept }; } allow nginx_t self:tcp_socket { read write accept }; # logs require { type var_log_t; class dir { search }; class file { open append }; } allow nginx_t var_log_t:dir { search }; allow nginx_t nginx_var_log_t:dir { search }; allow nginx_t nginx_var_log_t:file { open append }; # www require { class dir { search getattr }; class file { read getattr open }; } allow nginx_t nginx_var_www_t:dir { search getattr }; allow nginx_t nginx_var_www_t:file { read getattr open };
root/sysadm_r@sandbox:~# adduser alice ...skipped... root/sysadm_r@sandbox:~# adduser bob ...skipped... root/secadm_r@sandbox:~# semanage user -a -R user_r -L s1 -r s1-s1:c0 ninjas root/secadm_r@sandbox:~# semanage user -a -R user_r -L s2 -r s2-s2:c0 aliens root/secadm_r@sandbox:~# semanage login -a -s ninjas alice root/secadm_r@sandbox:~# semanage login -a -s aliens bob # or, ninjas to supervise alice root/secadm_r@sandbox:~# restorecon -RFvv /home/ # thats all, folks.
Total, we get:Source: https://habr.com/ru/post/199202/
All Articles