<pre style='margin:0'>
Joshua Root (jmroot) pushed a commit to branch master
in repository macports-base.

</pre>
<p><a href="https://github.com/macports/macports-base/commit/e0338e824ed0a2a1db3e7d16599019c8f05f54ea">https://github.com/macports/macports-base/commit/e0338e824ed0a2a1db3e7d16599019c8f05f54ea</a></p>
<pre style="white-space: pre; background: #F8F8F8">The following commit(s) were added to refs/heads/master by this push:
<span style='display:block; white-space:pre;color:#404040;'>     new e0338e82 Drop privileges for all VCS operations in mportsync
</span>e0338e82 is described below

<span style='display:block; white-space:pre;color:#808000;'>commit e0338e824ed0a2a1db3e7d16599019c8f05f54ea
</span>Author: Joshua Root <jmr@macports.org>
AuthorDate: Thu Apr 21 11:49:36 2022 +1000

<span style='display:block; white-space:pre;color:#404040;'>    Drop privileges for all VCS operations in mportsync
</span><span style='display:block; white-space:pre;color:#404040;'>    
</span><span style='display:block; white-space:pre;color:#404040;'>    Recent git versions will by default refuse to operate on directories
</span><span style='display:block; white-space:pre;color:#404040;'>    that are not owned by the current user. Always dropping privileges is
</span><span style='display:block; white-space:pre;color:#404040;'>    probably a safer approach in general anyway.
</span><span style='display:block; white-space:pre;color:#404040;'>    
</span><span style='display:block; white-space:pre;color:#404040;'>    The privilege dropping and restoring code is split out into new procs,
</span><span style='display:block; white-space:pre;color:#404040;'>    and called such that the checks for whether a directory is a VCS repo
</span><span style='display:block; white-space:pre;color:#404040;'>    are done as the dir's owner, as well as the VCS update itself.
</span>---
 src/macports1.0/macports.tcl | 90 ++++++++++++++++++++++++++++++--------------
 1 file changed, 61 insertions(+), 29 deletions(-)

<span style='display:block; white-space:pre;color:#808080;'>diff --git a/src/macports1.0/macports.tcl b/src/macports1.0/macports.tcl
</span><span style='display:block; white-space:pre;color:#808080;'>index b59f5d1d..ebd4f312 100644
</span><span style='display:block; white-space:pre;background:#e0e0ff;'>--- a/src/macports1.0/macports.tcl
</span><span style='display:block; white-space:pre;background:#e0e0ff;'>+++ b/src/macports1.0/macports.tcl
</span><span style='display:block; white-space:pre;background:#e0e0e0;'>@@ -2581,6 +2581,54 @@ proc macports::getindex {source} {
</span>     return [file join [macports::getsourcepath $source] PortIndex]
 }
 
<span style='display:block; white-space:pre;background:#e0ffe0;'>+# macports::VCSPrepare
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+#
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+# Prepare to run a VCS command in the given directory, including
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+# dropping privileges by taking on the euid of the owner of the
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+# directory, if running as root.
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+#
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+# @param portDir Path to directory to prepare to operate on.
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+# @param state Variable name to save relevant state in. Pass this to
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+#              VCSCleanup after running the VCS commands.
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+proc macports::VCSPrepare {dir state} {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    if {[getuid] == 0} {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+        global env macports::user_ssh_auth_sock
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+        upvar $state state
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+        # Must change egid before dropping root euid.
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+        set state(oldEGID) [getegid]
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+        set newEGID [name_to_gid [file attributes $dir -group]]
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+        setegid $newEGID
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+        set state(oldEUID) [geteuid]
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+        set newEUID [name_to_uid [file attributes $dir -owner]]
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+        seteuid $newEUID
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+        set state(oldEnv) [array get env]
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+        set env(HOME) [getpwuid $newEUID dir]
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+        set envdebug "HOME=$env(HOME)"
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+        if {[info exists macports::user_ssh_auth_sock]} {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+            set env(SSH_AUTH_SOCK) $macports::user_ssh_auth_sock
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+            append envdebug " SSH_AUTH_SOCK=$env(SSH_AUTH_SOCK)"
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+        }
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+        ui_debug "euid/egid changed to: $newEUID/$newEGID, env: $envdebug"
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    }
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+}
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+# macports::VCSCleanup
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+#
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+# Clean up after running VCS commands. Undoes the effects of VCSPrepare
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+# including restoring privileges.
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+#
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+# @param state Variable name that was passed to VCSPrepare previously.
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+proc macports::VCSCleanup {state} {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    if {[getuid] == 0} {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+        upvar $state state
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+        seteuid $state(oldEUID)
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+        setegid $state(oldEGID)
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+        array unset env *
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+        array set env $state(oldEnv)
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+        ui_debug "euid/egid restored to: $state(oldEUID)/$state(oldEGID), env restored"
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    }
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+}
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span> # macports::GetVCSUpdateCmd --
 #
 # Determine whether the given directory is associated with a repository
