2
0
mirror of https://github.com/xcat2/xcat-dep.git synced 2026-10-17 09:10:30 +00:00

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>
This commit is contained in:
Daniel Hilst
2026-10-14 05:40:14 -03:00
parent 1d742828e9
commit e6f2e8a794
2 changed files with 31 additions and 7 deletions
+27 -4
View File
@@ -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;
+4 -3
View File
@@ -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