net-fs/openafs-kernel: remove vulnerable versions
[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 # $Id$
4
5 # Eclass for installing SELinux policy, and optionally
6 # reloading the reference-policy based modules.
7
8 # @ECLASS: selinux-policy-2.eclass
9 # @MAINTAINER:
10 # selinux@gentoo.org
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:="git://anongit.gentoo.org/proj/hardened-refpolicy.git 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 extra_eclass=""
78 case ${BASEPOL} in
79         9999)   extra_eclass="git-r3";
80                         EGIT_REPO_URI="${SELINUX_GIT_REPO}";
81                         EGIT_BRANCH="${SELINUX_GIT_BRANCH}";
82                         EGIT_CHECKOUT_DIR="${WORKDIR}/refpolicy";;
83 esac
84
85 inherit eutils ${extra_eclass}
86
87 IUSE=""
88
89 HOMEPAGE="https://wiki.gentoo.org/wiki/Project:SELinux"
90 if [[ -n ${BASEPOL} ]] && [[ "${BASEPOL}" != "9999" ]];
91 then
92         SRC_URI="https://raw.githubusercontent.com/wiki/TresysTechnology/refpolicy/files/refpolicy-${PV}.tar.bz2
93                 https://dev.gentoo.org/~swift/patches/selinux-base-policy/patchbundle-selinux-base-policy-${BASEPOL}.tar.bz2"
94 elif [[ "${BASEPOL}" != "9999" ]];
95 then
96         SRC_URI="https://raw.githubusercontent.com/wiki/TresysTechnology/refpolicy/files/refpolicy-${PV}.tar.bz2"
97 else
98         SRC_URI=""
99 fi
100
101 LICENSE="GPL-2"
102 SLOT="0"
103 S="${WORKDIR}/"
104 PATCHBUNDLE="${DISTDIR}/patchbundle-selinux-base-policy-${BASEPOL}.tar.bz2"
105
106 # Modules should always depend on at least the first release of the
107 # selinux-base-policy for which they are generated.
108 if [[ -n ${BASEPOL} ]];
109 then
110         RDEPEND=">=sys-apps/policycoreutils-2.0.82
111                 >=sec-policy/selinux-base-policy-${BASEPOL}"
112 else
113         RDEPEND=">=sys-apps/policycoreutils-2.0.82
114                 >=sec-policy/selinux-base-policy-${PV}"
115 fi
116 DEPEND="${RDEPEND}
117         sys-devel/m4
118         >=sys-apps/checkpolicy-2.0.21"
119
120 case "${EAPI:-0}" in
121         0|1|2|3|4) die "EAPI<5 is not supported";;
122         *) : ;;
123 esac
124
125 EXPORT_FUNCTIONS src_unpack src_prepare src_compile src_install pkg_postinst pkg_postrm
126
127 # @FUNCTION: selinux-policy-2_src_unpack
128 # @DESCRIPTION:
129 # Unpack the policy sources as offered by upstream (refpolicy).
130 selinux-policy-2_src_unpack() {
131         if [[ "${BASEPOL}" != "9999" ]];
132         then
133                 unpack ${A}
134         else
135                 git-r3_src_unpack
136         fi
137 }
138
139 # @FUNCTION: selinux-policy-2_src_prepare
140 # @DESCRIPTION:
141 # Patch the reference policy sources with our set of enhancements. Start with
142 # the base patchbundle referred to by the ebuilds through the BASEPOL variable,
143 # then apply the additional patches as offered by the ebuild.
144 #
145 # Next, extract only those files needed for this particular module (i.e. the .te
146 # and .fc files for the given module in the MODS variable).
147 #
148 # Finally, prepare the build environments for each of the supported SELinux
149 # types (such as targeted or strict), depending on the POLICY_TYPES variable
150 # content.
151 selinux-policy-2_src_prepare() {
152         local modfiles
153         local add_interfaces=0;
154
155         # Create 3rd_party location for user-contributed policies
156         cd "${S}/refpolicy/policy/modules" && mkdir 3rd_party;
157
158         # Patch the sources with the base patchbundle
159         if [[ -n ${BASEPOL} ]] && [[ "${BASEPOL}" != "9999" ]];
160         then
161                 cd "${S}"
162                 EPATCH_MULTI_MSG="Applying SELinux policy updates ... " \
163                 EPATCH_SUFFIX="patch" \
164                 EPATCH_SOURCE="${WORKDIR}" \
165                 EPATCH_FORCE="yes" \
166                 epatch
167         fi
168
169         # Call in epatch_user. We do this early on as we start moving
170         # files left and right hereafter.
171         epatch_user
172
173         # Copy additional files to the 3rd_party/ location
174         if [[ "$(declare -p POLICY_FILES 2>/dev/null 2>&1)" == "declare -a"* ]] ||
175            [[ -n ${POLICY_FILES} ]];
176         then
177             add_interfaces=1;
178                 cd "${S}/refpolicy/policy/modules"
179                 for POLFILE in ${POLICY_FILES[@]};
180                 do
181                         cp "${FILESDIR}/${POLFILE}" 3rd_party/ || die "Could not copy ${POLFILE} to 3rd_party/ location";
182                 done
183         fi
184
185         # Apply the additional patches refered to by the module ebuild.
186         # But first some magic to differentiate between bash arrays and strings
187         if [[ "$(declare -p POLICY_PATCH 2>/dev/null 2>&1)" == "declare -a"* ]] ||
188            [[ -n ${POLICY_PATCH} ]];
189         then
190                 cd "${S}/refpolicy/policy/modules"
191                 for POLPATCH in ${POLICY_PATCH[@]};
192                 do
193                         epatch "${POLPATCH}"
194                 done
195         fi
196
197         # Collect only those files needed for this particular module
198         for i in ${MODS}; do
199                 modfiles="$(find ${S}/refpolicy/policy/modules -iname $i.te) $modfiles"
200                 modfiles="$(find ${S}/refpolicy/policy/modules -iname $i.fc) $modfiles"
201                 modfiles="$(find ${S}/refpolicy/policy/modules -iname $i.cil) $modfiles"
202                 if [ ${add_interfaces} -eq 1 ];
203                 then
204                         modfiles="$(find ${S}/refpolicy/policy/modules -iname $i.if) $modfiles"
205                 fi
206         done
207
208         for i in ${POLICY_TYPES}; do
209                 mkdir "${S}"/${i} || die "Failed to create directory ${S}/${i}"
210                 cp "${S}"/refpolicy/doc/Makefile.example "${S}"/${i}/Makefile \
211                         || die "Failed to copy Makefile.example to ${S}/${i}/Makefile"
212
213                 cp ${modfiles} "${S}"/${i} \
214                         || die "Failed to copy the module files to ${S}/${i}"
215         done
216 }
217
218 # @FUNCTION: selinux-policy-2_src_compile
219 # @DESCRIPTION:
220 # Build the SELinux policy module (.pp file) for just the selected module, and
221 # this for each SELinux policy mentioned in POLICY_TYPES
222 selinux-policy-2_src_compile() {
223         local makeuse=""
224         for useflag in ${IUSE};
225         do
226                 use ${useflag} && makeuse="${makeuse} -D use_${useflag}"
227         done
228
229         for i in ${POLICY_TYPES}; do
230                 # Support USE flags in builds
231                 export M4PARAM="${makeuse}"
232                 if [[ ${BASEPOL} == 2.20140311* ]]; then
233                         # Parallel builds are broken in 2.20140311-r7 and earlier, bug 530178
234                         emake -j1 NAME=$i -C "${S}"/${i} || die "${i} compile failed"
235                 else
236                         emake NAME=$i -C "${S}"/${i} || die "${i} compile failed"
237                 fi
238         done
239 }
240
241 # @FUNCTION: selinux-policy-2_src_install
242 # @DESCRIPTION:
243 # Install the built .pp (or copied .cil) files in the correct subdirectory within
244 # /usr/share/selinux.
245 selinux-policy-2_src_install() {
246         local BASEDIR="/usr/share/selinux"
247
248         for i in ${POLICY_TYPES}; do
249                 for j in ${MODS}; do
250                         einfo "Installing ${i} ${j} policy package"
251                         insinto ${BASEDIR}/${i}
252                         if [ -f "${S}/${i}/${j}.pp" ] ; then
253                           doins "${S}"/${i}/${j}.pp || die "Failed to add ${j}.pp to ${i}"
254                         elif [ -f "${S}/${i}/${j}.cil" ] ; then
255                           doins "${S}"/${i}/${j}.cil || die "Failed to add ${j}.cil to ${i}"
256                         fi
257
258                         if [[ "${POLICY_FILES[@]}" == *"${j}.if"* ]];
259                         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         # build up the command in the case of multiple modules
273         local COMMAND
274
275         for i in ${POLICY_TYPES}; do
276                 if [ "${i}" == "strict" ] && [ "${MODS}" = "unconfined" ];
277                 then
278                         einfo "Ignoring loading of unconfined module in strict module store.";
279                         continue;
280                 fi
281                 einfo "Inserting the following modules into the $i module store: ${MODS}"
282
283                 cd /usr/share/selinux/${i} || die "Could not enter /usr/share/selinux/${i}"
284                 for j in ${MODS} ; do
285                         if [ -f "${j}.pp" ] ; then
286                                 COMMAND="${j}.pp ${COMMAND}"
287                         elif [ -f "${j}.cil" ] ; then
288                                 COMMAND="${j}.cil ${COMMAND}"
289                         fi
290                 done
291                 semodule -s ${i} -i ${COMMAND}
292                 if [ $? -ne 0 ];
293                 then
294                         ewarn "SELinux module load failed. Trying full reload...";
295                         if [ "${i}" == "targeted" ];
296                         then
297                                 semodule -s ${i} -b base.pp -i $(ls *.pp | grep -v base.pp);
298                         else
299                                 semodule -s ${i} -b base.pp -i $(ls *.pp | grep -v base.pp | grep -v unconfined.pp);
300                         fi
301                         if [ $? -ne 0 ];
302                         then
303                                 ewarn "Failed to reload SELinux policies."
304                                 ewarn ""
305                                 ewarn "If this is *not* the last SELinux module package being installed,"
306                                 ewarn "then you can safely ignore this as the reloads will be retried"
307                                 ewarn "with other, recent modules."
308                                 ewarn ""
309                                 ewarn "If it is the last SELinux module package being installed however,"
310                                 ewarn "then it is advised to look at the error above and take appropriate"
311                                 ewarn "action since the new SELinux policies are not loaded until the"
312                                 ewarn "command finished succesfully."
313                                 ewarn ""
314                                 ewarn "To reload, run the following command from within /usr/share/selinux/${i}:"
315                                 ewarn "  semodule -b base.pp -i \$(ls *.pp | grep -v base.pp)"
316                                 ewarn "or"
317                                 ewarn "  semodule -b base.pp -i \$(ls *.pp | grep -v base.pp | grep -v unconfined.pp)"
318                                 ewarn "depending on if you need the unconfined domain loaded as well or not."
319                         else
320                                 einfo "SELinux modules reloaded succesfully."
321                         fi
322                 else
323                         einfo "SELinux modules loaded succesfully."
324                 fi
325                 COMMAND="";
326         done
327
328         # Relabel depending packages
329         PKGSET="";
330         if [ -x /usr/bin/qdepends ] ; then
331           PKGSET=$(/usr/bin/qdepends -Cq -r -Q ${CATEGORY}/${PN} | grep -v "sec-policy/selinux-");
332         elif [ -x /usr/bin/equery ] ; then
333           PKGSET=$(/usr/bin/equery -Cq depends ${CATEGORY}/${PN} | grep -v "sec-policy/selinux-");
334         fi
335     if [ -n "${PKGSET}" ] ; then
336           rlpkg ${PKGSET};
337         fi
338 }
339
340 # @FUNCTION: selinux-policy-2_pkg_postrm
341 # @DESCRIPTION:
342 # Uninstall the module(s) from the SELinux policy stores, effectively
343 # deactivating the policy on the system.
344 selinux-policy-2_pkg_postrm() {
345         # Only if we are not upgrading
346         if [[ -z "${REPLACED_BY_VERSION}" ]];
347         then
348                 # build up the command in the case of multiple modules
349                 local COMMAND
350                 for i in ${MODS}; do
351                         COMMAND="-r ${i} ${COMMAND}"
352                 done
353
354                 for i in ${POLICY_TYPES}; do
355                         einfo "Removing the following modules from the $i module store: ${MODS}"
356
357                         semodule -s ${i} ${COMMAND}
358                         if [ $? -ne 0 ];
359                         then
360                                 ewarn "SELinux module unload failed.";
361                         else
362                                 einfo "SELinux modules unloaded succesfully."
363                         fi
364                 done
365         fi
366 }
367