Compare commits

...

2 Commits

Author SHA1 Message Date
Petr Lautrbach cfde702672 policycoreutils-3.6-2 2024-02-14 04:09:40 +00:00
Petr Lautrbach a9239d604f SELinux userspace 3.6 release
Resolves: RHEL-16238, RHEL-15434, RHEL-2254
2023-12-14 08:37:21 +01:00
6 changed files with 482 additions and 8 deletions

1
.gitignore vendored
View File

@ -350,3 +350,4 @@ policycoreutils-2.0.83.tgz
/selinux-sandbox.zip
/selinux-gui.zip
/selinux-3.6-rc1.tar.gz
/selinux-3.6.tar.gz

View File

@ -0,0 +1,5 @@
c1d6c443723b91295ca887eeea5c2d84a420593f selinux-3.6.tar.gz
8aec9d92a940e35756c4cf66891db7b070e00c5c selinux-policycoreutils.zip
6a9a8a86bf4b66b484533e5a5b91acd9f2ba4ed1 selinux-python.zip
c2957ae26fcabe856439915bc03fb7d25c91b724 selinux-gui.zip
c9b684345b0b6940afd38d8679e2838ad7ef5ffe selinux-sandbox.zip

View File

@ -0,0 +1,395 @@
From 1afa3a9462e78d17a0a1fe2594fa6f1e8d57d47f Mon Sep 17 00:00:00 2001
From: Vit Mojzis <vmojzis@redhat.com>
Date: Wed, 24 Jan 2024 13:45:38 +0100
Subject: [PATCH] python/semanage: Allow modifying records on "add"
Content-type: text/plain
When trying to add a record with a key that already exists, modify
the existing record instead.
Also, fix "semanage -m -e" (add_equal was called instead of
modify_equal), which meant that existing local equivalency couldn't be
modified (though a user could remove it and add a modified
equivalency).
Fixes:
https://github.com/SELinuxProject/selinux/issues/412
When a port or login definition present in the policy is modified
using "semanage port -m", "semanage export" exports the command as
"port -a" instead of "port -m". This results in "semanage import"
failing (port already defined). The same is true for port, user,
login, ibpkey, ibendport, node, interface and fcontext.
Signed-off-by: Vit Mojzis <vmojzis@redhat.com>
Acked-by: James Carter <jwcart2@gmail.com>
---
python/semanage/semanage | 2 +-
python/semanage/seobject.py | 206 +++++++++++++++++++++++++-----------
2 files changed, 145 insertions(+), 63 deletions(-)
diff --git a/python/semanage/semanage b/python/semanage/semanage
index 4fdb490f7df4..b269b9fca65b 100644
--- a/python/semanage/semanage
+++ b/python/semanage/semanage
@@ -322,7 +322,7 @@ def handleFcontext(args):
OBJECT.add(args.file_spec, args.type, args.ftype, args.range, args.seuser)
if args.action == "modify":
if args.equal:
- OBJECT.add_equal(args.file_spec, args.equal)
+ OBJECT.modify_equal(args.file_spec, args.equal)
else:
OBJECT.modify(args.file_spec, args.type, args.ftype, args.range, args.seuser)
if args.action == "delete":
diff --git a/python/semanage/seobject.py b/python/semanage/seobject.py
index cc944ae202c9..dfb15b1d77e4 100644
--- a/python/semanage/seobject.py
+++ b/python/semanage/seobject.py
@@ -557,11 +557,6 @@ class loginRecords(semanageRecords):
if rc < 0:
raise ValueError(_("Could not create a key for %s") % name)
- (rc, exists) = semanage_seuser_exists(self.sh, k)
- if rc < 0:
- raise ValueError(_("Could not check if login mapping for %s is defined") % name)
- if exists:
- raise ValueError(_("Login mapping for %s is already defined") % name)
if name[0] == '%':
try:
grp.getgrnam(name[1:])
@@ -600,11 +595,29 @@ class loginRecords(semanageRecords):
def add(self, name, sename, serange):
try:
self.begin()
- self.__add(name, sename, serange)
+ # Add a new mapping, or modify an existing one
+ if self.__exists(name):
+ print(_("Login mapping for %s is already defined, modifying instead") % name)
+ self.__modify(name, sename, serange)
+ else:
+ self.__add(name, sename, serange)
self.commit()
except ValueError as error:
raise error
+ # check if login mapping for given user exists
+ def __exists(self, name):
+ (rc, k) = semanage_seuser_key_create(self.sh, name)
+ if rc < 0:
+ raise ValueError(_("Could not create a key for %s") % name)
+
+ (rc, exists) = semanage_seuser_exists(self.sh, k)
+ if rc < 0:
+ raise ValueError(_("Could not check if login mapping for %s is defined") % name)
+ semanage_seuser_key_free(k)
+
+ return exists
+
def __modify(self, name, sename="", serange=""):
rec, self.oldsename, self.oldserange = selinux.getseuserbyname(name)
if sename == "" and serange == "":
@@ -821,12 +834,6 @@ class seluserRecords(semanageRecords):
if rc < 0:
raise ValueError(_("Could not create a key for %s") % name)
- (rc, exists) = semanage_user_exists(self.sh, k)
- if rc < 0:
- raise ValueError(_("Could not check if SELinux user %s is defined") % name)
- if exists:
- raise ValueError(_("SELinux user %s is already defined") % name)
-
(rc, u) = semanage_user_create(self.sh)
if rc < 0:
raise ValueError(_("Could not create SELinux user for %s") % name)
@@ -866,12 +873,28 @@ class seluserRecords(semanageRecords):
def add(self, name, roles, selevel, serange, prefix):
try:
self.begin()
- self.__add(name, roles, selevel, serange, prefix)
+ if self.__exists(name):
+ print(_("SELinux user %s is already defined, modifying instead") % name)
+ self.__modify(name, roles, selevel, serange, prefix)
+ else:
+ self.__add(name, roles, selevel, serange, prefix)
self.commit()
except ValueError as error:
self.mylog.commit(0)
raise error
+ def __exists(self, name):
+ (rc, k) = semanage_user_key_create(self.sh, name)
+ if rc < 0:
+ raise ValueError(_("Could not create a key for %s") % name)
+
+ (rc, exists) = semanage_user_exists(self.sh, k)
+ if rc < 0:
+ raise ValueError(_("Could not check if SELinux user %s is defined") % name)
+ semanage_user_key_free(k)
+
+ return exists
+
def __modify(self, name, roles=[], selevel="", serange="", prefix=""):
oldserole = ""
oldserange = ""
@@ -1103,12 +1126,6 @@ class portRecords(semanageRecords):
(k, proto_d, low, high) = self.__genkey(port, proto)
- (rc, exists) = semanage_port_exists(self.sh, k)
- if rc < 0:
- raise ValueError(_("Could not check if port {proto}/{port} is defined").format(proto=proto, port=port))
- if exists:
- raise ValueError(_("Port {proto}/{port} already defined").format(proto=proto, port=port))
-
(rc, p) = semanage_port_create(self.sh)
if rc < 0:
raise ValueError(_("Could not create port for {proto}/{port}").format(proto=proto, port=port))
@@ -1152,9 +1169,23 @@ class portRecords(semanageRecords):
def add(self, port, proto, serange, type):
self.begin()
- self.__add(port, proto, serange, type)
+ if self.__exists(port, proto):
+ print(_("Port {proto}/{port} already defined, modifying instead").format(proto=proto, port=port))
+ self.__modify(port, proto, serange, type)
+ else:
+ self.__add(port, proto, serange, type)
self.commit()
+ def __exists(self, port, proto):
+ (k, proto_d, low, high) = self.__genkey(port, proto)
+
+ (rc, exists) = semanage_port_exists(self.sh, k)
+ if rc < 0:
+ raise ValueError(_("Could not check if port {proto}/{port} is defined").format(proto=proto, port=port))
+ semanage_port_key_free(k)
+
+ return exists
+
def __modify(self, port, proto, serange, setype):
if serange == "" and setype == "":
if is_mls_enabled == 1:
@@ -1377,12 +1408,6 @@ class ibpkeyRecords(semanageRecords):
(k, subnet_prefix, low, high) = self.__genkey(pkey, subnet_prefix)
- (rc, exists) = semanage_ibpkey_exists(self.sh, k)
- if rc < 0:
- raise ValueError(_("Could not check if ibpkey {subnet_prefix}/{pkey} is defined").formnat(subnet_prefix=subnet_prefix, pkey=pkey))
- if exists:
- raise ValueError(_("ibpkey {subnet_prefix}/{pkey} already defined").format(subnet_prefix=subnet_prefix, pkey=pkey))
-
(rc, p) = semanage_ibpkey_create(self.sh)
if rc < 0:
raise ValueError(_("Could not create ibpkey for {subnet_prefix}/{pkey}").format(subnet_prefix=subnet_prefix, pkey=pkey))
@@ -1424,9 +1449,23 @@ class ibpkeyRecords(semanageRecords):
def add(self, pkey, subnet_prefix, serange, type):
self.begin()
- self.__add(pkey, subnet_prefix, serange, type)
+ if self.__exists(pkey, subnet_prefix):
+ print(_("ibpkey {subnet_prefix}/{pkey} already defined, modifying instead").format(subnet_prefix=subnet_prefix, pkey=pkey))
+ self.__modify(pkey, subnet_prefix, serange, type)
+ else:
+ self.__add(pkey, subnet_prefix, serange, type)
self.commit()
+ def __exists(self, pkey, subnet_prefix):
+ (k, subnet_prefix, low, high) = self.__genkey(pkey, subnet_prefix)
+
+ (rc, exists) = semanage_ibpkey_exists(self.sh, k)
+ if rc < 0:
+ raise ValueError(_("Could not check if ibpkey {subnet_prefix}/{pkey} is defined").formnat(subnet_prefix=subnet_prefix, pkey=pkey))
+ semanage_ibpkey_key_free(k)
+
+ return exists
+
def __modify(self, pkey, subnet_prefix, serange, setype):
if serange == "" and setype == "":
if is_mls_enabled == 1:
@@ -1631,12 +1670,6 @@ class ibendportRecords(semanageRecords):
raise ValueError(_("Type %s is invalid, must be an ibendport type") % type)
(k, ibendport, port) = self.__genkey(ibendport, ibdev_name)
- (rc, exists) = semanage_ibendport_exists(self.sh, k)
- if rc < 0:
- raise ValueError(_("Could not check if ibendport {ibdev_name}/{port} is defined").format(ibdev_name=ibdev_name, port=port))
- if exists:
- raise ValueError(_("ibendport {ibdev_name}/{port} already defined").format(ibdev_name=ibdev_name, port=port))
-
(rc, p) = semanage_ibendport_create(self.sh)
if rc < 0:
raise ValueError(_("Could not create ibendport for {ibdev_name}/{port}").format(ibdev_name=ibdev_name, port=port))
@@ -1678,9 +1711,23 @@ class ibendportRecords(semanageRecords):
def add(self, ibendport, ibdev_name, serange, type):
self.begin()
- self.__add(ibendport, ibdev_name, serange, type)
+ if self.__exists(ibendport, ibdev_name):
+ print(_("ibendport {ibdev_name}/{port} already defined, modifying instead").format(ibdev_name=ibdev_name, port=port))
+ self.__modify(ibendport, ibdev_name, serange, type)
+ else:
+ self.__add(ibendport, ibdev_name, serange, type)
self.commit()
+ def __exists(self, ibendport, ibdev_name):
+ (k, ibendport, port) = self.__genkey(ibendport, ibdev_name)
+
+ (rc, exists) = semanage_ibendport_exists(self.sh, k)
+ if rc < 0:
+ raise ValueError(_("Could not check if ibendport {ibdev_name}/{port} is defined").format(ibdev_name=ibdev_name, port=port))
+ semanage_ibendport_key_free(k)
+
+ return exists
+
def __modify(self, ibendport, ibdev_name, serange, setype):
if serange == "" and setype == "":
if is_mls_enabled == 1:
@@ -1902,12 +1949,6 @@ class nodeRecords(semanageRecords):
if rc < 0:
raise ValueError(_("Could not create key for %s") % addr)
- (rc, exists) = semanage_node_exists(self.sh, k)
- if rc < 0:
- raise ValueError(_("Could not check if addr %s is defined") % addr)
- if exists:
- raise ValueError(_("Addr %s already defined") % addr)
-
(rc, node) = semanage_node_create(self.sh)
if rc < 0:
raise ValueError(_("Could not create addr for %s") % addr)
@@ -1955,9 +1996,25 @@ class nodeRecords(semanageRecords):
def add(self, addr, mask, proto, serange, ctype):
self.begin()
- self.__add(addr, mask, proto, serange, ctype)
+ if self.__exists(addr, mask, proto):
+ print(_("Addr %s already defined, modifying instead") % addr)
+ self.__modify(addr, mask, proto, serange, ctype)
+ else:
+ self.__add(addr, mask, proto, serange, ctype)
self.commit()
+ def __exists(self, addr, mask, proto):
+ (rc, k) = semanage_node_key_create(self.sh, addr, mask, proto)
+ if rc < 0:
+ raise ValueError(_("Could not create key for %s") % addr)
+
+ (rc, exists) = semanage_node_exists(self.sh, k)
+ if rc < 0:
+ raise ValueError(_("Could not check if addr %s is defined") % addr)
+ semanage_node_key_free(k)
+
+ return exists
+
def __modify(self, addr, mask, proto, serange, setype):
addr, mask, proto, audit_proto = self.validate(addr, mask, proto)
@@ -2111,12 +2168,6 @@ class interfaceRecords(semanageRecords):
if rc < 0:
raise ValueError(_("Could not create key for %s") % interface)
- (rc, exists) = semanage_iface_exists(self.sh, k)
- if rc < 0:
- raise ValueError(_("Could not check if interface %s is defined") % interface)
- if exists:
- raise ValueError(_("Interface %s already defined") % interface)
-
(rc, iface) = semanage_iface_create(self.sh)
if rc < 0:
raise ValueError(_("Could not create interface for %s") % interface)
@@ -2163,9 +2214,25 @@ class interfaceRecords(semanageRecords):
def add(self, interface, serange, ctype):
self.begin()
- self.__add(interface, serange, ctype)
+ if self.__exists(interface):
+ print(_("Interface %s already defined, modifying instead") % interface)
+ self.__modify(interface, serange, ctype)
+ else:
+ self.__add(interface, serange, ctype)
self.commit()
+ def __exists(self, interface):
+ (rc, k) = semanage_iface_key_create(self.sh, interface)
+ if rc < 0:
+ raise ValueError(_("Could not create key for %s") % interface)
+
+ (rc, exists) = semanage_iface_exists(self.sh, k)
+ if rc < 0:
+ raise ValueError(_("Could not check if interface %s is defined") % interface)
+ semanage_iface_key_free(k)
+
+ return exists
+
def __modify(self, interface, serange, setype):
if serange == "" and setype == "":
raise ValueError(_("Requires setype or serange"))
@@ -2353,7 +2420,13 @@ class fcontextRecords(semanageRecords):
raise ValueError(_("Substitute %s is not valid. Substitute is not allowed to end with '/'") % substitute)
if target in self.equiv.keys():
- raise ValueError(_("Equivalence class for %s already exists") % target)
+ print(_("Equivalence class for %s already exists, modifying instead") % target)
+ self.equiv[target] = substitute
+ self.equal_ind = True
+ self.mylog.log_change("resrc=fcontext op=modify-equal %s %s" % (audit.audit_encode_nv_string("sglob", target, 0), audit.audit_encode_nv_string("tglob", substitute, 0)))
+ self.commit()
+ return
+
self.validate(target)
for fdict in (self.equiv, self.equiv_dist):
@@ -2429,18 +2502,6 @@ class fcontextRecords(semanageRecords):
if rc < 0:
raise ValueError(_("Could not create key for %s") % target)
- (rc, exists) = semanage_fcontext_exists(self.sh, k)
- if rc < 0:
- raise ValueError(_("Could not check if file context for %s is defined") % target)
-
- if not exists:
- (rc, exists) = semanage_fcontext_exists_local(self.sh, k)
- if rc < 0:
- raise ValueError(_("Could not check if file context for %s is defined") % target)
-
- if exists:
- raise ValueError(_("File context for %s already defined") % target)
-
(rc, fcontext) = semanage_fcontext_create(self.sh)
if rc < 0:
raise ValueError(_("Could not create file context for %s") % target)
@@ -2479,9 +2540,30 @@ class fcontextRecords(semanageRecords):
def add(self, target, type, ftype="", serange="", seuser="system_u"):
self.begin()
- self.__add(target, type, ftype, serange, seuser)
+ if self.__exists(target, ftype):
+ print(_("File context for %s already defined, modifying instead") % target)
+ self.__modify(target, type, ftype, serange, seuser)
+ else:
+ self.__add(target, type, ftype, serange, seuser)
self.commit()
+ def __exists(self, target, ftype):
+ (rc, k) = semanage_fcontext_key_create(self.sh, target, file_types[ftype])
+ if rc < 0:
+ raise ValueError(_("Could not create key for %s") % target)
+
+ (rc, exists) = semanage_fcontext_exists(self.sh, k)
+ if rc < 0:
+ raise ValueError(_("Could not check if file context for %s is defined") % target)
+
+ if not exists:
+ (rc, exists) = semanage_fcontext_exists_local(self.sh, k)
+ if rc < 0:
+ raise ValueError(_("Could not check if file context for %s is defined") % target)
+ semanage_fcontext_key_free(k)
+
+ return exists
+
def __modify(self, target, setype, ftype, serange, seuser):
if serange == "" and setype == "" and seuser == "":
raise ValueError(_("Requires setype, serange or seuser"))
--
2.43.0

