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 # @SUPPORTED_EAPIS: 5 6
11 # @BLURB: This eclass supports the deployment of the various SELinux modules in sec-policy
13 # The selinux-policy-2.eclass supports deployment of the various SELinux modules
14 # defined in the sec-policy category. It is responsible for extracting the
15 # specific bits necessary for single-module deployment (instead of full-blown
16 # policy rebuilds) and applying the necessary patches.
18 # Also, it supports for bundling patches to make the whole thing just a bit more
21 # @ECLASS-VARIABLE: MODS
23 # This variable contains the (upstream) module name for the SELinux module.
24 # This name is only the module name, not the category!
27 # @ECLASS-VARIABLE: BASEPOL
29 # This variable contains the version string of the selinux-base-policy package
30 # that this module build depends on. It is used to patch with the appropriate
31 # patch bundle(s) that are part of selinux-base-policy.
34 # @ECLASS-VARIABLE: POLICY_PATCH
36 # This variable contains the additional patch(es) that need to be applied on top
37 # of the patchset already contained within the BASEPOL variable. The variable
38 # can be both a simple string (space-separated) or a bash array.
41 # @ECLASS-VARIABLE: POLICY_FILES
43 # When defined, this contains the files (located in the ebuilds' files/
44 # directory) which should be copied as policy module files into the store.
45 # Generally, users would want to include at least a .te and .fc file, but .if
46 # files are supported as well. The variable can be both a simple string
47 # (space-separated) or a bash array.
50 # @ECLASS-VARIABLE: POLICY_TYPES
52 # This variable informs the eclass for which SELinux policies the module should
53 # be built. Currently, Gentoo supports targeted, strict, mcs and mls.
54 # This variable is the same POLICY_TYPES variable that we tell SELinux
55 # users to set in make.conf. Therefore, it is not the module that should
56 # override it, but the user.
57 : ${POLICY_TYPES:="targeted strict mcs mls"}
59 # @ECLASS-VARIABLE: SELINUX_GIT_REPO
61 # When defined, this variable overrides the default repository URL as used by
62 # this eclass. It allows end users to point to a different policy repository
63 # using a single variable, rather than having to set the packagename_LIVE_REPO
64 # variable for each and every SELinux policy module package they want to install.
65 # The default value is Gentoo's hardened-refpolicy repository.
66 : ${SELINUX_GIT_REPO:="https://anongit.gentoo.org/git/proj/hardened-refpolicy.git"};
68 # @ECLASS-VARIABLE: SELINUX_GIT_BRANCH
70 # When defined, this variable sets the Git branch to use of the repository. This
71 # allows for users and developers to use a different branch for the entire set of
72 # SELinux policy packages, rather than having to override them one by one with the
73 # packagename_LIVE_BRANCH variable.
74 # The default value is the 'master' branch.
75 : ${SELINUX_GIT_BRANCH:="master"};
78 0|1|2|3|4) die "EAPI<5 is not supported";;
80 *) die "unknown EAPI" ;;
85 EGIT_REPO_URI="${SELINUX_GIT_REPO}";
86 EGIT_BRANCH="${SELINUX_GIT_BRANCH}";
87 EGIT_CHECKOUT_DIR="${WORKDIR}/refpolicy";;
90 if [[ ${EAPI:-0} == 5 ]]; then
96 HOMEPAGE="https://wiki.gentoo.org/wiki/Project:SELinux"
97 if [[ -n ${BASEPOL} ]] && [[ "${BASEPOL}" != "9999" ]]; then
98 SRC_URI="https://github.com/SELinuxProject/refpolicy/releases/download/RELEASE_${PV/./_}/refpolicy-${PV}.tar.bz2
99 https://dev.gentoo.org/~perfinion/patches/selinux-base-policy/patchbundle-selinux-base-policy-${BASEPOL}.tar.bz2"
100 elif [[ "${BASEPOL}" != "9999" ]]; then
101 SRC_URI="https://github.com/SELinuxProject/refpolicy/releases/download/RELEASE_${PV/./_}/refpolicy-${PV}.tar.bz2"
109 PATCHBUNDLE="${DISTDIR}/patchbundle-selinux-base-policy-${BASEPOL}.tar.bz2"
111 # Modules should always depend on at least the first release of the
112 # selinux-base-policy for which they are generated.
113 if [[ -n ${BASEPOL} ]]; then
114 RDEPEND=">=sys-apps/policycoreutils-2.0.82
115 >=sec-policy/selinux-base-policy-${BASEPOL}"
117 RDEPEND=">=sys-apps/policycoreutils-2.0.82
118 >=sec-policy/selinux-base-policy-${PV}"
122 >=sys-apps/checkpolicy-2.0.21"
124 EXPORT_FUNCTIONS src_unpack src_prepare src_compile src_install pkg_postinst pkg_postrm
126 # @FUNCTION: selinux-policy-2_src_unpack
128 # Unpack the policy sources as offered by upstream (refpolicy).
129 selinux-policy-2_src_unpack() {
130 if [[ "${BASEPOL}" != "9999" ]]; then
137 # @FUNCTION: selinux-policy-2_src_prepare
139 # Patch the reference policy sources with our set of enhancements. Start with
140 # the base patchbundle referred to by the ebuilds through the BASEPOL variable,
141 # then apply the additional patches as offered by the ebuild.
143 # Next, extract only those files needed for this particular module (i.e. the .te
144 # and .fc files for the given module in the MODS variable).
146 # Finally, prepare the build environments for each of the supported SELinux
147 # types (such as targeted or strict), depending on the POLICY_TYPES variable
149 selinux-policy-2_src_prepare() {
151 local add_interfaces=0;
153 # Create 3rd_party location for user-contributed policies
154 cd "${S}/refpolicy/policy/modules" && mkdir 3rd_party;
156 # Patch the sources with the base patchbundle
157 if [[ -n ${BASEPOL} ]] && [[ "${BASEPOL}" != "9999" ]]; then
159 if [[ ${EAPI:-0} == 5 ]]; then
160 EPATCH_MULTI_MSG="Applying SELinux policy updates ... " \
161 EPATCH_SUFFIX="patch" \
162 EPATCH_SOURCE="${WORKDIR}" \
166 einfo "Applying SELinux policy updates ... "
167 eapply -p0 "${WORKDIR}/0001-full-patch-against-stable-release.patch"
171 # Call in epatch_user. We do this early on as we start moving
172 # files left and right hereafter.
173 if [[ ${EAPI:-0} == 5 ]]; then
179 # Copy additional files to the 3rd_party/ location
180 if [[ "$(declare -p POLICY_FILES 2>/dev/null 2>&1)" == "declare -a"* ]] ||
181 [[ -n ${POLICY_FILES} ]]; then
183 cd "${S}/refpolicy/policy/modules"
184 for POLFILE in ${POLICY_FILES[@]};
186 cp "${FILESDIR}/${POLFILE}" 3rd_party/ || die "Could not copy ${POLFILE} to 3rd_party/ location";
190 # Apply the additional patches refered to by the module ebuild.
191 # But first some magic to differentiate between bash arrays and strings
192 if [[ "$(declare -p POLICY_PATCH 2>/dev/null 2>&1)" == "declare -a"* ]] ||
193 [[ -n ${POLICY_PATCH} ]]; then
194 cd "${S}/refpolicy/policy/modules"
195 for POLPATCH in ${POLICY_PATCH[@]};
197 if [[ ${EAPI:-0} == 5 ]]; then
205 # Collect only those files needed for this particular module
207 modfiles="$(find ${S}/refpolicy/policy/modules -iname $i.te) $modfiles"
208 modfiles="$(find ${S}/refpolicy/policy/modules -iname $i.fc) $modfiles"
209 modfiles="$(find ${S}/refpolicy/policy/modules -iname $i.cil) $modfiles"
210 if [[ ${add_interfaces} -eq 1 ]]; then
211 modfiles="$(find ${S}/refpolicy/policy/modules -iname $i.if) $modfiles"
215 for i in ${POLICY_TYPES}; do
216 mkdir "${S}"/${i} || die "Failed to create directory ${S}/${i}"
217 cp "${S}"/refpolicy/doc/Makefile.example "${S}"/${i}/Makefile \
218 || die "Failed to copy Makefile.example to ${S}/${i}/Makefile"
220 cp ${modfiles} "${S}"/${i} \
221 || die "Failed to copy the module files to ${S}/${i}"
225 # @FUNCTION: selinux-policy-2_src_compile
227 # Build the SELinux policy module (.pp file) for just the selected module, and
228 # this for each SELinux policy mentioned in POLICY_TYPES
229 selinux-policy-2_src_compile() {
231 for useflag in ${IUSE};
233 use ${useflag} && makeuse="${makeuse} -D use_${useflag}"
236 for i in ${POLICY_TYPES}; do
237 # Support USE flags in builds
238 export M4PARAM="${makeuse}"
239 emake NAME=$i SHAREDIR="${ROOT%/}"/usr/share/selinux -C "${S}"/${i} || die "${i} compile failed"
243 # @FUNCTION: selinux-policy-2_src_install
245 # Install the built .pp (or copied .cil) files in the correct subdirectory within
246 # /usr/share/selinux.
247 selinux-policy-2_src_install() {
248 local BASEDIR="/usr/share/selinux"
250 for i in ${POLICY_TYPES}; do
252 einfo "Installing ${i} ${j} policy package"
253 insinto ${BASEDIR}/${i}
254 if [[ -f "${S}/${i}/${j}.pp" ]] ; then
255 doins "${S}"/${i}/${j}.pp || die "Failed to add ${j}.pp to ${i}"
256 elif [[ -f "${S}/${i}/${j}.cil" ]] ; then
257 doins "${S}"/${i}/${j}.cil || die "Failed to add ${j}.cil to ${i}"
260 if [[ "${POLICY_FILES[@]}" == *"${j}.if"* ]]; then
261 insinto ${BASEDIR}/${i}/include/3rd_party
262 doins "${S}"/${i}/${j}.if || die "Failed to add ${j}.if to ${i}"
268 # @FUNCTION: selinux-policy-2_pkg_postinst
270 # Install the built .pp (or copied .cil) files in the SELinux policy stores, effectively
271 # activating the policy on the system.
272 selinux-policy-2_pkg_postinst() {
273 # Set root path and don't load policy into the kernel when cross compiling
275 if [[ "${ROOT%/}" != "" ]]; then
276 root_opts="-p ${ROOT%/} -n"
279 # build up the command in the case of multiple modules
282 for i in ${POLICY_TYPES}; do
283 if [[ "${i}" == "strict" ]] && [[ "${MODS}" = "unconfined" ]]; then
284 einfo "Ignoring loading of unconfined module in strict module store.";
287 einfo "Inserting the following modules into the $i module store: ${MODS}"
289 cd "${ROOT%/}/usr/share/selinux/${i}" || die "Could not enter /usr/share/selinux/${i}"
290 for j in ${MODS} ; do
291 if [[ -f "${j}.pp" ]] ; then
292 COMMAND="${j}.pp ${COMMAND}"
293 elif [[ -f "${j}.cil" ]] ; then
294 COMMAND="${j}.cil ${COMMAND}"
298 semodule ${root_opts} -s ${i} -i ${COMMAND}
299 if [[ $? -ne 0 ]]; then
300 ewarn "SELinux module load failed. Trying full reload...";
301 local COMMAND_base="-i base.pp"
302 if has_version "<sys-apps/policycoreutils-2.5"; then
303 COMMAND_base="-b base.pp"
306 if [[ "${i}" == "targeted" ]]; then
307 semodule ${root_opts} -s ${i} ${COMMAND_base} -i $(ls *.pp | grep -v base.pp);
309 semodule ${root_opts} -s ${i} ${COMMAND_base} -i $(ls *.pp | grep -v base.pp | grep -v unconfined.pp);
311 if [[ $? -ne 0 ]]; then
312 ewarn "Failed to reload SELinux policies."
314 ewarn "If this is *not* the last SELinux module package being installed,"
315 ewarn "then you can safely ignore this as the reloads will be retried"
316 ewarn "with other, recent modules."
318 ewarn "If it is the last SELinux module package being installed however,"
319 ewarn "then it is advised to look at the error above and take appropriate"
320 ewarn "action since the new SELinux policies are not loaded until the"
321 ewarn "command finished succesfully."
323 ewarn "To reload, run the following command from within /usr/share/selinux/${i}:"
324 ewarn " semodule ${COMMAND_base} -i \$(ls *.pp | grep -v base.pp)"
326 ewarn " semodule ${COMMAND_base} -i \$(ls *.pp | grep -v base.pp | grep -v unconfined.pp)"
327 ewarn "depending on if you need the unconfined domain loaded as well or not."
329 einfo "SELinux modules reloaded succesfully."
332 einfo "SELinux modules loaded succesfully."
337 # Don't relabel when cross compiling
338 if [[ "${ROOT%/}" == "" ]]; then
339 # Relabel depending packages
341 if [[ -x /usr/bin/qdepends ]] ; then
342 PKGSET=$(/usr/bin/qdepends -Cq -r -Q ${CATEGORY}/${PN} | grep -v "sec-policy/selinux-");
343 elif [[ -x /usr/bin/equery ]] ; then
344 PKGSET=$(/usr/bin/equery -Cq depends ${CATEGORY}/${PN} | grep -v "sec-policy/selinux-");
346 if [[ -n "${PKGSET}" ]] ; then
352 # @FUNCTION: selinux-policy-2_pkg_postrm
354 # Uninstall the module(s) from the SELinux policy stores, effectively
355 # deactivating the policy on the system.
356 selinux-policy-2_pkg_postrm() {
357 # Only if we are not upgrading
358 if [[ -z "${REPLACED_BY_VERSION}" ]]; then
359 # Set root path and don't load policy into the kernel when cross compiling
361 if [[ "${ROOT%/}" != "" ]]; then
362 root_opts="-p ${ROOT%/} -n"
365 # build up the command in the case of multiple modules
368 COMMAND="-r ${i} ${COMMAND}"
371 for i in ${POLICY_TYPES}; do
372 einfo "Removing the following modules from the $i module store: ${MODS}"
374 semodule ${root_opts} -s ${i} ${COMMAND}
375 if [[ $? -ne 0 ]]; then
376 ewarn "SELinux module unload failed.";
378 einfo "SELinux modules unloaded succesfully."