From e6f2e8a794b76dfab64e935707febc81d4469e0e Mon Sep 17 00:00:00 2001 From: Daniel Hilst <392820+dhilst@users.noreply.github.com> Date: Wed, 14 Oct 2026 05:40:14 -0300 Subject: [PATCH] fix(xcat-dep): the mock result owner ignores sudo and fresh parents mock_chroot_uid ran mock's loader as root. mock itself loads its configuration as the user that sudo names, so with no chrootuid it builds as SUDO_UID. The helper reported uid 0, and mock_result_dirs gave the result directories to root. As root, the loader now builds the uid manager with mock's own setup_uid_manager() and loads the configuration through run_in_subprocess_without_privileges(), as mock main() does. make_traversable_path gives mode 0755 to the directories that it creates, because make_path applies the umask. mock_result_dirs and mockbuild-perl-packages.pl use it for the work and package directories. Directories that already exist keep their mode. Signed-off-by: Daniel Hilst <392820+dhilst@users.noreply.github.com> --- MockBuildUtils.pm | 31 +++++++++++++++++++++++++++---- mockbuild-perl-packages.pl | 7 ++++--- 2 files changed, 31 insertions(+), 7 deletions(-) diff --git a/MockBuildUtils.pm b/MockBuildUtils.pm index 153a48c..7ac9de2 100644 --- a/MockBuildUtils.pm +++ b/MockBuildUtils.pm @@ -25,6 +25,7 @@ our @EXPORT_OK = qw( cross_copy_genesis finalize_xcat_dep bump_dep_release_suffix createrepo_c_cmd sign_and_index_repo build_mock_uniqueext rpm_in_cell resolve_mock_cfg mock_chroot_uid mock_result_dirs + make_traversable_path native_owner_command NATIVE_BUILD_GID openeuler_build_target openeuler_repo_subdir recover_common_repository @@ -922,14 +923,23 @@ sub resolve_mock_cfg { } # mock's own loader reads the configuration, so include() and the assignments around it resolve as -# they do in a build. With no chrootuid, the loader returns the uid that runs it, as mock does. +# they do in a build. With no chrootuid, the loader returns the caller, as mock does: as root, the +# user that SUDO_UID, USERHELPER_UID or PKEXEC_UID names. my $MOCK_CHROOTUID_LOADER = <<'PYTHON'; +import os import sys try: from mockbuild.config import MOCKCONFDIR, load_config + from mockbuild.uid import setup_uid_manager except ImportError: sys.exit('mock is not installed: cannot import mockbuild.config') -print(load_config(MOCKCONFDIR, sys.argv[1])['chrootuid']) +args = (MOCKCONFDIR, sys.argv[1]) +if os.geteuid() == 0: + # As mock main(): load the configuration as the user that sudo names. + opts = setup_uid_manager().run_in_subprocess_without_privileges(load_config, *args) +else: + opts = load_config(*args) +print(opts['chrootuid']) PYTHON # mock_chroot_uid($cfg): the uid mock builds as with configuration file $cfg. @@ -943,15 +953,28 @@ sub mock_chroot_uid { return $1; } +# make_traversable_path(@dirs): make_path(@dirs), then give mode 0755 to each directory it created, +# because make_path applies the umask. Directories that already exist keep their mode. +# Returns the directories it created. +sub make_traversable_path { + my @made = make_path(@_); + for my $dir (@made) { + chmod 0755, $dir or die "Cannot make $dir traversable: $!\n"; + } + return @made; +} + # mock_result_dirs($dir, $cfg): create the three --resultdir directories one package build gives # mock, below $dir, owned by the uid mock builds as with $cfg. mock 6.8 reloads its uid manager from -# chrootuid, so it opens state.log, build.log and root.log in --resultdir as that uid. +# chrootuid, so it opens state.log, build.log and root.log in --resultdir as that uid. The parents +# that this sub creates get mode 0755, so that uid can reach the result directories. sub mock_result_dirs { my ($dir, $cfg) = @_; my $uid = mock_chroot_uid($cfg); my @dirs = map { "$dir/$_" } qw(srpm restamp-srpm rpm); + make_traversable_path($dir); + make_path(@dirs); for my $result (@dirs) { - make_path($result); chown $uid, -1, $result or die "Cannot give $result to uid $uid: $!\n"; } return @dirs; diff --git a/mockbuild-perl-packages.pl b/mockbuild-perl-packages.pl index 87bfb44..8d16aee 100755 --- a/mockbuild-perl-packages.pl +++ b/mockbuild-perl-packages.pl @@ -10,7 +10,7 @@ use FindBin qw($RealBin); use Getopt::Long qw(GetOptions); use Parallel::ForkManager; use lib $RealBin, "$RealBin/lib"; -use MockBuildUtils qw(mock_result_dirs); +use MockBuildUtils qw(mock_result_dirs make_traversable_path); my $repo_root = abs_path(dirname(__FILE__)); my $work_dir = '/tmp/perl-list6-mockbuild'; @@ -335,7 +335,8 @@ if (@packages && $jobs > scalar(@packages)) { make_path($result_dir); make_path($log_dir); -make_path($work_dir); +# mock reaches its result directories through the work directory. +make_traversable_path($work_dir); print_step("Configuration"); print "repo_root: $repo_root\n"; @@ -513,7 +514,7 @@ sub build_package { my $status_file = "$pkg_log/status.txt"; remove_tree($pkg_run_dir) if -d $pkg_run_dir; - make_path($pkg_run_dir); + make_traversable_path($pkg_run_dir); make_path($pkg_result); make_path($pkg_log); # Clear any status/error left by an earlier run in a reused log dir BEFORE building, so a crash