View File

@ -0,0 +1,64 @@
From 616db16b5729a9473cf27edc32a03f38eca417e7 Mon Sep 17 00:00:00 2001
From: Vit Mojzis <vmojzis@redhat.com>
Date: Wed, 7 Feb 2024 15:46:23 +0100
Subject: [PATCH] python/semanage: Do not sort local fcontext definitions
Content-type: text/plain
Entries in file_contexts.local are processed from the most recent one to
the oldest, with first match being used. Therefore it is important to
preserve their order when listing (semanage fcontext -lC) and exporting
(semanage export).
Signed-off-by: Vit Mojzis <vmojzis@redhat.com>
---
gui/fcontextPage.py | 6 +++++-
python/semanage/seobject.py | 9 +++++++--
2 files changed, 12 insertions(+), 3 deletions(-)
diff --git a/gui/fcontextPage.py b/gui/fcontextPage.py
index 767664f26ec8..c88df580400f 100644
--- a/gui/fcontextPage.py
+++ b/gui/fcontextPage.py
@@ -133,7 +133,11 @@ class fcontextPage(semanagePage):
self.fcontext = seobject.fcontextRecords()
self.store.clear()
fcon_dict = self.fcontext.get_all(self.local)
- for k in sorted(fcon_dict.keys()):
+ if self.local:
+ fkeys = fcon_dict.keys()
+ else:
+ fkeys = sorted(fcon_dict.keys())
+ for k in fkeys:
if not self.match(fcon_dict, k, filter):
continue
iter = self.store.append()
diff --git a/python/semanage/seobject.py b/python/semanage/seobject.py
index dfb15b1d77e4..25ec43154848 100644
--- a/python/semanage/seobject.py
+++ b/python/semanage/seobject.py
@@ -2735,7 +2735,7 @@ class fcontextRecords(semanageRecords):
def customized(self):
l = []
fcon_dict = self.get_all(True)
- for k in sorted(fcon_dict.keys()):
+ for k in fcon_dict.keys():
if fcon_dict[k]:
if fcon_dict[k][3]:
l.append("-a -f %s -t %s -r '%s' '%s'" % (file_type_str_to_option[k[1]], fcon_dict[k][2], fcon_dict[k][3], k[0]))
@@ -2752,7 +2752,12 @@ class fcontextRecords(semanageRecords):
if len(fcon_dict) != 0:
if heading:
print("%-50s %-18s %s\n" % (_("SELinux fcontext"), _("type"), _("Context")))
- for k in sorted(fcon_dict.keys()):
+ # do not sort local customizations since they are evaluated based on the order they where added in
+ if locallist:
+ fkeys = fcon_dict.keys()
+ else:
+ fkeys = sorted(fcon_dict.keys())
+ for k in fkeys:
if fcon_dict[k]:
if is_mls_enabled:
print("%-50s %-18s %s:%s:%s:%s " % (k[0], k[1], fcon_dict[k][0], fcon_dict[k][1], fcon_dict[k][2], translate(fcon_dict[k][3], False)))
--
2.43.0

