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