aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBryn M. Reeves <bmr@redhat.com>2012-12-12 19:06:40 +0000
committerBryn M. Reeves <bmr@redhat.com>2012-12-12 19:06:40 +0000
commit7d3d1473510b07962ec04b6449fe18b8ace77c40 (patch)
tree32e23afb7c129064ada2f55e115407375e1dd2a4
parent653ad8f21452a4d73ebe1664ae761e296690a0e9 (diff)
downloadsos-7d3d1473510b07962ec04b6449fe18b8ace77c40.tar.gz
Work around non-writable directories in host file systems
Distributions that have moved to reduced capabilities and replaced suid and sgid binaries with fscaps have tightened the permissions on several standard system paths. For e.g.: dr-xr-xr-x. 18 root root 4096 Nov 23 19:04 / -rw-r--r--. 1 root root 1174 Dec 11 18:05 /etc/passwd ----------. 1 root root 742 Dec 11 18:05 /etc/shadow dr-xr-x---. 8 root root 4096 Dec 12 19:06 /root Processes that need to write to these paths on the host system must possess cap_dac_override in order to work but in the archive this creates problems when unpacking the archive without this capability. For files this is not a problem since the user only requires write permissions to the containing directory to remove the file. For directories it causes real problems for unprivileged users working with sosreport archives. This includes problems unpacking the archive (since directories are created without write permissions causing subsequent file creation beneath that path to fail) as well as problems cleaning up archives as a typical 'rm -rf' fails to remove these paths. These problems make it impossible to create archives that are both failthful to the host system and easy to work with for typical analysis users. Ultimately this may necessitate dropping permission preservation in the archive and instead storing these (and other information like ACLs and SELinux context) in files within the archive instead). Works around Issue #85
-rw-r--r--sos/utilities.py25
1 files changed, 18 insertions, 7 deletions
diff --git a/sos/utilities.py b/sos/utilities.py
index 94298c9e..32e08012 100644
--- a/sos/utilities.py
+++ b/sos/utilities.py
@@ -228,11 +228,14 @@ class TarFileArchive(Archive):
except:
return None
- def set_tar_info_from_stat(self, tar_info, fstat):
+ def set_tar_info_from_stat(self, tar_info, fstat, mode=None):
tar_info.mtime = fstat.st_mtime
tar_info.pax_headers['atime'] = "%.9f" % fstat.st_atime
tar_info.pax_headers['ctime'] = "%.9f" % fstat.st_ctime
- tar_info.mode = fstat.st_mode
+ if mode:
+ tar_info.mode = mode
+ else:
+ tar_info.mode = fstat.st_mode
tar_info.uid = fstat.st_uid
tar_info.gid = fstat.st_gid
@@ -240,8 +243,6 @@ class TarFileArchive(Archive):
return "%s.%s" % (self._name, self._suffix)
def add_parent(self, path):
- if (path == '/'):
- return
path = os.path.split(path)[0]
self.add_file(path)
@@ -251,6 +252,9 @@ class TarFileArchive(Archive):
else:
dest = self.prepend(src)
+ if src != '/':
+ self.add_parent(src)
+
tar_info = tarfile.TarInfo(name=dest)
if os.path.isdir(src):
@@ -262,7 +266,7 @@ class TarFileArchive(Archive):
fp.close()
tar_info.size = len(content)
fileobj = StringIO(content)
- fstat = os.stat(src)
+
# FIXME: handle this at a higher level?
if src.startswith("/sys/") or src.startswith ("/proc/"):
context = None
@@ -270,8 +274,15 @@ class TarFileArchive(Archive):
context = self.get_selinux_context(src)
if context:
tar_info.pax_headers['RHT.security.selinux'] = context
- self.set_tar_info_from_stat(tar_info,fstat)
- self.add_parent(src)
+
+ fstat = os.stat(src)
+ if os.path.isdir(src) and not (fstat.st_mode & 000200):
+ # directories not writable by their owner are a world of pain
+ # in tar archives. Do not allow them (see Issue #85).
+ mode = fstat.st_mode | 000200
+ else:
+ mode = None
+ self.set_tar_info_from_stat(tar_info,fstat, mode)
self.tarfile.addfile(tar_info, fileobj)
def add_string(self, content, dest):