View File

@ -1,7 +1,7 @@
%global libauditver 3.0
%global libsepolver 3.6-0
%global libsemanagever 3.6-0
%global libselinuxver 3.6-0
%global libsepolver 3.6-1
%global libsemanagever 3.6-1
%global libselinuxver 3.6-1
%global generatorsdir %{_prefix}/lib/systemd/system-generators
@ -11,10 +11,10 @@
Summary: SELinux policy core utilities
Name: policycoreutils
Version: 3.6
Release: 0.rc1.1%{?dist}
Release: 2%{?dist}
License: GPL-2.0-or-later
# https://github.com/SELinuxProject/selinux/wiki/Releases
Source0: https://github.com/SELinuxProject/selinux/releases/download/3.6-rc1/selinux-3.6-rc1.tar.gz
Source0: https://github.com/SELinuxProject/selinux/releases/download/3.6/selinux-3.6.tar.gz
URL: https://github.com/SELinuxProject/selinux
Source13: system-config-selinux.png
Source14: sepolicy-icons.tgz
@ -33,7 +33,7 @@ Source22: selinux-gui.zip
# wlc --key <apikey> --url https://translate.fedoraproject.org/api/ download selinux/sandbox --output ./
Source23: selinux-sandbox.zip
# https://github.com/fedora-selinux/selinux
# $ git format-patch -N 3.6-rc1 -- policycoreutils python gui sandbox dbus semodule-utils restorecond
# $ git format-patch -N 3.6 -- policycoreutils python gui sandbox dbus semodule-utils restorecond
# $ for j in [0-9]*.patch; do printf "Patch%s: %s\n" ${j/-*/} $j; done
# Patch list start
Patch0001: 0001-sandbox-add-reset-to-Xephyr-as-it-works-better-with-.patch
@ -53,6 +53,8 @@ Patch0014: 0014-Revert-python-Remove-the-Russian-translations.patch
Patch0015: 0015-Revert-python-Remove-the-Russian-translations.patch
Patch0016: 0016-Revert-policycoreutils-Remove-the-Russian-translatio.patch
Patch0017: 0017-Revert-gui-Remove-the-Russian-translations.patch
Patch0018: 0018-python-semanage-Allow-modifying-records-on-add.patch
Patch0019: 0019-python-semanage-Do-not-sort-local-fcontext-definitio.patch
# Patch list end
Obsoletes: policycoreutils < 2.0.61-2
Conflicts: filesystem < 3, selinux-policy-base < 3.13.1-138
@ -87,7 +89,7 @@ load_policy to load policies, setfiles to label filesystems, newrole
to switch roles.
%prep -p /usr/bin/bash
%autosetup -p 1 -n selinux-%{version}-rc1
%autosetup -p 1 -n selinux-%{version}
cp %{SOURCE13} gui/
tar -xvf %{SOURCE14} -C python/sepolicy/
@ -462,6 +464,13 @@ The policycoreutils-restorecond package contains the restorecond service.
%systemd_postun_with_restart restorecond.service
%changelog
* Tue Feb 13 2024 Petr Lautrbach <lautrbach@redhat.com> - 3.6-2
- semanage: Allow modifying records on "add"
- semanage: Do not sort local fcontext definitions
* Thu Dec 14 2023 Petr Lautrbach <lautrbach@redhat.com> - 3.6-1
- SELinux userspace 3.6 release
* Mon Nov 13 2023 Petr Lautrbach <lautrbach@redhat.com> - 3.0-0.rc1.1
- SELinux userspace 3.6-rc1 release

