diff options
author | Bryn M. Reeves <bmr@redhat.com> | 2012-12-12 19:06:40 +0000 |
---|---|---|
committer | Bryn M. Reeves <bmr@redhat.com> | 2012-12-12 19:06:40 +0000 |
commit | 7d3d1473510b07962ec04b6449fe18b8ace77c40 (patch) | |
tree | 32e23afb7c129064ada2f55e115407375e1dd2a4 | |
parent | 653ad8f21452a4d73ebe1664ae761e296690a0e9 (diff) | |
download | sos-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.py | 25 |
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): |