diff --git a/gui-po.tgz b/gui-po.tgz new file mode 100644 index 0000000000000000000000000000000000000000..67438c4022a703298c17ba09c15fd335ba16eb43 Binary files /dev/null and b/gui-po.tgz differ diff --git a/policycoreutils-fedora.patch b/policycoreutils-fedora.patch new file mode 100644 index 0000000000000000000000000000000000000000..1c82fb2b2d8ec36f4c48891cf2f86f1db3f670bc --- /dev/null +++ b/policycoreutils-fedora.patch @@ -0,0 +1,139 @@ +diff --git policycoreutils-2.8/newrole/newrole.1 policycoreutils-2.8/newrole/newrole.1 +index 0d9738a..893c42f 100644 +--- policycoreutils-2.8/newrole/newrole.1 ++++ policycoreutils-2.8/newrole/newrole.1 +@@ -44,7 +44,7 @@ specified by that range. If the + or + .B --preserve-environment + option is specified, the shell with the new SELinux context will preserve environment variables, +-otherwise a new minimal enviroment is created. ++otherwise a new minimal environment is created. + .PP + Additional arguments + .I ARGS +diff --git policycoreutils-2.8/po/Makefile policycoreutils-2.8/po/Makefile +index 575e143..18bc1df 100644 +--- policycoreutils-2.8/po/Makefile ++++ policycoreutils-2.8/po/Makefile +@@ -3,7 +3,6 @@ + # + + PREFIX ?= /usr +-TOP = ../.. + + # What is this package? + NLSPACKAGE = policycoreutils +@@ -32,74 +31,13 @@ USE_LINGUAS := $(if $(USER_LINGUAS),$(USER_LINGUAS),$(PO_LINGUAS)) + + POFILES = $(patsubst %,%.po,$(USE_LINGUAS)) + MOFILES = $(patsubst %.po,%.mo,$(POFILES)) +-POTFILES = \ +- ../run_init/open_init_pty.c \ +- ../run_init/run_init.c \ +- ../semodule_link/semodule_link.c \ +- ../audit2allow/audit2allow \ +- ../semanage/seobject.py \ +- ../setsebool/setsebool.c \ +- ../newrole/newrole.c \ +- ../load_policy/load_policy.c \ +- ../sestatus/sestatus.c \ +- ../semodule/semodule.c \ +- ../setfiles/setfiles.c \ +- ../semodule_package/semodule_package.c \ +- ../semodule_deps/semodule_deps.c \ +- ../semodule_expand/semodule_expand.c \ +- ../scripts/chcat \ +- ../scripts/fixfiles \ +- ../restorecond/stringslist.c \ +- ../restorecond/restorecond.h \ +- ../restorecond/utmpwatcher.h \ +- ../restorecond/stringslist.h \ +- ../restorecond/restorecond.c \ +- ../restorecond/utmpwatcher.c \ +- ../gui/booleansPage.py \ +- ../gui/fcontextPage.py \ +- ../gui/loginsPage.py \ +- ../gui/mappingsPage.py \ +- ../gui/modulesPage.py \ +- ../gui/polgen.glade \ +- ../gui/polgengui.py \ +- ../gui/portsPage.py \ +- ../gui/semanagePage.py \ +- ../gui/statusPage.py \ +- ../gui/system-config-selinux.glade \ +- ../gui/system-config-selinux.py \ +- ../gui/usersPage.py \ +- ../secon/secon.c \ +- booleans.py \ +- ../sepolicy/sepolicy.py \ +- ../sepolicy/sepolicy/communicate.py \ +- ../sepolicy/sepolicy/__init__.py \ +- ../sepolicy/sepolicy/network.py \ +- ../sepolicy/sepolicy/generate.py \ +- ../sepolicy/sepolicy/sepolicy.glade \ +- ../sepolicy/sepolicy/gui.py \ +- ../sepolicy/sepolicy/manpage.py \ +- ../sepolicy/sepolicy/transition.py \ +- ../sepolicy/sepolicy/templates/executable.py \ +- ../sepolicy/sepolicy/templates/__init__.py \ +- ../sepolicy/sepolicy/templates/network.py \ +- ../sepolicy/sepolicy/templates/rw.py \ +- ../sepolicy/sepolicy/templates/script.py \ +- ../sepolicy/sepolicy/templates/semodule.py \ +- ../sepolicy/sepolicy/templates/tmp.py \ +- ../sepolicy/sepolicy/templates/user.py \ +- ../sepolicy/sepolicy/templates/var_lib.py \ +- ../sepolicy/sepolicy/templates/var_log.py \ +- ../sepolicy/sepolicy/templates/var_run.py \ +- ../sepolicy/sepolicy/templates/var_spool.py ++POTFILES = $(shell cat POTFILES) + + #default:: clean + +-all:: $(MOFILES) ++all:: $(POTFILE) $(MOFILES) + +-booleans.py: +- sepolicy booleans -a > booleans.py +- +-$(POTFILE): $(POTFILES) booleans.py ++$(POTFILE): $(POTFILES) + $(XGETTEXT) --keyword=_ --keyword=N_ $(POTFILES) + @if cmp -s $(NLSPACKAGE).po $(POTFILE); then \ + rm -f $(NLSPACKAGE).po; \ +@@ -107,8 +45,6 @@ $(POTFILE): $(POTFILES) booleans.py + mv -f $(NLSPACKAGE).po $(POTFILE); \ + fi; \ + +-update-po: Makefile $(POTFILE) refresh-po +- @rm -f booleans.py + + refresh-po: Makefile + for cat in $(POFILES); do \ +diff --git policycoreutils-2.8/po/POTFILES policycoreutils-2.8/po/POTFILES +new file mode 100644 +index 0000000..12237dc +--- /dev/null ++++ policycoreutils-2.8/po/POTFILES +@@ -0,0 +1,9 @@ ++../run_init/open_init_pty.c ++../run_init/run_init.c ++../setsebool/setsebool.c ++../newrole/newrole.c ++../load_policy/load_policy.c ++../sestatus/sestatus.c ++../semodule/semodule.c ++../setfiles/setfiles.c ++../secon/secon.c +diff --git policycoreutils-2.8/scripts/fixfiles policycoreutils-2.8/scripts/fixfiles +index b277958..53d28c7 100755 +--- policycoreutils-2.8/scripts/fixfiles ++++ policycoreutils-2.8/scripts/fixfiles +@@ -108,6 +108,7 @@ exclude_dirs_from_relabelling() { + fullFlag=0 + BOOTTIME="" + VERBOSE="-p" ++[ -t 1 ] || VERBOSE="" + FORCEFLAG="" + RPMFILES="" + PREFC="" diff --git a/policycoreutils-po.tgz b/policycoreutils-po.tgz new file mode 100644 index 0000000000000000000000000000000000000000..bbb1489ff18e63b896e531e8099173e2f72ab577 Binary files /dev/null and b/policycoreutils-po.tgz differ diff --git a/policycoreutils.spec b/policycoreutils.spec index 9ddbef5910132bf1886030a1e0ffd5ef5399b3c0..26c5d342067d503480c4bcec4b5ef19e5856b79b 100644 --- a/policycoreutils.spec +++ b/policycoreutils.spec @@ -2,17 +2,37 @@ Name: policycoreutils Version: 2.8 -Release: 12 +Release: 10 Summary: Policy core utilities of selinux License: GPLv2 URL: https://github.com/SELinuxProject Source0: https://raw.githubusercontent.com/wiki/SELinuxProject/selinux/files/releases/20180524/policycoreutils-2.8.tar.gz Source1: https://raw.githubusercontent.com/wiki/SELinuxProject/selinux/files/releases/20180524/selinux-python-2.8.tar.gz +Source2: https://raw.githubusercontent.com/wiki/SELinuxProject/selinux/files/releases/20180524/selinux-gui-2.8.tar.gz Source3: https://raw.githubusercontent.com/wiki/SELinuxProject/selinux/files/releases/20180524/selinux-sandbox-2.8.tar.gz Source4: https://raw.githubusercontent.com/wiki/SELinuxProject/selinux/files/releases/20180524/selinux-dbus-2.8.tar.gz Source5: https://raw.githubusercontent.com/wiki/SELinuxProject/selinux/files/releases/20180524/semodule-utils-2.8.tar.gz Source6: https://raw.githubusercontent.com/wiki/SELinuxProject/selinux/files/releases/20180524/restorecond-2.8.tar.gz +Source7: policycoreutils_man_ru2.tar.bz2 +Source8: system-config-selinux.png +Source9: sepolicy-icons.tgz +Source10: selinux-autorelabel +Source11: selinux-autorelabel.service +Source12: selinux-autorelabel-mark.service +Source13: selinux-autorelabel.target +Source14: selinux-autorelabel-generator.sh +Source15: policycoreutils-po.tgz +Source16: python-po.tgz +Source17: gui-po.tgz +Source18: sandbox-po.tgz + +Patch0: policycoreutils-fedora.patch +Patch1: selinux-python-fedora.patch +Patch2: selinux-gui-fedora.patch +Patch3: selinux-sandbox-fedora.patch +Patch4: selinux-dbus-fedora.patch + Patch6000: python-sepolgen-fix-typo-in-PathChoooser-name.patch Patch6001: policycoreutils-secon-free-scon_trans-before-returni.patch Patch6002: python-sepolicy-fix-procotol-misspelling.patch @@ -38,7 +58,7 @@ Patch9021: fix-fixfiles-N-date-function.patch Patch9022: fix-fixfiles-N-date-function-two.patch BuildRequires: pam-devel libsepol-static libsemanage-static libselinux-devel libcap-devel audit-libs-devel gettext -BuildRequires: desktop-file-utils dbus-devel dbus-glib-devel python2-devel python3-devel libcap-ng-devel +BuildRequires: desktop-file-utils dbus-devel dbus-glib-devel python2-devel python3-devel BuildRequires: systemd systemd-units Requires: libsepol libselinux-utils util-linux grep gawk diffutils rpm sed coreutils @@ -116,8 +136,21 @@ Requires: selinux-policy-devel %description devel It contains policy core devel utilities for selinux + +%package gui +Summary: configuration gui for selinux +BuildRequires: desktop-file-utils +Requires: policycoreutils-devel = %{version}-%{release}, python3-policycoreutils = %{version}-%{release} +Requires: policycoreutils-dbus = %{version}-%{release} +Requires: gtk3, python3-gobject +BuildArch: noarch + +%description gui +It contains configuration gui for selinux + %package sandbox Summary: Sandbox utilities for selinux +BuildRequires: libcap-ng-devel Requires: python3-policycoreutils = %{version}-%{release} Requires: xorg-x11-server-Xephyr >= 1.14.1-2 /usr/bin/rsync /usr/bin/xmodmap Requires: openbox @@ -136,23 +169,61 @@ This contains man files for the using of selinux. %prep %setup -q -c -n selinux %setup -q -T -D -a 1 -n selinux +%setup -q -T -D -a 2 -n selinux %setup -q -T -D -a 3 -n selinux %setup -q -T -D -a 4 -n selinux %setup -q -T -D -a 5 -n selinux %setup -q -T -D -a 6 -n selinux -%autopatch -p1 +%patch0 -p0 -b .policycoreutils-fedora +cp %{SOURCE8} selinux-gui-2.8/ +tar -xvf %{SOURCE9} -C selinux-python-2.8/sepolicy/ +%patch1 -p0 -b .selinux-python +%patch2 -p0 -b .selinux-gui +%patch3 -p0 -b .selinux-sandbox +%patch4 -p0 -b .selinux-dbus + +%patch6000 -p1 +%patch6001 -p1 +%patch6002 -p1 +%patch6003 -p1 +%patch6004 -p1 +%patch6005 -p1 +%patch6006 -p1 +%patch6007 -p1 +%patch6008 -p1 +%patch6009 -p1 +%patch6010 -p1 +%patch6011 -p1 +%patch6012 -p1 +%patch6013 -p1 +%patch6014 -p1 +%patch6015 -p1 +%patch6016 -p1 +%patch6017 -p1 +%patch6018 -p1 +%patch6019 -p1 +%patch6020 -p1 +%patch9021 -p1 +%patch9022 -p1 + +tar -x -f %{SOURCE15} -C policycoreutils-2.8 -z +tar -x -f %{SOURCE16} -C selinux-python-2.8 -z +tar -x -f %{SOURCE17} -C selinux-gui-2.8 -z +tar -x -f %{SOURCE18} -C selinux-sandbox-2.8 -z %build export PYTHON=%{__python3} make -C policycoreutils-2.8 LSPP_PRIV=y SBINDIR="%{_sbindir}" LIBDIR="%{_libdir}" SEMODULE_PATH="%{_sbindir}" LIBSEPOLA="%{_libdir}/libsepol.a" all -make -C selinux-python-2.8 SBINDIR="%{_sbindir}" LSPP_PRIV=y LIBDIR="%{_libdir}" LIBSEPOLA="%{_libdir}/libsepol.a" all make -C semodule-utils-2.8 SBINDIR="%{_sbindir}" LSPP_PRIV=y LIBDIR="%{_libdir}" LIBSEPOLA="%{_libdir}/libsepol.a" all make -C restorecond-2.8 SBINDIR="%{_sbindir}" LSPP_PRIV=y LIBDIR="%{_libdir}" LIBSEPOLA="%{_libdir}/libsepol.a" all +make -C selinux-python-2.8 SBINDIR="%{_sbindir}" LSPP_PRIV=y LIBDIR="%{_libdir}" LIBSEPOLA="%{_libdir}/libsepol.a" all +make -C selinux-gui-2.8 SBINDIR="%{_sbindir}" LSPP_PRIV=y LIBDIR="%{_libdir}" LIBSEPOLA="%{_libdir}/libsepol.a" all make -C selinux-sandbox-2.8 SBINDIR="%{_sbindir}" LSPP_PRIV=y LIBDIR="%{_libdir}" LIBSEPOLA="%{_libdir}/libsepol.a" all make -C selinux-dbus-2.8 SBINDIR="%{_sbindir}" LSPP_PRIV=y LIBDIR="%{_libdir}" LIBSEPOLA="%{_libdir}/libsepol.a" all + %install mkdir -p %{buildroot}/%{_defaultdocdir}/%{name}/ make -C policycoreutils-2.8 LSPP_PRIV=y DESTDIR="%{buildroot}" SBINDIR="%{_sbindir}" LIBDIR="%{_libdir}" SEMODULE_PATH="/usr/sbin" LIBSEPOLA="%{_libdir}/libsepol.a" install @@ -160,11 +231,14 @@ make -C selinux-python-2.8 PYTHON=%{__python2} DESTDIR="%{buildroot}" SBINDIR=" make -C selinux-python-2.8 PYTHON=%{__python3} DESTDIR="%{buildroot}" SBINDIR="%{_sbindir}" LIBDIR="%{_libdir}" LIBSEPOLA="%{_libdir}/libsepol.a" install make -C semodule-utils-2.8 PYTHON=%{__python3} DESTDIR="%{buildroot}" SBINDIR="%{_sbindir}" LIBDIR="%{_libdir}" LIBSEPOLA="%{_libdir}/libsepol.a" install make -C restorecond-2.8 PYTHON=%{__python3} DESTDIR="%{buildroot}" SBINDIR="%{_sbindir}" LIBDIR="%{_libdir}" LIBSEPOLA="%{_libdir}/libsepol.a" install +make -C selinux-gui-2.8 PYTHON=%{__python3} DESTDIR="%{buildroot}" SBINDIR="%{_sbindir}" LIBDIR="%{_libdir}" LIBSEPOLA="%{_libdir}/libsepol.a" install make -C selinux-sandbox-2.8 PYTHON=%{__python3} DESTDIR="%{buildroot}" SBINDIR="%{_sbindir}" LIBDIR="%{_libdir}" LIBSEPOLA="%{_libdir}/libsepol.a" install make -C selinux-dbus-2.8 PYTHON=%{__python3} DESTDIR="%{buildroot}" SBINDIR="%{_sbindir}" LIBDIR="%{_libdir}" LIBSEPOLA="%{_libdir}/libsepol.a" install rm -rf %{buildroot}/%{_sysconfdir}/rc.d/init.d/restorecond + +tar -jxf %{SOURCE7} -C %{buildroot}/ rm -f %{buildroot}/%{_sbindir}/open_init_pty rm -f %{buildroot}/%{_sbindir}/run_init rm -f %{buildroot}/%{_mandir}/man8/open_init_pty.8 @@ -172,12 +246,28 @@ rm -f %{buildroot}/%{_mandir}/ru/man8/run_init.8* rm -f %{buildroot}/%{_mandir}/man8/run_init.8* rm -f %{buildroot}/etc/pam.d/run_init* +ln -sf %{_datarootdir}/system-config-selinux/polgengui.py %{buildroot}%{_bindir}/selinux-polgengui + +desktop-file-install --dir %{buildroot}%{_datadir}/applications --add-category Settings \ + %{buildroot}%{_datadir}/system-config-selinux/sepolicy.desktop + +desktop-file-install --dir %{buildroot}%{_datadir}/applications --add-category Settings \ + %{buildroot}%{_datadir}/system-config-selinux/system-config-selinux.desktop + +desktop-file-install --dir %{buildroot}%{_datadir}/applications \ + %{buildroot}%{_datadir}/system-config-selinux/selinux-polgengui.desktop + + rm -f %{buildroot}%{python2_sitelib}/sepolicy/gui.* rm -f %{buildroot}%{python2_sitelib}/sepolicy/sepolicy.glade rm -rf %{buildroot}%{python2_sitelib}/sepolicy/help -rm -f %{buildroot}%{python3_sitelib}/sepolicy/gui.* -rm -f %{buildroot}%{python3_sitelib}/sepolicy/sepolicy.glade +install -m 644 -p %{SOURCE11} %{buildroot}/%{_unitdir}/ +install -m 644 -p %{SOURCE12} %{buildroot}/%{_unitdir}/ +install -m 644 -p %{SOURCE13} %{buildroot}/%{_unitdir}/ +install -D -m 755 -p %{SOURCE14} %{buildroot}/%{_systemdgeneratordir}/%{basename:%{SOURCE14}} +install -m 755 -p %{SOURCE10} %{buildroot}/%{_libexecdir}/selinux/ + pathfix.py -i "%{__python2} -Es" -p %{buildroot}%{python2_sitelib} pathfix.py -i "%{__python3} -Es" -p %{buildroot}%{python3_sitelib} @@ -185,7 +275,9 @@ pathfix.py -i "%{__python3} -Es" -p %{buildroot}%{_sbindir}/semanage %{buildroo %{buildroot}%{_bindir}/chcat %{buildroot}%{_bindir}/audit2allow \ %{buildroot}%{_bindir}/sepolicy %{buildroot}%{_bindir}/sepolgen-ifgen \ %{buildroot}%{_datadir}/sandbox/start \ - %{buildroot}%{_datadir}/system-config-selinux/selinux_server.py + %{buildroot}%{_datadir}/system-config-selinux/system-config-selinux.py \ + %{buildroot}%{_datadir}/system-config-selinux/selinux_server.py \ + %{buildroot}%{_datadir}/system-config-selinux/polgengui.py find %{buildroot}%{python2_sitelib} %{buildroot}%{python3_sitelib} %{buildroot}%{python2_sitearch} %{buildroot}%{python3_sitearch} \ @@ -193,13 +285,17 @@ find %{buildroot}%{python2_sitelib} %{buildroot}%{python3_sitelib} %{buildroot}% %py_byte_compile %{__python3} %{buildroot}%{_datadir}/system-config-selinux +%find_lang selinux-gui +%find_lang selinux-sandbox %find_lang policycoreutils +%find_lang selinux-python + %post -%systemd_post restorecond.service +%systemd_post selinux-autorelabel-mark.service restorecond.service %preun -%systemd_preun restorecond.service +%systemd_preun selinux-autorelabel-mark.service restorecond.service %postun %systemd_postun_with_restart restorecond.service @@ -220,13 +316,19 @@ find %{buildroot}%{python2_sitelib} %{buildroot}%{python3_sitelib} %{buildroot}% %{_bindir}/semodule_package %{_bindir}/semodule_unpackage %{_libexecdir}/selinux/hll -%dir %{_datadir}/bash-completion -%{_datadir}/bash-completion/completions/setsebool +%{_libexecdir}/selinux/selinux-autorelabel +%{_unitdir}/selinux-autorelabel-mark.service +%{_unitdir}/selinux-autorelabel.service +%{_unitdir}/selinux-autorelabel.target %{_unitdir}/restorecond.service +%{_systemdgeneratordir}/selinux-autorelabel-generator.sh %{_sysconfdir}/xdg/autostart/restorecond.desktop +%dir %{_datadir}/bash-completion +%{_datadir}/bash-completion/completions/setsebool %{_datadir}/dbus-1/services/org.selinux.Restorecond.service %attr(0755,root,root) %caps(cap_dac_read_search,cap_setpcap,cap_audit_write,cap_sys_admin,cap_fowner,cap_chown,cap_dac_override=pe) %{_bindir}/newrole + %files python-utils %{_bindir}/audit2allow %{_bindir}/audit2why @@ -236,13 +338,17 @@ find %{buildroot}%{python2_sitelib} %{buildroot}%{python3_sitelib} %{buildroot}% %{_sysconfdir}/dbus-1/system.d/org.selinux.conf %{_datadir}/bash-completion/completions/semanage + %files dbus %{_datadir}/system-config-selinux/selinux_server.py %{_datadir}/polkit-1/actions/org.selinux.policy +%{_datadir}/polkit-1/actions/org.selinux.config.policy %{_sysconfdir}/dbus-1/system.d/org.selinux.conf %{_datadir}/dbus-1/system-services/org.selinux.service %dir %{_datadir}/system-config-selinux/__pycache__ %{_datadir}/system-config-selinux/__pycache__/selinux_server.* +%exclude %{_datadir}/system-config-selinux/{selinux-polgengui.desktop,sepolicy.desktop,system-config-selinux.desktop} + %files -n python2-policycoreutils %{python2_sitelib}/seobject.py* @@ -260,7 +366,8 @@ find %{buildroot}%{python2_sitelib} %{buildroot}%{python3_sitelib} %{buildroot}% %{python2_sitelib}/sepolicy/manpage.py* %{python2_sitelib}/sepolicy/templates -%files -n python3-policycoreutils + +%files -f selinux-python.lang -n python3-policycoreutils %{python3_sitelib}/__pycache__ %{python3_sitelib}/sepolgen %dir %{python3_sitelib}/sepolicy @@ -280,6 +387,7 @@ find %{buildroot}%{python2_sitelib} %{buildroot}%{python3_sitelib} %{buildroot}% %{python3_sitelib}/sepolicy/interface.py* %{python3_sitelib}/seobject.py* + %files devel %{_bindir}/sepolicy %{_bindir}/sepolgen @@ -288,21 +396,45 @@ find %{buildroot}%{python2_sitelib} %{buildroot}%{python3_sitelib} %{buildroot}% %dir /var/lib/sepolgen /var/lib/sepolgen/perm_map -%files sandbox + +%files -f selinux-sandbox.lang sandbox %config(noreplace) %{_sysconfdir}/sysconfig/sandbox %{_datadir}/sandbox/{start,sandboxX.sh} %caps(cap_setpcap,cap_setuid,cap_fowner,cap_dac_override,cap_sys_admin,cap_sys_nice=pe) %{_sbindir}/seunshare + +%files -f selinux-gui.lang gui +%{_bindir}/system-config-selinux +%{_bindir}/selinux-polgengui +%{_datadir}/applications/*.desktop +%{_datadir}/pixmaps/system-config-selinux.png +%{_datadir}/icons/hicolor/24x24/apps/*.png +%dir %{_datadir}/system-config-selinux +%dir %{_datadir}/system-config-selinux/__pycache__ +%{_datadir}/system-config-selinux/system-config-selinux.png +%{_datadir}/system-config-selinux/*Page.py +%{_datadir}/system-config-selinux/__pycache__/polgengui.* +%{_datadir}/system-config-selinux/system-config-selinux.py +%{_datadir}/system-config-selinux/__pycache__/*Page.* +%{_datadir}/system-config-selinux/html_util.py +%{_datadir}/system-config-selinux/__pycache__/system-config-selinux.* +%{_datadir}/system-config-selinux/*.ui +%{_datadir}/system-config-selinux/__pycache__/html_util.* +%{_datadir}/system-config-selinux/polgengui.py + + +%{python3_sitelib}/sepolicy/gui.py* +%{python3_sitelib}/sepolicy/sepolicy.glade +%{_datadir}/pixmaps/sepolicy.png +%{_datadir}/icons/hicolor/*/apps/sepolicy.png + + %files help %{_mandir}/* +%exclude %{_mandir}/ru/man8/{genhomedircon.8.gz,open_init_pty.8.gz,semodule_deps.8.gz} -%changelog -* Wed Jan 15 2020 openEuler Buildteam - 2.8-12 -- clean code - -* Fri Dec 20 2019 openEuler Buildteam - 2.8-11 -- Simplify functions +%changelog * Fri Dec 20 2019 openEuler Buildteam - 2.8-10 - Delete unused patch diff --git a/policycoreutils_man_ru2.tar.bz2 b/policycoreutils_man_ru2.tar.bz2 new file mode 100644 index 0000000000000000000000000000000000000000..cbf126b1085706d4b66f8999cb991cbaafe4e796 Binary files /dev/null and b/policycoreutils_man_ru2.tar.bz2 differ diff --git a/python-po.tgz b/python-po.tgz new file mode 100644 index 0000000000000000000000000000000000000000..5826c0ad6853dad6ac04ca76566ee84d781b7e32 Binary files /dev/null and b/python-po.tgz differ diff --git a/sandbox-po.tgz b/sandbox-po.tgz new file mode 100644 index 0000000000000000000000000000000000000000..075dad0c58f870152c5924ea07c0c1bc7e719fa6 Binary files /dev/null and b/sandbox-po.tgz differ diff --git a/selinux-autorelabel b/selinux-autorelabel new file mode 100644 index 0000000000000000000000000000000000000000..22c21438280b21290883f851edaf0ecd80b717e7 --- /dev/null +++ b/selinux-autorelabel @@ -0,0 +1,73 @@ +#!/bin/bash +# +# Do automatic relabelling +# + +# . /etc/init.d/functions + +# If the user has this (or similar) UEFI boot order: +# +# Windows | grub | Linux +# +# And decides to boot into grub/Linux, then the reboot at the end of autorelabel +# would cause the system to boot into Windows again, if the autorelabel was run. +# +# This function restores the UEFI boot order, so the user will boot into the +# previously set (and expected) partition. +efi_set_boot_next() { + # NOTE: The [ -x /usr/sbin/efibootmgr ] test is not sufficent -- it could + # succeed even on system which is not EFI-enabled... + if ! efibootmgr > /dev/null 2>&1; then + return + fi + + # NOTE: It it possible that some other services might be setting the + # 'BootNext' item for any reasons, and we shouldn't override it if so. + if ! efibootmgr | grep --quiet -e 'BootNext'; then + CURRENT_BOOT="$(efibootmgr | grep -e 'BootCurrent' | sed -re 's/(^.+:[[:space:]]*)([[:xdigit:]]+)/\2/')" + efibootmgr -n "${CURRENT_BOOT}" > /dev/null 2>&1 + fi +} + +relabel_selinux() { + # if /sbin/init is not labeled correctly this process is running in the + # wrong context, so a reboot will be required after relabel + AUTORELABEL= + . /etc/selinux/config + echo "0" > /sys/fs/selinux/enforce + [ -x /bin/plymouth ] && plymouth --quit + + if [ "$AUTORELABEL" = "0" ]; then + echo + echo $"*** Warning -- SELinux ${SELINUXTYPE} policy relabel is required. " + echo $"*** /etc/selinux/config indicates you want to manually fix labeling" + echo $"*** problems. Dropping you to a shell; the system will reboot" + echo $"*** when you leave the shell." + sulogin + + else + echo + echo $"*** Warning -- SELinux ${SELINUXTYPE} policy relabel is required." + echo $"*** Relabeling could take a very long time, depending on file" + echo $"*** system size and speed of hard drives." + + FORCE=`cat /.autorelabel` + [ -x "/usr/sbin/quotaoff" ] && /usr/sbin/quotaoff -aug + /sbin/fixfiles $FORCE restore + fi + + rm -f /.autorelabel + /usr/lib/dracut/dracut-initramfs-restore + efi_set_boot_next + if [ -x /usr/bin/grub2-editenv ]; then + grub2-editenv - incr boot_indeterminate >/dev/null 2>&1 + fi + sync + systemctl --force reboot +} + +# Check to see if a full relabel is needed +if [ "$READONLY" != "yes" ]; then + restorecon $(awk '!/^#/ && $4 !~ /noauto/ && $2 ~ /^\// { print $2 }' /etc/fstab) >/dev/null 2>&1 + relabel_selinux +fi diff --git a/selinux-autorelabel-generator.sh b/selinux-autorelabel-generator.sh new file mode 100644 index 0000000000000000000000000000000000000000..be6048766dcc1e7d26636b62a5a4454c57af96cb --- /dev/null +++ b/selinux-autorelabel-generator.sh @@ -0,0 +1,29 @@ +#!/bin/sh + +# This systemd.generator(7) detects if SELinux is running and if the +# user requested an autorelabel, and if so sets the default target to +# selinux-autorelabel.target, which will cause the filesystem to be +# relabelled and then the system will reboot again and boot into the +# real default target. + +PATH=/usr/sbin:$PATH +unitdir=/usr/lib/systemd/system + +# If invoked with no arguments (for testing) write to /tmp. +earlydir="/tmp" +if [ -n "$2" ]; then + earlydir="$2" +fi + +set_target () +{ + ln -sf "$unitdir/selinux-autorelabel.target" "$earlydir/default.target" +} + +if selinuxenabled; then + if test -f /.autorelabel; then + set_target + elif grep -sqE "\bautorelabel\b" /proc/cmdline; then + set_target + fi +fi diff --git a/selinux-autorelabel-mark.service b/selinux-autorelabel-mark.service new file mode 100644 index 0000000000000000000000000000000000000000..dc17df384d33b480d26737dc8bfcf367d63285d8 --- /dev/null +++ b/selinux-autorelabel-mark.service @@ -0,0 +1,18 @@ +[Unit] +Description=Mark the need to relabel after reboot +DefaultDependencies=no +Requires=local-fs.target +Conflicts=shutdown.target +After=local-fs.target +Before=sysinit.target shutdown.target +ConditionSecurity=!selinux +ConditionPathIsDirectory=/etc/selinux +ConditionPathExists=!/.autorelabel + +[Service] +ExecStart=-/bin/touch /.autorelabel +Type=oneshot +RemainAfterExit=yes + +[Install] +WantedBy=sysinit.target diff --git a/selinux-autorelabel.service b/selinux-autorelabel.service new file mode 100644 index 0000000000000000000000000000000000000000..b8461e6d318b11433a52a4fb3b6475e2813dcb8f --- /dev/null +++ b/selinux-autorelabel.service @@ -0,0 +1,14 @@ +[Unit] +Description=Relabel all filesystems +DefaultDependencies=no +Conflicts=shutdown.target +After=sysinit.target +Before=shutdown.target +ConditionSecurity=selinux + +[Service] +ExecStart=/usr/libexec/selinux/selinux-autorelabel +Type=oneshot +TimeoutSec=0 +RemainAfterExit=yes +StandardInput=tty diff --git a/selinux-autorelabel.target b/selinux-autorelabel.target new file mode 100644 index 0000000000000000000000000000000000000000..a4f63abe53dc6075a9d711977486fef81068806f --- /dev/null +++ b/selinux-autorelabel.target @@ -0,0 +1,7 @@ +[Unit] +Description=Relabel all filesystems and reboot +DefaultDependencies=no +Requires=sysinit.target selinux-autorelabel.service +Conflicts=shutdown.target +After=sysinit.target selinux-autorelabel.service +ConditionSecurity=selinux diff --git a/selinux-dbus-fedora.patch b/selinux-dbus-fedora.patch new file mode 100644 index 0000000000000000000000000000000000000000..28e4cc2c8650e6d251b0fddcde742811c7e3aa0c --- /dev/null +++ b/selinux-dbus-fedora.patch @@ -0,0 +1,35 @@ +diff --git selinux-dbus-2.8/org.selinux.conf selinux-dbus-2.8/org.selinux.conf +index a350978..1ae079d 100644 +--- selinux-dbus-2.8/org.selinux.conf ++++ selinux-dbus-2.8/org.selinux.conf +@@ -12,12 +12,8 @@ + + +- +- +- + +- ++ + + + +diff --git selinux-dbus-2.8/org.selinux.policy selinux-dbus-2.8/org.selinux.policy +index 0126610..9772127 100644 +--- selinux-dbus-2.8/org.selinux.policy ++++ selinux-dbus-2.8/org.selinux.policy +@@ -70,9 +70,9 @@ + auth_admin_keep + + +- +- SELinux write access +- System policy prevents change_policy_type access to SELinux ++ ++ Change SELinux default enforcing mode ++ System policy prevents change_default_policy access to SELinux + + no + no diff --git a/selinux-gui-2.8.tar.gz b/selinux-gui-2.8.tar.gz new file mode 100644 index 0000000000000000000000000000000000000000..a48f699d45a2ed9ca7e406ec4857221bec9227dd Binary files /dev/null and b/selinux-gui-2.8.tar.gz differ diff --git a/selinux-gui-fedora.patch b/selinux-gui-fedora.patch new file mode 100644 index 0000000000000000000000000000000000000000..934de65fdfbb8dfde8dc659946dbedfbec884306 --- /dev/null +++ b/selinux-gui-fedora.patch @@ -0,0 +1,275 @@ +diff --git selinux-gui-2.8/Makefile selinux-gui-2.8/Makefile +index a72e58c..ffe8b97 100644 +--- selinux-gui-2.8/Makefile ++++ selinux-gui-2.8/Makefile +@@ -21,6 +21,7 @@ system-config-selinux.ui \ + usersPage.py + + all: $(TARGETS) system-config-selinux.py polgengui.py ++ (cd po && $(MAKE) $@) + + install: all + -mkdir -p $(DESTDIR)$(MANDIR)/man8 +@@ -46,6 +47,8 @@ install: all + install -m 644 sepolicy_$${i}.png $(DESTDIR)$(DATADIR)/icons/hicolor/$${i}x$${i}/apps/sepolicy.png; \ + done + install -m 644 org.selinux.config.policy $(DESTDIR)$(DATADIR)/polkit-1/actions/ ++ (cd po && $(MAKE) $@) ++ + clean: + + indent: +diff --git selinux-gui-2.8/booleansPage.py selinux-gui-2.8/booleansPage.py +index 7849bea..dd12b6d 100644 +--- selinux-gui-2.8/booleansPage.py ++++ selinux-gui-2.8/booleansPage.py +@@ -38,7 +38,7 @@ DISABLED = 2 + ## + ## I18N + ## +-PROGNAME = "policycoreutils" ++PROGNAME = "selinux-gui" + try: + import gettext + kwargs = {} +diff --git selinux-gui-2.8/domainsPage.py selinux-gui-2.8/domainsPage.py +index bad5140..6bbe4de 100644 +--- selinux-gui-2.8/domainsPage.py ++++ selinux-gui-2.8/domainsPage.py +@@ -30,7 +30,7 @@ from semanagePage import * + ## + ## I18N + ## +-PROGNAME = "policycoreutils" ++PROGNAME = "selinux-gui" + try: + import gettext + kwargs = {} +diff --git selinux-gui-2.8/fcontextPage.py selinux-gui-2.8/fcontextPage.py +index 370bbee..e424366 100644 +--- selinux-gui-2.8/fcontextPage.py ++++ selinux-gui-2.8/fcontextPage.py +@@ -47,7 +47,7 @@ class context: + ## + ## I18N + ## +-PROGNAME = "policycoreutils" ++PROGNAME = "selinux-gui" + try: + import gettext + kwargs = {} +diff --git selinux-gui-2.8/loginsPage.py selinux-gui-2.8/loginsPage.py +index b67eb8b..cbfb0cc 100644 +--- selinux-gui-2.8/loginsPage.py ++++ selinux-gui-2.8/loginsPage.py +@@ -29,7 +29,7 @@ from semanagePage import * + ## + ## I18N + ## +-PROGNAME = "policycoreutils" ++PROGNAME = "selinux-gui" + try: + import gettext + kwargs = {} +diff --git selinux-gui-2.8/modulesPage.py selinux-gui-2.8/modulesPage.py +index 34c5d9e..627ad95 100644 +--- selinux-gui-2.8/modulesPage.py ++++ selinux-gui-2.8/modulesPage.py +@@ -30,7 +30,7 @@ from semanagePage import * + ## + ## I18N + ## +-PROGNAME = "policycoreutils" ++PROGNAME = "selinux-gui" + try: + import gettext + kwargs = {} +diff --git selinux-gui-2.8/po/Makefile selinux-gui-2.8/po/Makefile +new file mode 100644 +index 0000000..a0f5439 +--- /dev/null ++++ selinux-gui-2.8/po/Makefile +@@ -0,0 +1,82 @@ ++# ++# Makefile for the PO files (translation) catalog ++# ++ ++PREFIX ?= /usr ++ ++# What is this package? ++NLSPACKAGE = gui ++POTFILE = $(NLSPACKAGE).pot ++INSTALL = /usr/bin/install -c -p ++INSTALL_DATA = $(INSTALL) -m 644 ++INSTALL_DIR = /usr/bin/install -d ++ ++# destination directory ++INSTALL_NLS_DIR = $(PREFIX)/share/locale ++ ++# PO catalog handling ++MSGMERGE = msgmerge ++MSGMERGE_FLAGS = -q ++XGETTEXT = xgettext --default-domain=$(NLSPACKAGE) ++MSGFMT = msgfmt ++ ++# All possible linguas ++PO_LINGUAS := $(sort $(patsubst %.po,%,$(wildcard *.po))) ++ ++# Only the files matching what the user has set in LINGUAS ++USER_LINGUAS := $(filter $(patsubst %,%%,$(LINGUAS)),$(PO_LINGUAS)) ++ ++# if no valid LINGUAS, build all languages ++USE_LINGUAS := $(if $(USER_LINGUAS),$(USER_LINGUAS),$(PO_LINGUAS)) ++ ++POFILES = $(patsubst %,%.po,$(USE_LINGUAS)) ++MOFILES = $(patsubst %.po,%.mo,$(POFILES)) ++POTFILES = $(shell cat POTFILES) ++ ++#default:: clean ++ ++all:: $(MOFILES) ++ ++$(POTFILE): $(POTFILES) ++ $(XGETTEXT) --keyword=_ --keyword=N_ $(POTFILES) ++ @if cmp -s $(NLSPACKAGE).po $(POTFILE); then \ ++ rm -f $(NLSPACKAGE).po; \ ++ else \ ++ mv -f $(NLSPACKAGE).po $(POTFILE); \ ++ fi; \ ++ ++ ++refresh-po: Makefile ++ for cat in $(POFILES); do \ ++ lang=`basename $$cat .po`; \ ++ if $(MSGMERGE) $(MSGMERGE_FLAGS) $$lang.po $(POTFILE) > $$lang.pot ; then \ ++ mv -f $$lang.pot $$lang.po ; \ ++ echo "$(MSGMERGE) of $$lang succeeded" ; \ ++ else \ ++ echo "$(MSGMERGE) of $$lang failed" ; \ ++ rm -f $$lang.pot ; \ ++ fi \ ++ done ++ ++clean: ++ @rm -fv *mo *~ .depend ++ @rm -rf tmp ++ ++install: $(MOFILES) ++ @for n in $(MOFILES); do \ ++ l=`basename $$n .mo`; \ ++ $(INSTALL_DIR) $(DESTDIR)$(INSTALL_NLS_DIR)/$$l/LC_MESSAGES; \ ++ $(INSTALL_DATA) --verbose $$n $(DESTDIR)$(INSTALL_NLS_DIR)/$$l/LC_MESSAGES/selinux-$(NLSPACKAGE).mo; \ ++ done ++ ++%.mo: %.po ++ $(MSGFMT) -o $@ $< ++report: ++ @for cat in $(wildcard *.po); do \ ++ echo -n "$$cat: "; \ ++ msgfmt -v --statistics -o /dev/null $$cat; \ ++ done ++ ++.PHONY: missing depend ++ ++relabel: +diff --git selinux-gui-2.8/po/POTFILES selinux-gui-2.8/po/POTFILES +new file mode 100644 +index 0000000..1795c5c +--- /dev/null ++++ selinux-gui-2.8/po/POTFILES +@@ -0,0 +1,17 @@ ++../booleansPage.py ++../domainsPage.py ++../fcontextPage.py ++../loginsPage.py ++../modulesPage.py ++../org.selinux.config.policy ++../polgengui.py ++../polgen.ui ++../portsPage.py ++../selinux-polgengui.desktop ++../semanagePage.py ++../sepolicy.desktop ++../statusPage.py ++../system-config-selinux.desktop ++../system-config-selinux.py ++../system-config-selinux.ui ++../usersPage.py +diff --git selinux-gui-2.8/polgengui.py selinux-gui-2.8/polgengui.py +index 1601dbe..7e0d9d0 100644 +--- selinux-gui-2.8/polgengui.py ++++ selinux-gui-2.8/polgengui.py +@@ -63,7 +63,7 @@ def get_all_modules(): + ## + ## I18N + ## +-PROGNAME = "policycoreutils" ++PROGNAME = "selinux-gui" + try: + import gettext + kwargs = {} +diff --git selinux-gui-2.8/portsPage.py selinux-gui-2.8/portsPage.py +index 30f5838..a537ecc 100644 +--- selinux-gui-2.8/portsPage.py ++++ selinux-gui-2.8/portsPage.py +@@ -35,7 +35,7 @@ from semanagePage import * + ## + ## I18N + ## +-PROGNAME = "policycoreutils" ++PROGNAME = "selinux-gui" + try: + import gettext + kwargs = {} +diff --git selinux-gui-2.8/semanagePage.py selinux-gui-2.8/semanagePage.py +index 4127804..5361d69 100644 +--- selinux-gui-2.8/semanagePage.py ++++ selinux-gui-2.8/semanagePage.py +@@ -22,7 +22,7 @@ from gi.repository import Gdk, Gtk + ## + ## I18N + ## +-PROGNAME = "policycoreutils" ++PROGNAME = "selinux-gui" + try: + import gettext + kwargs = {} +diff --git selinux-gui-2.8/statusPage.py selinux-gui-2.8/statusPage.py +index 766854b..a8f079b 100644 +--- selinux-gui-2.8/statusPage.py ++++ selinux-gui-2.8/statusPage.py +@@ -35,7 +35,7 @@ RELABELFILE = "/.autorelabel" + ## + ## I18N + ## +-PROGNAME = "policycoreutils" ++PROGNAME = "selinux-gui" + try: + import gettext + kwargs = {} +diff --git selinux-gui-2.8/system-config-selinux.py selinux-gui-2.8/system-config-selinux.py +index ce7c74b..a81e9dd 100644 +--- selinux-gui-2.8/system-config-selinux.py ++++ selinux-gui-2.8/system-config-selinux.py +@@ -45,7 +45,7 @@ import selinux + ## + ## I18N + ## +-PROGNAME = "policycoreutils" ++PROGNAME = "selinux-gui" + try: + import gettext + kwargs = {} +diff --git selinux-gui-2.8/usersPage.py selinux-gui-2.8/usersPage.py +index 26794ed..d15d4c5 100644 +--- selinux-gui-2.8/usersPage.py ++++ selinux-gui-2.8/usersPage.py +@@ -29,7 +29,7 @@ from semanagePage import * + ## + ## I18N + ## +-PROGNAME = "policycoreutils" ++PROGNAME = "selinux-gui" + try: + import gettext + kwargs = {} diff --git a/selinux-python-fedora.patch b/selinux-python-fedora.patch new file mode 100644 index 0000000000000000000000000000000000000000..f3dc3d63797cc6928faa32e915bf5269213d7b49 --- /dev/null +++ b/selinux-python-fedora.patch @@ -0,0 +1,1665 @@ +diff --git selinux-python-2.8/Makefile selinux-python-2.8/Makefile +index 80bc124..891bdee 100644 +--- selinux-python-2.8/Makefile ++++ selinux-python-2.8/Makefile +@@ -1,4 +1,4 @@ +-SUBDIRS = sepolicy audit2allow semanage sepolgen chcat ++SUBDIRS = sepolicy audit2allow semanage sepolgen chcat po + + all install relabel clean indent: + @for subdir in $(SUBDIRS); do \ +diff --git selinux-python-2.8/audit2allow/audit2allow selinux-python-2.8/audit2allow/audit2allow +index 37ab23a..195f151 100644 +--- selinux-python-2.8/audit2allow/audit2allow ++++ selinux-python-2.8/audit2allow/audit2allow +@@ -86,6 +86,8 @@ class AuditToPolicy: + dest="type") + parser.add_option("--perm-map", dest="perm_map", help="file name of perm map") + parser.add_option("--interface-info", dest="interface_info", help="file name of interface information") ++ parser.add_option("-x", "--xperms", action="store_true", dest="xperms", ++ default=False, help="generate extended permission rules") + parser.add_option("--debug", dest="debug", action="store_true", default=False, + help="leave generated modules for -M") + parser.add_option("-w", "--why", dest="audit2why", action="store_true", default=(os.path.basename(sys.argv[0]) == "audit2why"), +@@ -314,6 +316,10 @@ class AuditToPolicy: + ifs, perm_maps = self.__load_interface_info() + g.set_gen_refpol(ifs, perm_maps) + ++ # Extended permissions ++ if self.__options.xperms: ++ g.set_gen_xperms(True) ++ + # Explanation + if self.__options.verbose: + g.set_gen_explain(policygen.SHORT_EXPLANATION) +diff --git selinux-python-2.8/audit2allow/audit2allow.1 selinux-python-2.8/audit2allow/audit2allow.1 +index 21d286b..c61067b 100644 +--- selinux-python-2.8/audit2allow/audit2allow.1 ++++ selinux-python-2.8/audit2allow/audit2allow.1 +@@ -85,6 +85,9 @@ This is the default behavior. + Generate reference policy using installed macros. + This attempts to match denials against interfaces and may be inaccurate. + .TP ++.B "\-x" | "\-\-xperms" ++Generate extended permission access vector rules ++.TP + .B "\-w" | "\-\-why" + Translates SELinux audit messages into a description of why the access was denied + +diff --git selinux-python-2.8/audit2allow/test.log selinux-python-2.8/audit2allow/test.log +index 05249dc..718aca7 100644 +--- selinux-python-2.8/audit2allow/test.log ++++ selinux-python-2.8/audit2allow/test.log +@@ -34,3 +34,4 @@ node=mary.example.com type=AVC msg=audit(1166023021.373:910): avc: denied { re + node=lilly.example.com type=AVC_PATH msg=audit(1164783469.561:109): path="/linuxtest/LVT/lvt/log.current" + node=lilly.example.com type=SYSCALL msg=audit(1164783469.561:109): arch=14 syscall=11 success=yes exit=0 a0=10120520 a1=10120a78 a2=10120970 a3=118 items=0 ppid=8310 pid=8311 auid=0 uid=0 gid=0 euid=0 suid=0 fsuid=0 egid=0 sgid=0 fsgid=0 tty=(none) comm="smbd" exe="/usr/sbin/smbd" subj=root:system_r:smbd_t:s0 key=(null) + node=lilly.example.com type=AVC msg=audit(1164783469.561:109): avc: denied { append } for pid=8311 comm="smbd" name="log.current" dev=dm-0 ino=130930 scontext=root:system_r:smbd_t:s0 tcontext=root:object_r:default_t:s0 tclass=dir ++node=lilly.example.com type=AVC msg=audit(1164783469.561:109): avc: denied { ioctl } for pid=8311 comm="smbd" name="log.current" ioctlcmd=0x2a scontext=root:system_r:smbd_t:s0 tcontext=root:object_r:default_t:s0 tclass=tcp_socket +diff --git selinux-python-2.8/audit2allow/test_audit2allow.py selinux-python-2.8/audit2allow/test_audit2allow.py +index a826a9f..4427dea 100644 +--- selinux-python-2.8/audit2allow/test_audit2allow.py ++++ selinux-python-2.8/audit2allow/test_audit2allow.py +@@ -47,5 +47,14 @@ class Audit2allowTests(unittest.TestCase): + print(out, err) + self.assertSuccess("audit2why", p.returncode, err) + ++ def test_xperms(self): ++ "Verify that xperms generation works" ++ p = Popen(['python', './audit2allow', "-x", "-i", "test.log"], stdout=PIPE) ++ out, err = p.communicate() ++ if err: ++ print(out, err) ++ self.assertTrue(b"allowxperm" in out) ++ self.assertSuccess("xperms", p.returncode, err) ++ + if __name__ == "__main__": + unittest.main() +diff --git selinux-python-2.8/chcat/chcat selinux-python-2.8/chcat/chcat +index 4bd9fc6..edfe571 100755 +--- selinux-python-2.8/chcat/chcat ++++ selinux-python-2.8/chcat/chcat +@@ -34,7 +34,7 @@ import getopt + import selinux + import seobject + +-PROGNAME = "policycoreutils" ++PROGNAME = "selinux-python" + try: + import gettext + kwargs = {} +diff --git selinux-python-2.8/po/Makefile selinux-python-2.8/po/Makefile +new file mode 100644 +index 0000000..4e052d5 +--- /dev/null ++++ selinux-python-2.8/po/Makefile +@@ -0,0 +1,83 @@ ++# ++# Makefile for the PO files (translation) catalog ++# ++ ++PREFIX ?= /usr ++ ++# What is this package? ++NLSPACKAGE = python ++POTFILE = $(NLSPACKAGE).pot ++INSTALL = /usr/bin/install -c -p ++INSTALL_DATA = $(INSTALL) -m 644 ++INSTALL_DIR = /usr/bin/install -d ++ ++# destination directory ++INSTALL_NLS_DIR = $(PREFIX)/share/locale ++ ++# PO catalog handling ++MSGMERGE = msgmerge ++MSGMERGE_FLAGS = -q ++XGETTEXT = xgettext --default-domain=$(NLSPACKAGE) ++MSGFMT = msgfmt ++ ++# All possible linguas ++PO_LINGUAS := $(sort $(patsubst %.po,%,$(wildcard *.po))) ++ ++# Only the files matching what the user has set in LINGUAS ++USER_LINGUAS := $(filter $(patsubst %,%%,$(LINGUAS)),$(PO_LINGUAS)) ++ ++# if no valid LINGUAS, build all languages ++USE_LINGUAS := $(if $(USER_LINGUAS),$(USER_LINGUAS),$(PO_LINGUAS)) ++ ++POFILES = $(patsubst %,%.po,$(USE_LINGUAS)) ++MOFILES = $(patsubst %.po,%.mo,$(POFILES)) ++POTFILES = $(shell cat POTFILES) ++ ++#default:: clean ++ ++all:: $(MOFILES) ++ ++$(POTFILE): $(POTFILES) ++ $(XGETTEXT) -L Python --keyword=_ --keyword=N_ $(POTFILES) ++ $(XGETTEXT) -j --keyword=_ --keyword=N_ ../sepolicy/sepolicy/sepolicy.glade ++ @if cmp -s $(NLSPACKAGE).po $(POTFILE); then \ ++ rm -f $(NLSPACKAGE).po; \ ++ else \ ++ mv -f $(NLSPACKAGE).po $(POTFILE); \ ++ fi; \ ++ ++ ++refresh-po: Makefile ++ for cat in $(POFILES); do \ ++ lang=`basename $$cat .po`; \ ++ if $(MSGMERGE) $(MSGMERGE_FLAGS) $$lang.po $(POTFILE) > $$lang.pot ; then \ ++ mv -f $$lang.pot $$lang.po ; \ ++ echo "$(MSGMERGE) of $$lang succeeded" ; \ ++ else \ ++ echo "$(MSGMERGE) of $$lang failed" ; \ ++ rm -f $$lang.pot ; \ ++ fi \ ++ done ++ ++clean: ++ @rm -fv *mo *~ .depend ++ @rm -rf tmp ++ ++install: $(MOFILES) ++ @for n in $(MOFILES); do \ ++ l=`basename $$n .mo`; \ ++ $(INSTALL_DIR) $(DESTDIR)$(INSTALL_NLS_DIR)/$$l/LC_MESSAGES; \ ++ $(INSTALL_DATA) --verbose $$n $(DESTDIR)$(INSTALL_NLS_DIR)/$$l/LC_MESSAGES/selinux-$(NLSPACKAGE).mo; \ ++ done ++ ++%.mo: %.po ++ $(MSGFMT) -o $@ $< ++report: ++ @for cat in $(wildcard *.po); do \ ++ echo -n "$$cat: "; \ ++ msgfmt -v --statistics -o /dev/null $$cat; \ ++ done ++ ++.PHONY: missing depend ++ ++relabel: +diff --git selinux-python-2.8/po/POTFILES selinux-python-2.8/po/POTFILES +new file mode 100644 +index 0000000..128eb87 +--- /dev/null ++++ selinux-python-2.8/po/POTFILES +@@ -0,0 +1,10 @@ ++../audit2allow/audit2allow ++../chcat/chcat ++../semanage/semanage ++../semanage/seobject.py ++../sepolgen/src/sepolgen/interfaces.py ++../sepolicy/sepolicy/generate.py ++../sepolicy/sepolicy/gui.py ++../sepolicy/sepolicy/__init__.py ++../sepolicy/sepolicy/interface.py ++../sepolicy/sepolicy.py +diff --git selinux-python-2.8/semanage/semanage selinux-python-2.8/semanage/semanage +index 8d8a086..8fd9395 100644 +--- selinux-python-2.8/semanage/semanage ++++ selinux-python-2.8/semanage/semanage +@@ -27,7 +27,7 @@ import traceback + import argparse + import seobject + import sys +-PROGNAME = "policycoreutils" ++PROGNAME = "selinux-python" + try: + import gettext + kwargs = {} +diff --git selinux-python-2.8/semanage/semanage.8 selinux-python-2.8/semanage/semanage.8 +index 0bdb90f..0cdcfcc 100644 +--- selinux-python-2.8/semanage/semanage.8 ++++ selinux-python-2.8/semanage/semanage.8 +@@ -57,9 +57,8 @@ to SELinux user identities (which controls the initial security context + assigned to Linux users when they login and bounds their authorized role set) + as well as security context mappings for various kinds of objects, such + as network ports, interfaces, infiniband pkeys and endports, and nodes (hosts) +-as well as the file context mapping. See the EXAMPLES section below for some +-examples of common usage. Note that the semanage login command deals with the +-mapping from Linux usernames (logins) to SELinux user identities, ++as well as the file context mapping. Note that the semanage login command deals ++with the mapping from Linux usernames (logins) to SELinux user identities, + while the semanage user command deals with the mapping from SELinux + user identities to authorized role sets. In most cases, only the + former mapping needs to be adjusted by the administrator; the latter +diff --git selinux-python-2.8/semanage/seobject.py selinux-python-2.8/semanage/seobject.py +index c76dce8..27e859e 100644 +--- selinux-python-2.8/semanage/seobject.py ++++ selinux-python-2.8/semanage/seobject.py +@@ -30,7 +30,7 @@ import sys + import stat + import socket + from semanage import * +-PROGNAME = "policycoreutils" ++PROGNAME = "selinux-python" + import sepolicy + import setools + from IPy import IP +@@ -101,6 +101,8 @@ ftype_to_audit = {"": "any", + + try: + import audit ++ #test if audit module is enabled ++ audit.audit_close(audit.audit_open()) + + class logger: + +@@ -138,7 +140,7 @@ try: + + self.log_list = [] + self.log_change_list = [] +-except: ++except (OSError, ImportError): + class logger: + + def __init__(self): +@@ -593,7 +595,6 @@ class loginRecords(semanageRecords): + + semanage_seuser_key_free(k) + semanage_seuser_free(u) +- self.mylog.log("login", name, sename=sename, serange=serange, serole=",".join(serole), oldserole=",".join(oldserole), oldsename=self.oldsename, oldserange=self.oldserange) + + def add(self, name, sename, serange): + try: +@@ -601,7 +602,6 @@ class loginRecords(semanageRecords): + self.__add(name, sename, serange) + self.commit() + except ValueError as error: +- self.mylog.commit(0) + raise error + + def __modify(self, name, sename="", serange=""): +@@ -653,7 +653,6 @@ class loginRecords(semanageRecords): + + semanage_seuser_key_free(k) + semanage_seuser_free(u) +- self.mylog.log("login", name, sename=self.sename, serange=self.serange, serole=",".join(serole), oldserole=",".join(oldserole), oldsename=self.oldsename, oldserange=self.oldserange) + + def modify(self, name, sename="", serange=""): + try: +@@ -661,7 +660,6 @@ class loginRecords(semanageRecords): + self.__modify(name, sename, serange) + self.commit() + except ValueError as error: +- self.mylog.commit(0) + raise error + + def __delete(self, name): +@@ -694,8 +692,6 @@ class loginRecords(semanageRecords): + rec, self.sename, self.serange = selinux.getseuserbyname("__default__") + range, (rc, serole) = userrec.get(self.sename) + +- self.mylog.log_remove("login", name, sename=self.sename, serange=self.serange, serole=",".join(serole), oldserole=",".join(oldserole), oldsename=self.oldsename, oldserange=self.oldserange) +- + def delete(self, name): + try: + self.begin() +@@ -703,7 +699,6 @@ class loginRecords(semanageRecords): + self.commit() + + except ValueError as error: +- self.mylog.commit(0) + raise error + + def deleteall(self): +@@ -717,7 +712,6 @@ class loginRecords(semanageRecords): + self.__delete(semanage_seuser_get_name(u)) + self.commit() + except ValueError as error: +- self.mylog.commit(0) + raise error + + def get_all_logins(self): +diff --git selinux-python-2.8/sepolgen/src/sepolgen/access.py selinux-python-2.8/sepolgen/src/sepolgen/access.py +index a5d8698..ba80f93 100644 +--- selinux-python-2.8/sepolgen/src/sepolgen/access.py ++++ selinux-python-2.8/sepolgen/src/sepolgen/access.py +@@ -78,6 +78,7 @@ class AccessVector(util.Comparison): + .obj_class - The object class to which access is allowed. [String or None] + .perms - The permissions allowed to the object class. [IdSet] + .audit_msgs - The audit messages that generated this access vector [List of strings] ++ .xperms - Extended permissions attached to the AV. [Dictionary {operation: xperm set}] + """ + def __init__(self, init_list=None): + if init_list: +@@ -87,9 +88,11 @@ class AccessVector(util.Comparison): + self.tgt_type = None + self.obj_class = None + self.perms = refpolicy.IdSet() +- self.audit_msgs = [] +- self.type = audit2why.TERULE +- self.data = [] ++ ++ self.audit_msgs = [] ++ self.type = audit2why.TERULE ++ self.data = [] ++ self.xperms = {} + # when implementing __eq__ also __hash__ is needed on py2 + # if object is muttable __hash__ should be None + self.__hash__ = None +@@ -131,6 +134,15 @@ class AccessVector(util.Comparison): + l.extend(sorted(self.perms)) + return l + ++ def merge(self, av): ++ """Add permissions and extended permissions from AV""" ++ self.perms.update(av.perms) ++ ++ for op in av.xperms: ++ if op not in self.xperms: ++ self.xperms[op] = refpolicy.XpermSet() ++ self.xperms[op].extend(av.xperms[op]) ++ + def __str__(self): + return self.to_string() + +@@ -260,28 +272,28 @@ class AccessVectorSet: + def add(self, src_type, tgt_type, obj_class, perms, audit_msg=None, avc_type=audit2why.TERULE, data=[]): + """Add an access vector to the set. + """ +- tgt = self.src.setdefault(src_type, { }) +- cls = tgt.setdefault(tgt_type, { }) +- +- if (obj_class, avc_type) in cls: +- access = cls[obj_class, avc_type] +- else: +- access = AccessVector() +- access.src_type = src_type +- access.tgt_type = tgt_type +- access.obj_class = obj_class +- access.data = data +- access.type = avc_type +- cls[obj_class, avc_type] = access +- +- access.perms.update(perms) +- if audit_msg: +- access.audit_msgs.append(audit_msg) ++ av = AccessVector() ++ av.src_type = src_type ++ av.tgt_type = tgt_type ++ av.obj_class = obj_class ++ av.perms = perms ++ av.data = data ++ av.type = avc_type ++ ++ self.add_av(av, audit_msg) + + def add_av(self, av, audit_msg=None): + """Add an access vector to the set.""" +- self.add(av.src_type, av.tgt_type, av.obj_class, av.perms) ++ tgt = self.src.setdefault(av.src_type, { }) ++ cls = tgt.setdefault(av.tgt_type, { }) + ++ if (av.obj_class, av.type) in cls: ++ cls[av.obj_class, av.type].merge(av) ++ else: ++ cls[av.obj_class, av.type] = av ++ ++ if audit_msg: ++ cls[av.obj_class, av.type].audit_msgs.append(audit_msg) + + def avs_extract_types(avs): + types = refpolicy.IdSet() +diff --git selinux-python-2.8/sepolgen/src/sepolgen/audit.py selinux-python-2.8/sepolgen/src/sepolgen/audit.py +index 26ce6c9..daed58c 100644 +--- selinux-python-2.8/sepolgen/src/sepolgen/audit.py ++++ selinux-python-2.8/sepolgen/src/sepolgen/audit.py +@@ -152,6 +152,7 @@ class AVCMessage(AuditMessage): + access - list of accesses that were allowed or denied + denial - boolean indicating whether this was a denial (True) or granted + (False) message. ++ ioctlcmd - ioctl 'request' parameter + + An example audit message generated from the audit daemon looks like (line breaks + added): +@@ -178,6 +179,7 @@ class AVCMessage(AuditMessage): + self.name = "" + self.accesses = [] + self.denial = True ++ self.ioctlcmd = None + self.type = audit2why.TERULE + + def __parse_access(self, recs, start): +@@ -237,6 +239,11 @@ class AVCMessage(AuditMessage): + self.exe = fields[1][1:-1] + elif fields[0] == "name": + self.name = fields[1][1:-1] ++ elif fields[0] == "ioctlcmd": ++ try: ++ self.ioctlcmd = int(fields[1], 16) ++ except ValueError: ++ pass + + if not found_src or not found_tgt or not found_class or not found_access: + raise ValueError("AVC message in invalid format [%s]\n" % self.message) +@@ -522,13 +529,20 @@ class AuditParser: + for avc in self.avc_msgs: + if avc.denial != True and only_denials: + continue +- if avc_filter: +- if avc_filter.filter(avc): +- av_set.add(avc.scontext.type, avc.tcontext.type, avc.tclass, +- avc.accesses, avc, avc_type=avc.type, data=avc.data) +- else: +- av_set.add(avc.scontext.type, avc.tcontext.type, avc.tclass, +- avc.accesses, avc, avc_type=avc.type, data=avc.data) ++ ++ if not avc_filter or avc_filter.filter(avc): ++ av = access.AccessVector([avc.scontext.type, avc.tcontext.type, ++ avc.tclass] + avc.accesses) ++ av.data = avc.data ++ av.type = avc.type ++ ++ if avc.ioctlcmd: ++ xperm_set = refpolicy.XpermSet() ++ xperm_set.add(avc.ioctlcmd) ++ av.xperms["ioctl"] = xperm_set ++ ++ av_set.add_av(av, audit_msg=avc) ++ + return av_set + + class AVCTypeFilter: +diff --git selinux-python-2.8/sepolgen/src/sepolgen/policygen.py selinux-python-2.8/sepolgen/src/sepolgen/policygen.py +index ee664fb..319da15 100644 +--- selinux-python-2.8/sepolgen/src/sepolgen/policygen.py ++++ selinux-python-2.8/sepolgen/src/sepolgen/policygen.py +@@ -50,10 +50,11 @@ class PolicyGenerator: + in the form of access vectors. + + It generates allow rules and optionally module require +- statements and reference policy interfaces. By default +- only allow rules are generated. The methods .set_gen_refpol +- and .set_gen_requires turns on interface generation and +- requires generation respectively. ++ statements, reference policy interfaces, and extended ++ permission access vector rules. By default only allow rules ++ are generated. The methods .set_gen_refpol, .set_gen_requires ++ and .set_gen_xperms turns on interface generation, ++ requires generation, and xperms rules genration respectively. + + PolicyGenerator can also optionally add comments explaining + why a particular access was allowed based on the audit +@@ -82,6 +83,7 @@ class PolicyGenerator: + self.module = refpolicy.Module() + + self.dontaudit = False ++ self.xperms = False + + self.domains = None + def set_gen_refpol(self, if_set=None, perm_maps=None): +@@ -120,6 +122,12 @@ class PolicyGenerator: + def set_gen_dontaudit(self, dontaudit): + self.dontaudit = dontaudit + ++ def set_gen_xperms(self, xperms): ++ """Set whether extended permission access vector rules ++ are generated. ++ """ ++ self.xperms = xperms ++ + def __set_module_style(self): + if self.ifgen: + refpolicy = True +@@ -153,51 +161,69 @@ class PolicyGenerator: + """Return the generated module""" + return self.module + +- def __add_allow_rules(self, avs): +- for av in avs: +- rule = refpolicy.AVRule(av) ++ def __add_av_rule(self, av): ++ """Add access vector rule. ++ """ ++ rule = refpolicy.AVRule(av) ++ ++ if self.dontaudit: ++ rule.rule_type = rule.DONTAUDIT ++ rule.comment = "" ++ if self.explain: ++ rule.comment = str(refpolicy.Comment(explain_access(av, verbosity=self.explain))) ++ ++ if av.type == audit2why.ALLOW: ++ rule.comment += "\n#!!!! This avc is allowed in the current policy" ++ ++ if av.xperms: ++ rule.comment += "\n#!!!! This av rule may have been overridden by an extended permission av rule" ++ ++ if av.type == audit2why.DONTAUDIT: ++ rule.comment += "\n#!!!! This avc has a dontaudit rule in the current policy" ++ ++ if av.type == audit2why.BOOLEAN: ++ if len(av.data) > 1: ++ rule.comment += "\n#!!!! This avc can be allowed using one of the these booleans:\n# %s" % ", ".join([x[0] for x in av.data]) ++ else: ++ rule.comment += "\n#!!!! This avc can be allowed using the boolean '%s'" % av.data[0][0] ++ ++ if av.type == audit2why.CONSTRAINT: ++ rule.comment += "\n#!!!! This avc is a constraint violation. You would need to modify the attributes of either the source or target types to allow this access." ++ rule.comment += "\n#Constraint rule: " ++ rule.comment += "\n#\t" + av.data[0] ++ for reason in av.data[1:]: ++ rule.comment += "\n#\tPossible cause is the source %s and target %s are different." % reason ++ ++ try: ++ if ( av.type == audit2why.TERULE and ++ "write" in av.perms and ++ ( "dir" in av.obj_class or "open" in av.perms )): ++ if not self.domains: ++ self.domains = seinfo(ATTRIBUTE, name="domain")[0]["types"] ++ types=[] ++ ++ for i in [x[TCONTEXT] for x in sesearch([ALLOW], {SCONTEXT: av.src_type, CLASS: av.obj_class, PERMS: av.perms})]: ++ if i not in self.domains: ++ types.append(i) ++ if len(types) == 1: ++ rule.comment += "\n#!!!! The source type '%s' can write to a '%s' of the following type:\n# %s\n" % ( av.src_type, av.obj_class, ", ".join(types)) ++ elif len(types) >= 1: ++ rule.comment += "\n#!!!! The source type '%s' can write to a '%s' of the following types:\n# %s\n" % ( av.src_type, av.obj_class, ", ".join(types)) ++ except: ++ pass ++ ++ self.module.children.append(rule) ++ ++ def __add_ext_av_rules(self, av): ++ """Add extended permission access vector rules. ++ """ ++ for op in av.xperms.keys(): ++ extrule = refpolicy.AVExtRule(av, op) ++ + if self.dontaudit: +- rule.rule_type = rule.DONTAUDIT +- rule.comment = "" +- if self.explain: +- rule.comment = str(refpolicy.Comment(explain_access(av, verbosity=self.explain))) +- if av.type == audit2why.ALLOW: +- rule.comment += "\n#!!!! This avc is allowed in the current policy" +- if av.type == audit2why.DONTAUDIT: +- rule.comment += "\n#!!!! This avc has a dontaudit rule in the current policy" +- +- if av.type == audit2why.BOOLEAN: +- if len(av.data) > 1: +- rule.comment += "\n#!!!! This avc can be allowed using one of the these booleans:\n# %s" % ", ".join([x[0] for x in av.data]) +- else: +- rule.comment += "\n#!!!! This avc can be allowed using the boolean '%s'" % av.data[0][0] +- +- if av.type == audit2why.CONSTRAINT: +- rule.comment += "\n#!!!! This avc is a constraint violation. You would need to modify the attributes of either the source or target types to allow this access." +- rule.comment += "\n#Constraint rule: " +- rule.comment += "\n#\t" + av.data[0] +- for reason in av.data[1:]: +- rule.comment += "\n#\tPossible cause is the source %s and target %s are different." % reason +- +- try: +- if ( av.type == audit2why.TERULE and +- "write" in av.perms and +- ( "dir" in av.obj_class or "open" in av.perms )): +- if not self.domains: +- self.domains = seinfo(ATTRIBUTE, name="domain")[0]["types"] +- types=[] +- +- for i in [x[TCONTEXT] for x in sesearch([ALLOW], {SCONTEXT: av.src_type, CLASS: av.obj_class, PERMS: av.perms})]: +- if i not in self.domains: +- types.append(i) +- if len(types) == 1: +- rule.comment += "\n#!!!! The source type '%s' can write to a '%s' of the following type:\n# %s\n" % ( av.src_type, av.obj_class, ", ".join(types)) +- elif len(types) >= 1: +- rule.comment += "\n#!!!! The source type '%s' can write to a '%s' of the following types:\n# %s\n" % ( av.src_type, av.obj_class, ", ".join(types)) +- except: +- pass +- self.module.children.append(rule) ++ extrule.rule_type = extrule.DONTAUDITXPERM + ++ self.module.children.append(extrule) + + def add_access(self, av_set): + """Add the access from the access vector set to this +@@ -215,7 +241,10 @@ class PolicyGenerator: + raw_allow = av_set + + # Generate the raw allow rules from the filtered list +- self.__add_allow_rules(raw_allow) ++ for av in raw_allow: ++ self.__add_av_rule(av) ++ if self.xperms and av.xperms: ++ self.__add_ext_av_rules(av) + + def add_role_types(self, role_type_set): + for role_type in role_type_set: +diff --git selinux-python-2.8/sepolgen/src/sepolgen/refparser.py selinux-python-2.8/sepolgen/src/sepolgen/refparser.py +index 2cef8e8..3415aff 100644 +--- selinux-python-2.8/sepolgen/src/sepolgen/refparser.py ++++ selinux-python-2.8/sepolgen/src/sepolgen/refparser.py +@@ -786,7 +786,7 @@ def p_role_allow(p): + + def p_permissive(p): + 'permissive : PERMISSIVE names SEMI' +- t.skip(1) ++ pass + + def p_avrule_def(p): + '''avrule_def : ALLOW names names COLON names names SEMI +diff --git selinux-python-2.8/sepolgen/src/sepolgen/refpolicy.py selinux-python-2.8/sepolgen/src/sepolgen/refpolicy.py +index 352b187..c30a8c7 100644 +--- selinux-python-2.8/sepolgen/src/sepolgen/refpolicy.py ++++ selinux-python-2.8/sepolgen/src/sepolgen/refpolicy.py +@@ -109,6 +109,9 @@ class Node(PolicyBase): + def avrules(self): + return filter(lambda x: isinstance(x, AVRule), walktree(self)) + ++ def avextrules(self): ++ return filter(lambda x: isinstance(x, AVExtRule), walktree(self)) ++ + def typerules(self): + return filter(lambda x: isinstance(x, TypeRule), walktree(self)) + +@@ -352,6 +355,65 @@ class ObjectClass(Leaf): + self.name = name + self.perms = IdSet() + ++class XpermSet(): ++ """Extended permission set. ++ ++ This class represents one or more extended permissions ++ represented by numeric values or ranges of values. The ++ .complement attribute is used to specify all permission ++ except those specified. ++ ++ Two xperm set can be merged using the .extend() method. ++ """ ++ def __init__(self, complement=False): ++ self.complement = complement ++ self.ranges = [] ++ ++ def __normalize_ranges(self): ++ """Ensure that ranges are not overlapping. ++ """ ++ self.ranges.sort() ++ ++ i = 0 ++ while i < len(self.ranges): ++ while i + 1 < len(self.ranges): ++ if self.ranges[i + 1][0] <= self.ranges[i][1] + 1: ++ self.ranges[i] = (self.ranges[i][0], max(self.ranges[i][1], ++ self.ranges[i + 1][1])) ++ del self.ranges[i + 1] ++ else: ++ break ++ i += 1 ++ ++ def extend(self, s): ++ """Add ranges from an xperm set ++ """ ++ self.ranges.extend(s.ranges) ++ self.__normalize_ranges() ++ ++ def add(self, minimum, maximum=None): ++ """Add value of range of values to the xperm set. ++ """ ++ if maximum is None: ++ maximum = minimum ++ self.ranges.append((minimum, maximum)) ++ self.__normalize_ranges() ++ ++ def to_string(self): ++ if not self.ranges: ++ return "" ++ ++ compl = "~ " if self.complement else "" ++ ++ # print single value without braces ++ if len(self.ranges) == 1 and self.ranges[0][0] == self.ranges[0][1]: ++ return compl + str(self.ranges[0][0]) ++ ++ vals = map(lambda x: str(x[0]) if x[0] == x[1] else "%s-%s" % x, ++ self.ranges) ++ ++ return "%s{ %s }" % (compl, " ".join(vals)) ++ + # Basic statements + + class TypeAttribute(Leaf): +@@ -472,8 +534,10 @@ class AVRule(Leaf): + return "allow" + elif self.rule_type == self.DONTAUDIT: + return "dontaudit" +- else: ++ elif self.rule_type == self.AUDITALLOW: + return "auditallow" ++ elif self.rule_type == self.NEVERALLOW: ++ return "neverallow" + + def from_av(self, av): + """Add the access from an access vector to this allow +@@ -497,6 +561,65 @@ class AVRule(Leaf): + self.tgt_types.to_space_str(), + self.obj_classes.to_space_str(), + self.perms.to_space_str()) ++ ++class AVExtRule(Leaf): ++ """Extended permission access vector rule. ++ ++ The AVExtRule class represents allowxperm, dontauditxperm, ++ auditallowxperm, and neverallowxperm rules. ++ ++ The source and target types, and object classes are represented ++ by sets containing strings. The operation is a single string, ++ e.g. 'ioctl'. Extended permissions are represented by an XpermSet. ++ """ ++ ALLOWXPERM = 0 ++ DONTAUDITXPERM = 1 ++ AUDITALLOWXPERM = 2 ++ NEVERALLOWXPERM = 3 ++ ++ def __init__(self, av=None, op=None, parent=None): ++ Leaf.__init__(self, parent) ++ self.src_types = IdSet() ++ self.tgt_types = IdSet() ++ self.obj_classes = IdSet() ++ self.rule_type = self.ALLOWXPERM ++ self.xperms = XpermSet() ++ self.operation = op ++ if av: ++ self.from_av(av, op) ++ ++ def __rule_type_str(self): ++ if self.rule_type == self.ALLOWXPERM: ++ return "allowxperm" ++ elif self.rule_type == self.DONTAUDITXPERM: ++ return "dontauditxperm" ++ elif self.rule_type == self.AUDITALLOWXPERM: ++ return "auditallowxperm" ++ elif self.rule_type == self.NEVERALLOWXPERM: ++ return "neverallowxperm" ++ ++ def from_av(self, av, op): ++ self.src_types.add(av.src_type) ++ if av.src_type == av.tgt_type: ++ self.tgt_types.add("self") ++ else: ++ self.tgt_types.add(av.tgt_type) ++ self.obj_classes.add(av.obj_class) ++ self.operation = op ++ self.xperms = av.xperms[op] ++ ++ def to_string(self): ++ """Return a string representation of the rule that is ++ a valid policy language representation (assuming that ++ the types, object class, etc. are valid). ++ """ ++ return "%s %s %s:%s %s %s;" % (self.__rule_type_str(), ++ self.src_types.to_space_str(), ++ self.tgt_types.to_space_str(), ++ self.obj_classes.to_space_str(), ++ self.operation, ++ self.xperms.to_string()) ++ + class TypeRule(Leaf): + """SELinux type rules. + +diff --git selinux-python-2.8/sepolgen/src/sepolgen/sepolgeni18n.py selinux-python-2.8/sepolgen/src/sepolgen/sepolgeni18n.py +index 998c435..56ebd80 100644 +--- selinux-python-2.8/sepolgen/src/sepolgen/sepolgeni18n.py ++++ selinux-python-2.8/sepolgen/src/sepolgen/sepolgeni18n.py +@@ -19,7 +19,7 @@ + + try: + import gettext +- t = gettext.translation( 'yumex' ) ++ t = gettext.translation( 'selinux-python' ) + _ = t.gettext + except: + def _(str): +diff --git selinux-python-2.8/sepolgen/src/sepolgen/util.py selinux-python-2.8/sepolgen/src/sepolgen/util.py +index 1fca971..b3d2616 100644 +--- selinux-python-2.8/sepolgen/src/sepolgen/util.py ++++ selinux-python-2.8/sepolgen/src/sepolgen/util.py +@@ -125,7 +125,7 @@ class Comparison(): + _compare function within your class.""" + + def _compare(self, other, method): +- raise NotImplemented ++ return NotImplemented + + def __eq__(self, other): + return self._compare(other, lambda a, b: a == b) +diff --git selinux-python-2.8/sepolgen/tests/test_access.py selinux-python-2.8/sepolgen/tests/test_access.py +index d45a823..73a5407 100644 +--- selinux-python-2.8/sepolgen/tests/test_access.py ++++ selinux-python-2.8/sepolgen/tests/test_access.py +@@ -32,6 +32,7 @@ class TestAccessVector(unittest.TestCase): + self.assertEqual(a.obj_class, None) + self.assertTrue(isinstance(a.perms, refpolicy.IdSet)) + self.assertTrue(isinstance(a.audit_msgs, type([]))) ++ self.assertTrue(isinstance(a.xperms, type({}))) + self.assertEqual(len(a.audit_msgs), 0) + + # Construction from a list +@@ -61,6 +62,10 @@ class TestAccessVector(unittest.TestCase): + self.assertEqual(a.obj_class, l.obj_class) + self.assertEqual(a.perms, l.perms) + ++ l2 = access.AccessVector() ++ with self.assertRaises(ValueError): ++ l2.from_list(['foo', 'bar', 'file']) ++ + def test_to_list(self): + a = access.AccessVector() + a.src_type = "foo" +@@ -145,7 +150,80 @@ class TestAccessVector(unittest.TestCase): + + b.perms = refpolicy.IdSet(["read", "append"]) + self.assertNotEqual(a, b) ++ ++ def test_merge_noxperm(self): ++ """Test merging two AVs without xperms""" ++ a = access.AccessVector(["foo", "bar", "file", "read", "write"]) ++ b = access.AccessVector(["foo", "bar", "file", "append"]) ++ ++ a.merge(b) ++ self.assertEqual(sorted(list(a.perms)), ["append", "read", "write"]) ++ ++ def text_merge_xperm1(self): ++ """Test merging AV that contains xperms with AV that does not""" ++ a = access.AccessVector(["foo", "bar", "file", "read"]) ++ b = access.AccessVector(["foo", "bar", "file", "read"]) ++ xp = refpolicy.XpermSet() ++ xp.add(42) ++ xp.add(12345) ++ b.xperms = {"ioctl": xp} ++ ++ a.merge(b) ++ self.assertEqual(sorted(list(a.perms)), ["append", "read", "write"]) ++ self.assertEqual(list(a.xperms.keys()), ["ioctl"]) ++ self.assertEqual(a.xperms["ioctl"].to_string(), "{ 42 12345 }") ++ ++ def text_merge_xperm2(self): ++ """Test merging AV that does not contain xperms with AV that does""" ++ a = access.AccessVector(["foo", "bar", "file", "read"]) ++ xp = refpolicy.XpermSet() ++ xp.add(42) ++ xp.add(12345) ++ a.xperms = {"ioctl": xp} ++ b = access.AccessVector(["foo", "bar", "file", "read"]) ++ ++ a.merge(b) ++ self.assertEqual(sorted(list(a.perms)), ["append", "read", "write"]) ++ self.assertEqual(list(a.xperms.keys()), ["ioctl"]) ++ self.assertEqual(a.xperms["ioctl"].to_string(), "{ 42 12345 }") ++ ++ def test_merge_xperm_diff_op(self): ++ """Test merging two AVs that contain xperms with different operation""" ++ a = access.AccessVector(["foo", "bar", "file", "read"]) ++ xp1 = refpolicy.XpermSet() ++ xp1.add(23) ++ a.xperms = {"asdf": xp1} ++ ++ b = access.AccessVector(["foo", "bar", "file", "read"]) ++ xp2 = refpolicy.XpermSet() ++ xp2.add(42) ++ xp2.add(12345) ++ b.xperms = {"ioctl": xp2} ++ ++ a.merge(b) ++ self.assertEqual(list(a.perms), ["read"]) ++ self.assertEqual(sorted(list(a.xperms.keys())), ["asdf", "ioctl"]) ++ self.assertEqual(a.xperms["asdf"].to_string(), "23") ++ self.assertEqual(a.xperms["ioctl"].to_string(), "{ 42 12345 }") + ++ def test_merge_xperm_same_op(self): ++ """Test merging two AVs that contain xperms with same operation""" ++ a = access.AccessVector(["foo", "bar", "file", "read"]) ++ xp1 = refpolicy.XpermSet() ++ xp1.add(23) ++ a.xperms = {"ioctl": xp1} ++ ++ b = access.AccessVector(["foo", "bar", "file", "read"]) ++ xp2 = refpolicy.XpermSet() ++ xp2.add(42) ++ xp2.add(12345) ++ b.xperms = {"ioctl": xp2} ++ ++ a.merge(b) ++ self.assertEqual(list(a.perms), ["read"]) ++ self.assertEqual(list(a.xperms.keys()), ["ioctl"]) ++ self.assertEqual(a.xperms["ioctl"].to_string(), "{ 23 42 12345 }") ++ + class TestUtilFunctions(unittest.TestCase): + def test_is_idparam(self): + self.assertTrue(access.is_idparam("$1")) +@@ -260,3 +338,53 @@ class TestAccessVectorSet(unittest.TestCase): + b = access.AccessVectorSet() + b.from_list(avl) + self.assertEqual(len(b), 3) ++ ++ def test_add_av_first(self): ++ """Test adding first AV to the AV set""" ++ avs = access.AccessVectorSet() ++ av = access.AccessVector(['foo', 'bar', 'file', 'read']) ++ ++ avs.add_av(av) ++ ++ self.assertEqual(avs.to_list(), [['foo', 'bar', 'file', 'read']]) ++ ++ def test_add_av_second(self): ++ """Test adding second AV to the AV set with same source and target ++ context and class""" ++ avs = access.AccessVectorSet() ++ av1 = access.AccessVector(['foo', 'bar', 'file', 'read']) ++ av2 = access.AccessVector(['foo', 'bar', 'file', 'write']) ++ ++ avs.add_av(av1) ++ avs.add_av(av2) ++ ++ self.assertEqual(avs.to_list(), [['foo', 'bar', 'file', 'read', ++ 'write']]) ++ ++ def test_add_av_with_msg(self): ++ """Test adding audit message""" ++ avs = access.AccessVectorSet() ++ av = access.AccessVector(['foo', 'bar', 'file', 'read']) ++ ++ avs.add_av(av, 'test message') ++ ++ self.assertEqual(avs.src['foo']['bar']['file', av.type].audit_msgs, ++ ['test message']) ++ ++ def test_add(self): ++ """Test adding AV to the set""" ++ s = access.AccessVectorSet() ++ ++ def test_add_av(av, audit_msg=None): ++ self.assertEqual(av.src_type, 'foo') ++ self.assertEqual(av.tgt_type, 'bar') ++ self.assertEqual(av.obj_class, 'file') ++ self.assertEqual(list(av.perms), ['read']) ++ self.assertEqual(av.data, 'test data') ++ self.assertEqual(av.type, 42) ++ self.assertEqual(audit_msg, 'test message') ++ ++ s.add_av = test_add_av ++ ++ s.add("foo", "bar", "file", refpolicy.IdSet(["read"]), ++ audit_msg='test message', avc_type=42, data='test data') +diff --git selinux-python-2.8/sepolgen/tests/test_audit.py selinux-python-2.8/sepolgen/tests/test_audit.py +index 6379954..dbe6be2 100644 +--- selinux-python-2.8/sepolgen/tests/test_audit.py ++++ selinux-python-2.8/sepolgen/tests/test_audit.py +@@ -56,6 +56,18 @@ type=SYSCALL msg=audit(1162852201.019:1225): arch=40000003 syscall=11 success=ye + type=AVC msg=audit(1162852201.019:1225): avc: denied { execute_no_trans } for pid=6974 comm="sh" name="sa1" dev=dm-0 ino=13061698 scontext=system_u:system_r:crond_t:s0-s0:c0.c1023 tcontext=system_u:object_r:lib_t:s0 tclass=file + type=AVC msg=audit(1162852201.019:1225): avc: denied { execute } for pid=6974 comm="sh" name="sa1" dev=dm-0 ino=13061698 scontext=system_u:system_r:crond_t:s0-s0:c0.c1023 tcontext=system_u:object_r:lib_t:s0 tclass=file""" + ++xperms1 = """type=AVC msg=audit(1516626657.910:4461): avc: denied { ioctl } for pid=4310 comm="test" path="/root/test" ino=8619937 ioctlcmd=0x42 scontext=unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023 tcontext=unconfined_u:object_r:test_file_t:s0 tclass=file permissive=0 ++""" ++xperms2 = """type=AVC msg=audit(1516626657.910:4461): avc: denied { ioctl } for pid=4310 comm="test" path="/root/test" ino=8619937 ioctlcmd=0x42 scontext=unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023 tcontext=unconfined_u:object_r:test_file_t:s0 tclass=file permissive=0 ++type=AVC msg=audit(1516626657.910:4461): avc: denied { ioctl } for pid=4310 comm="test" path="/root/test" ino=8619937 ioctlcmd=0x1234 scontext=unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023 tcontext=unconfined_u:object_r:test_file_t:s0 tclass=file permissive=0 ++type=AVC msg=audit(1516626657.910:4461): avc: denied { ioctl } for pid=4310 comm="test" path="/root/test" ino=8619937 ioctlcmd=0xdead scontext=unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023 tcontext=unconfined_u:object_r:test_file_t:s0 tclass=file permissive=0 ++type=AVC msg=audit(1516626657.910:4461): avc: denied { getattr } for pid=4310 comm="test" path="/root/test" ino=8619937 scontext=unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023 tcontext=unconfined_u:object_r:test_file_t:s0 tclass=dir permissive=0 ++""" ++xperms_invalid = """type=AVC msg=audit(1516626657.910:4461): avc: denied { ioctl } for pid=4310 comm="test" path="/root/test" ino=8619937 ioctlcmd=asdf scontext=unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023 tcontext=unconfined_u:object_r:test_file_t:s0 tclass=file permissive=0 ++""" ++xperms_without = """type=AVC msg=audit(1516626657.910:4461): avc: denied { ioctl } for pid=4310 comm="test" path="/root/test" ino=8619937 scontext=unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023 tcontext=unconfined_u:object_r:test_file_t:s0 tclass=file permissive=0 ++""" ++ + class TestAVCMessage(unittest.TestCase): + def test_defs(self): + avc = sepolgen.audit.AVCMessage(audit1) +@@ -64,6 +76,7 @@ class TestAVCMessage(unittest.TestCase): + self.assertEqual(avc.tcontext, sc) + self.assertEqual(avc.tclass, "") + self.assertEqual(avc.accesses, []) ++ self.assertEqual(avc.ioctlcmd, None) + + def test_granted(self): + avc = sepolgen.audit.AVCMessage(granted1) +@@ -84,6 +97,29 @@ class TestAVCMessage(unittest.TestCase): + + self.assertEqual(avc.denial, False) + ++ def test_xperms(self): ++ """Test that the ioctlcmd field is parsed""" ++ avc = sepolgen.audit.AVCMessage(xperms1) ++ recs = xperms1.split() ++ avc.from_split_string(recs) ++ ++ self.assertEqual(avc.ioctlcmd, 66) ++ ++ def test_xperms_invalid(self): ++ """Test message with invalid value in the ioctlcmd field""" ++ avc = sepolgen.audit.AVCMessage(xperms_invalid) ++ recs = xperms_invalid.split() ++ avc.from_split_string(recs) ++ ++ self.assertIsNone(avc.ioctlcmd) ++ ++ def test_xperms_without(self): ++ """Test message without the ioctlcmd field""" ++ avc = sepolgen.audit.AVCMessage(xperms_without) ++ recs = xperms_without.split() ++ avc.from_split_string(recs) ++ ++ self.assertIsNone(avc.ioctlcmd) + + def test_from_split_string(self): + # syslog message +@@ -172,6 +208,20 @@ class TestAuditParser(unittest.TestCase): + self.assertEqual(len(a.invalid_msgs), 0) + self.assertEqual(len(a.policy_load_msgs), 0) + ++ def test_parse_xperms(self): ++ """ Test that correct access vectors are generated from a set of AVC ++ denial messages. """ ++ a = sepolgen.audit.AuditParser() ++ a.parse_string(xperms2) ++ av_set = a.to_access() ++ ++ self.assertEqual(len(av_set), 2) ++ av_list = list(sorted(av_set)) ++ self.assertEqual(av_list[0].xperms, {}) ++ self.assertEqual(list(av_list[1].xperms), ["ioctl"]) ++ self.assertEqual(av_list[1].xperms["ioctl"].ranges, [(66,66), ++ (4660,4660), (57005,57005)]) ++ + class TestGeneration(unittest.TestCase): + def test_generation(self): + parser = sepolgen.audit.AuditParser() +diff --git selinux-python-2.8/sepolgen/tests/test_policygen.py selinux-python-2.8/sepolgen/tests/test_policygen.py +index 58d1adf..59496e8 100644 +--- selinux-python-2.8/sepolgen/tests/test_policygen.py ++++ selinux-python-2.8/sepolgen/tests/test_policygen.py +@@ -19,13 +19,117 @@ + + import unittest + import sepolgen.policygen as policygen ++import sepolgen.access as access ++import sepolgen.refpolicy as refpolicy + +-class PolicyGenerator(unittest.TestCase): +- def __init__(self): +- g = policygen.PolicyGenerator() +- ++class TestPolicyGenerator(unittest.TestCase): ++ def setUp(self): ++ self.g = policygen.PolicyGenerator() + ++ def test_init(self): ++ """ Test that extended permission AV rules are not generated by ++ default. """ ++ self.assertFalse(self.g.xperms) + ++ def test_set_gen_xperms(self): ++ """ Test turning on and off generating of extended permission ++ AV rules. """ ++ self.g.set_gen_xperms(True) ++ self.assertTrue(self.g.xperms) ++ self.g.set_gen_xperms(False) ++ self.assertFalse(self.g.xperms) + ++ def test_av_rules(self): ++ """ Test generating of AV rules from access vectors. """ ++ av1 = access.AccessVector(["test_src_t", "test_tgt_t", "file", "ioctl"]) ++ av2 = access.AccessVector(["test_src_t", "test_tgt_t", "file", "open"]) ++ av3 = access.AccessVector(["test_src_t", "test_tgt_t", "file", "read"]) + ++ avs = access.AccessVectorSet() ++ avs.add_av(av1) ++ avs.add_av(av2) ++ avs.add_av(av3) ++ ++ self.g.add_access(avs) ++ ++ self.assertEqual(len(self.g.module.children), 1) ++ r = self.g.module.children[0] ++ self.assertIsInstance(r, refpolicy.AVRule) ++ self.assertEqual(r.to_string(), ++ "allow test_src_t test_tgt_t:file { ioctl open read };") ++ ++ def test_ext_av_rules(self): ++ """ Test generating of extended permission AV rules from access ++ vectors. """ ++ self.g.set_gen_xperms(True) ++ ++ av1 = access.AccessVector(["test_src_t", "test_tgt_t", "file", "ioctl"]) ++ av1.xperms['ioctl'] = refpolicy.XpermSet() ++ av1.xperms['ioctl'].add(42) ++ av2 = access.AccessVector(["test_src_t", "test_tgt_t", "file", "ioctl"]) ++ av2.xperms['ioctl'] = refpolicy.XpermSet() ++ av2.xperms['ioctl'].add(1234) ++ av3 = access.AccessVector(["test_src_t", "test_tgt_t", "dir", "ioctl"]) ++ av3.xperms['ioctl'] = refpolicy.XpermSet() ++ av3.xperms['ioctl'].add(2345) ++ ++ avs = access.AccessVectorSet() ++ avs.add_av(av1) ++ avs.add_av(av2) ++ avs.add_av(av3) ++ ++ self.g.add_access(avs) ++ ++ self.assertEqual(len(self.g.module.children), 4) ++ ++ # we cannot sort the rules, so find all rules manually ++ av_rule1 = av_rule2 = av_ext_rule1 = av_ext_rule2 = None ++ ++ for r in self.g.module.children: ++ if isinstance(r, refpolicy.AVRule): ++ if 'file' in r.obj_classes: ++ av_rule1 = r ++ else: ++ av_rule2 = r ++ elif isinstance(r, refpolicy.AVExtRule): ++ if 'file' in r.obj_classes: ++ av_ext_rule1 = r ++ else: ++ av_ext_rule2 = r ++ else: ++ self.fail("Unexpected rule type '%s'" % type(r)) ++ ++ # check that all rules are present ++ self.assertNotIn(None, (av_rule1, av_rule2, av_ext_rule1, av_ext_rule2)) ++ ++ self.assertEqual(av_rule1.rule_type, av_rule1.ALLOW) ++ self.assertEqual(av_rule1.src_types, {"test_src_t"}) ++ self.assertEqual(av_rule1.tgt_types, {"test_tgt_t"}) ++ self.assertEqual(av_rule1.obj_classes, {"file"}) ++ self.assertEqual(av_rule1.perms, {"ioctl"}) ++ ++ self.assertEqual(av_ext_rule1.rule_type, av_ext_rule1.ALLOWXPERM) ++ self.assertEqual(av_ext_rule1.src_types, {"test_src_t"}) ++ self.assertEqual(av_ext_rule1.tgt_types, {"test_tgt_t"}) ++ self.assertEqual(av_ext_rule1.obj_classes, {"file"}) ++ self.assertEqual(av_ext_rule1.operation, "ioctl") ++ xp1 = refpolicy.XpermSet() ++ xp1.add(42) ++ xp1.add(1234) ++ self.assertEqual(av_ext_rule1.xperms.ranges, xp1.ranges) ++ ++ self.assertEqual(av_rule2.rule_type, av_rule2.ALLOW) ++ self.assertEqual(av_rule2.src_types, {"test_src_t"}) ++ self.assertEqual(av_rule2.tgt_types, {"test_tgt_t"}) ++ self.assertEqual(av_rule2.obj_classes, {"dir"}) ++ self.assertEqual(av_rule2.perms, {"ioctl"}) ++ ++ self.assertEqual(av_ext_rule2.rule_type, av_ext_rule2.ALLOWXPERM) ++ self.assertEqual(av_ext_rule2.src_types, {"test_src_t"}) ++ self.assertEqual(av_ext_rule2.tgt_types, {"test_tgt_t"}) ++ self.assertEqual(av_ext_rule2.obj_classes, {"dir"}) ++ self.assertEqual(av_ext_rule2.operation, "ioctl") ++ xp2 = refpolicy.XpermSet() ++ xp2.add(2345) ++ self.assertEqual(av_ext_rule2.xperms.ranges, xp2.ranges) + +diff --git selinux-python-2.8/sepolgen/tests/test_refpolicy.py selinux-python-2.8/sepolgen/tests/test_refpolicy.py +index 16e6680..64c48df 100644 +--- selinux-python-2.8/sepolgen/tests/test_refpolicy.py ++++ selinux-python-2.8/sepolgen/tests/test_refpolicy.py +@@ -19,6 +19,7 @@ + + import unittest + import sepolgen.refpolicy as refpolicy ++import sepolgen.access as access + import selinux + + class TestIdSet(unittest.TestCase): +@@ -33,6 +34,74 @@ class TestIdSet(unittest.TestCase): + s.add("read") + self.assertEqual(s.to_space_str(), "read") + ++class TestXpermSet(unittest.TestCase): ++ def test_init(self): ++ """ Test that all atttributes are correctly initialized. """ ++ s1 = refpolicy.XpermSet() ++ self.assertEqual(s1.complement, False) ++ self.assertEqual(s1.ranges, []) ++ ++ s2 = refpolicy.XpermSet(True) ++ self.assertEqual(s2.complement, True) ++ self.assertEqual(s2.ranges, []) ++ ++ def test_normalize_ranges(self): ++ """ Test that ranges that are overlapping or neighboring are correctly ++ merged into one range. """ ++ s = refpolicy.XpermSet() ++ s.ranges = [(1, 7), (5, 10), (100, 110), (102, 107), (200, 205), ++ (205, 210), (300, 305), (306, 310), (400, 405), (407, 410), ++ (500, 502), (504, 508), (500, 510)] ++ s._XpermSet__normalize_ranges() ++ ++ i = 0 ++ r = list(sorted(s.ranges)) ++ while i < len(r) - 1: ++ # check that range low bound is less than equal than the upper bound ++ self.assertLessEqual(r[i][0], r[i][1]) ++ # check that two ranges are not overlapping or neighboring ++ self.assertGreater(r[i + 1][0] - r[i][1], 1) ++ i += 1 ++ ++ def test_add(self): ++ """ Test adding new values or ranges to the set. """ ++ s = refpolicy.XpermSet() ++ s.add(1, 7) ++ s.add(5, 10) ++ s.add(42) ++ self.assertEqual(s.ranges, [(1,10), (42,42)]) ++ ++ def test_extend(self): ++ """ Test adding ranges from another XpermSet object. """ ++ a = refpolicy.XpermSet() ++ a.add(1, 7) ++ ++ b = refpolicy.XpermSet() ++ b.add(5, 10) ++ ++ a.extend(b) ++ self.assertEqual(a.ranges, [(1,10)]) ++ ++ def test_to_string(self): ++ """ Test printing the values to a string. """ ++ a = refpolicy.XpermSet() ++ a.complement = False ++ self.assertEqual(a.to_string(), "") ++ a.complement = True ++ self.assertEqual(a.to_string(), "") ++ a.add(1234) ++ self.assertEqual(a.to_string(), "~ 1234") ++ a.complement = False ++ self.assertEqual(a.to_string(), "1234") ++ a.add(2345) ++ self.assertEqual(a.to_string(), "{ 1234 2345 }") ++ a.complement = True ++ self.assertEqual(a.to_string(), "~ { 1234 2345 }") ++ a.add(42,64) ++ self.assertEqual(a.to_string(), "~ { 42-64 1234 2345 }") ++ a.complement = False ++ self.assertEqual(a.to_string(), "{ 42-64 1234 2345 }") ++ + class TestSecurityContext(unittest.TestCase): + def test_init(self): + sc = refpolicy.SecurityContext() +@@ -110,6 +179,76 @@ class TestAVRule(unittest.TestCase): + b.sort() + self.assertEqual(a, b) + ++class TestAVExtRule(unittest.TestCase): ++ def test_init(self): ++ """ Test initialization of attributes """ ++ a = refpolicy.AVExtRule() ++ self.assertEqual(a.rule_type, a.ALLOWXPERM) ++ self.assertIsInstance(a.src_types, set) ++ self.assertIsInstance(a.tgt_types, set) ++ self.assertIsInstance(a.obj_classes, set) ++ self.assertIsNone(a.operation) ++ self.assertIsInstance(a.xperms, refpolicy.XpermSet) ++ ++ def test_rule_type_str(self): ++ """ Test strings returned by __rule_type_str() """ ++ a = refpolicy.AVExtRule() ++ self.assertEqual(a._AVExtRule__rule_type_str(), "allowxperm") ++ a.rule_type = a.ALLOWXPERM ++ self.assertEqual(a._AVExtRule__rule_type_str(), "allowxperm") ++ a.rule_type = a.DONTAUDITXPERM ++ self.assertEqual(a._AVExtRule__rule_type_str(), "dontauditxperm") ++ a.rule_type = a.NEVERALLOWXPERM ++ self.assertEqual(a._AVExtRule__rule_type_str(), "neverallowxperm") ++ a.rule_type = a.AUDITALLOWXPERM ++ self.assertEqual(a._AVExtRule__rule_type_str(), "auditallowxperm") ++ a.rule_type = 42 ++ self.assertIsNone(a._AVExtRule__rule_type_str()) ++ ++ def test_from_av(self): ++ """ Test creating the rule from an access vector. """ ++ av = access.AccessVector(["foo", "bar", "file", "ioctl"]) ++ xp = refpolicy.XpermSet() ++ av.xperms = { "ioctl": xp } ++ ++ a = refpolicy.AVExtRule() ++ ++ a.from_av(av, "ioctl") ++ self.assertEqual(a.src_types, {"foo"}) ++ self.assertEqual(a.tgt_types, {"bar"}) ++ self.assertEqual(a.obj_classes, {"file"}) ++ self.assertEqual(a.operation, "ioctl") ++ self.assertIs(a.xperms, xp) ++ ++ def test_from_av_self(self): ++ """ Test creating the rule from an access vector that has same ++ source and target context. """ ++ av = access.AccessVector(["foo", "foo", "file", "ioctl"]) ++ xp = refpolicy.XpermSet() ++ av.xperms = { "ioctl": xp } ++ ++ a = refpolicy.AVExtRule() ++ ++ a.from_av(av, "ioctl") ++ self.assertEqual(a.src_types, {"foo"}) ++ self.assertEqual(a.tgt_types, {"self"}) ++ self.assertEqual(a.obj_classes, {"file"}) ++ self.assertEqual(a.operation, "ioctl") ++ self.assertIs(a.xperms, xp) ++ ++ def test_to_string(self): ++ """ Test printing the rule to a string. """ ++ a = refpolicy.AVExtRule() ++ a._AVExtRule__rule_type_str = lambda: "first" ++ a.src_types.to_space_str = lambda: "second" ++ a.tgt_types.to_space_str = lambda: "third" ++ a.obj_classes.to_space_str = lambda: "fourth" ++ a.operation = "fifth" ++ a.xperms.to_string = lambda: "seventh" ++ ++ self.assertEqual(a.to_string(), ++ "first second third:fourth fifth seventh;") ++ + class TestTypeRule(unittest.TestCase): + def test_init(self): + a = refpolicy.TypeRule() +diff --git selinux-python-2.8/sepolicy/sepolicy.py selinux-python-2.8/sepolicy/sepolicy.py +index 141f64e..580972c 100755 +--- selinux-python-2.8/sepolicy/sepolicy.py ++++ selinux-python-2.8/sepolicy/sepolicy.py +@@ -27,7 +27,7 @@ import selinux + import sepolicy + from sepolicy import get_os_version, get_conditionals, get_conditionals_format_text + import argparse +-PROGNAME = "policycoreutils" ++PROGNAME = "selinux-python" + try: + import gettext + kwargs = {} +diff --git selinux-python-2.8/sepolicy/sepolicy/__init__.py selinux-python-2.8/sepolicy/sepolicy/__init__.py +index 89346ab..8132055 100644 +--- selinux-python-2.8/sepolicy/sepolicy/__init__.py ++++ selinux-python-2.8/sepolicy/sepolicy/__init__.py +@@ -15,7 +15,7 @@ import os + import re + import gzip + +-PROGNAME = "policycoreutils" ++PROGNAME = "selinux-python" + try: + import gettext + kwargs = {} +@@ -1160,27 +1160,14 @@ def boolean_desc(boolean): + + + def get_os_version(): +- os_version = "" +- pkg_name = "selinux-policy" ++ system_release = "" + try: +- try: +- from commands import getstatusoutput +- except ImportError: +- from subprocess import getstatusoutput +- rc, output = getstatusoutput("rpm -q '%s'" % pkg_name) +- if rc == 0: +- os_version = output.split(".")[-2] +- except: +- os_version = "" +- +- if os_version[0:2] == "fc": +- os_version = "Fedora" + os_version[2:] +- elif os_version[0:2] == "el": +- os_version = "RHEL" + os_version[2:] +- else: +- os_version = "" ++ with open('/etc/system-release') as f: ++ system_release = f.readline().rstrip() ++ except IOError: ++ system_release = "Misc" + +- return os_version ++ return system_release + + + def reinit(): +diff --git selinux-python-2.8/sepolicy/sepolicy/generate.py selinux-python-2.8/sepolicy/sepolicy/generate.py +index f814e27..efab71e 100644 +--- selinux-python-2.8/sepolicy/sepolicy/generate.py ++++ selinux-python-2.8/sepolicy/sepolicy/generate.py +@@ -52,7 +52,7 @@ import sepolgen.defaults as defaults + ## + ## I18N + ## +-PROGNAME = "policycoreutils" ++PROGNAME = "selinux-python" + try: + import gettext + kwargs = {} +diff --git selinux-python-2.8/sepolicy/sepolicy/gui.py selinux-python-2.8/sepolicy/sepolicy/gui.py +index 537d516..63aa02c 100644 +--- selinux-python-2.8/sepolicy/sepolicy/gui.py ++++ selinux-python-2.8/sepolicy/sepolicy/gui.py +@@ -43,7 +43,7 @@ import os + import re + import unicodedata + +-PROGNAME = "policycoreutils" ++PROGNAME = "selinux-python" + try: + import gettext + kwargs = {} +diff --git selinux-python-2.8/sepolicy/sepolicy/interface.py selinux-python-2.8/sepolicy/sepolicy/interface.py +index 18374dc..ca0122d 100644 +--- selinux-python-2.8/sepolicy/sepolicy/interface.py ++++ selinux-python-2.8/sepolicy/sepolicy/interface.py +@@ -32,7 +32,7 @@ __all__ = ['get_all_interfaces', 'get_interfaces_from_xml', 'get_admin', 'get_us + ## + ## I18N + ## +-PROGNAME = "policycoreutils" ++PROGNAME = "selinux-python" + try: + import gettext + kwargs = {} +diff --git selinux-python-2.8/sepolicy/sepolicy/manpage.py selinux-python-2.8/sepolicy/sepolicy/manpage.py +index ed8cb71..8121e5c 100755 +--- selinux-python-2.8/sepolicy/sepolicy/manpage.py ++++ selinux-python-2.8/sepolicy/sepolicy/manpage.py +@@ -126,8 +126,33 @@ def gen_domains(): + domains.sort() + return domains + +-types = None + ++exec_types = None ++ ++def _gen_exec_types(): ++ global exec_types ++ if exec_types is None: ++ exec_types = next(sepolicy.info(sepolicy.ATTRIBUTE, "exec_type"))["types"] ++ return exec_types ++ ++entry_types = None ++ ++def _gen_entry_types(): ++ global entry_types ++ if entry_types is None: ++ entry_types = next(sepolicy.info(sepolicy.ATTRIBUTE, "entry_type"))["types"] ++ return entry_types ++ ++mcs_constrained_types = None ++ ++def _gen_mcs_constrained_types(): ++ global mcs_constrained_types ++ if mcs_constrained_types is None: ++ mcs_constrained_types = next(sepolicy.info(sepolicy.ATTRIBUTE, "mcs_constrained_type")) ++ return mcs_constrained_types ++ ++ ++types = None + + def _gen_types(): + global types +@@ -150,10 +175,6 @@ def prettyprint(f, trim): + manpage_domains = [] + manpage_roles = [] + +-fedora_releases = ["Fedora17", "Fedora18"] +-rhel_releases = ["RHEL6", "RHEL7"] +- +- + def get_alphabet_manpages(manpage_list): + alphabet_manpages = dict.fromkeys(string.ascii_letters, []) + for i in string.ascii_letters: +@@ -183,7 +204,7 @@ def convert_manpage_to_html(html_manpage, manpage): + class HTMLManPages: + + """ +- Generate a HHTML Manpages on an given SELinux domains ++ Generate a HTML Manpages on an given SELinux domains + """ + + def __init__(self, manpage_roles, manpage_domains, path, os_version): +@@ -191,9 +212,9 @@ class HTMLManPages: + self.manpage_domains = get_alphabet_manpages(manpage_domains) + self.os_version = os_version + self.old_path = path + "/" +- self.new_path = self.old_path + self.os_version + "/" ++ self.new_path = self.old_path + +- if self.os_version in fedora_releases or self.os_version in rhel_releases: ++ if self.os_version: + self.__gen_html_manpages() + else: + print("SELinux HTML man pages can not be generated for this %s" % os_version) +@@ -202,7 +223,6 @@ class HTMLManPages: + def __gen_html_manpages(self): + self._write_html_manpage() + self._gen_index() +- self._gen_body() + self._gen_css() + + def _write_html_manpage(self): +@@ -220,67 +240,21 @@ class HTMLManPages: + convert_manpage_to_html((self.new_path + r.rsplit("_selinux", 1)[0] + ".html"), self.old_path + r) + + def _gen_index(self): +- index = self.old_path + "index.html" +- fd = open(index, 'w') +- fd.write(""" +- +- +- +- SELinux man pages online +- +- +-

