Fix log uid for logrotate-3.8 compat (bug 378451)
authorZac Medico <zmedico@gentoo.org>
Fri, 12 Aug 2011 09:47:04 +0000 (02:47 -0700)
committerZac Medico <zmedico@gentoo.org>
Fri, 12 Aug 2011 09:47:04 +0000 (02:47 -0700)
If PORT_LOGDIR is writable by the portage group but its uid is not
portage_uid, then set the uid to portage_uid if we have privileges to
do so, and also copy the uid to the logfile. This fixes logrotate
chown failures during the compression phase, when it attempts to copy
the uid from the logfile to a temp file. With the "su portage portage"
directive and logrotate-3.8.0, logrotate's chown call during the
compression phase will only succeed if the log file's uid is
portage_uid.

pym/portage/elog/mod_save.py
pym/portage/elog/mod_save_summary.py
pym/portage/package/ebuild/prepare_build_dirs.py

index 9350a6e580b666c20e4a2173ab2ebfe0115666b3..091bbf86d5a6d3177630313083290aa33f00052b 100644 (file)
@@ -4,13 +4,14 @@
 
 import io
 import time
+import portage
 from portage import os
 from portage import _encodings
 from portage import _unicode_decode
 from portage import _unicode_encode
 from portage.data import portage_gid, portage_uid
 from portage.package.ebuild.prepare_build_dirs import _ensure_log_subdirs
-from portage.util import ensure_dirs, normalize_path
+from portage.util import apply_permissions, ensure_dirs, normalize_path
 
 def process(mysettings, key, logentries, fulltext):
 
@@ -25,7 +26,10 @@ def process(mysettings, key, logentries, fulltext):
                # were previously set by the administrator.
                # NOTE: These permissions should be compatible with our
                # default logrotate config as discussed in bug 374287.
-               ensure_dirs(logdir, uid=portage_uid, gid=portage_gid, mode=0o2770)
+               uid = -1
+               if portage.data.secpass >= 2:
+                       uid = portage_uid
+               ensure_dirs(logdir, uid=uid, gid=portage_gid, mode=0o2770)
 
        cat = mysettings['CATEGORY']
        pf = mysettings['PF']
@@ -48,4 +52,21 @@ def process(mysettings, key, logentries, fulltext):
        elogfile.write(_unicode_decode(fulltext))
        elogfile.close()
 
+       # Copy group permission bits from parent directory.
+       elogdir_st = os.stat(log_subdir)
+       elogdir_gid = elogdir_st.st_gid
+       elogdir_grp_mode = 0o060 & elogdir_st.st_mode
+
+       # Copy the uid from the parent directory if we have privileges
+       # to do so, for compatibility with our default logrotate
+       # config (see bug 378451). With the "su portage portage"
+       # directive and logrotate-3.8.0, logrotate's chown call during
+       # the compression phase will only succeed if the log file's uid
+       # is portage_uid.
+       logfile_uid = -1
+       if portage.data.secpass >= 2:
+               logfile_uid = elogdir_st.st_uid
+       apply_permissions(elogfilename, uid=logfile_uid, gid=elogdir_gid,
+               mode=elogdir_grp_mode, mask=0)
+
        return elogfilename
index 4adc6f34cae9338b7c86458ef396709c9fb49d27..ab71724db230bf9899df1b2d4892a4c43141c4cb 100644 (file)
@@ -4,6 +4,7 @@
 
 import io
 import time
+import portage
 from portage import os
 from portage import _encodings
 from portage import _unicode_decode
@@ -25,7 +26,10 @@ def process(mysettings, key, logentries, fulltext):
                # were previously set by the administrator.
                # NOTE: These permissions should be compatible with our
                # default logrotate config as discussed in bug 374287.
-               ensure_dirs(logdir, uid=portage_uid, gid=portage_gid, mode=0o2770)
+               logdir_uid = -1
+               if portage.data.secpass >= 2:
+                       logdir_uid = portage_uid
+               ensure_dirs(logdir, uid=logdir_uid, gid=portage_gid, mode=0o2770)
 
        elogdir = os.path.join(logdir, "elog")
        _ensure_log_subdirs(logdir, elogdir)
@@ -40,7 +44,17 @@ def process(mysettings, key, logentries, fulltext):
        elogdir_st = os.stat(elogdir)
        elogdir_gid = elogdir_st.st_gid
        elogdir_grp_mode = 0o060 & elogdir_st.st_mode
-       apply_permissions(elogfilename, gid=elogdir_gid,
+
+       # Copy the uid from the parent directory if we have privileges
+       # to do so, for compatibility with our default logrotate
+       # config (see bug 378451). With the "su portage portage"
+       # directive and logrotate-3.8.0, logrotate's chown call during
+       # the compression phase will only succeed if the log file's uid
+       # is portage_uid.
+       logfile_uid = -1
+       if portage.data.secpass >= 2:
+               logfile_uid = elogdir_st.st_uid
+       apply_permissions(elogfilename, uid=logfile_uid, gid=elogdir_gid,
                mode=elogdir_grp_mode, mask=0)
 
        time_str = time.strftime("%Y-%m-%d %H:%M:%S %Z",
index 616dc2e06844438f12eed35768b2bfe47784bc06..9104d0e63955321ba9a52b5c06918e21f23cdcf6 100644 (file)
@@ -9,6 +9,7 @@ import shutil
 import stat
 import time
 
+import portage
 from portage import os, _encodings, _unicode_encode, _unicode_decode
 from portage.data import portage_gid, portage_uid, secpass
 from portage.exception import DirectoryNotFound, FileNotFound, \
@@ -358,13 +359,27 @@ def _ensure_log_subdirs(logdir, subdir):
        and subdir are assumed to be normalized absolute paths.
        """
        st = os.stat(logdir)
+       uid = -1
        gid = st.st_gid
        grp_mode = 0o2070 & st.st_mode
 
+       # If logdir is writable by the portage group but its uid
+       # is not portage_uid, then set the uid to portage_uid if
+       # we have privileges to do so, for compatibility with our
+       # default logrotate config (see bug 378451). With the
+       # "su portage portage" directive and logrotate-3.8.0,
+       # logrotate's chown call during the compression phase will
+       # only succeed if the log file's uid is portage_uid.
+       if grp_mode and gid == portage_gid and \
+               portage.data.secpass >= 2:
+               uid = portage_uid
+               if st.st_uid != portage_uid:
+                       ensure_dirs(logdir, uid=uid)
+
        logdir_split_len = len(logdir.split(os.sep))
        subdir_split = subdir.split(os.sep)[logdir_split_len:]
        subdir_split.reverse()
        current = logdir
        while subdir_split:
                current = os.path.join(current, subdir_split.pop())
-               ensure_dirs(current, gid=gid, mode=grp_mode, mask=0)
+               ensure_dirs(current, uid=uid, gid=gid, mode=grp_mode, mask=0)