# Copyright 1999-2026 Gentoo Authors # Distributed under the terms of the GNU General Public License v2 EAPI=8 DESCRIPTION="SELinux policy for core modules" HOMEPAGE="https://wiki.gentoo.org/wiki/Project:SELinux" if [[ "${PV}" = 9999* ]]; then EGIT_REPO_URI="${SELINUX_GIT_REPO:-https://anongit.gentoo.org/git/proj/hardened-refpolicy.git}" EGIT_BRANCH="${SELINUX_GIT_BRANCH:-master}" EGIT_CHECKOUT_DIR="${WORKDIR}/refpolicy" inherit git-r3 else MY_PV=$(ver_cut 1-2) SRC_URI="https://github.com/SELinuxProject/refpolicy/releases/download/RELEASE_${MY_PV/./_}/refpolicy-${MY_PV}.tar.bz2 https://dev.gentoo.org/~perfinion/patches/${PN}/patchbundle-${PN}-${PV/_p/-r}.tar.bz2" KEYWORDS="amd64 arm arm64 ~riscv x86" fi S="${WORKDIR}" LICENSE="GPL-2" SLOT="0" IUSE=" systemd +unconfined +selinux_policy_types_targeted +selinux_policy_types_strict +selinux_policy_types_mcs +selinux_policy_types_mls " REQUIRED_USE=" || ( selinux_policy_types_targeted selinux_policy_types_strict selinux_policy_types_mcs selinux_policy_types_mls ) selinux_policy_types_targeted? ( unconfined ) " PDEPEND="unconfined? ( sec-policy/selinux-unconfined )" DEPEND=" =sec-policy/selinux-base-${PVR}[selinux_policy_types_targeted?,selinux_policy_types_strict?,selinux_policy_types_mcs?,selinux_policy_types_mls?,systemd?] " RDEPEND="${DEPEND}" BDEPEND=" sys-apps/checkpolicy sys-devel/m4 " MODS="application authlogin bootloader clock consoletype cron dmesg fstools getty hostname init iptables libraries locallogin logging lvm miscfiles modutils mount mta netutils nscd portage raid rsync selinuxutil setrans ssh staff storage su sysadm sysnetwork systemd tmpfiles udev userdomain usermanage unprivuser xdg" # A previous, old release of refpolicy had the hotplug policy module. However, # it has since been removed[1]. As such, remove it if we see it installed. # [1] https://github.com/gentoo/hardened-refpolicy/commit/5618680a2e148db02ae5614a13cc878f1616d8a2 DEL_MODS="hotplug" # Code entirely copied from selinux-eclass (cannot inherit due to dependency on # itself), when reworked reinclude it. Only postinstall (where -b base.pp is # added) needs to remain then. src_prepare() { local modfiles if [[ "${PV}" != 9999* ]]; then einfo "Applying SELinux policy updates ... " eapply -p0 "${WORKDIR}/0001-full-patch-against-stable-release.patch" fi eapply_user # Collect only those files needed for this particular module for mod in ${MODS}; do modfiles="$(find "${S}/refpolicy/policy/modules" -iname "${mod}.te") $modfiles" modfiles="$(find "${S}/refpolicy/policy/modules" -iname "${mod}.fc") $modfiles" modfiles="$(find "${S}/refpolicy/policy/modules" -iname "${mod}.cil") $modfiles" done # TODO: should probably be done earlier? for i in ${DEL_MODS}; do [[ "${MODS}" != *${i}* ]] || die "Duplicate module in MODS and DEL_MODS: ${i}" done for type in targeted strict mcs mls; do if use "selinux_policy_types_${type}"; then mkdir "${S}/${type}" || die "Failed to create directory ${S}/${type}" cp "${S}/refpolicy/doc/Makefile.example" "${S}/${type}/Makefile" \ || die "Failed to copy Makefile.example to ${S}/${type}/Makefile" cp ${modfiles} "${S}/${type}" \ || die "Failed to copy the module files to ${S}/${type}" fi done } src_compile() { local makeuse="" # We use IUSE instead of USE so that other variables set in the ebuild # environment, such as architecture ones, are not included. for useflag in ${IUSE}; do # Advance past a possible '+' character: that is NOT part of the USE flag, # but instead indicates whether it is enabled by default. useflag="${useflag##+}" # Only additional USE flags defined in our consumers should be added to # build options: SELINUX_POLICY_TYPES should NOT be passed to the policy # build system. [[ "${useflag}" = selinux_policy_types_* ]] && continue use ${useflag} && makeuse="${makeuse} -D use_${useflag}" done for type in targeted strict mcs mls; do if use "selinux_policy_types_${type}"; then # Support USE flags in builds export M4PARAM="${makeuse}" emake NAME="${type}" SHAREDIR="${EPREFIX}/usr/share/selinux" -C "${S}/${type}" fi done } src_install() { local BASEDIR="/usr/share/selinux" for type in targeted strict mcs mls; do if use "selinux_policy_types_${type}"; then for mod in ${MODS}; do einfo "Installing ${type} ${mod} policy package" insinto "${BASEDIR}/${type}" if [[ -f "${S}/${type}/${mod}.pp" ]]; then doins "${S}/${type}/${mod}.pp" elif [[ -f "${S}/${type}/${mod}.cil" ]]; then doins "${S}/${type}/${mod}.cil" fi done fi done } pkg_postinst() { # Set root path and don't load policy into the kernel when cross compiling local root_opts="" if [[ -n ${ROOT} ]]; then root_opts="-p ${ROOT} -n" fi # Override the command from the eclass, we need to load in base as well here local COMMAND="-i base.pp" for type in targeted strict mcs mls; do if use "selinux_policy_types_${type}"; then einfo "Inserting the following modules, with base, into the ${type} module store: ${MODS}" cd "${ROOT}/usr/share/selinux/${type}" || die "Could not enter /usr/share/selinux/${type}" for mod in ${MODS}; do if [[ -f "${mod}.pp" ]]; then COMMAND="${mod}.pp ${COMMAND}" elif [[ -f "${mod}.cil" ]]; then COMMAND="${mod}.cil ${COMMAND}" fi done semodule ${root_opts} -s ${type} -i ${COMMAND} if [[ $? -ne 0 ]]; then ewarn "SELinux module load failed. Trying full reload..." semodule ${root_opts} -s ${type} -i ./*.pp if [[ $? -ne 0 ]]; then ewarn "Failed to reload SELinux policies." ewarn "" ewarn "If this is *not* the last SELinux module package being installed," ewarn "then you can safely ignore this as the reloads will be retried" ewarn "with other, recent modules." ewarn "" ewarn "If it is the last SELinux module package being installed however," ewarn "then it is advised to look at the error above and take appropriate" ewarn "action since the new SELinux policies are not loaded until the" ewarn "command finished successfully." ewarn "" ewarn "To reload, run the following command:" ewarn " semodule -i /usr/share/selinux/${type}/*.pp" else einfo "SELinux modules reloaded successfully." fi else einfo "SELinux modules loaded successfully." fi # And now, remove any old modules that should no longer be installed. for mod in ${DEL_MODS}; do if semodule ${root_opts} -s "${type}" -l | grep -q "\b${mod}\b"; then einfo "Removing obsolete ${type} ${mod} policy package" semodule ${root_opts} -s "${type}" -r "${mod}" if [[ $? -ne 0 ]]; then ewarn "Failed to remove obsolete ${type} ${mod} policy package" fi fi done COMMAND="" fi done # Don't relabel when cross compiling if [[ -z ${ROOT} ]]; then # Relabel depending packages. This entire section is a hack, and a violation of tree policy; # it relies on PM specific functionality (qdepends and equery, which are portage specific) and # hence is not PMS compliant. This should be remove and replaced with a more robust, PMS-compliant # implementation as soon as possible. local PKGSET=() local out local status local cmd if command -v qdepends &>/dev/null; then out=$(qdepends -CiqqrF '%[CATEGORY]%[PN]%[SLOT]' -Q "${CATEGORY}/${PN}") status=$? cmd='qdepends' elif command -v equery &>/dev/null; then out=$(equery -Cq depends "${CATEGORY}/${PN}") status=$? cmd='equery' else ewarn "Unable to calculate reverse dependencies for policy: both qdepends and equery were not found." ewarn "Skipping package file relabelling..." return fi if [[ "${status}" -ne 0 ]]; then ewarn "Failed to calculate reverse dependencies for policy: ${cmd} returned ${status}." ewarn "Skipping package file relabelling..." return fi # Policy packages may pull in other policy packages, filter those out. readarray -t PKGSET <<<"$(echo "${out}" | grep -v 'sec-policy/selinux-')" [[ "${#PKGSET[@]}" -ne 0 ]] && rlpkg "${PKGSET[@]}" fi }