From 12eefb56e9dbbaa8d33a8c96855085a1ea7f9751 Mon Sep 17 00:00:00 2001
From: Petr Lautrbach <plautrba@redhat.com>
Date: Mar 27 2020 14:36:03 +0000
Subject: [PATCH 1/4] Do not refer to hardcoded selinux-policy rpm in signature


Get package name and version from package which owns /etc/selinux/SELINUXTYPE

Fixes: https://pagure.io/setroubleshoot/issue/7

---

diff --git a/framework/src/setroubleshoot/signature.py b/framework/src/setroubleshoot/signature.py
index bcc3740..6fa5ac0 100755
--- a/framework/src/setroubleshoot/signature.py
+++ b/framework/src/setroubleshoot/signature.py
@@ -141,7 +141,7 @@ class SEEnvironment(XmlSerialize):
 
         self.platform, self.kernel = get_os_environment()
         self.policy_type = selinux.selinux_getpolicytype()[1]
-        self.policy_rpm = get_rpm_nvr_by_name("selinux-policy")
+        self.policy_rpm = get_rpm_nvr_by_file_path("/etc/selinux/%s" % self.policy_type)
         self.local_policy_rpm = self.policy_rpm
         self.policyvers = str(selinux.security_policyvers())
         enforce = selinux.security_getenforce()

From 1b5f51898e7bfdbb80e938fe968a46eced43cbb9 Mon Sep 17 00:00:00 2001
From: Petr Lautrbach <plautrba@redhat.com>
Date: Mar 27 2020 14:36:03 +0000
Subject: [PATCH 2/4] framework: Add dpkg support


Detect whether there's `rpm` or `dpkg` available and use it for package queries.

Resolves: https://pagure.io/setroubleshoot/issue/6

---

diff --git a/framework/src/setroubleshoot/audit_data.py b/framework/src/setroubleshoot/audit_data.py
index d66e757..a4fc3f6 100644
--- a/framework/src/setroubleshoot/audit_data.py
+++ b/framework/src/setroubleshoot/audit_data.py
@@ -1025,12 +1025,12 @@ class AVC:
     def derive_environmental_info(self):
         if self.query_environment:
             if self.spath:
-                self.source_pkg = get_rpm_nvr_by_file_path(self.spath)
+                self.source_pkg = get_package_nvr_by_file_path(self.spath)
                 if self.source_pkg:
                     self.src_rpms.append(self.source_pkg)
 
             if self.tpath:
-                rpm = get_rpm_nvr_by_file_path(self.tpath)
+                rpm = get_package_nvr_by_file_path(self.tpath)
                 if rpm:
                     self.tgt_rpms.append(rpm)
 
diff --git a/framework/src/setroubleshoot/browser.py b/framework/src/setroubleshoot/browser.py
index 9bbd07b..4870590 100644
--- a/framework/src/setroubleshoot/browser.py
+++ b/framework/src/setroubleshoot/browser.py
@@ -121,7 +121,7 @@ def old():
     desktop_icon_dict = {}
     for desktop_app_info in Gio.app_info_get_all():
         exe = fullpath(desktop_app_info.get_executable())
-        rpmver = get_rpm_nvr_by_file_path(exe)
+        rpmver = get_package_nvr_by_file_path(exe)
         if rpmver:
             if rpmver in desktop_icon_dict:
                 desktop_icon_dict[rpmver].append(desktop_app_info)
@@ -144,7 +144,7 @@ def get_icon(path, tclass="*"):
                 if icon:
                     return icon
 
-        rpmver = get_rpm_nvr_by_file_path(path)
+        rpmver = get_package_nvr_by_file_path(path)
         if rpmver in desktop_icon_dict:
             for m in desktop_icon_dict[rpmver]:
                 icon = m.get_icon()
diff --git a/framework/src/setroubleshoot/signature.py b/framework/src/setroubleshoot/signature.py
index 6fa5ac0..a3f4f1c 100755
--- a/framework/src/setroubleshoot/signature.py
+++ b/framework/src/setroubleshoot/signature.py
@@ -141,7 +141,7 @@ class SEEnvironment(XmlSerialize):
 
         self.platform, self.kernel = get_os_environment()
         self.policy_type = selinux.selinux_getpolicytype()[1]
-        self.policy_rpm = get_rpm_nvr_by_file_path("/etc/selinux/%s" % self.policy_type)
+        self.policy_rpm = get_package_nvr_by_file_path("/etc/selinux/%s" % self.policy_type)
         self.local_policy_rpm = self.policy_rpm
         self.policyvers = str(selinux.security_policyvers())
         enforce = selinux.security_getenforce()
