diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 96605d8e21..85d455fcb5 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -3,21 +3,27 @@ name: Build tests on: [push, pull_request] env: - # Minimum userspace version to build refpolicy. - SELINUX_USERSPACE_VERSION: checkpolicy-3.1 + # Minimum versions to build refpolicy. + PYTHON_VERSION: "3.10" + SELINUX_USERSPACE_VERSION: checkpolicy-3.2 + USERSPACE_SRC: "selinux-src" + # branch for sechecker + SECHECKER_VERSION: "4.4" + SETOOLS_SRC: "setools-src" jobs: lint: - runs-on: ubuntu-20.04 + runs-on: ubuntu-22.04 steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 # This version should be the minimum required to run the fc checker + # or the standard Python version on Ubuntu. - name: Set up Python - uses: actions/setup-python@v4 + uses: actions/setup-python@v5 with: - python-version: 3.7 + python-version: "${{env.PYTHON_VERSION}}" - name: Install dependencies run: | @@ -56,7 +62,7 @@ jobs: selint --source --recursive --summary --fail --disable C-005 --disable C-008 --disable W-005 policy build: - runs-on: ubuntu-20.04 + runs-on: ubuntu-22.04 strategy: fail-fast: false @@ -119,13 +125,29 @@ jobs: - {type: mls, distro: gentoo, monolithic: y, systemd: n, apps-off: unconfined, direct_initrc: y} steps: - - uses: actions/checkout@v3 + - name: Checkout Reference Policy + uses: actions/checkout@v4 + + - name: Checkout SELinux userspace tools and libs + uses: actions/checkout@v4 + with: + repository: SELinuxProject/selinux + ref: "${{env.SELINUX_USERSPACE_VERSION}}" + path: "${{env.USERSPACE_SRC}}" + + - name: Checkout setools + uses: actions/checkout@v4 + with: + repository: SELinuxProject/setools + ref: "${{env.SECHECKER_VERSION}}" + path: "${{env.SETOOLS_SRC}}" # This should be the minimum required Python version to build refpolicy. + # or the standard Python version on Ubuntu. - name: Set up Python - uses: actions/setup-python@v4 + uses: actions/setup-python@v5 with: - python-version: 3.5 + python-version: "${{env.PYTHON_VERSION}}" - name: Install dependencies run: | @@ -144,7 +166,6 @@ jobs: run: | echo "DESTDIR=/tmp/refpolicy" >> $GITHUB_ENV echo "PYTHON=python" >> $GITHUB_ENV - echo "TEST_TOOLCHAIN_SRC=/tmp/selinux-src" >> $GITHUB_ENV echo "TEST_TOOLCHAIN=/tmp/selinux" >> $GITHUB_ENV echo "TYPE=${{matrix.build-opts.type}}" >> $GITHUB_ENV echo "DISTRO=${{matrix.build-opts.distro}}" >> $GITHUB_ENV @@ -153,21 +174,25 @@ jobs: echo "APPS_OFF=${{matrix.build-opts.apps-off}}" >> $GITHUB_ENV echo "DIRECT_INITRC=${{matrix.build-opts.direct_initrc}}" >> $GITHUB_ENV echo "WERROR=y" >> $GITHUB_ENV + echo "CFLAGS=\"-O2\"" >> $GITHUB_ENV - name: Build toolchain run: | - # Download current SELinux userspace tools and libraries - git clone https://github.com/SELinuxProject/selinux.git ${TEST_TOOLCHAIN_SRC} -b ${SELINUX_USERSPACE_VERSION} # Drop secilc to break xmlto dependence (secilc isn't used here anyway) - sed -i -e 's/secilc//' ${TEST_TOOLCHAIN_SRC}/Makefile + sed -i -e 's/secilc//' ${USERSPACE_SRC}/Makefile # Drop sepolicy to break setools dependence (sepolicy isn't used anyway) - sed -i -e 's/sepolicy//' ${TEST_TOOLCHAIN_SRC}/policycoreutils/Makefile + sed -i -e 's/sepolicy//' ${USERSPACE_SRC}/policycoreutils/Makefile # Drop restorecond to break glib dependence - sed -i -e 's/ restorecond//' ${TEST_TOOLCHAIN_SRC}/policycoreutils/Makefile + sed -i -e 's/ restorecond//' ${USERSPACE_SRC}/policycoreutils/Makefile # Drop sandbox to break libcap-ng dependence - sed -i -e 's/ sandbox//' ${TEST_TOOLCHAIN_SRC}/policycoreutils/Makefile + sed -i -e 's/ sandbox//' ${USERSPACE_SRC}/policycoreutils/Makefile # Compile and install SELinux toolchain - make OPT_SUBDIRS=semodule-utils DESTDIR=${TEST_TOOLCHAIN} -C ${TEST_TOOLCHAIN_SRC} install + make OPT_SUBDIRS=semodule-utils DESTDIR=${TEST_TOOLCHAIN} -C ${USERSPACE_SRC} install + + - name: Build setools + run: | + cd ${SETOOLS_SRC} + pip install . - name: Build refpolicy run: | @@ -192,3 +217,14 @@ jobs: make install-docs make install-udica-templates make install-appconfig + + # This skips some combinations to keep GitHub actions runtime lower by + # eliminating duplicate analyses. + - name: Validate security goals + run: | + if [[ $MONOLITHIC == "y" ]] && [[ $TYPE != "standard" ]] && [[ $APPS_OFF ]] && [[ $SYSTEMD == "y" ]]; then + policy_file=$(make MONOLITHIC=y --eval='output_filename: ; @echo $(polver)' output_filename) + sechecker testing/sechecker.ini "${policy_file}" + else + echo "Skipped" + fi diff --git a/testing/sechecker.ini b/testing/sechecker.ini new file mode 100644 index 0000000000..b873b94ec2 --- /dev/null +++ b/testing/sechecker.ini @@ -0,0 +1,401 @@ +# +# SELinux Reference policy validation checks +# +# Note to users: This file is a good starting point for tightening your own +# policy. However, these checks are for the entire Reference Policy, i.e., +# all modules are included in the policy. If you are using a subset of the +# modules, the best starting place is to review each of the checks and remove +# the types in the exempt lists that are not in your policy. Types that are +# in these lists but not in your policy will *NOT* cause sechecker to fail. +# +# Note to developers: In general, please avoid using attributes in the +# exempt lists. This will make it less likely for unexpected types to pass. +# + +[PRIVILEGE-load_policy] +check_type = assert_te +desc = Verify only the load_policy program can load a SELinux policy update. +tclass = security +perms = load_policy +exempt_source = kernel_t # Kernel thread loading policy at boot + load_policy_t # SELinux policy loading tool + +[PRIVILEGE-setbool] +check_type = assert_te +desc = Verify SELinux Booleans can be changed only by expected domains. +tclass = security +perms = setbool +exempt_source = cloud_init_t # VM configuration on initial boot + init_t + load_policy_t # Persist Boolean state across policy loads + puppet_t # Puppet can configure Booleans + secadm_t # Security admin role + semanage_t # SELinux management tool, including Booleans + sysadm_t # System admin role + +[PRIVILEGE-setenforce] +check_type = assert_te +desc = Verify only expected domains can change SELinux to permissive mode. +tclass = security +perms = setenforce +exempt_source = cloud_init_t # VM configuration on initial boot + secadm_t # Security admin role + sysadm_t # System admin role + +[PRIVILEGE-CAP_SYS_MODULE] +check_type = assert_te +desc = Verify only expected domains have CAP_SYS_MODULE (kernel module capability) +tclass = capability +perms = sys_module +exempt_source = init_t + kernel_t + kmod_t + spc_t + systemd_modules_load_t + udev_t + +[PRIVILEGE-module_load] +check_type = assert_te +desc = Verify only expected domains can directly load kernel modules +tclass = system +perms = module_load +# This list should match the above PRIVILEGE-CAP_SYS_MODULE exempt_source list. +exempt_source = init_t + kernel_t + kmod_t + spc_t + systemd_modules_load_t + udev_t + +[PRIVILEGE-CAP_SYS_ADMIN] +check_type = assert_te +desc = Verify only expected domains have CAP_SYS_ADMIN +tclass = capability +perms = sys_admin +# CAP_SYS_ADMIN is a kitchen sink of privileges, which means many privileged domains need it. +exempt_source = acpi_t + acpid_t + afs_t + auditadm_sudo_t # Conditional access (allow_polyinstantiation) + automount_t + bluetooth_t + bootloader_t # Install bootloader + cachefilesd_t + cgclear_t # Move processes out of cgroups + cgconfig_t # Configure cgroups + cgmanager_t # Container cgroup manager + cgred_t # Move processes to cgroups based on configurable rules + chromium_sandbox_t + cockpit_session_t + container_engine_t + consoletype_t + container_t # Conditional access (container_use_sysadmin or container_use_host_all_caps) + corosync_t + crio_t + crond_t # Conditional access (allow_polyinstantiation) + cryfs_t + cupsd_t + devicekit_disk_t + devicekit_power_t + disk_munin_plugin_t + dmesg_t # Clear kernel printk buffer/set kernel log level + dockerd_t # Container engine (namespacing) + dockerd_user_t # Container engine (namespacing) + dphysswapfile_t # Configure swap files + entropyd_t # Add entropy to the system + fapolicyd_t + fsadm_t + fsdaemon_t + ftpd_t + getty_t # Configure tty devices + glusterd_t + gpm_t + hostname_t # Set hostname + hypervvssd_t + ifconfig_t + init_t + initrc_t + iscsid_t + kdump_t + kernel_t # Kernel threads have all caps + klogd_t + kubeadm_t + lircd_t + local_login_t # Conditional access (allow_polyinstantiation) + lvm_t # Configure logical volumes + mcelog_t # Decode and log CPU machine check exceptions + mdadm_t # Configure software RAID + modemmanager_t + mon_local_test_t + mount_t # (un)mount filesystems + nagios_checkdisk_plugin_t + newrole_t # Conditional access (allow_polyinstantiation) + nfsd_t + ntop_t + plymouthd_t + podman_t + podman_user_t + postgresql_t + pppd_t + quota_t # Configure filesystem quotas + remote_login_t # Conditional access (allow_polyinstantiation) + resmgrd_t + rlogind_t # Conditional access (allow_polyinstantiation) + rngd_t + rootlesskit_t # Container engine (namespacing) + rpcd_t + rpm_script_t # Package manager post-install scripts + rshd_t # Conditional access (allow_polyinstantiation) + secadm_sudo_t # Conditional access (allow_polyinstantiation) + seunshare_t # Create new flesystem namespaces + shorewall_t + smbd_t + smbmount_t # Mount SMB and CIFS filesystems + sosreport_t + spc_t + sshd_t # Conditional access (allow_polyinstantiation) + sssd_t + staff_sudo_t # Conditional access (allow_polyinstantiation) + sulogin_t + sysadm_t # System admin role + sysadm_sudo_t # Conditional access (allow_polyinstantiation) + syslogd_t + sysstat_t + systemd_generator_t + systemd_homework_t # Mount home directory images + systemd_hostnamed_t # Set hostname + systemd_logind_t + systemd_machine_id_setup_t + systemd_nspawn_t + systemd_sysctl_t + systemd_tmpfiles_t + systemd_user_runtime_dir_t + tuned_t + udev_t + user_sudo_t # Conditional access (allow_polyinstantiation) + vbetool_t + virtd_t # libvirt virtualization manager + virtd_lxc_t # libvirt LXC container engine (namespacing) + vmware_t # VMWare virtualization manager + watchdog_t + xserver_t + zed_t # ZFS events daemon (filesystem event monitoring) + zfs_t # ZFS filesystem tools + +[PRIVILEGE-CAP_SYS_RAWIO] +check_type = assert_te +desc = Verify only expected domains can use CAP_SYS_RAWIO +tclass = capability +perms = sys_rawio +exempt_source = abrt_t # Conditional access (allow_raw_memory_access) + blkmapd_t + bootloader_t # Install bootloader, raw disk access + cdrecord_t # Burn optical media + container_t # Conditional access (container_use_host_all_caps) + cpucontrol_t + cupsd_t + devicekit_disk_t + disk_munin_plugin_t + dmidecode_t + fsadm_t + fsdaemon_t + hddtemp_t + hwclock_t + init_t + initrc_t + kernel_t # Kernel threads have all caps + kdump_t + klogd_t # Conditional access (allow_raw_memory_access) + lvm_t + mcelog_t # Conditional access (allow_raw_memory_access) + mount_t + munin_t + nagios_checkdisk_plugin_t + rasdaemon_t # Monitors ECC errors + resmgrd_t # Device resource manager + rpm_script_t # Package manager post-install scripts + smbmount_t + sosreport_t # Conditional access (allow_raw_memory_access) + spc_t + sysadm_t # System admin role + udev_t + vbetool_t # Conditional access (allow_raw_memory_access) + vmware_t + xdm_t + xserver_t + zfs_t + +[PRIVILEGE-CAP_NET_ADMIN] +check_type = assert_te +desc = Verify only expected domains can use CAP_NET_ADMIN. +tclass = capability +perms = net_admin +exempt_source = arpwatch_t + asterisk_t + avahi_t + bird_t + blueman_t + bluetooth_t + brctl_t + cgred_t + chronyd_t # Conditional access (chronyd_hwtimestamp) + condor_startd_t + container_engine_t + container_t # Conditional access (container_use_host_all_caps) + crio_t + ctdbd_t + devicekit_disk_t + devicekit_power_t + dhcpc_t + dnsmasq_t + dockerd_t + dockerd_user_t + dpkg_script_t + drbd_t + fcoemon_t + firewalld_t + hostapd_t + hypervkvpd_t + hypervvssd_t + ifconfig_t + ifplugd_t + init_t + initrc_t + iodined_t + ipsec_t + ipsec_mgmt_t + ipsec_supervisor_t + iptables_t + iscsid_t + kernel_t + kismet_t + krb5kdc_t + kubeadm_t + kubelet_t + l2tpd_t + lldpad_t + lvm_t + minissdpd_t + modemmanager_t + ncftool_t + ndc_t + netlabel_mgmt_t + netutils_t + NetworkManager_t + nsd_t + ntop_t + openvpn_t + openvswitch_t + pegasus_t + podman_t + podman_user_t + portslave_t + pppd_t + pptp_t + psad_t + racoon_t + radvd_t + rkhunter_t + rootlesskit_t + rpm_script_t + setkey_t + shorewall_t + snmpd_t + snort_t + sosreport_t + spc_t + squid_t # Conditional access (squid_use_tproxy) + sssd_t + sysadm_t + syslogd_t # Conditional network config (logging_syslog_can_network) + system_cronjob_t + system_munin_plugin_t + systemd_cgroups_t + systemd_networkd_t + systemd_nspawn_t + systemd_sysctl_t + systemd_tmpfiles_t + traceroute_t + udev_t + ulogd_t + virt_bridgehelper_t + virtd_t + virtd_lxc_t + vpnc_t + watchdog_t + wireguard_t + wireshark_t + xm_t + zebra_t + +[PRIVILEGE-setcurrent] +check_type = assert_te +desc = Verify only the expected domains can change their process label. +tclass = process +perms = setcurrent +exempt_source = chromium_t # Changes MCS level for each tab + kernel_t # When systemd loads the policy it has the kernel_t label and changes context to init_t + sepgsql_ranged_proc_t # Changes MCS level + +[NONTRANQUILITY-systemd] +check_type = assert_te +desc = Verify dynamic transition allowed by PRIVILEGE-setcurrent test can only + go from kernel_t to init_t (systemd) +source = kernel_t +tclass = process +perms = dyntransition +# kernel_t -> kernel_t and kernel_t -> init_t +exempt_target = init_t kernel_t + +[INTEGRITY-readonly-executables] +check_type = ro_execs +# +# This is an expensive check, but this security goal is important to verify. +# To tighten your policy, first try to remove entries from exempt_file, as it +# is very broad in terms of this check, as the type is simply ignored both for +# write checks and for execute checks. +# +# Next, try to remove entries from exempt_write_domain. These are domains that +# are accepted as able to write executables. +# +# If you don't have unconfined domains, you should remove the +# exempt_exec_domain option. The only purpose for this option is because all +# file types would be considered executable otherwise. +# +# When you have a failure on this test, first verify that the file type is +# supposed to be executable; if not, remove the exec access. If it is supposed +# to be executable, verify domains that have write access are legitimate +# writers. If the access is legitimate, e.g. by a package manager, add the +# domain to exempt_write_domain. If not, remove the write access. +# +desc = Enforce executable files (including libraries) are not writable + except from expected domains, such as package managers. +exempt_file = container_file_t # Container files don't distinguish executables. + container_ro_file_t # Container files don't distinguish executables. + gstreamer_orcexec_t # OIL Runtime Compiler code optimizer is used by pulseaudio + httpd_script_exec_type # Web admin can edit scripts + httpdcontent # Web admin can edit scripts, webalizer output, etc. + noxattrfs # Filesystem does not support xattrs; executable by users, can't distinguish executables + user_home_content_type # User home content, users can install apps in own home, write scripts, etc. JIT compiles, and libFFI use. +exempt_write_domain = cloud_init_t # Can conditionally manage all non-auth files (cloudinit_manage_non_security) + dpkg_t # Package manager + dpkg_script_t # Package manager + gcc_config_t # Gentoo compiler chooser + init_t # Systemd can create file mountpoints + ftpd_t # Can conditionally manage all non-auth files (allow_ftpd_full_access) + kernel_t # Can conditionally manage all non-auth files (nfs_export_all_rw) + nfsd_t # Can conditionally manage all non-auth files (nfs_export_all_rw) + nmbd_t # Can conditionally manage all non-auth files (samba_export_all_rw) + prelink_t # Prelinking executables + portage_t # Package manager + puppet_t # Can conditionally manage all non-auth files (puppet_manage_all_files) + rpm_t # Package manager + rpm_script_t # Package manager + sftpd_t # Can conditionally manage all non-auth files (sftpd_full_access) + smbd_t # Can conditionally manage all non-auth files (samba_export_all_rw) + systemd_tmpfiles_t # Can conditionally manage all non-auth files (systemd_tmpfiles_manage_all) + sysadm_t # Privileged admin domain + files_unconfined_type +# files_unconfined_type: Unconfined; can execute anything; muddies the water on what is +# intended to be executable by constrained domains. +exempt_exec_domain = files_unconfined_type