|
|
28e5f0 |
From 6038fdf8617319a13b0b42f3283ec2066d54b283 Mon Sep 17 00:00:00 2001
|
|
|
28e5f0 |
From: "Bryn M. Reeves" <bmr@redhat.com>
|
|
|
28e5f0 |
Date: Thu, 19 Nov 2015 18:46:36 +0000
|
|
|
28e5f0 |
Subject: [PATCH] [policies] move hash determination to policies
|
|
|
28e5f0 |
|
|
|
28e5f0 |
It's crazy having the Policy classes call a function in the
|
|
|
28e5f0 |
utilities module only to have that function then load the Policy
|
|
|
28e5f0 |
module, call policy.get_preferred_hash_algorithm() and then test
|
|
|
28e5f0 |
the result.
|
|
|
28e5f0 |
|
|
|
28e5f0 |
Get rid of the get_hash_name() function in the utilities module
|
|
|
28e5f0 |
and simplify the calls in the policies module to obtain the
|
|
|
28e5f0 |
preferred hash name.
|
|
|
28e5f0 |
|
|
|
28e5f0 |
Signed-off-by: Bryn M. Reeves <bmr@redhat.com>
|
|
|
28e5f0 |
---
|
|
|
28e5f0 |
sos/policies/__init__.py | 22 +++++++++++++++-------
|
|
|
28e5f0 |
sos/utilities.py | 12 ------------
|
|
|
28e5f0 |
tests/utilities_tests.py | 2 +-
|
|
|
28e5f0 |
3 files changed, 16 insertions(+), 20 deletions(-)
|
|
|
28e5f0 |
|
|
|
28e5f0 |
diff --git a/sos/policies/__init__.py b/sos/policies/__init__.py
|
|
|
28e5f0 |
index a403bb9..bf9afde 100644
|
|
|
28e5f0 |
--- a/sos/policies/__init__.py
|
|
|
28e5f0 |
+++ b/sos/policies/__init__.py
|
|
|
28e5f0 |
@@ -10,7 +10,6 @@ from os import environ
|
|
|
28e5f0 |
|
|
|
28e5f0 |
from sos.utilities import (ImporterHelper,
|
|
|
28e5f0 |
import_module,
|
|
|
28e5f0 |
- get_hash_name,
|
|
|
28e5f0 |
shell_out)
|
|
|
28e5f0 |
from sos.plugins import IndependentPlugin
|
|
|
28e5f0 |
from sos import _sos as _
|
|
|
28e5f0 |
@@ -286,17 +285,17 @@ No changes will be made to system configuration.
|
|
|
28e5f0 |
considered to be a superuser"""
|
|
|
28e5f0 |
return (os.getuid() == 0)
|
|
|
28e5f0 |
|
|
|
28e5f0 |
- def _create_checksum(self, final_filename=None):
|
|
|
28e5f0 |
+ def _create_checksum(self, hash_name, final_filename=None):
|
|
|
28e5f0 |
if not final_filename:
|
|
|
28e5f0 |
return False
|
|
|
28e5f0 |
|
|
|
28e5f0 |
archive_fp = open(final_filename, 'rb')
|
|
|
28e5f0 |
- digest = hashlib.new(get_hash_name())
|
|
|
28e5f0 |
+ digest = hashlib.new(hash_name)
|
|
|
28e5f0 |
digest.update(archive_fp.read())
|
|
|
28e5f0 |
archive_fp.close()
|
|
|
28e5f0 |
return digest.hexdigest()
|
|
|
28e5f0 |
|
|
|
28e5f0 |
- def get_preferred_hash_algorithm(self):
|
|
|
28e5f0 |
+ def get_preferred_hash_name(self):
|
|
|
28e5f0 |
"""Returns the string name of the hashlib-supported checksum algorithm
|
|
|
28e5f0 |
to use"""
|
|
|
28e5f0 |
return "md5"
|
|
|
28e5f0 |
@@ -309,10 +308,11 @@ No changes will be made to system configuration.
|
|
|
28e5f0 |
|
|
|
28e5f0 |
self._print()
|
|
|
28e5f0 |
|
|
|
28e5f0 |
+ hash_name = self.get_preferred_hash_name()
|
|
|
28e5f0 |
if not build:
|
|
|
28e5f0 |
# store checksum into file
|
|
|
28e5f0 |
- fp = open(final_filename + "." + get_hash_name(), "w")
|
|
|
28e5f0 |
- checksum = self._create_checksum(final_filename)
|
|
|
28e5f0 |
+ fp = open(final_filename + "." + hash_name, "w")
|
|
|
28e5f0 |
+ checksum = self._create_checksum(hash_name, final_filename)
|
|
|
28e5f0 |
if checksum:
|
|
|
28e5f0 |
fp.write(checksum + "\n")
|
|
|
28e5f0 |
fp.close()
|
|
|
28e5f0 |
@@ -373,20 +373,28 @@ class LinuxPolicy(Policy):
|
|
|
28e5f0 |
vendor = "None"
|
|
|
28e5f0 |
PATH = "/bin:/sbin:/usr/bin:/usr/sbin"
|
|
|
28e5f0 |
|
|
|
28e5f0 |
+ _preferred_hash_name = None
|
|
|
28e5f0 |
+
|
|
|
28e5f0 |
def __init__(self, sysroot=None):
|
|
|
28e5f0 |
super(LinuxPolicy, self).__init__(sysroot=sysroot)
|
|
|
28e5f0 |
|
|
|
28e5f0 |
- def get_preferred_hash_algorithm(self):
|
|
|
28e5f0 |
+ def get_preferred_hash_name(self):
|
|
|
28e5f0 |
+
|
|
|
28e5f0 |
+ if self._preferred_hash_name:
|
|
|
28e5f0 |
+ return self._preferred_hash_name
|
|
|
28e5f0 |
+
|
|
|
28e5f0 |
checksum = "md5"
|
|
|
28e5f0 |
try:
|
|
|
28e5f0 |
fp = open("/proc/sys/crypto/fips_enabled", "r")
|
|
|
28e5f0 |
except:
|
|
|
28e5f0 |
+ self._preferred_hash_name = checksum
|
|
|
28e5f0 |
return checksum
|
|
|
28e5f0 |
|
|
|
28e5f0 |
fips_enabled = fp.read()
|
|
|
28e5f0 |
if fips_enabled.find("1") >= 0:
|
|
|
28e5f0 |
checksum = "sha256"
|
|
|
28e5f0 |
fp.close()
|
|
|
28e5f0 |
+ self._preferred_hash_name = checksum
|
|
|
28e5f0 |
return checksum
|
|
|
28e5f0 |
|
|
|
28e5f0 |
def default_runlevel(self):
|
|
|
28e5f0 |
diff --git a/sos/utilities.py b/sos/utilities.py
|
|
|
28e5f0 |
index d3a1048..63e7ee4 100644
|
|
|
28e5f0 |
--- a/sos/utilities.py
|
|
|
28e5f0 |
+++ b/sos/utilities.py
|
|
|
28e5f0 |
@@ -52,18 +52,6 @@ def fileobj(path_or_file, mode='r'):
|
|
|
28e5f0 |
return closing(path_or_file)
|
|
|
28e5f0 |
|
|
|
28e5f0 |
|
|
|
28e5f0 |
-def get_hash_name():
|
|
|
28e5f0 |
- """Returns the algorithm used when computing a hash"""
|
|
|
28e5f0 |
- import sos.policies
|
|
|
28e5f0 |
- policy = sos.policies.load()
|
|
|
28e5f0 |
- try:
|
|
|
28e5f0 |
- name = policy.get_preferred_hash_algorithm()
|
|
|
28e5f0 |
- hashlib.new(name)
|
|
|
28e5f0 |
- return name
|
|
|
28e5f0 |
- except:
|
|
|
28e5f0 |
- return 'sha256'
|
|
|
28e5f0 |
-
|
|
|
28e5f0 |
-
|
|
|
28e5f0 |
def convert_bytes(bytes_, K=1 << 10, M=1 << 20, G=1 << 30, T=1 << 40):
|
|
|
28e5f0 |
"""Converts a number of bytes to a shorter, more human friendly format"""
|
|
|
28e5f0 |
fn = float(bytes_)
|
|
|
28e5f0 |
diff --git a/tests/utilities_tests.py b/tests/utilities_tests.py
|
|
|
28e5f0 |
index c464692..f1b60e2 100644
|
|
|
28e5f0 |
--- a/tests/utilities_tests.py
|
|
|
28e5f0 |
+++ b/tests/utilities_tests.py
|
|
|
28e5f0 |
@@ -5,7 +5,7 @@ import unittest
|
|
|
28e5f0 |
import six
|
|
|
28e5f0 |
from six import StringIO
|
|
|
28e5f0 |
|
|
|
28e5f0 |
-from sos.utilities import grep, get_hash_name, is_executable, sos_get_command_output, find, tail, shell_out
|
|
|
28e5f0 |
+from sos.utilities import grep, is_executable, sos_get_command_output, find, tail, shell_out
|
|
|
28e5f0 |
import sos
|
|
|
28e5f0 |
|
|
|
28e5f0 |
TEST_DIR = os.path.dirname(__file__)
|
|
|
28e5f0 |
--
|
|
|
28e5f0 |
2.4.3
|
|
|
28e5f0 |
|
|
|
28e5f0 |
From 7f2727749d0c37095a20c5d4cf6f9a2e086a2375 Mon Sep 17 00:00:00 2001
|
|
|
28e5f0 |
From: "Bryn M. Reeves" <bmr@redhat.com>
|
|
|
28e5f0 |
Date: Thu, 19 Nov 2015 19:07:50 +0000
|
|
|
28e5f0 |
Subject: [PATCH] [policies] refactor Policy.display_results() args
|
|
|
28e5f0 |
|
|
|
28e5f0 |
Pass explicit archive and build directory arguments to the
|
|
|
28e5f0 |
Policy.display_results() method rather than a single path name
|
|
|
28e5f0 |
argument and a boolean to indicate whether it is an archive file
|
|
|
28e5f0 |
or a build directory path.
|
|
|
28e5f0 |
|
|
|
28e5f0 |
Signed-off-by: Bryn M. Reeves <bmr@redhat.com>
|
|
|
28e5f0 |
---
|
|
|
28e5f0 |
sos/policies/__init__.py | 24 ++++++++++++++----------
|
|
|
28e5f0 |
sos/sosreport.py | 12 +++++++++---
|
|
|
28e5f0 |
2 files changed, 23 insertions(+), 13 deletions(-)
|
|
|
28e5f0 |
|
|
|
28e5f0 |
diff --git a/sos/policies/__init__.py b/sos/policies/__init__.py
|
|
|
28e5f0 |
index bf9afde..5b0b706 100644
|
|
|
28e5f0 |
--- a/sos/policies/__init__.py
|
|
|
28e5f0 |
+++ b/sos/policies/__init__.py
|
|
|
28e5f0 |
@@ -285,11 +285,11 @@ No changes will be made to system configuration.
|
|
|
28e5f0 |
considered to be a superuser"""
|
|
|
28e5f0 |
return (os.getuid() == 0)
|
|
|
28e5f0 |
|
|
|
28e5f0 |
- def _create_checksum(self, hash_name, final_filename=None):
|
|
|
28e5f0 |
- if not final_filename:
|
|
|
28e5f0 |
+ def _create_checksum(self, hash_name, archive=None):
|
|
|
28e5f0 |
+ if not archive:
|
|
|
28e5f0 |
return False
|
|
|
28e5f0 |
|
|
|
28e5f0 |
- archive_fp = open(final_filename, 'rb')
|
|
|
28e5f0 |
+ archive_fp = open(archive, 'rb')
|
|
|
28e5f0 |
digest = hashlib.new(hash_name)
|
|
|
28e5f0 |
digest.update(archive_fp.read())
|
|
|
28e5f0 |
archive_fp.close()
|
|
|
28e5f0 |
@@ -300,29 +300,33 @@ No changes will be made to system configuration.
|
|
|
28e5f0 |
to use"""
|
|
|
28e5f0 |
return "md5"
|
|
|
28e5f0 |
|
|
|
28e5f0 |
- def display_results(self, final_filename=None, build=False):
|
|
|
28e5f0 |
+ def display_results(self, archive, directory):
|
|
|
28e5f0 |
+ # Display results is called from the tail of SoSReport.final_work()
|
|
|
28e5f0 |
+ #
|
|
|
28e5f0 |
+ # Logging is already shutdown and all terminal output must use the
|
|
|
28e5f0 |
+ # print() call.
|
|
|
28e5f0 |
|
|
|
28e5f0 |
# make sure a report exists
|
|
|
28e5f0 |
- if not final_filename:
|
|
|
28e5f0 |
+ if not archive and not directory:
|
|
|
28e5f0 |
return False
|
|
|
28e5f0 |
|
|
|
28e5f0 |
self._print()
|
|
|
28e5f0 |
|
|
|
28e5f0 |
hash_name = self.get_preferred_hash_name()
|
|
|
28e5f0 |
- if not build:
|
|
|
28e5f0 |
+ if archive:
|
|
|
28e5f0 |
# store checksum into file
|
|
|
28e5f0 |
- fp = open(final_filename + "." + hash_name, "w")
|
|
|
28e5f0 |
- checksum = self._create_checksum(hash_name, final_filename)
|
|
|
28e5f0 |
+ fp = open(archive + "." + hash_name, "w")
|
|
|
28e5f0 |
+ checksum = self._create_checksum(hash_name, archive)
|
|
|
28e5f0 |
if checksum:
|
|
|
28e5f0 |
fp.write(checksum + "\n")
|
|
|
28e5f0 |
fp.close()
|
|
|
28e5f0 |
|
|
|
28e5f0 |
self._print(_("Your sosreport has been generated and saved "
|
|
|
28e5f0 |
- "in:\n %s") % final_filename)
|
|
|
28e5f0 |
+ "in:\n %s") % archive)
|
|
|
28e5f0 |
else:
|
|
|
28e5f0 |
checksum = None
|
|
|
28e5f0 |
self._print(_("sosreport build tree is located at : %s" %
|
|
|
28e5f0 |
- final_filename))
|
|
|
28e5f0 |
+ directory))
|
|
|
28e5f0 |
|
|
|
28e5f0 |
self._print()
|
|
|
28e5f0 |
if checksum:
|
|
|
28e5f0 |
diff --git a/sos/sosreport.py b/sos/sosreport.py
|
|
|
28e5f0 |
index a1f1b96..f3e0f34 100644
|
|
|
28e5f0 |
--- a/sos/sosreport.py
|
|
|
28e5f0 |
+++ b/sos/sosreport.py
|
|
|
28e5f0 |
@@ -1436,6 +1436,10 @@ class SoSReport(object):
|
|
|
28e5f0 |
# this must come before archive creation to ensure that log
|
|
|
28e5f0 |
# files are closed and cleaned up at exit.
|
|
|
28e5f0 |
self._finish_logging()
|
|
|
28e5f0 |
+
|
|
|
28e5f0 |
+ archive = None # archive path
|
|
|
28e5f0 |
+ directory = None # report directory path (--build)
|
|
|
28e5f0 |
+
|
|
|
28e5f0 |
# package up the results for the support organization
|
|
|
28e5f0 |
if not self.opts.build:
|
|
|
28e5f0 |
old_umask = os.umask(0o077)
|
|
|
28e5f0 |
@@ -1443,7 +1447,7 @@ class SoSReport(object):
|
|
|
28e5f0 |
print(_("Creating compressed archive..."))
|
|
|
28e5f0 |
# compression could fail for a number of reasons
|
|
|
28e5f0 |
try:
|
|
|
28e5f0 |
- final_filename = self.archive.finalize(
|
|
|
28e5f0 |
+ archive = self.archive.finalize(
|
|
|
28e5f0 |
self.opts.compression_type)
|
|
|
28e5f0 |
except (OSError, IOError) as e:
|
|
|
28e5f0 |
if e.errno in fatal_fs_errors:
|
|
|
28e5f0 |
@@ -1460,8 +1464,10 @@ class SoSReport(object):
|
|
|
28e5f0 |
finally:
|
|
|
28e5f0 |
os.umask(old_umask)
|
|
|
28e5f0 |
else:
|
|
|
28e5f0 |
- final_filename = self.archive.get_archive_path()
|
|
|
28e5f0 |
- self.policy.display_results(final_filename, build=self.opts.build)
|
|
|
28e5f0 |
+ directory = self.archive.get_archive_path()
|
|
|
28e5f0 |
+
|
|
|
28e5f0 |
+ self.policy.display_results(archive, directory)
|
|
|
28e5f0 |
+
|
|
|
28e5f0 |
self.tempfile_util.clean()
|
|
|
28e5f0 |
return True
|
|
|
28e5f0 |
|
|
|
28e5f0 |
--
|
|
|
28e5f0 |
2.4.3
|
|
|
28e5f0 |
|
|
|
28e5f0 |
From 19e2bbccb6a86d6ea94f5c82860bed4d2276bbf3 Mon Sep 17 00:00:00 2001
|
|
|
28e5f0 |
From: "Bryn M. Reeves" <bmr@redhat.com>
|
|
|
28e5f0 |
Date: Thu, 19 Nov 2015 19:19:42 +0000
|
|
|
28e5f0 |
Subject: [PATCH] [sosreport] move archive checksumming to sosreport
|
|
|
28e5f0 |
|
|
|
28e5f0 |
Although the digest algorithm is policy controlled the actual
|
|
|
28e5f0 |
mechanism to checksum the archive does not belong in the policies
|
|
|
28e5f0 |
module: historically this was done to keep the code that calculates
|
|
|
28e5f0 |
the checksum close to the UI code that reports it.
|
|
|
28e5f0 |
|
|
|
28e5f0 |
Move the calculation to the main SoSReport class's final_work()
|
|
|
28e5f0 |
method and add a 'checksum' argument to the display_results()
|
|
|
28e5f0 |
method so that the value can be reported.
|
|
|
28e5f0 |
|
|
|
28e5f0 |
In future it may make sense to push the checksum code directly into
|
|
|
28e5f0 |
the archive class.
|
|
|
28e5f0 |
|
|
|
28e5f0 |
Signed-off-by: Bryn M. Reeves <bmr@redhat.com>
|
|
|
28e5f0 |
---
|
|
|
28e5f0 |
sos/policies/__init__.py | 22 +---------------------
|
|
|
28e5f0 |
sos/sosreport.py | 26 +++++++++++++++++++++++++-
|
|
|
28e5f0 |
2 files changed, 26 insertions(+), 22 deletions(-)
|
|
|
28e5f0 |
|
|
|
28e5f0 |
diff --git a/sos/policies/__init__.py b/sos/policies/__init__.py
|
|
|
28e5f0 |
index 5b0b706..20e0e3b 100644
|
|
|
28e5f0 |
--- a/sos/policies/__init__.py
|
|
|
28e5f0 |
+++ b/sos/policies/__init__.py
|
|
|
28e5f0 |
@@ -13,7 +13,6 @@ from sos.utilities import (ImporterHelper,
|
|
|
28e5f0 |
shell_out)
|
|
|
28e5f0 |
from sos.plugins import IndependentPlugin
|
|
|
28e5f0 |
from sos import _sos as _
|
|
|
28e5f0 |
-import hashlib
|
|
|
28e5f0 |
from textwrap import fill
|
|
|
28e5f0 |
from six import print_
|
|
|
28e5f0 |
from six.moves import input
|
|
|
28e5f0 |
@@ -285,22 +284,12 @@ No changes will be made to system configuration.
|
|
|
28e5f0 |
considered to be a superuser"""
|
|
|
28e5f0 |
return (os.getuid() == 0)
|
|
|
28e5f0 |
|
|
|
28e5f0 |
- def _create_checksum(self, hash_name, archive=None):
|
|
|
28e5f0 |
- if not archive:
|
|
|
28e5f0 |
- return False
|
|
|
28e5f0 |
-
|
|
|
28e5f0 |
- archive_fp = open(archive, 'rb')
|
|
|
28e5f0 |
- digest = hashlib.new(hash_name)
|
|
|
28e5f0 |
- digest.update(archive_fp.read())
|
|
|
28e5f0 |
- archive_fp.close()
|
|
|
28e5f0 |
- return digest.hexdigest()
|
|
|
28e5f0 |
-
|
|
|
28e5f0 |
def get_preferred_hash_name(self):
|
|
|
28e5f0 |
"""Returns the string name of the hashlib-supported checksum algorithm
|
|
|
28e5f0 |
to use"""
|
|
|
28e5f0 |
return "md5"
|
|
|
28e5f0 |
|
|
|
28e5f0 |
- def display_results(self, archive, directory):
|
|
|
28e5f0 |
+ def display_results(self, archive, directory, checksum):
|
|
|
28e5f0 |
# Display results is called from the tail of SoSReport.final_work()
|
|
|
28e5f0 |
#
|
|
|
28e5f0 |
# Logging is already shutdown and all terminal output must use the
|
|
|
28e5f0 |
@@ -312,19 +301,10 @@ No changes will be made to system configuration.
|
|
|
28e5f0 |
|
|
|
28e5f0 |
self._print()
|
|
|
28e5f0 |
|
|
|
28e5f0 |
- hash_name = self.get_preferred_hash_name()
|
|
|
28e5f0 |
if archive:
|
|
|
28e5f0 |
- # store checksum into file
|
|
|
28e5f0 |
- fp = open(archive + "." + hash_name, "w")
|
|
|
28e5f0 |
- checksum = self._create_checksum(hash_name, archive)
|
|
|
28e5f0 |
- if checksum:
|
|
|
28e5f0 |
- fp.write(checksum + "\n")
|
|
|
28e5f0 |
- fp.close()
|
|
|
28e5f0 |
-
|
|
|
28e5f0 |
self._print(_("Your sosreport has been generated and saved "
|
|
|
28e5f0 |
"in:\n %s") % archive)
|
|
|
28e5f0 |
else:
|
|
|
28e5f0 |
- checksum = None
|
|
|
28e5f0 |
self._print(_("sosreport build tree is located at : %s" %
|
|
|
28e5f0 |
directory))
|
|
|
28e5f0 |
|
|
|
28e5f0 |
diff --git a/sos/sosreport.py b/sos/sosreport.py
|
|
|
28e5f0 |
index f3e0f34..f7a5f11 100644
|
|
|
28e5f0 |
--- a/sos/sosreport.py
|
|
|
28e5f0 |
+++ b/sos/sosreport.py
|
|
|
28e5f0 |
@@ -33,6 +33,7 @@ from stat import ST_UID, ST_GID, ST_MODE, ST_CTIME, ST_ATIME, ST_MTIME, S_IMODE
|
|
|
28e5f0 |
from time import strftime, localtime
|
|
|
28e5f0 |
from collections import deque
|
|
|
28e5f0 |
import tempfile
|
|
|
28e5f0 |
+import hashlib
|
|
|
28e5f0 |
|
|
|
28e5f0 |
from sos import _sos as _
|
|
|
28e5f0 |
from sos import __version__
|
|
|
28e5f0 |
@@ -1432,6 +1433,18 @@ class SoSReport(object):
|
|
|
28e5f0 |
raise
|
|
|
28e5f0 |
self._log_plugin_exception(plugname, "postproc")
|
|
|
28e5f0 |
|
|
|
28e5f0 |
+ def _create_checksum(self, archive=None):
|
|
|
28e5f0 |
+ if not archive:
|
|
|
28e5f0 |
+ return False
|
|
|
28e5f0 |
+
|
|
|
28e5f0 |
+ hash_name = self.policy.get_preferred_hash_name()
|
|
|
28e5f0 |
+
|
|
|
28e5f0 |
+ archive_fp = open(archive, 'rb')
|
|
|
28e5f0 |
+ digest = hashlib.new(hash_name)
|
|
|
28e5f0 |
+ digest.update(archive_fp.read())
|
|
|
28e5f0 |
+ archive_fp.close()
|
|
|
28e5f0 |
+ return digest.hexdigest()
|
|
|
28e5f0 |
+
|
|
|
28e5f0 |
def final_work(self):
|
|
|
28e5f0 |
# this must come before archive creation to ensure that log
|
|
|
28e5f0 |
# files are closed and cleaned up at exit.
|
|
|
28e5f0 |
@@ -1466,7 +1479,18 @@ class SoSReport(object):
|
|
|
28e5f0 |
else:
|
|
|
28e5f0 |
directory = self.archive.get_archive_path()
|
|
|
28e5f0 |
|
|
|
28e5f0 |
- self.policy.display_results(archive, directory)
|
|
|
28e5f0 |
+ hash_name = self.policy.get_preferred_hash_name()
|
|
|
28e5f0 |
+ checksum = None
|
|
|
28e5f0 |
+
|
|
|
28e5f0 |
+ if hash_name and not self.opts.build:
|
|
|
28e5f0 |
+ # store checksum into file
|
|
|
28e5f0 |
+ fp = open(archive + "." + hash_name, "w")
|
|
|
28e5f0 |
+ checksum = self._create_checksum(archive)
|
|
|
28e5f0 |
+ if checksum:
|
|
|
28e5f0 |
+ fp.write(checksum + "\n")
|
|
|
28e5f0 |
+ fp.close()
|
|
|
28e5f0 |
+
|
|
|
28e5f0 |
+ self.policy.display_results(archive, directory, checksum)
|
|
|
28e5f0 |
|
|
|
28e5f0 |
self.tempfile_util.clean()
|
|
|
28e5f0 |
return True
|
|
|
28e5f0 |
--
|
|
|
28e5f0 |
2.4.3
|
|
|
28e5f0 |
|
|
|
28e5f0 |
From 4a9b919a7f1b9542a23982e49cc9035e84551e13 Mon Sep 17 00:00:00 2001
|
|
|
28e5f0 |
From: "Bryn M. Reeves" <bmr@redhat.com>
|
|
|
28e5f0 |
Date: Fri, 20 Nov 2015 18:48:33 +0000
|
|
|
28e5f0 |
Subject: [PATCH] [sosreport] prepare report in a private subdirectory
|
|
|
28e5f0 |
|
|
|
28e5f0 |
To avoid file creation races in shared temporary directories like
|
|
|
28e5f0 |
/tmp and /var/tmp use a private (0700) subdirectory to build the
|
|
|
28e5f0 |
FileCacheArchive and subsequent archive and compressed archive
|
|
|
28e5f0 |
files: only create a file in the containing directory when it can
|
|
|
28e5f0 |
be done as a single atomic rename.
|
|
|
28e5f0 |
|
|
|
28e5f0 |
This prevents sos from writing to an arbitrary location under the
|
|
|
28e5f0 |
control of another user: a malicious user could steal data or over
|
|
|
28e5f0 |
write files in /etc resulting in a local privilege escalation.
|
|
|
28e5f0 |
|
|
|
28e5f0 |
There remains a further race since once the archive name is known
|
|
|
28e5f0 |
the checksum file name becomes predictable: as the checksum file
|
|
|
28e5f0 |
is also prepared in the subdirectory and moved into place the
|
|
|
28e5f0 |
result is always either success or an error that is reported to
|
|
|
28e5f0 |
the user.
|
|
|
28e5f0 |
|
|
|
28e5f0 |
The correct checksum value is still reported to the user via the
|
|
|
28e5f0 |
terminal.
|
|
|
28e5f0 |
|
|
|
28e5f0 |
Signed-off-by: Bryn M. Reeves <bmr@redhat.com>
|
|
|
28e5f0 |
---
|
|
|
28e5f0 |
sos/sosreport.py | 100 ++++++++++++++++++++++++++++++++++++++++++-------------
|
|
|
28e5f0 |
1 file changed, 77 insertions(+), 23 deletions(-)
|
|
|
28e5f0 |
|
|
|
28e5f0 |
diff --git a/sos/sosreport.py b/sos/sosreport.py
|
|
|
28e5f0 |
index f7a5f11..fe251ed 100644
|
|
|
28e5f0 |
--- a/sos/sosreport.py
|
|
|
28e5f0 |
+++ b/sos/sosreport.py
|
|
|
28e5f0 |
@@ -32,6 +32,7 @@ from sos.utilities import ImporterHelper
|
|
|
28e5f0 |
from stat import ST_UID, ST_GID, ST_MODE, ST_CTIME, ST_ATIME, ST_MTIME, S_IMODE
|
|
|
28e5f0 |
from time import strftime, localtime
|
|
|
28e5f0 |
from collections import deque
|
|
|
28e5f0 |
+from shutil import rmtree
|
|
|
28e5f0 |
import tempfile
|
|
|
28e5f0 |
import hashlib
|
|
|
28e5f0 |
|
|
|
28e5f0 |
@@ -678,6 +679,7 @@ class SoSReport(object):
|
|
|
28e5f0 |
self.tempfile_util = None
|
|
|
28e5f0 |
self._args = args
|
|
|
28e5f0 |
self.sysroot = "/"
|
|
|
28e5f0 |
+ self.sys_tmp = None
|
|
|
28e5f0 |
|
|
|
28e5f0 |
try:
|
|
|
28e5f0 |
import signal
|
|
|
28e5f0 |
@@ -678,15 +678,22 @@ class SoSReport(object):
|
|
|
28e5f0 |
|
|
|
28e5f0 |
self._is_root = self.policy.is_root()
|
|
|
28e5f0 |
|
|
|
28e5f0 |
- self.tmpdir = os.path.abspath(
|
|
|
28e5f0 |
- self.policy.get_tmp_dir(self.opts.tmp_dir))
|
|
|
28e5f0 |
- if not os.path.isdir(self.tmpdir) \
|
|
|
28e5f0 |
- or not os.access(self.tmpdir, os.W_OK):
|
|
|
28e5f0 |
+ # system temporary directory to use
|
|
|
28e5f0 |
+ tmp = os.path.abspath(self.policy.get_tmp_dir(self.opts.tmp_dir))
|
|
|
28e5f0 |
+
|
|
|
28e5f0 |
+ if not os.path.isdir(tmp) \
|
|
|
28e5f0 |
+ or not os.access(tmp, os.W_OK):
|
|
|
28e5f0 |
# write directly to stderr as logging is not initialised yet
|
|
|
28e5f0 |
- sys.stderr.write("temporary directory %s " % self.tmpdir
|
|
|
28e5f0 |
+ sys.stderr.write("temporary directory %s " % tmp
|
|
|
28e5f0 |
+ "does not exist or is not writable\n")
|
|
|
28e5f0 |
self._exit(1)
|
|
|
28e5f0 |
+
|
|
|
28e5f0 |
+ self.sys_tmp = tmp
|
|
|
28e5f0 |
+
|
|
|
28e5f0 |
+ # our (private) temporary directory
|
|
|
28e5f0 |
+ self.tmpdir = tempfile.mkdtemp(prefix="sos.", dir=self.sys_tmp)
|
|
|
28e5f0 |
self.tempfile_util = TempFileUtil(self.tmpdir)
|
|
|
28e5f0 |
+
|
|
|
28e5f0 |
self._set_directories()
|
|
|
28e5f0 |
|
|
|
28e5f0 |
self._setup_logging()
|
|
|
28e5f0 |
@@ -1433,27 +1442,34 @@ class SoSReport(object):
|
|
|
28e5f0 |
raise
|
|
|
28e5f0 |
self._log_plugin_exception(plugname, "postproc")
|
|
|
28e5f0 |
|
|
|
28e5f0 |
- def _create_checksum(self, archive=None):
|
|
|
28e5f0 |
+ def _create_checksum(self, archive, hash_name):
|
|
|
28e5f0 |
if not archive:
|
|
|
28e5f0 |
return False
|
|
|
28e5f0 |
|
|
|
28e5f0 |
- hash_name = self.policy.get_preferred_hash_name()
|
|
|
28e5f0 |
-
|
|
|
28e5f0 |
archive_fp = open(archive, 'rb')
|
|
|
28e5f0 |
digest = hashlib.new(hash_name)
|
|
|
28e5f0 |
digest.update(archive_fp.read())
|
|
|
28e5f0 |
archive_fp.close()
|
|
|
28e5f0 |
return digest.hexdigest()
|
|
|
28e5f0 |
|
|
|
28e5f0 |
+ def _write_checksum(self, archive, hash_name, checksum):
|
|
|
28e5f0 |
+ # store checksum into file
|
|
|
28e5f0 |
+ fp = open(archive + "." + hash_name, "w")
|
|
|
28e5f0 |
+ if checksum:
|
|
|
28e5f0 |
+ fp.write(checksum + "\n")
|
|
|
28e5f0 |
+ fp.close()
|
|
|
28e5f0 |
+
|
|
|
28e5f0 |
def final_work(self):
|
|
|
28e5f0 |
- # this must come before archive creation to ensure that log
|
|
|
28e5f0 |
+ # This must come before archive creation to ensure that log
|
|
|
28e5f0 |
# files are closed and cleaned up at exit.
|
|
|
28e5f0 |
+ #
|
|
|
28e5f0 |
+ # All subsequent terminal output must use print().
|
|
|
28e5f0 |
self._finish_logging()
|
|
|
28e5f0 |
|
|
|
28e5f0 |
archive = None # archive path
|
|
|
28e5f0 |
directory = None # report directory path (--build)
|
|
|
28e5f0 |
|
|
|
28e5f0 |
- # package up the results for the support organization
|
|
|
28e5f0 |
+ # package up and compress the results
|
|
|
28e5f0 |
if not self.opts.build:
|
|
|
28e5f0 |
old_umask = os.umask(0o077)
|
|
|
28e5f0 |
if not self.opts.quiet:
|
|
|
28e5f0 |
@@ -1464,10 +1480,9 @@ class SoSReport(object):
|
|
|
28e5f0 |
self.opts.compression_type)
|
|
|
28e5f0 |
except (OSError, IOError) as e:
|
|
|
28e5f0 |
if e.errno in fatal_fs_errors:
|
|
|
28e5f0 |
- self.ui_log.error("")
|
|
|
28e5f0 |
- self.ui_log.error(" %s while finalizing archive"
|
|
|
28e5f0 |
- % e.strerror)
|
|
|
28e5f0 |
- self.ui_log.error("")
|
|
|
28e5f0 |
+ print("")
|
|
|
28e5f0 |
+ print(_(" %s while finalizing archive" % e.strerror))
|
|
|
28e5f0 |
+ print("")
|
|
|
28e5f0 |
self._exit(1)
|
|
|
28e5f0 |
except:
|
|
|
28e5f0 |
if self.opts.debug:
|
|
|
28e5f0 |
@@ -1477,18 +1492,55 @@ class SoSReport(object):
|
|
|
28e5f0 |
finally:
|
|
|
28e5f0 |
os.umask(old_umask)
|
|
|
28e5f0 |
else:
|
|
|
28e5f0 |
+ # move the archive root out of the private tmp directory.
|
|
|
28e5f0 |
directory = self.archive.get_archive_path()
|
|
|
28e5f0 |
+ dir_name = os.path.basename(directory)
|
|
|
28e5f0 |
+ try:
|
|
|
28e5f0 |
+ os.rename(directory, os.path.join(self.sys_tmp, dir_name))
|
|
|
28e5f0 |
+ except (OSError, IOError):
|
|
|
28e5f0 |
+ print(_("Error moving directory: %s" % directory))
|
|
|
28e5f0 |
+ return False
|
|
|
28e5f0 |
|
|
|
28e5f0 |
- hash_name = self.policy.get_preferred_hash_name()
|
|
|
28e5f0 |
checksum = None
|
|
|
28e5f0 |
|
|
|
28e5f0 |
- if hash_name and not self.opts.build:
|
|
|
28e5f0 |
- # store checksum into file
|
|
|
28e5f0 |
- fp = open(archive + "." + hash_name, "w")
|
|
|
28e5f0 |
- checksum = self._create_checksum(archive)
|
|
|
28e5f0 |
- if checksum:
|
|
|
28e5f0 |
- fp.write(checksum + "\n")
|
|
|
28e5f0 |
- fp.close()
|
|
|
28e5f0 |
+ if not self.opts.build:
|
|
|
28e5f0 |
+ # compute and store the archive checksum
|
|
|
28e5f0 |
+ hash_name = self.policy.get_preferred_hash_name()
|
|
|
28e5f0 |
+ checksum = self._create_checksum(archive, hash_name)
|
|
|
28e5f0 |
+ self._write_checksum(archive, hash_name, checksum)
|
|
|
28e5f0 |
+
|
|
|
28e5f0 |
+ # output filename is in the private tmpdir - move it to the
|
|
|
28e5f0 |
+ # containing directory.
|
|
|
28e5f0 |
+ final_name = os.path.join(self.sys_tmp, os.path.basename(archive))
|
|
|
28e5f0 |
+
|
|
|
28e5f0 |
+ archive_hash = archive + "." + hash_name
|
|
|
28e5f0 |
+ final_hash = final_name + "." + hash_name
|
|
|
28e5f0 |
+
|
|
|
28e5f0 |
+ # move the archive and checksum file
|
|
|
28e5f0 |
+ try:
|
|
|
28e5f0 |
+ os.rename(archive, final_name)
|
|
|
28e5f0 |
+ archive = final_name
|
|
|
28e5f0 |
+ except (OSError, IOError):
|
|
|
28e5f0 |
+ print(_("Error moving archive file: %s" % archive))
|
|
|
28e5f0 |
+ return False
|
|
|
28e5f0 |
+
|
|
|
28e5f0 |
+ # There is a race in the creation of the final checksum file:
|
|
|
28e5f0 |
+ # since the archive has already been published and the checksum
|
|
|
28e5f0 |
+ # file name is predictable once the archive name is known a
|
|
|
28e5f0 |
+ # malicious user could attempt to create a symbolic link in order
|
|
|
28e5f0 |
+ # to misdirect writes to a file of the attacker's choosing.
|
|
|
28e5f0 |
+ #
|
|
|
28e5f0 |
+ # To mitigate this we write the checksum inside the private tmp
|
|
|
28e5f0 |
+ # directory and use an atomic rename that is guaranteed to either
|
|
|
28e5f0 |
+ # succeed or fail: at worst the move will fail and be reported to
|
|
|
28e5f0 |
+ # the user. The correct checksum value is still written to the
|
|
|
28e5f0 |
+ # terminal and nothing is written to a location under the control
|
|
|
28e5f0 |
+ # of the user creating the link.
|
|
|
28e5f0 |
+ try:
|
|
|
28e5f0 |
+ os.rename(archive_hash, final_hash)
|
|
|
28e5f0 |
+ except (OSError, IOError):
|
|
|
28e5f0 |
+ print(_("Error moving checksum file: %s" % archive_hash))
|
|
|
28e5f0 |
+ return False
|
|
|
28e5f0 |
|
|
|
28e5f0 |
self.policy.display_results(archive, directory, checksum)
|
|
|
28e5f0 |
|
|
|
28e5f0 |
@@ -1546,8 +1598,10 @@ class SoSReport(object):
|
|
|
28e5f0 |
self.archive.cleanup()
|
|
|
28e5f0 |
if self.tempfile_util:
|
|
|
28e5f0 |
self.tempfile_util.clean()
|
|
|
28e5f0 |
+ if self.tmpdir:
|
|
|
28e5f0 |
+ rmtree(self.tmpdir)
|
|
|
28e5f0 |
except:
|
|
|
28e5f0 |
- pass
|
|
|
28e5f0 |
+ raise
|
|
|
28e5f0 |
|
|
|
28e5f0 |
return False
|
|
|
28e5f0 |
|
|
|
28e5f0 |
--
|
|
|
28e5f0 |
2.4.3
|
|
|
28e5f0 |
|
|
|
28e5f0 |
From 08121d877741e33333a1ae01280f6898d7d4ca15 Mon Sep 17 00:00:00 2001
|
|
|
28e5f0 |
From: "Bryn M. Reeves" <bmr@redhat.com>
|
|
|
28e5f0 |
Date: Thu, 10 Dec 2015 11:50:49 +0000
|
|
|
28e5f0 |
Subject: [PATCH] [sosreport] clean up private temporary directory
|
|
|
28e5f0 |
|
|
|
28e5f0 |
Signed-off-by: Bryn M. Reeves <bmr@redhat.com>
|
|
|
28e5f0 |
---
|
|
|
28e5f0 |
sos/sosreport.py | 7 ++++++-
|
|
|
28e5f0 |
1 file changed, 6 insertions(+), 1 deletion(-)
|
|
|
28e5f0 |
|
|
|
28e5f0 |
diff --git a/sos/sosreport.py b/sos/sosreport.py
|
|
|
28e5f0 |
index fe251ed..bc7792a 100644
|
|
|
28e5f0 |
--- a/sos/sosreport.py
|
|
|
28e5f0 |
+++ b/sos/sosreport.py
|
|
|
28e5f0 |
@@ -1544,7 +1544,12 @@ class SoSReport(object):
|
|
|
28e5f0 |
|
|
|
28e5f0 |
self.policy.display_results(archive, directory, checksum)
|
|
|
28e5f0 |
|
|
|
28e5f0 |
- self.tempfile_util.clean()
|
|
|
28e5f0 |
+ # clean up
|
|
|
28e5f0 |
+ if self.tempfile_util:
|
|
|
28e5f0 |
+ self.tempfile_util.clean()
|
|
|
28e5f0 |
+ if self.tmpdir:
|
|
|
28e5f0 |
+ rmtree(self.tmpdir)
|
|
|
28e5f0 |
+
|
|
|
28e5f0 |
return True
|
|
|
28e5f0 |
|
|
|
28e5f0 |
def verify_plugins(self):
|
|
|
28e5f0 |
--
|
|
|
28e5f0 |
2.4.3
|
|
|
28e5f0 |
|
|
|
28e5f0 |
From a7a2dd8eb1791257f80fd2ae2993b06472690aea Mon Sep 17 00:00:00 2001
|
|
|
28e5f0 |
From: "Bryn M. Reeves" <bmr@redhat.com>
|
|
|
28e5f0 |
Date: Wed, 13 Jan 2016 10:57:59 +0000
|
|
|
28e5f0 |
Subject: [PATCH] [sosreport] report correct final path with --build
|
|
|
28e5f0 |
|
|
|
28e5f0 |
Ensure the correct path (in the system temporary directory) is
|
|
|
28e5f0 |
reported when the --build option is used.
|
|
|
28e5f0 |
|
|
|
28e5f0 |
Signed-off-by: Bryn M. Reeves <bmr@redhat.com>
|
|
|
28e5f0 |
---
|
|
|
28e5f0 |
sos/sosreport.py | 4 +++-
|
|
|
28e5f0 |
1 file changed, 3 insertions(+), 1 deletion(-)
|
|
|
28e5f0 |
|
|
|
28e5f0 |
diff --git a/sos/sosreport.py b/sos/sosreport.py
|
|
|
28e5f0 |
index bc7792a..f61ea4a 100644
|
|
|
28e5f0 |
--- a/sos/sosreport.py
|
|
|
28e5f0 |
+++ b/sos/sosreport.py
|
|
|
28e5f0 |
@@ -1496,7 +1496,9 @@ class SoSReport(object):
|
|
|
28e5f0 |
directory = self.archive.get_archive_path()
|
|
|
28e5f0 |
dir_name = os.path.basename(directory)
|
|
|
28e5f0 |
try:
|
|
|
28e5f0 |
- os.rename(directory, os.path.join(self.sys_tmp, dir_name))
|
|
|
28e5f0 |
+ final_dir = os.path.join(self.sys_tmp, dir_name)
|
|
|
28e5f0 |
+ os.rename(directory, final_dir)
|
|
|
28e5f0 |
+ directory = final_dir
|
|
|
28e5f0 |
except (OSError, IOError):
|
|
|
28e5f0 |
print(_("Error moving directory: %s" % directory))
|
|
|
28e5f0 |
return False
|
|
|
28e5f0 |
--
|
|
|
28e5f0 |
2.4.3
|
|
|
28e5f0 |
|