<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>