SELinux man pages

+-

+-Fedora or Red Hat Enterprise Linux Man Pages. +-

+-
+-

Fedora

+- +- +-
+-
+-
+-""")
+-        for f in fedora_releases:
+-            fd.write("""
+-%s - SELinux man pages for %s """ % (f, f, f, f))
+-
+-        fd.write("""
+-
+-
+-

RHEL

+- +- +-
+-
+-
+-""")
+-        for r in rhel_releases:
+-            fd.write("""
+-%s - SELinux man pages for %s """ % (r, r, r, r))
+-
+-        fd.write("""
+-
+- """) +- fd.close() +- print("%s has been created" % index) +- +- def _gen_body(self): + html = self.new_path + self.os_version + ".html" + fd = open(html, 'w') + fd.write(""" + + +- +- Linux man-pages online for Fedora18 ++ ++ SELinux man pages + + +-

SELinux man pages for Fedora18

++

SELinux man pages for %s

+
+ +
+

SELinux roles

+-""") ++""" % self.os_version) + for letter in self.manpage_roles: + if len(self.manpage_roles[letter]): + fd.write(""" +@@ -424,6 +398,9 @@ class ManPage: + self.all_file_types = sepolicy.get_all_file_types() + self.role_allows = sepolicy.get_all_role_allows() + self.types = _gen_types() ++ self.exec_types = _gen_exec_types() ++ self.entry_types = _gen_entry_types() ++ self.mcs_constrained_types = _gen_mcs_constrained_types() + + if self.source_files: + self.fcpath = self.root + "file_contexts" +@@ -736,10 +713,13 @@ Default Defined Ports:""") + + def _file_context(self): + flist = [] ++ flist_non_exec = [] + mpaths = [] + for f in self.all_file_types: + if f.startswith(self.domainname): + flist.append(f) ++ if not f in self.exec_types or not f in self.entry_types: ++ flist_non_exec.append(f) + if f in self.fcdict: + mpaths = mpaths + self.fcdict[f]["regex"] + if len(mpaths) == 0: +@@ -791,19 +771,20 @@ SELinux %(domainname)s policy is very flexible allowing users to setup their %(d + .PP + """ % {'domainname': self.domainname, 'equiv': e, 'alt': e.split('/')[-1]}) + +- self.fd.write(r""" ++ if flist_non_exec: ++ self.fd.write(r""" + .PP + .B STANDARD FILE CONTEXT + + SELinux defines the file context types for the %(domainname)s, if you wanted to + store files with these types in a diffent paths, you need to execute the semanage command to sepecify alternate labeling and then use restorecon to put the labels on disk. + +-.B semanage fcontext -a -t %(type)s '/srv/%(domainname)s/content(/.*)?' ++.B semanage fcontext -a -t %(type)s '/srv/my%(domainname)s_content(/.*)?' + .br + .B restorecon -R -v /srv/my%(domainname)s_content + + Note: SELinux often uses regular expressions to specify labels that match multiple files. +-""" % {'domainname': self.domainname, "type": flist[0]}) ++""" % {'domainname': self.domainname, "type": flist_non_exec[-1]}) + + self.fd.write(r""" + .I The following file types are defined for %(domainname)s: +@@ -974,11 +955,7 @@ All executeables with the default executable label, usually stored in /usr/bin a + %s""" % ", ".join(paths)) + + def _mcs_types(self): +- try: +- mcs_constrained_type = next(sepolicy.info(sepolicy.ATTRIBUTE, "mcs_constrained_type")) +- except StopIteration: +- return +- if self.type not in mcs_constrained_type['types']: ++ if self.type not in self.mcs_constrained_types['types']: + return + self.fd.write (""" + .SH "MCS Constrained" diff --git a/selinux-sandbox-fedora.patch b/selinux-sandbox-fedora.patch new file mode 100644 index 0000000000000000000000000000000000000000..1bf6dbfc5d3e741b85bb1b7d8914cdefc2486950 --- /dev/null +++ b/selinux-sandbox-fedora.patch @@ -0,0 +1,141 @@ +diff --git selinux-sandbox-2.8/Makefile selinux-sandbox-2.8/Makefile +index 49c1d3f..9e45329 100644 +--- selinux-sandbox-2.8/Makefile ++++ selinux-sandbox-2.8/Makefile +@@ -12,6 +12,7 @@ override LDLIBS += -lselinux -lcap-ng + SEUNSHARE_OBJS = seunshare.o + + all: sandbox seunshare sandboxX.sh start ++ (cd po && $(MAKE) $@) + + seunshare: $(SEUNSHARE_OBJS) + +@@ -30,6 +31,7 @@ install: all + install -m 755 start $(DESTDIR)$(SHAREDIR) + -mkdir -p $(DESTDIR)$(SYSCONFDIR) + install -m 644 sandbox.conf $(DESTDIR)$(SYSCONFDIR)/sandbox ++ (cd po && $(MAKE) $@) + + test: + @$(PYTHON) test_sandbox.py -v +diff --git selinux-sandbox-2.8/po/Makefile selinux-sandbox-2.8/po/Makefile +new file mode 100644 +index 0000000..0556bbe +--- /dev/null ++++ selinux-sandbox-2.8/po/Makefile +@@ -0,0 +1,82 @@ ++# ++# Makefile for the PO files (translation) catalog ++# ++ ++PREFIX ?= /usr ++ ++# What is this package? ++NLSPACKAGE = sandbox ++POTFILE = $(NLSPACKAGE).pot ++INSTALL = /usr/bin/install -c -p ++INSTALL_DATA = $(INSTALL) -m 644 ++INSTALL_DIR = /usr/bin/install -d ++ ++# destination directory ++INSTALL_NLS_DIR = $(PREFIX)/share/locale ++ ++# PO catalog handling ++MSGMERGE = msgmerge ++MSGMERGE_FLAGS = -q ++XGETTEXT = xgettext -L Python --default-domain=$(NLSPACKAGE) ++MSGFMT = msgfmt ++ ++# All possible linguas ++PO_LINGUAS := $(sort $(patsubst %.po,%,$(wildcard *.po))) ++ ++# Only the files matching what the user has set in LINGUAS ++USER_LINGUAS := $(filter $(patsubst %,%%,$(LINGUAS)),$(PO_LINGUAS)) ++ ++# if no valid LINGUAS, build all languages ++USE_LINGUAS := $(if $(USER_LINGUAS),$(USER_LINGUAS),$(PO_LINGUAS)) ++ ++POFILES = $(patsubst %,%.po,$(USE_LINGUAS)) ++MOFILES = $(patsubst %.po,%.mo,$(POFILES)) ++POTFILES = $(shell cat POTFILES) ++ ++#default:: clean ++ ++all:: $(POTFILE) $(MOFILES) ++ ++$(POTFILE): $(POTFILES) ++ $(XGETTEXT) --keyword=_ --keyword=N_ $(POTFILES) ++ @if cmp -s $(NLSPACKAGE).po $(POTFILE); then \ ++ rm -f $(NLSPACKAGE).po; \ ++ else \ ++ mv -f $(NLSPACKAGE).po $(POTFILE); \ ++ fi; \ ++ ++ ++refresh-po: Makefile ++ for cat in $(POFILES); do \ ++ lang=`basename $$cat .po`; \ ++ if $(MSGMERGE) $(MSGMERGE_FLAGS) $$lang.po $(POTFILE) > $$lang.pot ; then \ ++ mv -f $$lang.pot $$lang.po ; \ ++ echo "$(MSGMERGE) of $$lang succeeded" ; \ ++ else \ ++ echo "$(MSGMERGE) of $$lang failed" ; \ ++ rm -f $$lang.pot ; \ ++ fi \ ++ done ++ ++clean: ++ @rm -fv *mo *~ .depend ++ @rm -rf tmp ++ ++install: $(MOFILES) ++ @for n in $(MOFILES); do \ ++ l=`basename $$n .mo`; \ ++ $(INSTALL_DIR) $(DESTDIR)$(INSTALL_NLS_DIR)/$$l/LC_MESSAGES; \ ++ $(INSTALL_DATA) --verbose $$n $(DESTDIR)$(INSTALL_NLS_DIR)/$$l/LC_MESSAGES/selinux-$(NLSPACKAGE).mo; \ ++ done ++ ++%.mo: %.po ++ $(MSGFMT) -o $@ $< ++report: ++ @for cat in $(wildcard *.po); do \ ++ echo -n "$$cat: "; \ ++ msgfmt -v --statistics -o /dev/null $$cat; \ ++ done ++ ++.PHONY: missing depend ++ ++relabel: +diff --git selinux-sandbox-2.8/po/POTFILES selinux-sandbox-2.8/po/POTFILES +new file mode 100644 +index 0000000..deff3f2 +--- /dev/null ++++ selinux-sandbox-2.8/po/POTFILES +@@ -0,0 +1 @@ ++../sandbox +diff --git selinux-sandbox-2.8/sandbox selinux-sandbox-2.8/sandbox +index c07a1d8..a051360 100644 +--- selinux-sandbox-2.8/sandbox ++++ selinux-sandbox-2.8/sandbox +@@ -37,7 +37,7 @@ import sepolicy + + SEUNSHARE = "/usr/sbin/seunshare" + SANDBOXSH = "/usr/share/sandbox/sandboxX.sh" +-PROGNAME = "policycoreutils" ++PROGNAME = "selinux-sandbox" + try: + import gettext + kwargs = {} +diff --git selinux-sandbox-2.8/sandboxX.sh selinux-sandbox-2.8/sandboxX.sh +index eaa500d..4774528 100644 +--- selinux-sandbox-2.8/sandboxX.sh ++++ selinux-sandbox-2.8/sandboxX.sh +@@ -20,7 +20,7 @@ cat > ~/.config/openbox/rc.xml << EOF + + EOF + +-(/usr/bin/Xephyr -resizeable -title "$TITLE" -terminate -screen $SCREENSIZE -dpi $DPI -nolisten tcp -displayfd 5 5>&1 2>/dev/null) | while read D; do ++(/usr/bin/Xephyr -resizeable -title "$TITLE" -terminate -reset -screen $SCREENSIZE -dpi $DPI -nolisten tcp -displayfd 5 5>&1 2>/dev/null) | while read D; do + export DISPLAY=:$D + cat > ~/seremote << __EOF + #!/bin/sh diff --git a/sepolicy-icons.tgz b/sepolicy-icons.tgz new file mode 100644 index 0000000000000000000000000000000000000000..722135fb6947a2cea2f89fc3be2308b13498046d Binary files /dev/null and b/sepolicy-icons.tgz differ diff --git a/system-config-selinux.png b/system-config-selinux.png new file mode 100644 index 0000000000000000000000000000000000000000..68ffcb77bd9f8cd01043f566e539ce2f8c4820f6 Binary files /dev/null and b/system-config-selinux.png differ