<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/7a7f01d60dffaf717abb537d3da1227be56478f7">https://github.com/macports/macports-base/commit/7a7f01d60dffaf717abb537d3da1227be56478f7</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 7a7f01d60 mportsync: run external programs unprivileged
</span>7a7f01d60 is described below

<span style='display:block; white-space:pre;color:#808000;'>commit 7a7f01d60dffaf717abb537d3da1227be56478f7
</span>Author: Joshua Root <jmr@macports.org>
AuthorDate: Tue Feb 18 13:39:59 2025 +1100

<span style='display:block; white-space:pre;color:#404040;'>    mportsync: run external programs unprivileged
</span>---
 src/macports1.0/macports.tcl | 78 +++++++++++++++++++++++++++++++++++++++-----
 1 file changed, 69 insertions(+), 9 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 1e43ba426..7fd97bd8d 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;'>@@ -3220,10 +3220,52 @@ proc macports::UpdateVCS {cmd dir} {
</span>     return -options $options $result
 }
 
<span style='display:block; white-space:pre;background:#e0ffe0;'>+proc macports::run_unprivileged {code {user {}}} {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    if {[geteuid] == 0} {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+        if {$user eq {}} {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+            variable macportsuser
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+            set uname $macportsuser
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+            set gname {}
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+        } else {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+            lassign $user uname gname
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+        }
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+        set uid [name_to_uid $uname]
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+        if {$gname ne {}} {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+            set gid [name_to_gid $gname]
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+        } else {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+            set gid [uname_to_gid $uname]
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+        }
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+        setegid $gid
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+        seteuid $uid
</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;'>+    try {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+        uplevel 1 $code
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    } finally {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+        if {[getuid] == 0} {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+            seteuid 0; setegid 0
</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;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+proc macports::chown {path user} {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    if {[getuid] != 0} {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+        ui_debug "Not root; skipping 'chown $path $user'"
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+        return
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    }
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    lchown $path $user
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    if {[file isdirectory $path]} {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+        fs-traverse myfile [list $path] {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+            lchown $myfile $user
</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;'>+
</span> proc mportsync {{options {}}} {
     global macports::sources macports::ui_prefix \
            macports::os_platform macports::os_major \
<span style='display:block; white-space:pre;background:#ffe0e0;'>-           macports::os_arch macports::autoconf::tar_path
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+           macports::os_arch macports::autoconf::tar_path \
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+           macports::macportsuser
</span> 
     if {[dict exists $options no_reindex]} {
         upvar [dict get $options needed_portindex_var] any_needed_portindex
<span style='display:block; white-space:pre;background:#e0e0e0;'>@@ -3309,10 +3351,11 @@ proc mportsync {{options {}}} {
</span>                     set include_option {}
                     set srcstr $source
                 }
<span style='display:block; white-space:pre;background:#e0ffe0;'>+                macports::chown $destdir $macportsuser
</span>                 # Do rsync fetch
                 set rsync_commandline "$rsync_path $rsync_options $include_option $exclude_option $srcstr $destdir"
                 macports_try -pass_signal {
<span style='display:block; white-space:pre;background:#ffe0e0;'>-                    system $rsync_commandline
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+                    macports::run_unprivileged {system $rsync_commandline}
</span>                 } on error {} {
                     ui_error "Synchronization of the local ports tree failed doing rsync"
                     incr numfailed
<span style='display:block; white-space:pre;background:#e0e0e0;'>@@ -3328,7 +3371,7 @@ proc mportsync {{options {}}} {
</span>                         set include_option "--include=/${filename} --include=/${filename}.rmd160"
                         set rsync_commandline "$rsync_path $rsync_options $include_option $exclude_option $srcstr $destdir"
                         macports_try -pass_signal {
<span style='display:block; white-space:pre;background:#ffe0e0;'>-                            system $rsync_commandline
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+                            macports::run_unprivileged {system $rsync_commandline}
</span>                         } on error {} {
                             ui_error "Synchronization of the local ports tree failed doing rsync"
                             incr numfailed
<span style='display:block; white-space:pre;background:#e0e0e0;'>@@ -3347,7 +3390,7 @@ proc mportsync {{options {}}} {
</span>                     set verified 0
                     foreach pubkey $archivefetch_pubkeys {
                         macports_try -pass_signal {
<span style='display:block; white-space:pre;background:#ffe0e0;'>-                            exec $openssl dgst -ripemd160 -verify $pubkey -signature $signature $tarball
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+                            macports::run_unprivileged {exec $openssl dgst -ripemd160 -verify $pubkey -signature $signature $tarball}
</span>                             set verified 1
                             ui_debug "successful verification with key $pubkey"
                             break
<span style='display:block; white-space:pre;background:#e0e0e0;'>@@ -3372,10 +3415,11 @@ proc mportsync {{options {}}} {
</span>                     }
                     # extract tarball and move into place
                     file mkdir ${extractdir}/tmp
<span style='display:block; white-space:pre;background:#e0ffe0;'>+                    macports::chown ${extractdir}/tmp $macportsuser
</span>                     set zflag [expr {[file extension $tarball] eq ".gz" ? "z" : ""}]
                     set tar_cmd "$tar -C ${extractdir}/tmp -x${zflag}f $tarball"
                     macports_try -pass_signal {
<span style='display:block; white-space:pre;background:#ffe0e0;'>-                        system $tar_cmd
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+                        macports::run_unprivileged {system $tar_cmd}
</span>                     } on error {eMessage} {
                         ui_error "Failed to extract ports tree from tarball: $eMessage"
                         incr numfailed
<span style='display:block; white-space:pre;background:#e0e0e0;'>@@ -3383,9 +3427,11 @@ proc mportsync {{options {}}} {
</span>                     }
                     # save the local PortIndex data
                     if {[file isfile $indexfile]} {
<span style='display:block; white-space:pre;background:#e0ffe0;'>+                        macports::chown $indexfile $macportsuser
</span>                         file copy -force $indexfile ${destdir}/
                         file rename -force $indexfile ${extractdir}/tmp/ports/
                         if {[file isfile ${indexfile}.quick]} {
<span style='display:block; white-space:pre;background:#e0ffe0;'>+                            macports::chown ${indexfile}.quick $macportsuser
</span>                             file rename -force ${indexfile}.quick ${extractdir}/tmp/ports/
                         }
                     }
<span style='display:block; white-space:pre;background:#e0e0e0;'>@@ -3413,7 +3459,7 @@ proc mportsync {{options {}}} {
</span>                     set remote_indexdir "${index_source}PortIndex_${os_platform}_${os_major}_${os_arch}/"
                     set rsync_commandline "$rsync_path $rsync_options $include_option $remote_indexdir $destdir"
                     macports_try -pass_signal {
<span style='display:block; white-space:pre;background:#ffe0e0;'>-                        system $rsync_commandline
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+                        macports::run_unprivileged {system $rsync_commandline}
</span>                         
                         set ok 1
                         set needs_portindex false
<span style='display:block; white-space:pre;background:#e0e0e0;'>@@ -3423,7 +3469,10 @@ proc mportsync {{options {}}} {
</span>                             # verify signature for PortIndex
                             foreach pubkey $archivefetch_pubkeys {
                                 macports_try -pass_signal {
<span style='display:block; white-space:pre;background:#ffe0e0;'>-                                    exec $openssl dgst -ripemd160 -verify $pubkey -signature ${destdir}/PortIndex.rmd160 ${destdir}/PortIndex
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+                                    macports::run_unprivileged {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+                                        exec $openssl dgst -ripemd160 -verify $pubkey \
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+                                            -signature ${destdir}/PortIndex.rmd160 ${destdir}/PortIndex
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+                                    }
</span>                                     set ok 1
                                     set needs_portindex false
                                     ui_debug "successful verification with key $pubkey"
<span style='display:block; white-space:pre;background:#e0e0e0;'>@@ -3479,6 +3528,7 @@ proc mportsync {{options {}}} {
</span>                 }
 
                 file mkdir $destdir
<span style='display:block; white-space:pre;background:#e0ffe0;'>+                macports::chown $destdir $macportsuser
</span> 
                 global macports::portverbose macports::ui_options
                 set progressflag {}
<span style='display:block; white-space:pre;background:#e0e0e0;'>@@ -3513,7 +3563,11 @@ proc mportsync {{options {}}} {
</span>                 set striparg "--strip-components=1"
 
                 set tar [macports::findBinary tar $tar_path]
<span style='display:block; white-space:pre;background:#ffe0e0;'>-                if {[catch {system -W ${destdir} "$tar $verboseflag $striparg $extflag -xf [macports::shellescape $tarpath]"} error]} {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+                if {[catch {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+                        macports::run_unprivileged {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+                            system -W ${destdir} "$tar $verboseflag $striparg $extflag -xf [macports::shellescape $tarpath]"
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+                        }
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+                } error]} {
</span>                     ui_error "Extracting $source failed ($error)"
                     incr numfailed
                     continue
<span style='display:block; white-space:pre;background:#e0e0e0;'>@@ -3549,7 +3603,13 @@ proc mportsync {{options {}}} {
</span>             if {![dict exists $options no_reindex]} {
                 global macports::prefix
                 set indexdir [file dirname [macports::getindex $source]]
<span style='display:block; white-space:pre;background:#ffe0e0;'>-                if {[catch {system "${prefix}/bin/portindex [macports::shellescape $indexdir]"}]} {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+                set owner [file attributes $indexdir -owner]
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+                set group [file attributes $indexdir -group]
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+                if {[catch {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+                        macports::run_unprivileged {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+                            system "${prefix}/bin/portindex [macports::shellescape $indexdir]"
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+                        } [list $owner $group]
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+                }]} {
</span>                     ui_error "updating PortIndex for $source failed"
                 }
             }
</pre><pre style='margin:0'>

</pre>