dev-qt/qtx11extras: stable 5.14.2 for ppc, bug #719732
[gentoo.git] / eclass / selinux-policy-2.eclass
1 # Copyright 1999-2015 Gentoo Foundation
2 # Distributed under the terms of the GNU General Public License v2
3
4 # Eclass for installing SELinux policy, and optionally
5 # reloading the reference-policy based modules.
6
7 # @ECLASS: selinux-policy-2.eclass
8 # @MAINTAINER:
9 # selinux@gentoo.org
10 # @SUPPORTED_EAPIS: 5 6
11 # @BLURB: This eclass supports the deployment of the various SELinux modules in sec-policy
12 # @DESCRIPTION:
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.
17 #
18 # Also, it supports for bundling patches to make the whole thing just a bit more
19 # manageable.
20
21 # @ECLASS-VARIABLE: MODS
22 # @DESCRIPTION:
23 # This variable contains the (upstream) module name for the SELinux module.
24 # This name is only the module name, not the category!
25 : ${MODS:="_illegal"}
26
27 # @ECLASS-VARIABLE: BASEPOL
28 # @DESCRIPTION:
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.
32 : ${BASEPOL:=${PVR}}
33
34 # @ECLASS-VARIABLE: POLICY_PATCH
35 # @DESCRIPTION:
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.
39 : ${POLICY_PATCH:=""}
40
41 # @ECLASS-VARIABLE: POLICY_FILES
42 # @DESCRIPTION:
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.
48 : ${POLICY_FILES:=""}
49
50 # @ECLASS-VARIABLE: POLICY_TYPES
51 # @DESCRIPTION:
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"}
58
59 # @ECLASS-VARIABLE: SELINUX_GIT_REPO
60 # @DESCRIPTION:
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"};
67
68 # @ECLASS-VARIABLE: SELINUX_GIT_BRANCH
69 # @DESCRIPTION:
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"};
76
77 case "${EAPI:-0}" in
78         0|1|2|3|4) die "EAPI<5 is not supported";;
79         5|6) : ;;
80         *) die "unknown EAPI" ;;
81 esac
82
83 case ${BASEPOL} in
84         9999)   inherit git-r3
85                         EGIT_REPO_URI="${SELINUX_GIT_REPO}";
86                         EGIT_BRANCH="${SELINUX_GIT_BRANCH}";
87                         EGIT_CHECKOUT_DIR="${WORKDIR}/refpolicy";;
88 esac
89
90 if [[ ${EAPI:-0} == 5 ]]; then
91         inherit eutils
92 fi
93
94 IUSE=""
95
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"
102 else
103         SRC_URI=""
104 fi
105
106 LICENSE="GPL-2"
107 SLOT="0"
108 S="${WORKDIR}/"
109 PATCHBUNDLE="${DISTDIR}/patchbundle-selinux-base-policy-${BASEPOL}.tar.bz2"
110
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}"
116 else
117         RDEPEND=">=sys-apps/policycoreutils-2.0.82
118                 >=sec-policy/selinux-base-policy-${PV}"
119 fi
120 DEPEND="${RDEPEND}
121         sys-devel/m4
122         >=sys-apps/checkpolicy-2.0.21"
123
124 EXPORT_FUNCTIONS src_unpack src_prepare src_compile src_install pkg_postinst pkg_postrm
125
126 # @FUNCTION: selinux-policy-2_src_unpack
127 # @DESCRIPTION:
128 # Unpack the policy sources as offered by upstream (refpolicy).
129 selinux-policy-2_src_unpack() {
130         if [[ "${BASEPOL}" != "9999" ]]; then
131                 unpack ${A}
132         else
133                 git-r3_src_unpack
134         fi
135 }
136
137 # @FUNCTION: selinux-policy-2_src_prepare
138 # @DESCRIPTION:
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.
142 #
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).
145 #
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
148 # content.
149 selinux-policy-2_src_prepare() {
150         local modfiles
151         local add_interfaces=0;
152
153         # Create 3rd_party location for user-contributed policies
154         cd "${S}/refpolicy/policy/modules" && mkdir 3rd_party;
155
156         # Patch the sources with the base patchbundle
157         if [[ -n ${BASEPOL} ]] && [[ "${BASEPOL}" != "9999" ]]; then
158                 cd "${S}"
159                 if [[ ${EAPI:-0} == 5 ]]; then
160                         EPATCH_MULTI_MSG="Applying SELinux policy updates ... " \
161                         EPATCH_SUFFIX="patch" \
162                         EPATCH_SOURCE="${WORKDIR}" \
163                         EPATCH_FORCE="yes" \
164                         epatch
165                 else
166                         einfo "Applying SELinux policy updates ... "
167                         eapply -p0 "${WORKDIR}/0001-full-patch-against-stable-release.patch"
168                 fi
169         fi
170
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
174                 epatch_user
175         else
176                 eapply_user
177         fi
178
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
182             add_interfaces=1;
183                 cd "${S}/refpolicy/policy/modules"
184                 for POLFILE in ${POLICY_FILES[@]};
185                 do
186                         cp "${FILESDIR}/${POLFILE}" 3rd_party/ || die "Could not copy ${POLFILE} to 3rd_party/ location";
187                 done
188         fi
189
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[@]};
196                 do
197                         if [[ ${EAPI:-0} == 5 ]]; then
198                                 epatch "${POLPATCH}"
199                         else
200                                 eapply "${POLPATCH}"
201                         fi
202                 done
203         fi
204
205         # Collect only those files needed for this particular module
206         for i in ${MODS}; do
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"
212                 fi
213         done
214
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"
219
220                 cp ${modfiles} "${S}"/${i} \
221                         || die "Failed to copy the module files to ${S}/${i}"
222         done
223 }
224
225 # @FUNCTION: selinux-policy-2_src_compile
226 # @DESCRIPTION:
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() {
230         local makeuse=""
231         for useflag in ${IUSE};
232         do
233                 use ${useflag} && makeuse="${makeuse} -D use_${useflag}"
234         done
235
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"
240         done
241 }
242
243 # @FUNCTION: selinux-policy-2_src_install
244 # @DESCRIPTION:
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"
249
250         for i in ${POLICY_TYPES}; do
251                 for j in ${MODS}; 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}"
258                         fi
259
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}"
263                         fi
264                 done
265         done
266 }
267
268 # @FUNCTION: selinux-policy-2_pkg_postinst
269 # @DESCRIPTION:
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
274         local root_opts=""
275         if [[ "${ROOT%/}" != "" ]]; then
276                 root_opts="-p ${ROOT%/} -n"
277         fi
278
279         # build up the command in the case of multiple modules
280         local COMMAND
281
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.";
285                         continue;
286                 fi
287                 einfo "Inserting the following modules into the $i module store: ${MODS}"
288
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}"
295                         fi
296                 done
297
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"
304                         fi
305
306                         if [[ "${i}" == "targeted" ]]; then
307                                 semodule ${root_opts} -s ${i} ${COMMAND_base} -i $(ls *.pp | grep -v base.pp);
308                         else
309                                 semodule ${root_opts} -s ${i} ${COMMAND_base} -i $(ls *.pp | grep -v base.pp | grep -v unconfined.pp);
310                         fi
311                         if [[ $? -ne 0 ]]; then
312                                 ewarn "Failed to reload SELinux policies."
313                                 ewarn ""
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."
317                                 ewarn ""
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."
322                                 ewarn ""
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)"
325                                 ewarn "or"
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."
328                         else
329                                 einfo "SELinux modules reloaded succesfully."
330                         fi
331                 else
332                         einfo "SELinux modules loaded succesfully."
333                 fi
334                 COMMAND="";
335         done
336
337         # Don't relabel when cross compiling
338         if [[ "${ROOT%/}" == "" ]]; then
339                 # Relabel depending packages
340                 local PKGSET="";
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-");
345                 fi
346                 if [[ -n "${PKGSET}" ]] ; then
347                         rlpkg ${PKGSET};
348                 fi
349         fi
350 }
351
352 # @FUNCTION: selinux-policy-2_pkg_postrm
353 # @DESCRIPTION:
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
360                 local root_opts=""
361                 if [[ "${ROOT%/}" != "" ]]; then
362                         root_opts="-p ${ROOT%/} -n"
363                 fi
364
365                 # build up the command in the case of multiple modules
366                 local COMMAND
367                 for i in ${MODS}; do
368                         COMMAND="-r ${i} ${COMMAND}"
369                 done
370
371                 for i in ${POLICY_TYPES}; do
372                         einfo "Removing the following modules from the $i module store: ${MODS}"
373
374                         semodule ${root_opts} -s ${i} ${COMMAND}
375                         if [[ $? -ne 0 ]]; then
376                                 ewarn "SELinux module unload failed.";
377                         else
378                                 einfo "SELinux modules unloaded succesfully."
379                         fi
380                 done
381         fi
382 }
383