diff --git a/framework/src/setroubleshoot/util.py b/framework/src/setroubleshoot/util.py
index 4d18555..e537bbe 100755
--- a/framework/src/setroubleshoot/util.py
+++ b/framework/src/setroubleshoot/util.py
@@ -33,8 +33,8 @@ __all__ = [
     'default_date_text',
     'get_standard_directories',
     'get_rpm_nvr_from_header',
-    'get_rpm_nvr_by_name',
-    'get_rpm_nvr_by_file_path',
+    'get_package_nvr_by_name',
+    'get_package_nvr_by_file_path',
     'get_rpm_nvr_by_type',
     'get_rpm_nvr_by_scontext',
     'get_rpm_source_package',
@@ -63,6 +63,7 @@ __all__ = [
 
     'TimeStamp',
     'Retry',
+    'PACKAGE_MANAGER',
 ]
 
 import bz2
@@ -74,7 +75,9 @@ from gi.repository import GObject
 import os
 import pwd
 import re
+import shutil
 import selinux
+import subprocess
 import sys
 import textwrap
 import time
@@ -98,6 +101,12 @@ def is_type(obj):
 DATABASE_MAJOR_VERSION = 3
 DATABASE_MINOR_VERSION = 0
 
+PACKAGE_MANAGER = None
+if shutil.which('rpm'):
+    PACKAGE_MANAGER = 'rpm'
+elif shutil.which('dpkg'):
+    PACKAGE_MANAGER = 'deb'
+
 redhat_release_path = '/etc/redhat-release'
 text_wrapper = textwrap.TextWrapper()
 fix_newline_re = re.compile(r"\s*\n+\s*")
@@ -305,15 +314,19 @@ def default_date_text(date):
 
 
 def get_standard_directories():
+    """
+>>> get_standard_directories()
+[...'/bin'...]
+    """
     lst = []
-    import rpm
     try:
-        ts = rpm.ts()
-        h = next(ts.dbMatch("name", "filesystem"))
-        for i in h.fiFromHeader():
-            lst.append(i[0])
+        if PACKAGE_MANAGER == "rpm":
+            lst = subprocess.check_output(["rpm", "-ql", "filesystem"], universal_newlines=True).rstrip().split("\n")
+        if PACKAGE_MANAGER == "deb":
+            lst = subprocess.check_output(["dpkg", "-L", "base-files"], universal_newlines=True).rstrip().split("\n")
+
     except:
-        syslog.syslog(syslog.LOG_ERR, "failed to get filesystem list from rpm")
+        syslog.syslog(syslog.LOG_ERR, "failed to get list from {}".format(PACKAGE_MANAGER))
 
     return lst
 
@@ -326,23 +339,33 @@ def get_rpm_nvr_from_header(hdr):
 
     return "%s-%s-%s" % (name, version, release)
 
-### these functions are for now until rpm memory leak gets a fix
-
-
-def get_rpm_nvr_by_name_temporary(name):
+def get_package_nvr_by_name(name):
+    """
+>>> get_package_nvr_by_name("coreutils")
+'coreutils-8.30-3+b1:amd64'
+    """
     if name is None:
         return None
 
     nvr = None
     try:
-        import subprocess
-        nvr = subprocess.check_output(["rpm", "-q", name], universal_newlines=True).rstrip()
+        if PACKAGE_MANAGER == 'rpm':
+            nvr = subprocess.check_output(["rpm", "-q", name], universal_newlines=True).rstrip()
+        if PACKAGE_MANAGER == 'deb':
+            # dpkg-query -f='${Package}_${Version}:${Architecture}\n' -W
+            nvr = subprocess.check_output(
+                ["dpkg-query", "-f=${Package}-${Version}:${Architecture}", "-W", name], universal_newlines=True
+            ).rstrip()
     except:
         syslog.syslog(syslog.LOG_ERR, "failed to retrieve rpm info for %s" % name)
     return nvr
 
 
-def get_rpm_nvr_by_file_path_temporary(name):
+def get_package_nvr_by_file_path(name):
+    """
+>>> get_package_nvr_by_file_path("/bin/ls")
+'coreutils-8.30-3+b1:amd64'
+    """
     if name is None:
         return None
 
@@ -352,8 +375,16 @@ def get_rpm_nvr_by_file_path_temporary(name):
 
     nvr = None
     try:
-        import subprocess
-        nvr = subprocess.check_output(["rpm", "-qf", name], universal_newlines=True).rstrip()
+        if PACKAGE_MANAGER == 'rpm':
+            nvr = subprocess.check_output(["rpm", "-qf", name], universal_newlines=True).rstrip()
+        if PACKAGE_MANAGER == 'deb':
+            # dpkg -S foo |cut -d: -1f
+            # dpkg-query -f='${Package}_${Version}:${Architecture}\n' -W
+            package_name = subprocess.check_output(["dpkg", "-S", name]).decode().split(": ")[0]
+            nvr = subprocess.check_output(
+                ["dpkg-query", "-f=${Package}-${Version}:${Architecture}", "-W", package_name], universal_newlines=True
+            ).rstrip()
+
     except:
         syslog.syslog(syslog.LOG_ERR, "failed to retrieve rpm info for %s" % name)
     return nvr
@@ -367,42 +398,6 @@ except ValueError:
     file_types = []
 
 
-def get_rpm_nvr_by_name(name):
-    return get_rpm_nvr_by_name_temporary(name)
-    if name is None:
-        return None
-
-    import rpm
-    nvr = None
-    try:
-        ts = rpm.ts()
-        mi = ts.dbMatch(rpm.RPMTAG_NAME, name)
-        for h in mi:
-            nvr = get_rpm_nvr_from_header(h)
-            break
-    except:
-        syslog.syslog(syslog.LOG_ERR, "failed to retrieve rpm info for %s" % name)
-    return nvr
-
-
-def get_rpm_nvr_by_file_path(path):
-    return get_rpm_nvr_by_file_path_temporary(path)
-    if path is None:
-        return None
-
-    import rpm
-    nvr = None
-    try:
-        ts = rpm.ts()
-        mi = ts.dbMatch(rpm.RPMTAG_BASENAMES, path)
-        for h in mi:
-            nvr = get_rpm_nvr_from_header(h)
-            break
-    except:
-        syslog.syslog(syslog.LOG_ERR, "failed to retrieve rpm info for %s" % path)
-    return nvr
-
-
 def split_rpm_nvr(nvr):
     components = nvr.split('-')
     release = components[-1]
@@ -455,7 +450,7 @@ Finds an SELinux module which defines given SELinux type
                 pass
 
     if len(modules) > 0:
-        return get_rpm_nvr_by_file_path(sorted(modules)[-1])
+        return get_package_nvr_by_file_path(sorted(modules)[-1])
 
     return None
 

From 1de3fd53785b0dca6bf3dc2c4d8f8005a597b232 Mon Sep 17 00:00:00 2001
From: Petr Lautrbach <plautrba@redhat.com>
Date: Mar 27 2020 14:36:03 +0000
Subject: [PATCH 3/4] plugins: Use get_package_nvr* functions instead of get_rpm_nvr*


Resolves: https://pagure.io/setroubleshoot/issue/6

---

diff --git a/plugins/src/mozplugger.py b/plugins/src/mozplugger.py
index b5705df..01f72d1 100644
--- a/plugins/src/mozplugger.py
+++ b/plugins/src/mozplugger.py
@@ -52,9 +52,9 @@ Either remove the mozplugger or spice-xpi package by executing 'yum remove mozpl
     def analyze(self, avc):
         if avc.matches_source_types(['mozilla_plugin_t']):
             reports = []
-            if get_rpm_nvr_by_name("mozplugger"):
+            if get_package_nvr_by_name("mozplugger"):
                 reports.append(self.report(("mozplugger", None)))
-            if get_rpm_nvr_by_name("spice-xpi"):
+            if get_package_nvr_by_name("spice-xpi"):
                 reports.append(self.report(("spice-xpi", None)))
             if len(reports) > 0:
                 return reports
diff --git a/plugins/src/mozplugger_remove.py b/plugins/src/mozplugger_remove.py
index d44c339..d6b514a 100644
--- a/plugins/src/mozplugger_remove.py
+++ b/plugins/src/mozplugger_remove.py
@@ -53,7 +53,7 @@ setsebool -P unconfined_mozilla_plugin_transition 0
 
     def analyze(self, avc):
         if (avc.matches_source_types(['mozilla_plugin_t']) and
-                get_rpm_nvr_by_name("mozplugger")):
+                get_package_nvr_by_name("mozplugger")):
             # MATCH
             return self.report()
         else:

From 7458f4c50ac07319b0aa1b766547137bb7e7d391 Mon Sep 17 00:00:00 2001
From: Petr Lautrbach <plautrba@redhat.com>
Date: Mar 27 2020 14:36:03 +0000
Subject: [PATCH 4/4] setroubleshoot.util: Catch exceptions from sepolicy import


Fixes the following bt on SELinux disable system:

  File "src/setroubleshoot/util.py", line 370, in <module>
    file_types = get_all_file_types()
  File "/usr/lib/python3/dist-packages/sepolicy/__init__.py", line 960, in get_all_file_types
    file_types = list(sorted(info(ATTRIBUTE, "file_type"))[0]["types"])
  File "/usr/lib/python3/dist-packages/sepolicy/__init__.py", line 224, in <genexpr>
    return ({
  File "/usr/lib/python3/dist-packages/setools/typeattrquery.py", line 65, in results
    for attr in self.policy.typeattributes():

---

diff --git a/framework/src/setroubleshoot/util.py b/framework/src/setroubleshoot/util.py
index e537bbe..023d1c4 100755
--- a/framework/src/setroubleshoot/util.py
+++ b/framework/src/setroubleshoot/util.py
@@ -390,11 +390,10 @@ def get_package_nvr_by_file_path(name):
     return nvr
 
 ###
-
-from sepolicy import get_all_file_types
 try:
+    from sepolicy import get_all_file_types
     file_types = get_all_file_types()
-except ValueError:
+except:
     file_types = []
 
 

