Compile the policy using a script executed by meson.
Signed-off-by: Vit Mojzis <vmojzis(a)redhat.com>
---
libvirt.spec.in | 12 ----
meson.build | 12 ++++
selinux/compile_policy.py | 128 ++++++++++++++++++++++++++++++++++++++
selinux/meson.build | 23 +++++++
4 files changed, 163 insertions(+), 12 deletions(-)
create mode 100755 selinux/compile_policy.py
create mode 100644 selinux/meson.build
diff --git a/libvirt.spec.in b/libvirt.spec.in
index 9cbdb2c513..1b807ec324 100644
--- a/libvirt.spec.in
+++ b/libvirt.spec.in
@@ -1239,14 +1239,6 @@ export SOURCE_DATE_EPOCH=$(stat --printf='%Y'
%{_specdir}/%{name}.spec)
%{?arg_login_shell}
%meson_build
-%if 0%{?with_selinux}
-# SELinux policy (originally from selinux-policy-contrib)
-# this policy module will override the production module
-cd selinux
-
-make -f %{_datadir}/selinux/devel/Makefile %{modulename}.pp
-bzip2 -9 %{modulename}.pp
-%endif
%install
rm -fr %{buildroot}
@@ -1331,10 +1323,6 @@ mv
$RPM_BUILD_ROOT%{_datadir}/systemtap/tapset/libvirt_qemu_probes.stp \
%endif
%endif
-%if 0%{?with_selinux}
-install -D -m 0644 selinux/%{modulename}.pp.bz2
%{buildroot}%{_datadir}/selinux/packages/%{selinuxtype}/%{modulename}.pp.bz2
-%endif
-
%check
# Building on slow archs, like emulated s390x in Fedora copr, requires
# raising the test timeout
diff --git a/meson.build b/meson.build
index 69a7b4c88e..884d3a490d 100644
--- a/meson.build
+++ b/meson.build
@@ -2182,6 +2182,18 @@ endif
subdir('build-aux')
+os_release = run_command('grep', '^ID=',
'/etc/os-release').stdout()
+os_version = run_command('grep', '^VERSION_ID=',
'/etc/os-release').stdout().split('=')
+if (os_version.length() == 2)
+ os_version = os_version[1]
+else
+ os_version = 0
+endif
+
+if ((os_release.contains('fedora') and
os_version.version_compare('>33')) or
+ (os_release.contains('rhel') and
os_version.version_compare('>8')))
+ subdir('selinux')
+endif
# install pkgconfig files
pkgconfig_files = [
diff --git a/selinux/compile_policy.py b/selinux/compile_policy.py
new file mode 100755
index 0000000000..2de26f21c7
--- /dev/null
+++ b/selinux/compile_policy.py
@@ -0,0 +1,128 @@
+#!/usr/bin/env python3
+#
+# Copyright (C) 2021 Red Hat, Inc.
+#
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public
+# License as published by the Free Software Foundation; either
+# version 2.1 of the License, or (at your option) any later version.
+#
+# This library is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with this library. If not, see
+# <
http://www.gnu.org/licenses/>.
+
+# This script is based on selinux-policy Makefile
+#
https://github.com/fedora-selinux/selinux-policy/blob/rawhide/support/Mak...
+
+import subprocess
+import sys
+import os
+import glob
+
+if len(sys.argv) != 6:
+ print("Usage: %s <policy>.te <policy>.if <policy>.fc
<output>.pp <tmpdir>"
+ % sys.argv[0], file=sys.stderr)
+ exit(os.EX_USAGE)
+
+module_name = os.path.splitext(os.path.basename(sys.argv[1]))[0]
+
+m4param = ["-D", "enable_mcs", "-D",
"distro_redhat", "-D",
+ "hide_broken_symptoms", "-D", "mls_num_sens=16",
"-D",
+ "mls_num_cats=1024", "-D", "mcs_num_cats=1024"]
+
+SHAREDIR = "/usr/share/selinux"
+HEADERDIR = os.path.join(SHAREDIR, "devel/include")
+
+m4support = sorted(glob.glob("{}/support/*.spt".format(HEADERDIR)))
+header_layers = glob.glob("{}/*/".format(HEADERDIR))
+header_layers = sorted([x for x in header_layers
+ if os.path.join(HEADERDIR, "support") not in x])
+
+header_interfaces = []
+for layer in header_layers:
+ header_interfaces.extend(glob.glob("{}/*.if".format(layer)))
+header_interfaces.sort()
+
+# prepare temp folder
+try:
+ os.makedirs(sys.argv[5])
+except Exception:
+ pass
+
+# remove old trash from the temp folder
+for name in ["iferror.m4" "all_interfaces.conf"
"{}.*".format(module_name)]:
+ try:
+ os.remove(os.path.join(sys.argv[5], name))
+ except Exception:
+ pass
+
+# tmp/all_interfaces.conf
+# echo "ifdef(\`__if_error',\`m4exit(1)')" > $5/iferror.m4
+with open(os.path.join(sys.argv[5], "iferror.m4"), "w") as file:
+ file.write("ifdef(`__if_error',`m4exit(1)')\n")
+
+# echo "divert(-1)" > $5/all_interfaces.conf
+with open(os.path.join(sys.argv[5], "all_interfaces.conf"), "w") as
int_file:
+ int_file.write("divert(-1)\n")
+
+# m4 $M4SUPPORT $HEADER_INTERFACES $2 $5/iferror.m4
+# | sed -e s/dollarsstar/\$\$\*/g >> $5/all_interfaces.conf
+subprocess.run(r"m4 {} | sed -e s/dollarsstar/\$\$\*/g >> {}".format(
+ " ".join([*m4support, *header_interfaces, sys.argv[2],
+ os.path.join(sys.argv[5], "iferror.m4")]),
+ os.path.join(sys.argv[5], "all_interfaces.conf")),
+ shell=True, check=True)
+
+# doesn't work properly without "shell=True"
+# m4_process = Popen(["m4", *m4support, *header_interfaces, sys.argv[2],
+# os.path.join(sys.argv[5], "iferror.m4")],
+# stdout=PIPE, stderr=PIPE)
+# sed_process = Popen(["sed", "-e",
"s/dollarsstar/\$\$\*/g"],
+# stdin=m4_process.stdout, stdout=int_file)
+# outs, errs = m4_process.communicate()
+
+# echo "divert" >> $5/all_interfaces.conf
+with open(os.path.join(sys.argv[5], "all_interfaces.conf"), "a") as
file:
+ file.write("divert\n")
+
+# tmp/%.mod
+# m4 $M4PARAM -s $M4SUPPORT $5/all_interfaces.conf $1 > $5/$MODULE_NAME.tmp
+with open(os.path.join(sys.argv[5], "{}.tmp".format(module_name)),
+ "w") as tmp_file:
+ subprocess.run(["m4", *m4param, "-s", *m4support,
+ os.path.join(sys.argv[5], "all_interfaces.conf"),
+ sys.argv[1]], stdout=tmp_file, check=True)
+
+# /usr/bin/checkmodule -M -m $5/$MODULE_NAME.tmp -o $5/$MODULE_NAME.mod
+subprocess.run(["/usr/bin/checkmodule",
+ "-M",
+ "-m",
+ os.path.join(sys.argv[5], "{}.tmp".format(module_name)),
+ "-o",
+ os.path.join(sys.argv[5], "{}.mod".format(module_name))],
+ check=True)
+
+
+# tmp/%.mod.fc
+# m4 $M4PARAM $M4SUPPORT $3 > $5/$MODULE_NAME.mod.fc
+with open(os.path.join(sys.argv[5],
+ "{}.mod.fc".format(module_name)), "w") as
mod_fc_file:
+ subprocess.run(["m4", *m4param, *m4support, sys.argv[3]],
+ stdout=mod_fc_file, check=True)
+
+# %.pp
+# /usr/bin/semodule_package -o $4 -m $5/$MODULE_NAME.mod
+# -f $5/$MODULE_NAME.mod.fc
+subprocess.run(["/usr/bin/semodule_package",
+ "-o",
+ sys.argv[4],
+ "-m",
+ os.path.join(sys.argv[5], "{}.mod".format(module_name)),
+ "-f",
+ os.path.join(sys.argv[5], "{}.mod.fc".format(module_name))],
+ check=True)
diff --git a/selinux/meson.build b/selinux/meson.build
new file mode 100644
index 0000000000..2737e60519
--- /dev/null
+++ b/selinux/meson.build
@@ -0,0 +1,23 @@
+selinux_sources = [
+ 'virt.te',
+ 'virt.if',
+ 'virt.fc',
+]
+
+compile_policy_prog = find_program('compile_policy.py')
+
+virt_pp = custom_target('virt.pp',
+ output : 'virt.pp',
+ input : selinux_sources,
+ command : [compile_policy_prog, '@INPUT@', '@OUTPUT@',
'selinux/tmp'],
+ install : false)
+
+bzip2_prog = find_program('bzip2')
+
+bzip = custom_target('virt.pp.bz2',
+ output : 'virt.pp.bz2',
+ input : virt_pp,
+ command : [bzip2_prog, '-c', '-9', '@INPUT@'],
+ capture : true,
+ install : true,
+ install_dir : 'share/selinux/packages/')
--
2.30.2