14. SELinux (optional)
Info
This chapter basically follows SELinux/Installation. Currently, I only use SELinux on servers, and only "mcs" policy type to be able to better isolate virtual machines from each other.
14.1. Enable SELinux¶
Reduce the number of services by disabling some unneeded ones in order to avoid a few SELinux denials. This may not be desired on "desktop" systems.
systemctl mask user@.service && \
systemctl disable systemd-userdbd.socket && \
rsync -a /etc/nsswitch.conf /etc/._cfg0000_nsswitch.conf && \
sed -i 's/^hosts:\([[:space:]]*\)mymachines \(.*\)$/hosts:\1\2/' /etc/._cfg0000_nsswitch.conf && \
echo -e "\e[1;32mSUCCESS\e[0m"
Setup "make.conf":
rsync -a /etc/portage/make.conf /etc/portage/._cfg0000_make.conf && \
echo -e '\nPOLICY_TYPES="mcs"' >> /etc/portage/._cfg0000_make.conf && \
sed -i 's/^USE_HARDENED="\(.*\)"/USE_HARDENED="\1 -ubac"/' /etc/portage/._cfg0000_make.conf && \
echo -e "\e[1;32mSUCCESS\e[0m"
Info
If you go with the default of unconfined
useflag being enabled, you need to patch the official sec-policy/selinux-base
ebuild to mitigate the problem described in bug 905371.
Thus, in regards to unconfined
useflag you have two options:
Download and verify repo-patches
script and sec-policy/selinux-base
patch (copy&paste one command after the other):
# Switch to non-root user
su -l david
# Switch to bash shell
bash --norc
# Set the correct e-mail address
gpg_mail="d at myCodebergUsername dot de"
(
cd /tmp/ && \
curl -fsS --proto '=https' --tlsv1.3 --remote-name-all \
https://codeberg.org/duxsco/gentoo-installation/raw/branch/main/bin/{repo-patches,sec-policy_selinux-base.patch,sha512.txt{,.asc}} && \
export GNUPGHOME="$(mktemp -d)" && \
gpg --locate-external-keys "${gpg_mail}" && \
echo "3AAE5FC903BB199165D4C02711BE5F68440E0758:6:" | gpg --batch --import-ownertrust --quiet && \
gpg_status="$(gpg --batch --status-fd 1 --verify sha512.txt.asc sha512.txt 2>/dev/null)" && \
gpgconf --kill all && \
grep -E -q "^\[GNUPG:\][[:space:]]+GOODSIG[[:space:]]+" <<< "${gpg_status}" && \
grep -E -q "^\[GNUPG:\][[:space:]]+VALIDSIG[[:space:]]+" <<< "${gpg_status}" && \
grep -E -q "^\[GNUPG:\][[:space:]]+TRUST_ULTIMATE[[:space:]]+" <<< "${gpg_status}" && \
sha512sum --quiet -c sha512.txt && \
echo -e "\e[1;32mSUCCESS\e[0m"
)
Apply the patch to sec-policy/selinux-base
as root
user:
mkdir -p /etc/portage/repo.postsync.d /etc/portage/repo-patches/gentoo && \
rsync -av --chown=0:0 --chmod=u=rwx,og=r /tmp/repo-patches /etc/portage/repo.postsync.d/ && \
rsync -av --chown=0:0 --chmod=a=r /tmp/sec-policy_selinux-base.patch /etc/portage/repo-patches/gentoo/ && \
ln -s /usr/share/portage/config/repos.conf /etc/portage/repos.conf/ && \
echo "dev-vcs/git -webdav" >> /etc/portage/package.use/main && \
emerge --noreplace dev-vcs/git sys-apps/pkgcore && \
eix-sync && \
echo -e "\e[1;32mSUCCESS\e[0m"
rsync -a /etc/portage/make.conf /etc/portage/._cfg0000_make.conf && \
sed -i 's/^USE_HARDENED="\(.*\)"/USE_HARDENED="\1 -unconfined"/' /etc/portage/._cfg0000_make.conf && \
echo -e "\e[1;32mSUCCESS\e[0m"
Switch to the SELinux profile:
eselect profile set "default/linux/amd64/23.0/hardened/selinux/systemd"
These commands are more or less required irrespective of the SELinux profile in use:
# (Recommended) Use the most recent SELinux policies
echo 'sec-policy/* ~amd64' >> /etc/portage/package.accept_keywords/main && \
# (Optional) To get a nice looking html site in /usr/share/doc/selinux-base-<VERSION>/mcs/html:
echo 'sec-policy/selinux-base doc' >> /etc/portage/package.use/main && \
# Definitely required:
FEATURES="-selinux" emerge --oneshot selinux-base && \
echo -e "\e[1;32mSUCCESS\e[0m"
Configure SELinux:
rsync -a /etc/selinux/config /etc/selinux/._cfg0000_config && \
sed -i 's/^SELINUXTYPE=strict$/SELINUXTYPE=mcs/' /etc/selinux/._cfg0000_config && \
echo -e "\e[1;32mSUCCESS\e[0m"
Update packages:
FEATURES="-selinux -sesandbox" emerge --oneshot selinux-base && \
FEATURES="-selinux -sesandbox" emerge --oneshot selinux-dbus && \
FEATURES="-selinux -sesandbox" emerge --oneshot selinux-base-policy && \
emerge -atuDN @world
Enable auditd logging:
systemctl enable auditd.service && \
echo -e "\e[1;32mSUCCESS\e[0m"
Rebuild the kernel with SELinux support:
emerge -at --oneshot \
$(qlist -eI sys-kernel/gentoo-kernel-bin >/dev/null && echo sys-kernel/gentoo-kernel-bin) \
$(qlist -eI sys-kernel/gentoo-kernel >/dev/null && echo sys-kernel/gentoo-kernel) && \
echo -e "\e[1;32mSUCCESS\e[0m"
Reboot with permissive kernel.
Make sure that UBAC gets disabled:
bash -c '(
cd /usr/share/selinux/mcs && \
semodule -i base.pp -i $(ls *.pp | grep -v base.pp) && \
echo -e "\e[1;32mSUCCESS\e[0m"
)'
14.2. Relabel¶
mkdir /mnt/gentoo && \
mount -o bind / /mnt/gentoo && \
setfiles -r /mnt/gentoo /etc/selinux/mcs/contexts/files/file_contexts /mnt/gentoo/{dev,home,proc,run,sys,tmp,boot/efi*,var/cache/binpkgs,var/cache/distfiles,var/db/repos/gentoo,var/tmp} && \
umount /mnt/gentoo && \
rlpkg -a -r && \
echo -e "\e[1;32mSUCCESS\e[0m"
Make sure that nothing (except perhaps ".keep" files) is unlabeled:
export tmpdir="$(mktemp -d)" && \
mount --bind / "$tmpdir" && \
find "$tmpdir" -context '*unlabeled_t*' -exec ls -dZ {} + && \
umount "$tmpdir" && \
echo -e "\e[1;32mSUCCESS\e[0m"
If "/proc" was listed by above codeblock you have to relabel to avoid a denial:
# [ 19.902620] audit: type=1400 audit(1663630933.439:3): avc: denied { mounton } for pid=1062 comm="(auditd)" path="/run/systemd/unit-root/proc" dev="dm-3" ino=67581 scontext=system_u:system_r:init_t:s0 tcontext=system_u:object_r:unlabeled_t:s0 tclass=dir permissive=1
# Credits: grift :)
export tmpdir="$(mktemp -d)" && mount --bind / "$tmpdir" && chcon system_u:object_r:proc_t:s0 "$tmpdir"/proc && umount "$tmpdir" && echo -e "\e[1;32mSUCCESS\e[0m"
In section 10. SSH Server (optional), the SSH port has been changed to 50022. This needs to be considered for no SELinux denials to occur:
❯ semanage port -l | grep -e ssh -e Port
SELinux Port Type Proto Port Number
ssh_port_t tcp 22
❯ semanage port -a -t ssh_port_t -p tcp 50022
❯ semanage port -l | grep -e ssh -e Port
SELinux Port Type Proto Port Number
ssh_port_t tcp 50022, 22
14.3. Users and services¶
Default "mcs" SELinux "login"settings:
❯ semanage login -l
Login Name SELinux User MLS/MCS Range Service
__default__ unconfined_u s0-s0 *
root root s0-s0:c0.c1023 *
❯ semanage login -l
Login Name SELinux User MLS/MCS Range Service
__default__ user_u s0-s0 *
root root s0-s0:c0.c1023 *
Default "mcs" SELinux "user" settings:
❯ semanage user -l
Labeling MLS/ MLS/
SELinux User Prefix MCS Level MCS Range SELinux Roles
root sysadm s0 s0-s0:c0.c1023 staff_r sysadm_r
staff_u staff s0 s0-s0:c0.c1023 staff_r sysadm_r
sysadm_u sysadm s0 s0-s0:c0.c1023 sysadm_r
system_u user s0 s0-s0:c0.c1023 system_r
unconfined_u unconfined s0 s0-s0:c0.c1023 unconfined_r
user_u user s0 s0 user_r
Add the initial user to the administration SELinux user:
semanage login -a -s staff_u david && \
restorecon -RFv /home/david && \
bash -c 'echo "%wheel ALL=(ALL) TYPE=sysadm_t ROLE=sysadm_r ALL" | EDITOR="tee" visudo -f /etc/sudoers.d/wheel && \
echo -e "\e[1;32mSUCCESS\e[0m"'
Now, we should have:
❯ semanage login -l
Login Name SELinux User MLS/MCS Range Service
__default__ unconfined_u s0-s0 *
david staff_u s0-s0:c0.c1023 *
root root s0-s0:c0.c1023 *
❯ semanage login -l
Login Name SELinux User MLS/MCS Range Service
__default__ user_u s0-s0 *
david staff_u s0-s0:c0.c1023 *
root root s0-s0:c0.c1023 *
Create "/var/lib/sepolgen/interface_info" for "audit2why -R" to work:
sepolgen-ifgen -i /usr/share/selinux/mcs/include/support/ && \
echo -e "\e[1;32mSUCCESS\e[0m"
14.4. SELinux policies¶
At this point, you can reboot into permissive mode again and use the selinux-policy-creator.sh script.