From 25d7cdc9f5eaf4ebd44d7e71dd7d1f1c4d603f78 Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Wed, 26 Aug 2026 05:48:22 +0900 Subject: [PATCH 1/5] tar-util: clear xattrs and acls in open_inode_done() Otherwise, if it is called multiple times for an object, then the xattrs and acls may be freed multiple times. --- src/shared/tar-util.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/shared/tar-util.c b/src/shared/tar-util.c index c60054b2d1..6e3c065141 100644 --- a/src/shared/tar-util.c +++ b/src/shared/tar-util.c @@ -79,12 +79,14 @@ static void open_inode_done(OpenInode *of) { of->fd = safe_close(of->fd); of->path = mfree(of->path); } + xattr_free_array(of->xattr, of->n_xattr); + of->xattr = NULL; + of->n_xattr = 0; + #if HAVE_ACL - if (of->acl_access) - sym_acl_free(of->acl_access); - if (of->acl_default) - sym_acl_free(of->acl_default); + acl_freep(&of->acl_access); + acl_freep(&of->acl_default); #endif } From 32798431ddf616892026ca8bffdac055c1667673 Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Wed, 26 Aug 2026 08:08:22 +0900 Subject: [PATCH 2/5] tar-util: do not call open_inode_done() twice on failure Previously, if open_inode_finalize() for an object was failed, the number count was not decremented, hence open_inode_done() is called twice for the object: once in the failed open_inode_finalize(), and once in the open_inode_free_array() invoked by the cleanup attribute. Note, with the previous commit, open_inode_done() is idempotent. Hence, calling open_inode_done() twice (or more) for the same object is harmless. Just for safety. --- src/shared/tar-util.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/shared/tar-util.c b/src/shared/tar-util.c index 6e3c065141..53833da105 100644 --- a/src/shared/tar-util.c +++ b/src/shared/tar-util.c @@ -847,11 +847,10 @@ int tar_x(int input_fd, int tree_fd, TarFlags flags) { /* Finalize all inodes we won't need anymore now (go backwards, i.e. close inner fds first) */ while (n_open_inodes > i) { - r = open_inode_finalize(open_inodes + n_open_inodes - 1); + n_open_inodes--; + r = open_inode_finalize(open_inodes + n_open_inodes); if (r < 0) return r; - - n_open_inodes--; } /* And now create all remaining components */ From 06318e7b98129050e14aef2370ac62da31176f6e Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Wed, 26 Aug 2026 06:22:13 +0900 Subject: [PATCH 3/5] tar-util: add missing dlopen libarchive Otherwise, if the library is not loaded yet, these functions will fail. Note, currently, all callers of tar_x/tar_c() load libarchive before calling them. So, this should not change any behavior. Just for safety and following our usual coding style. --- src/shared/tar-util.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/shared/tar-util.c b/src/shared/tar-util.c index 53833da105..f3b63fe98f 100644 --- a/src/shared/tar-util.c +++ b/src/shared/tar-util.c @@ -749,6 +749,10 @@ int tar_x(int input_fd, int tree_fd, TarFlags flags) { assert(input_fd >= 0); assert(tree_fd >= 0); + r = dlopen_libarchive(LOG_DEBUG); + if (r < 0) + return r; + _cleanup_(archive_read_freep) struct archive *a = NULL; a = sym_archive_read_new(); if (!a) @@ -1605,6 +1609,10 @@ int tar_c(int tree_fd, int output_fd, const char *filename, int hardlink_db_fd, assert(tree_fd >= 0); assert(output_fd >= 0); + r = dlopen_libarchive(LOG_DEBUG); + if (r < 0) + return r; + _cleanup_(archive_write_freep) struct archive *a = sym_archive_write_new(); if (!a) return log_oom(); From 1e615d7e4e6243c228694d49446f50ead2879b96 Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Wed, 26 Aug 2026 06:26:34 +0900 Subject: [PATCH 4/5] import: missing dlopen_libacl() before fork tar_x() and tar_c() may use libacl. Hence, libacl should be loaded before fork. --- src/import/import-common.c | 3 +++ src/import/meson.build | 1 + 2 files changed, 4 insertions(+) diff --git a/src/import/import-common.c b/src/import/import-common.c index 0b63828869..eb828d6b14 100644 --- a/src/import/import-common.c +++ b/src/import/import-common.c @@ -5,6 +5,7 @@ #include "sd-event.h" +#include "acl-util.h" #include "capability-util.h" #include "compress.h" #include "dirent-util.h" @@ -31,6 +32,7 @@ int import_fork_tar_x(int tree_fd, int userns_fd, PidRef *ret_pid) { assert(tree_fd >= 0); assert(ret_pid); + (void) dlopen_libacl(LOG_DEBUG); r = dlopen_libarchive(LOG_DEBUG); if (r < 0) return r; @@ -99,6 +101,7 @@ int import_fork_tar_c(int tree_fd, int userns_fd, PidRef *ret_pid) { assert(tree_fd >= 0); assert(ret_pid); + (void) dlopen_libacl(LOG_DEBUG); r = dlopen_libarchive(LOG_DEBUG); if (r < 0) return r; diff --git a/src/import/meson.build b/src/import/meson.build index 1bfdba1e55..a1ac50594f 100644 --- a/src/import/meson.build +++ b/src/import/meson.build @@ -17,6 +17,7 @@ executables += [ 'qcow2-util.c', ), 'dependencies' : [ + libacl_cflags, libarchive_cflags, libselinux_cflags, ], From 10adafa35809b842b423d29aa1d7e2e88a8381d3 Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Wed, 26 Aug 2026 06:32:43 +0900 Subject: [PATCH 5/5] test-tar: log failure in loading libarchive on LOG_ERR Other failures are logged on LOG_ERR. --- src/import/test-tar.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/import/test-tar.c b/src/import/test-tar.c index 6fca4b89cb..c73062e9ed 100644 --- a/src/import/test-tar.c +++ b/src/import/test-tar.c @@ -26,7 +26,7 @@ static int run(int argc, char **argv) { else return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Unknown operation '%s'.", argv[1]); - r = dlopen_libarchive(LOG_DEBUG); + r = dlopen_libarchive(LOG_ERR); if (r < 0) return r;