View File

@ -1,4 +1,4 @@
SHA512 (selinux-3.6-rc1.tar.gz) = b447b4f51055861730868dbe357cc740cef7ee97e10c59c1bc5840d3ea2141af0331d226d8fa9a4e06aea510a1854cfb5bc49a517b4ecd83ca527c1ab9bd1c6b
SHA512 (selinux-3.6.tar.gz) = 15ba9c5901ec4dc1e9e24374ffe61216301335fb07c0d653692251a59f210628775852f22d7c5eb784a43b65c133fad983ba1e6159d72fd3fd16e87f9a335fb6
SHA512 (selinux-policycoreutils.zip) = 0df9dc274e0d1a2e4e2467f95a18a5bf7b6de2428ac90a0a73d7f3bd766a897062af142ba3cf39cdb79565ba78af960bcd2e35865cc26e14bf2305321780c918
SHA512 (selinux-python.zip) = 35d209f8bcff498f66465499fcc4cef0780781276a4ba060b2d1d56eed1dd72d253f6b0eae5f679d46cf426b967a7aadac909363513be5d483c95a31249eacdd
SHA512 (selinux-gui.zip) = 3ae41eba5dd6d34e10dfdb97f4194d170ace2f3044e984077db7d26d05bdaad86625e48e5694e3e8680487ad99a50861d4bea30c4bf08e2820e3b7a8671270c7