selinux-policy-2.eclass 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368
  1. # Copyright 1999-2015 Gentoo Foundation
  2. # Distributed under the terms of the GNU General Public License v2
  3. # Eclass for installing SELinux policy, and optionally
  4. # reloading the reference-policy based modules.
  5. # @ECLASS: selinux-policy-2.eclass
  6. # @MAINTAINER:
  7. # selinux@gentoo.org
  8. # @BLURB: This eclass supports the deployment of the various SELinux modules in sec-policy
  9. # @DESCRIPTION:
  10. # The selinux-policy-2.eclass supports deployment of the various SELinux modules
  11. # defined in the sec-policy category. It is responsible for extracting the
  12. # specific bits necessary for single-module deployment (instead of full-blown
  13. # policy rebuilds) and applying the necessary patches.
  14. #
  15. # Also, it supports for bundling patches to make the whole thing just a bit more
  16. # manageable.
  17. # @ECLASS-VARIABLE: MODS
  18. # @DESCRIPTION:
  19. # This variable contains the (upstream) module name for the SELinux module.
  20. # This name is only the module name, not the category!
  21. : ${MODS:="_illegal"}
  22. # @ECLASS-VARIABLE: BASEPOL
  23. # @DESCRIPTION:
  24. # This variable contains the version string of the selinux-base-policy package
  25. # that this module build depends on. It is used to patch with the appropriate
  26. # patch bundle(s) that are part of selinux-base-policy.
  27. : ${BASEPOL:=${PVR}}
  28. # @ECLASS-VARIABLE: POLICY_PATCH
  29. # @DESCRIPTION:
  30. # This variable contains the additional patch(es) that need to be applied on top
  31. # of the patchset already contained within the BASEPOL variable. The variable
  32. # can be both a simple string (space-separated) or a bash array.
  33. : ${POLICY_PATCH:=""}
  34. # @ECLASS-VARIABLE: POLICY_FILES
  35. # @DESCRIPTION:
  36. # When defined, this contains the files (located in the ebuilds' files/
  37. # directory) which should be copied as policy module files into the store.
  38. # Generally, users would want to include at least a .te and .fc file, but .if
  39. # files are supported as well. The variable can be both a simple string
  40. # (space-separated) or a bash array.
  41. : ${POLICY_FILES:=""}
  42. # @ECLASS-VARIABLE: POLICY_TYPES
  43. # @DESCRIPTION:
  44. # This variable informs the eclass for which SELinux policies the module should
  45. # be built. Currently, Gentoo supports targeted, strict, mcs and mls.
  46. # This variable is the same POLICY_TYPES variable that we tell SELinux
  47. # users to set in make.conf. Therefore, it is not the module that should
  48. # override it, but the user.
  49. : ${POLICY_TYPES:="targeted strict mcs mls"}
  50. # @ECLASS-VARIABLE: SELINUX_GIT_REPO
  51. # @DESCRIPTION:
  52. # When defined, this variable overrides the default repository URL as used by
  53. # this eclass. It allows end users to point to a different policy repository
  54. # using a single variable, rather than having to set the packagename_LIVE_REPO
  55. # variable for each and every SELinux policy module package they want to install.
  56. # The default value is Gentoo's hardened-refpolicy repository.
  57. : ${SELINUX_GIT_REPO:="git://anongit.gentoo.org/proj/hardened-refpolicy.git https://anongit.gentoo.org/git/proj/hardened-refpolicy.git"};
  58. # @ECLASS-VARIABLE: SELINUX_GIT_BRANCH
  59. # @DESCRIPTION:
  60. # When defined, this variable sets the Git branch to use of the repository. This
  61. # allows for users and developers to use a different branch for the entire set of
  62. # SELinux policy packages, rather than having to override them one by one with the
  63. # packagename_LIVE_BRANCH variable.
  64. # The default value is the 'master' branch.
  65. : ${SELINUX_GIT_BRANCH:="master"};
  66. case "${EAPI:-0}" in
  67. 0|1|2|3|4) die "EAPI<5 is not supported";;
  68. 5|6) : ;;
  69. *) die "unknown EAPI" ;;
  70. esac
  71. case ${BASEPOL} in
  72. 9999) inherit git-r3
  73. EGIT_REPO_URI="${SELINUX_GIT_REPO}";
  74. EGIT_BRANCH="${SELINUX_GIT_BRANCH}";
  75. EGIT_CHECKOUT_DIR="${WORKDIR}/refpolicy";;
  76. esac
  77. if [[ ${EAPI:-0} == 5 ]]; then
  78. inherit eutils
  79. fi
  80. IUSE=""
  81. HOMEPAGE="https://wiki.gentoo.org/wiki/Project:SELinux"
  82. if [[ -n ${BASEPOL} ]] && [[ "${BASEPOL}" != "9999" ]]; then
  83. SRC_URI="https://raw.githubusercontent.com/wiki/TresysTechnology/refpolicy/files/refpolicy-${PV}.tar.bz2
  84. https://dev.gentoo.org/~swift/patches/selinux-base-policy/patchbundle-selinux-base-policy-${BASEPOL}.tar.bz2"
  85. elif [[ "${BASEPOL}" != "9999" ]]; then
  86. SRC_URI="https://raw.githubusercontent.com/wiki/TresysTechnology/refpolicy/files/refpolicy-${PV}.tar.bz2"
  87. else
  88. SRC_URI=""
  89. fi
  90. LICENSE="GPL-2"
  91. SLOT="0"
  92. S="${WORKDIR}/"
  93. PATCHBUNDLE="${DISTDIR}/patchbundle-selinux-base-policy-${BASEPOL}.tar.bz2"
  94. # Modules should always depend on at least the first release of the
  95. # selinux-base-policy for which they are generated.
  96. if [[ -n ${BASEPOL} ]]; then
  97. RDEPEND=">=sys-apps/policycoreutils-2.0.82
  98. >=sec-policy/selinux-base-policy-${BASEPOL}"
  99. else
  100. RDEPEND=">=sys-apps/policycoreutils-2.0.82
  101. >=sec-policy/selinux-base-policy-${PV}"
  102. fi
  103. DEPEND="${RDEPEND}
  104. sys-devel/m4
  105. >=sys-apps/checkpolicy-2.0.21"
  106. EXPORT_FUNCTIONS src_unpack src_prepare src_compile src_install pkg_postinst pkg_postrm
  107. # @FUNCTION: selinux-policy-2_src_unpack
  108. # @DESCRIPTION:
  109. # Unpack the policy sources as offered by upstream (refpolicy).
  110. selinux-policy-2_src_unpack() {
  111. if [[ "${BASEPOL}" != "9999" ]]; then
  112. unpack ${A}
  113. else
  114. git-r3_src_unpack
  115. fi
  116. }
  117. # @FUNCTION: selinux-policy-2_src_prepare
  118. # @DESCRIPTION:
  119. # Patch the reference policy sources with our set of enhancements. Start with
  120. # the base patchbundle referred to by the ebuilds through the BASEPOL variable,
  121. # then apply the additional patches as offered by the ebuild.
  122. #
  123. # Next, extract only those files needed for this particular module (i.e. the .te
  124. # and .fc files for the given module in the MODS variable).
  125. #
  126. # Finally, prepare the build environments for each of the supported SELinux
  127. # types (such as targeted or strict), depending on the POLICY_TYPES variable
  128. # content.
  129. selinux-policy-2_src_prepare() {
  130. local modfiles
  131. local add_interfaces=0;
  132. # Create 3rd_party location for user-contributed policies
  133. cd "${S}/refpolicy/policy/modules" && mkdir 3rd_party;
  134. # Patch the sources with the base patchbundle
  135. if [[ -n ${BASEPOL} ]] && [[ "${BASEPOL}" != "9999" ]]; then
  136. cd "${S}"
  137. if [[ ${EAPI:-0} == 5 ]]; then
  138. EPATCH_MULTI_MSG="Applying SELinux policy updates ... " \
  139. EPATCH_SUFFIX="patch" \
  140. EPATCH_SOURCE="${WORKDIR}" \
  141. EPATCH_FORCE="yes" \
  142. epatch
  143. else
  144. einfo "Applying SELinux policy updates ... "
  145. eapply -p0 "${WORKDIR}/0001-full-patch-against-stable-release.patch"
  146. fi
  147. fi
  148. # Call in epatch_user. We do this early on as we start moving
  149. # files left and right hereafter.
  150. if [[ ${EAPI:-0} == 5 ]]; then
  151. epatch_user
  152. else
  153. eapply_user
  154. fi
  155. # Copy additional files to the 3rd_party/ location
  156. if [[ "$(declare -p POLICY_FILES 2>/dev/null 2>&1)" == "declare -a"* ]] ||
  157. [[ -n ${POLICY_FILES} ]]; then
  158. add_interfaces=1;
  159. cd "${S}/refpolicy/policy/modules"
  160. for POLFILE in ${POLICY_FILES[@]};
  161. do
  162. cp "${FILESDIR}/${POLFILE}" 3rd_party/ || die "Could not copy ${POLFILE} to 3rd_party/ location";
  163. done
  164. fi
  165. # Apply the additional patches refered to by the module ebuild.
  166. # But first some magic to differentiate between bash arrays and strings
  167. if [[ "$(declare -p POLICY_PATCH 2>/dev/null 2>&1)" == "declare -a"* ]] ||
  168. [[ -n ${POLICY_PATCH} ]]; then
  169. cd "${S}/refpolicy/policy/modules"
  170. for POLPATCH in ${POLICY_PATCH[@]};
  171. do
  172. if [[ ${EAPI:-0} == 5 ]]; then
  173. epatch "${POLPATCH}"
  174. else
  175. eapply "${POLPATCH}"
  176. fi
  177. done
  178. fi
  179. # Collect only those files needed for this particular module
  180. for i in ${MODS}; do
  181. modfiles="$(find ${S}/refpolicy/policy/modules -iname $i.te) $modfiles"
  182. modfiles="$(find ${S}/refpolicy/policy/modules -iname $i.fc) $modfiles"
  183. modfiles="$(find ${S}/refpolicy/policy/modules -iname $i.cil) $modfiles"
  184. if [[ ${add_interfaces} -eq 1 ]]; then
  185. modfiles="$(find ${S}/refpolicy/policy/modules -iname $i.if) $modfiles"
  186. fi
  187. done
  188. for i in ${POLICY_TYPES}; do
  189. mkdir "${S}"/${i} || die "Failed to create directory ${S}/${i}"
  190. cp "${S}"/refpolicy/doc/Makefile.example "${S}"/${i}/Makefile \
  191. || die "Failed to copy Makefile.example to ${S}/${i}/Makefile"
  192. cp ${modfiles} "${S}"/${i} \
  193. || die "Failed to copy the module files to ${S}/${i}"
  194. done
  195. }
  196. # @FUNCTION: selinux-policy-2_src_compile
  197. # @DESCRIPTION:
  198. # Build the SELinux policy module (.pp file) for just the selected module, and
  199. # this for each SELinux policy mentioned in POLICY_TYPES
  200. selinux-policy-2_src_compile() {
  201. local makeuse=""
  202. for useflag in ${IUSE};
  203. do
  204. use ${useflag} && makeuse="${makeuse} -D use_${useflag}"
  205. done
  206. for i in ${POLICY_TYPES}; do
  207. # Support USE flags in builds
  208. export M4PARAM="${makeuse}"
  209. emake NAME=$i -C "${S}"/${i} || die "${i} compile failed"
  210. done
  211. }
  212. # @FUNCTION: selinux-policy-2_src_install
  213. # @DESCRIPTION:
  214. # Install the built .pp (or copied .cil) files in the correct subdirectory within
  215. # /usr/share/selinux.
  216. selinux-policy-2_src_install() {
  217. local BASEDIR="/usr/share/selinux"
  218. for i in ${POLICY_TYPES}; do
  219. for j in ${MODS}; do
  220. einfo "Installing ${i} ${j} policy package"
  221. insinto ${BASEDIR}/${i}
  222. if [[ -f "${S}/${i}/${j}.pp" ]] ; then
  223. doins "${S}"/${i}/${j}.pp || die "Failed to add ${j}.pp to ${i}"
  224. elif [[ -f "${S}/${i}/${j}.cil" ]] ; then
  225. doins "${S}"/${i}/${j}.cil || die "Failed to add ${j}.cil to ${i}"
  226. fi
  227. if [[ "${POLICY_FILES[@]}" == *"${j}.if"* ]]; then
  228. insinto ${BASEDIR}/${i}/include/3rd_party
  229. doins "${S}"/${i}/${j}.if || die "Failed to add ${j}.if to ${i}"
  230. fi
  231. done
  232. done
  233. }
  234. # @FUNCTION: selinux-policy-2_pkg_postinst
  235. # @DESCRIPTION:
  236. # Install the built .pp (or copied .cil) files in the SELinux policy stores, effectively
  237. # activating the policy on the system.
  238. selinux-policy-2_pkg_postinst() {
  239. # build up the command in the case of multiple modules
  240. local COMMAND
  241. for i in ${POLICY_TYPES}; do
  242. if [[ "${i}" == "strict" ]] && [[ "${MODS}" = "unconfined" ]]; then
  243. einfo "Ignoring loading of unconfined module in strict module store.";
  244. continue;
  245. fi
  246. einfo "Inserting the following modules into the $i module store: ${MODS}"
  247. cd /usr/share/selinux/${i} || die "Could not enter /usr/share/selinux/${i}"
  248. for j in ${MODS} ; do
  249. if [[ -f "${j}.pp" ]] ; then
  250. COMMAND="${j}.pp ${COMMAND}"
  251. elif [[ -f "${j}.cil" ]] ; then
  252. COMMAND="${j}.cil ${COMMAND}"
  253. fi
  254. done
  255. semodule -s ${i} -i ${COMMAND}
  256. if [[ $? -ne 0 ]]; then
  257. ewarn "SELinux module load failed. Trying full reload...";
  258. local COMMAND_base="-i base.pp"
  259. if has_version "<sys-apps/policycoreutils-2.5"; then
  260. COMMAND="-b base.pp"
  261. fi
  262. if [[ "${i}" == "targeted" ]]; then
  263. semodule -s ${i} ${COMMAND_base} -i $(ls *.pp | grep -v base.pp);
  264. else
  265. semodule -s ${i} ${COMMAND_base} -i $(ls *.pp | grep -v base.pp | grep -v unconfined.pp);
  266. fi
  267. if [[ $? -ne 0 ]]; then
  268. ewarn "Failed to reload SELinux policies."
  269. ewarn ""
  270. ewarn "If this is *not* the last SELinux module package being installed,"
  271. ewarn "then you can safely ignore this as the reloads will be retried"
  272. ewarn "with other, recent modules."
  273. ewarn ""
  274. ewarn "If it is the last SELinux module package being installed however,"
  275. ewarn "then it is advised to look at the error above and take appropriate"
  276. ewarn "action since the new SELinux policies are not loaded until the"
  277. ewarn "command finished succesfully."
  278. ewarn ""
  279. ewarn "To reload, run the following command from within /usr/share/selinux/${i}:"
  280. ewarn " semodule ${COMMAND_base} -i \$(ls *.pp | grep -v base.pp)"
  281. ewarn "or"
  282. ewarn " semodule ${COMMAND_base} -i \$(ls *.pp | grep -v base.pp | grep -v unconfined.pp)"
  283. ewarn "depending on if you need the unconfined domain loaded as well or not."
  284. else
  285. einfo "SELinux modules reloaded succesfully."
  286. fi
  287. else
  288. einfo "SELinux modules loaded succesfully."
  289. fi
  290. COMMAND="";
  291. done
  292. # Relabel depending packages
  293. local PKGSET="";
  294. if [[ -x /usr/bin/qdepends ]] ; then
  295. PKGSET=$(/usr/bin/qdepends -Cq -r -Q ${CATEGORY}/${PN} | grep -v "sec-policy/selinux-");
  296. elif [[ -x /usr/bin/equery ]] ; then
  297. PKGSET=$(/usr/bin/equery -Cq depends ${CATEGORY}/${PN} | grep -v "sec-policy/selinux-");
  298. fi
  299. if [[ -n "${PKGSET}" ]] ; then
  300. rlpkg ${PKGSET};
  301. fi
  302. }
  303. # @FUNCTION: selinux-policy-2_pkg_postrm
  304. # @DESCRIPTION:
  305. # Uninstall the module(s) from the SELinux policy stores, effectively
  306. # deactivating the policy on the system.
  307. selinux-policy-2_pkg_postrm() {
  308. # Only if we are not upgrading
  309. if [[ -z "${REPLACED_BY_VERSION}" ]]; then
  310. # build up the command in the case of multiple modules
  311. local COMMAND
  312. for i in ${MODS}; do
  313. COMMAND="-r ${i} ${COMMAND}"
  314. done
  315. for i in ${POLICY_TYPES}; do
  316. einfo "Removing the following modules from the $i module store: ${MODS}"
  317. semodule -s ${i} ${COMMAND}
  318. if [[ $? -ne 0 ]]; then
  319. ewarn "SELinux module unload failed.";
  320. else
  321. einfo "SELinux modules unloaded succesfully."
  322. fi
  323. done
  324. fi
  325. }