<span style='display:block; white-space:pre;background:#e0e0e0;'>@@ -2597,7 +2645,9 @@ proc macports::getindex {source} {
</span> # If the directory is not associated with any supported system, return
 # an empty list.
 #
<span style='display:block; white-space:pre;background:#ffe0e0;'>-proc macports::GetVCSUpdateCmd portDir {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+# @param portDir The directory to check.
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+#
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+proc macports::GetVCSUpdateCmd {portDir} {
</span> 
     set oldPWD [pwd]
     cd $portDir
<span style='display:block; white-space:pre;background:#e0e0e0;'>@@ -2637,40 +2687,18 @@ proc macports::GetVCSUpdateCmd portDir {
</span> 
 # macports::UpdateVCS --
 #
<span style='display:block; white-space:pre;background:#ffe0e0;'>-# Execute the given command in a shell. If called with superuser
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-# privileges, execute the command as the user/group that owns the given
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-# directory, restoring privileges before returning.
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+# Execute the given command in a shell. Should be run as the
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+# user/group that owns the given directory by calling VCSPrepare
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+# beforehand.
</span> #
 # This proc could probably be generalized and used elsewhere.
 #
<span style='display:block; white-space:pre;background:#e0ffe0;'>+# @param cmd The command to run.
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+# @param dir The directory to run the command in.
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+#
</span> proc macports::UpdateVCS {cmd dir} {
<span style='display:block; white-space:pre;background:#ffe0e0;'>-    global env macports::user_ssh_auth_sock
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-    if {[getuid] == 0} {
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-        # Must change egid before dropping root euid.
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-        set oldEGID [getegid]
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-        set newEGID [name_to_gid [file attributes $dir -group]]
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-        setegid $newEGID
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-        set oldEUID [geteuid]
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-        set newEUID [name_to_uid [file attributes $dir -owner]]
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-        seteuid $newEUID
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-        array set oldEnv [array get env]
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-        set env(HOME) [getpwuid $newEUID dir]
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-        set envdebug "HOME=$env(HOME)"
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-        if {[info exists macports::user_ssh_auth_sock]} {
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-            set env(SSH_AUTH_SOCK) $macports::user_ssh_auth_sock
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-            append envdebug " SSH_AUTH_SOCK=$env(SSH_AUTH_SOCK)"
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-        }
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-        ui_debug "euid/egid changed to: $newEUID/$newEGID, env: $envdebug"
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-    }
</span>     ui_debug $cmd
     catch {system -W $dir $cmd} result options
<span style='display:block; white-space:pre;background:#ffe0e0;'>-    if {[getuid] == 0} {
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-        seteuid $oldEUID
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-        setegid $oldEGID
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-        array unset env *
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-        array set env [array get oldEnv]
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-        ui_debug "euid/egid restored to: $oldEUID/$oldEGID, env restored"
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-    }
</span>     return -options $options $result
 }
 
<span style='display:block; white-space:pre;background:#e0e0e0;'>@@ -2700,6 +2728,7 @@ proc mportsync {{optionslist {}}} {
</span>         switch -regexp -- [macports::getprotocol $source] {
             {^file$} {
                 set portdir [macports::getportdir $source]
<span style='display:block; white-space:pre;background:#e0ffe0;'>+                macports::VCSPrepare $portdir statevar
</span>                 if {[_source_is_obsolete_svn_repo $portdir]} {
                     set obsoletesvn 1
                 }
<span style='display:block; white-space:pre;background:#e0e0e0;'>@@ -2709,6 +2738,7 @@ proc mportsync {{optionslist {}}} {
</span>                     ui_debug $::errorInfo
                     ui_info "Could not access contents of $portdir"
                     incr numfailed
<span style='display:block; white-space:pre;background:#e0ffe0;'>+                    macports::VCSCleanup statevar
</span>                     continue
                 }
                 if {[llength $repoInfo]} {
<span style='display:block; white-space:pre;background:#e0e0e0;'>@@ -2719,9 +2749,11 @@ proc mportsync {{optionslist {}}} {
</span>                         ui_debug $::errorInfo
                         ui_info "Syncing local $vcs ports tree failed"
                         incr numfailed
<span style='display:block; white-space:pre;background:#e0ffe0;'>+                        macports::VCSCleanup statevar
</span>                         continue
                     }
                 }
<span style='display:block; white-space:pre;background:#e0ffe0;'>+                macports::VCSCleanup statevar
</span>                 set needs_portindex true
             }
             {^rsync$} {
</pre><pre style='margin:0'>

</pre>