tar-util: make sure we can unpack hardlinked symlinks (#39619)

This commit is contained in:
Yu Watanabe
2025-11-08 00:08:44 +09:00
committed by GitHub
3 changed files with 15 additions and 5 deletions

View File

@@ -68,7 +68,7 @@ static int log_autofs_mount_point(int fd, const char *path, ChaseFlags flags) {
(void) fd_get_path(fd, &n1);
return log_warning_errno(SYNTHETIC_ERRNO(EREMOTE),
"Detected autofs mount point %s during canonicalization of %s.",
"Detected autofs mount point '%s' during canonicalization of '%s'.",
strna(n1), path);
}
@@ -83,7 +83,7 @@ static int log_prohibited_symlink(int fd, ChaseFlags flags) {
(void) fd_get_path(fd, &n1);
return log_warning_errno(SYNTHETIC_ERRNO(EREMCHG),
"Detected symlink where not symlink is allowed at %s, refusing.",
"Detected symlink where no symlink is allowed at '%s', refusing.",
strna(n1));
}

View File

@@ -827,7 +827,7 @@ int tar_x(int input_fd, int tree_fd, TarFlags flags) {
"Invalid hardlink path name '%s' in entry, refusing.", target);
_cleanup_close_ int target_fd = -EBADF;
r = chaseat(tree_fd, target, CHASE_PROHIBIT_SYMLINKS|CHASE_AT_RESOLVE_IN_ROOT, /* ret_path= */ NULL, &target_fd);
r = chaseat(tree_fd, target, CHASE_PROHIBIT_SYMLINKS|CHASE_AT_RESOLVE_IN_ROOT|CHASE_NOFOLLOW, /* ret_path= */ NULL, &target_fd);
if (r < 0)
return log_error_errno(
r,
@@ -856,7 +856,7 @@ int tar_x(int input_fd, int tree_fd, TarFlags flags) {
_cleanup_close_ int target_parent_fd = -EBADF;
_cleanup_free_ char *target_filename = NULL;
r = chaseat(tree_fd, target, CHASE_PROHIBIT_SYMLINKS|CHASE_AT_RESOLVE_IN_ROOT|CHASE_PARENT|CHASE_EXTRACT_FILENAME, &target_filename, &target_parent_fd);
r = chaseat(tree_fd, target, CHASE_PROHIBIT_SYMLINKS|CHASE_AT_RESOLVE_IN_ROOT|CHASE_PARENT|CHASE_EXTRACT_FILENAME|CHASE_NOFOLLOW, &target_filename, &target_parent_fd);
if (r < 0)
return log_error_errno(
r,

View File

@@ -175,9 +175,15 @@ chattr +A /home/testuser/.local/state/machines/inodetest/testfile
chown foreign-0:foreign-0 /home/testuser/.local/state/machines/inodetest/testfile.hard /home/testuser/.local/state/machines/inodetest
ls -al /home/testuser/.local/state/machines/inodetest
# Verify UID squashing
echo gaga > /home/testuser/.local/state/machines/inodetest/squashtest
chown 1000:1000 /home/testuser/.local/state/machines/inodetest/squashtest
# Ensure hardlinked symlinks work
ln -s sometarget /home/testuser/.local/state/machines/inodetest/testfile.sym
ln /home/testuser/.local/state/machines/inodetest/testfile.sym /home/testuser/.local/state/machines/inodetest/testfile.symhard
chown -h foreign-0:foreign-0 /home/testuser/.local/state/machines/inodetest/testfile.symhard
run0 --pipe -u testuser importctl -m --user export-tar inodetest |
run0 --pipe -u testuser importctl -m --user import-tar - inodetest2
@@ -199,7 +205,11 @@ cmp <(lsattr /home/testuser/.local/state/machines/inodetest/testfile | cut -d "
# verify that squashing outside of 64K works
test "$(stat -c'%U:%G' /home/testuser/.local/state/machines/inodetest2/squashtest)" = "foreign-65534:foreign-65534"
# chown to foreing UID range, so that removal works
# Verify that the hardlinked symlink is restored as such
cmp <(stat -c"%i" /home/testuser/.local/state/machines/inodetest2/testfile.sym) <(stat -c"%i" /home/testuser/.local/state/machines/inodetest2/testfile.symhard)
test "$(readlink /home/testuser/.local/state/machines/inodetest2/testfile.symhard)" = "sometarget"
# chown to foreign UID range, so that removal works
chown foreign-4711:foreign-4711 /home/testuser/.local/state/machines/inodetest/squashtest
run0 -u testuser machinectl --user remove inodetest