1 # Copyright 1999-2015 Gentoo Foundation
2 # Distributed under the terms of the GNU General Public License v2
4 # Eclass for installing SELinux policy, and optionally
5 # reloading the reference-policy based modules.
7 # @ECLASS: selinux-policy-2.eclass
10 # @BLURB: This eclass supports the deployment of the various SELinux modules in sec-policy
12 # The selinux-policy-2.eclass supports deployment of the various SELinux modules
13 # defined in the sec-policy category. It is responsible for extracting the
14 # specific bits necessary for single-module deployment (instead of full-blown
15 # policy rebuilds) and applying the necessary patches.
17 # Also, it supports for bundling patches to make the whole thing just a bit more
20 # @ECLASS-VARIABLE: MODS
22 # This variable contains the (upstream) module name for the SELinux module.
23 # This name is only the module name, not the category!
26 # @ECLASS-VARIABLE: BASEPOL
28 # This variable contains the version string of the selinux-base-policy package
29 # that this module build depends on. It is used to patch with the appropriate
30 # patch bundle(s) that are part of selinux-base-policy.
33 # @ECLASS-VARIABLE: POLICY_PATCH
35 # This variable contains the additional patch(es) that need to be applied on top
36 # of the patchset already contained within the BASEPOL variable. The variable
37 # can be both a simple string (space-separated) or a bash array.
40 # @ECLASS-VARIABLE: POLICY_FILES
42 # When defined, this contains the files (located in the ebuilds' files/
43 # directory) which should be copied as policy module files into the store.
44 # Generally, users would want to include at least a .te and .fc file, but .if
45 # files are supported as well. The variable can be both a simple string
46 # (space-separated) or a bash array.
49 # @ECLASS-VARIABLE: POLICY_TYPES
51 # This variable informs the eclass for which SELinux policies the module should
52 # be built. Currently, Gentoo supports targeted, strict, mcs and mls.
53 # This variable is the same POLICY_TYPES variable that we tell SELinux
54 # users to set in make.conf. Therefore, it is not the module that should
55 # override it, but the user.
56 : ${POLICY_TYPES:="targeted strict mcs mls"}
58 # @ECLASS-VARIABLE: SELINUX_GIT_REPO
60 # When defined, this variable overrides the default repository URL as used by
61 # this eclass. It allows end users to point to a different policy repository
62 # using a single variable, rather than having to set the packagename_LIVE_REPO
63 # variable for each and every SELinux policy module package they want to install.
64 # The default value is Gentoo's hardened-refpolicy repository.
65 : ${SELINUX_GIT_REPO:="https://anongit.gentoo.org/git/proj/hardened-refpolicy.git"};
67 # @ECLASS-VARIABLE: SELINUX_GIT_BRANCH
69 # When defined, this variable sets the Git branch to use of the repository. This
70 # allows for users and developers to use a different branch for the entire set of
71 # SELinux policy packages, rather than having to override them one by one with the
72 # packagename_LIVE_BRANCH variable.
73 # The default value is the 'master' branch.
74 : ${SELINUX_GIT_BRANCH:="master"};
77 0|1|2|3|4) die "EAPI<5 is not supported";;
79 *) die "unknown EAPI" ;;
84 EGIT_REPO_URI="${SELINUX_GIT_REPO}";
85 EGIT_BRANCH="${SELINUX_GIT_BRANCH}";
86 EGIT_CHECKOUT_DIR="${WORKDIR}/refpolicy";;
89 if [[ ${EAPI:-0} == 5 ]]; then
95 HOMEPAGE="https://wiki.gentoo.org/wiki/Project:SELinux"
96 if [[ -n ${BASEPOL} ]] && [[ "${BASEPOL}" != "9999" ]]; then
97 SRC_URI="https://github.com/SELinuxProject/refpolicy/releases/download/RELEASE_${PV/./_}/refpolicy-${PV}.tar.bz2
98 https://dev.gentoo.org/~swift/patches/selinux-base-policy/patchbundle-selinux-base-policy-${BASEPOL}.tar.bz2"
99 elif [[ "${BASEPOL}" != "9999" ]]; then
100 SRC_URI="https://github.com/SELinuxProject/refpolicy/releases/download/RELEASE_${PV/./_}/refpolicy-${PV}.tar.bz2"
108 PATCHBUNDLE="${DISTDIR}/patchbundle-selinux-base-policy-${BASEPOL}.tar.bz2"
110 # Modules should always depend on at least the first release of the
111 # selinux-base-policy for which they are generated.
112 if [[ -n ${BASEPOL} ]]; then
113 RDEPEND=">=sys-apps/policycoreutils-2.0.82
114 >=sec-policy/selinux-base-policy-${BASEPOL}"
116 RDEPEND=">=sys-apps/policycoreutils-2.0.82
117 >=sec-policy/selinux-base-policy-${PV}"
121 >=sys-apps/checkpolicy-2.0.21"
123 EXPORT_FUNCTIONS src_unpack src_prepare src_compile src_install pkg_postinst pkg_postrm
125 # @FUNCTION: selinux-policy-2_src_unpack
127 # Unpack the policy sources as offered by upstream (refpolicy).
128 selinux-policy-2_src_unpack() {
129 if [[ "${BASEPOL}" != "9999" ]]; then
136 # @FUNCTION: selinux-policy-2_src_prepare
138 # Patch the reference policy sources with our set of enhancements. Start with
139 # the base patchbundle referred to by the ebuilds through the BASEPOL variable,
140 # then apply the additional patches as offered by the ebuild.
142 # Next, extract only those files needed for this particular module (i.e. the .te
143 # and .fc files for the given module in the MODS variable).
145 # Finally, prepare the build environments for each of the supported SELinux
146 # types (such as targeted or strict), depending on the POLICY_TYPES variable
148 selinux-policy-2_src_prepare() {
150 local add_interfaces=0;
152 # Create 3rd_party location for user-contributed policies
153 cd "${S}/refpolicy/policy/modules" && mkdir 3rd_party;
155 # Patch the sources with the base patchbundle
156 if [[ -n ${BASEPOL} ]] && [[ "${BASEPOL}" != "9999" ]]; then
158 if [[ ${EAPI:-0} == 5 ]]; then
159 EPATCH_MULTI_MSG="Applying SELinux policy updates ... " \
160 EPATCH_SUFFIX="patch" \
161 EPATCH_SOURCE="${WORKDIR}" \
165 einfo "Applying SELinux policy updates ... "
166 eapply -p0 "${WORKDIR}/0001-full-patch-against-stable-release.patch"
170 # Call in epatch_user. We do this early on as we start moving
171 # files left and right hereafter.
172 if [[ ${EAPI:-0} == 5 ]]; then
178 # Copy additional files to the 3rd_party/ location
179 if [[ "$(declare -p POLICY_FILES 2>/dev/null 2>&1)" == "declare -a"* ]] ||
180 [[ -n ${POLICY_FILES} ]]; then
182 cd "${S}/refpolicy/policy/modules"
183 for POLFILE in ${POLICY_FILES[@]};
185 cp "${FILESDIR}/${POLFILE}" 3rd_party/ || die "Could not copy ${POLFILE} to 3rd_party/ location";
189 # Apply the additional patches refered to by the module ebuild.
190 # But first some magic to differentiate between bash arrays and strings
191 if [[ "$(declare -p POLICY_PATCH 2>/dev/null 2>&1)" == "declare -a"* ]] ||
192 [[ -n ${POLICY_PATCH} ]]; then
193 cd "${S}/refpolicy/policy/modules"
194 for POLPATCH in ${POLICY_PATCH[@]};
196 if [[ ${EAPI:-0} == 5 ]]; then
204 # Collect only those files needed for this particular module
206 modfiles="$(find ${S}/refpolicy/policy/modules -iname $i.te) $modfiles"
207 modfiles="$(find ${S}/refpolicy/policy/modules -iname $i.fc) $modfiles"
208 modfiles="$(find ${S}/refpolicy/policy/modules -iname $i.cil) $modfiles"
209 if [[ ${add_interfaces} -eq 1 ]]; then
210 modfiles="$(find ${S}/refpolicy/policy/modules -iname $i.if) $modfiles"
214 for i in ${POLICY_TYPES}; do
215 mkdir "${S}"/${i} || die "Failed to create directory ${S}/${i}"
216 cp "${S}"/refpolicy/doc/Makefile.example "${S}"/${i}/Makefile \
217 || die "Failed to copy Makefile.example to ${S}/${i}/Makefile"
219 cp ${modfiles} "${S}"/${i} \
220 || die "Failed to copy the module files to ${S}/${i}"
224 # @FUNCTION: selinux-policy-2_src_compile
226 # Build the SELinux policy module (.pp file) for just the selected module, and
227 # this for each SELinux policy mentioned in POLICY_TYPES
228 selinux-policy-2_src_compile() {
230 for useflag in ${IUSE};
232 use ${useflag} && makeuse="${makeuse} -D use_${useflag}"
235 for i in ${POLICY_TYPES}; do
236 # Support USE flags in builds
237 export M4PARAM="${makeuse}"
238 emake NAME=$i SHAREDIR="${ROOT%/}"/usr/share/selinux -C "${S}"/${i} || die "${i} compile failed"
242 # @FUNCTION: selinux-policy-2_src_install
244 # Install the built .pp (or copied .cil) files in the correct subdirectory within
245 # /usr/share/selinux.
246 selinux-policy-2_src_install() {
247 local BASEDIR="/usr/share/selinux"
249 for i in ${POLICY_TYPES}; do
251 einfo "Installing ${i} ${j} policy package"
252 insinto ${BASEDIR}/${i}
253 if [[ -f "${S}/${i}/${j}.pp" ]] ; then
254 doins "${S}"/${i}/${j}.pp || die "Failed to add ${j}.pp to ${i}"
255 elif [[ -f "${S}/${i}/${j}.cil" ]] ; then
256 doins "${S}"/${i}/${j}.cil || die "Failed to add ${j}.cil to ${i}"
259 if [[ "${POLICY_FILES[@]}" == *"${j}.if"* ]]; then
260 insinto ${BASEDIR}/${i}/include/3rd_party
261 doins "${S}"/${i}/${j}.if || die "Failed to add ${j}.if to ${i}"
267 # @FUNCTION: selinux-policy-2_pkg_postinst
269 # Install the built .pp (or copied .cil) files in the SELinux policy stores, effectively
270 # activating the policy on the system.
271 selinux-policy-2_pkg_postinst() {
272 # Set root path and don't load policy into the kernel when cross compiling
274 if [[ "${ROOT%/}" != "" ]]; then
275 root_opts="-p ${ROOT%/} -n"
278 # build up the command in the case of multiple modules
281 for i in ${POLICY_TYPES}; do
282 if [[ "${i}" == "strict" ]] && [[ "${MODS}" = "unconfined" ]]; then
283 einfo "Ignoring loading of unconfined module in strict module store.";
286 einfo "Inserting the following modules into the $i module store: ${MODS}"
288 cd "${ROOT%/}/usr/share/selinux/${i}" || die "Could not enter /usr/share/selinux/${i}"
289 for j in ${MODS} ; do
290 if [[ -f "${j}.pp" ]] ; then
291 COMMAND="${j}.pp ${COMMAND}"
292 elif [[ -f "${j}.cil" ]] ; then
293 COMMAND="${j}.cil ${COMMAND}"
297 semodule ${root_opts} -s ${i} -i ${COMMAND}
298 if [[ $? -ne 0 ]]; then
299 ewarn "SELinux module load failed. Trying full reload...";
300 local COMMAND_base="-i base.pp"
301 if has_version "<sys-apps/policycoreutils-2.5"; then
302 COMMAND_base="-b base.pp"
305 if [[ "${i}" == "targeted" ]]; then
306 semodule ${root_opts} -s ${i} ${COMMAND_base} -i $(ls *.pp | grep -v base.pp);
308 semodule ${root_opts} -s ${i} ${COMMAND_base} -i $(ls *.pp | grep -v base.pp | grep -v unconfined.pp);
310 if [[ $? -ne 0 ]]; then
311 ewarn "Failed to reload SELinux policies."
313 ewarn "If this is *not* the last SELinux module package being installed,"
314 ewarn "then you can safely ignore this as the reloads will be retried"
315 ewarn "with other, recent modules."
317 ewarn "If it is the last SELinux module package being installed however,"
318 ewarn "then it is advised to look at the error above and take appropriate"
319 ewarn "action since the new SELinux policies are not loaded until the"
320 ewarn "command finished succesfully."
322 ewarn "To reload, run the following command from within /usr/share/selinux/${i}:"
323 ewarn " semodule ${COMMAND_base} -i \$(ls *.pp | grep -v base.pp)"
325 ewarn " semodule ${COMMAND_base} -i \$(ls *.pp | grep -v base.pp | grep -v unconfined.pp)"
326 ewarn "depending on if you need the unconfined domain loaded as well or not."
328 einfo "SELinux modules reloaded succesfully."
331 einfo "SELinux modules loaded succesfully."
336 # Don't relabel when cross compiling
337 if [[ "${ROOT%/}" == "" ]]; then
338 # Relabel depending packages
340 if [[ -x /usr/bin/qdepends ]] ; then
341 PKGSET=$(/usr/bin/qdepends -Cq -r -Q ${CATEGORY}/${PN} | grep -v "sec-policy/selinux-");
342 elif [[ -x /usr/bin/equery ]] ; then
343 PKGSET=$(/usr/bin/equery -Cq depends ${CATEGORY}/${PN} | grep -v "sec-policy/selinux-");
345 if [[ -n "${PKGSET}" ]] ; then
351 # @FUNCTION: selinux-policy-2_pkg_postrm
353 # Uninstall the module(s) from the SELinux policy stores, effectively
354 # deactivating the policy on the system.
355 selinux-policy-2_pkg_postrm() {
356 # Only if we are not upgrading
357 if [[ -z "${REPLACED_BY_VERSION}" ]]; then
358 # Set root path and don't load policy into the kernel when cross compiling
360 if [[ "${ROOT%/}" != "" ]]; then
361 root_opts="-p ${ROOT%/} -n"
364 # build up the command in the case of multiple modules
367 COMMAND="-r ${i} ${COMMAND}"
370 for i in ${POLICY_TYPES}; do
371 einfo "Removing the following modules from the $i module store: ${MODS}"
373 semodule ${root_opts} -s ${i} ${COMMAND}
374 if [[ $? -ne 0 ]]; then
375 ewarn "SELinux module unload failed.";
377 einfo "SELinux modules unloaded succesfully."