From 9321ad5118d41476c15fbd316706fd0b5070bed2 Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Sun, 11 Sep 2022 23:07:29 +0900 Subject: [PATCH 1/4] dissect-image: introduce reference counter for DecryptedImage --- src/shared/dissect-image.c | 41 ++++++++++++++++++++++++++++---------- src/shared/dissect-image.h | 1 + 2 files changed, 32 insertions(+), 10 deletions(-) diff --git a/src/shared/dissect-image.c b/src/shared/dissect-image.c index 5e4883a7a7..5e1af80997 100644 --- a/src/shared/dissect-image.c +++ b/src/shared/dissect-image.c @@ -1544,19 +1544,22 @@ int dissected_image_mount_and_warn( } #if HAVE_LIBCRYPTSETUP -typedef struct DecryptedPartition { +struct DecryptedPartition { struct crypt_device *device; char *name; bool relinquished; -} DecryptedPartition; - -struct DecryptedImage { - DecryptedPartition *decrypted; - size_t n_decrypted; }; #endif -DecryptedImage* decrypted_image_unref(DecryptedImage* d) { +typedef struct DecryptedPartition DecryptedPartition; + +struct DecryptedImage { + unsigned n_ref; + DecryptedPartition *decrypted; + size_t n_decrypted; +}; + +static DecryptedImage* decrypted_image_free(DecryptedImage *d) { #if HAVE_LIBCRYPTSETUP int r; @@ -1584,7 +1587,25 @@ DecryptedImage* decrypted_image_unref(DecryptedImage* d) { return NULL; } +DEFINE_TRIVIAL_REF_UNREF_FUNC(DecryptedImage, decrypted_image, decrypted_image_free); + #if HAVE_LIBCRYPTSETUP +static int decrypted_image_new(DecryptedImage **ret) { + _cleanup_(decrypted_image_unrefp) DecryptedImage *d = NULL; + + assert(ret); + + d = new(DecryptedImage, 1); + if (!d) + return -ENOMEM; + + *d = (DecryptedImage) { + .n_ref = 1, + }; + + *ret = TAKE_PTR(d); + return 0; +} static int make_dm_name_and_node(const void *original_node, const char *suffix, char **ret_name, char **ret_node) { _cleanup_free_ char *name = NULL, *node = NULL; @@ -2080,9 +2101,9 @@ int dissected_image_decrypt( } #if HAVE_LIBCRYPTSETUP - d = new0(DecryptedImage, 1); - if (!d) - return -ENOMEM; + r = decrypted_image_new(&d); + if (r < 0) + return r; for (PartitionDesignator i = 0; i < _PARTITION_DESIGNATOR_MAX; i++) { DissectedPartition *p = m->partitions + i; diff --git a/src/shared/dissect-image.h b/src/shared/dissect-image.h index fe478bde49..6dd5246042 100644 --- a/src/shared/dissect-image.h +++ b/src/shared/dissect-image.h @@ -277,6 +277,7 @@ int dissected_image_mount_and_warn(DissectedImage *m, const char *where, uid_t u int dissected_image_acquire_metadata(DissectedImage *m, DissectImageFlags extra_flags); +DecryptedImage* decrypted_image_ref(DecryptedImage *p); DecryptedImage* decrypted_image_unref(DecryptedImage *p); DEFINE_TRIVIAL_CLEANUP_FUNC(DecryptedImage*, decrypted_image_unref); int decrypted_image_relinquish(DecryptedImage *d); From ac1e1b5fd7effb0925b3131290c3b5fab282bdaa Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Sun, 11 Sep 2022 23:08:25 +0900 Subject: [PATCH 2/4] dissect-image: take reference of DecryptedImage into DissectedImage No functional changes. Preparation for later commits. --- src/shared/dissect-image.c | 12 ++++++++++-- src/shared/dissect-image.h | 1 + 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/src/shared/dissect-image.c b/src/shared/dissect-image.c index 5e1af80997..e97c22d796 100644 --- a/src/shared/dissect-image.c +++ b/src/shared/dissect-image.c @@ -1112,9 +1112,14 @@ DissectedImage* dissected_image_unref(DissectedImage *m) { if (!m) return NULL; + /* First, clear dissected partitions. */ for (PartitionDesignator i = 0; i < _PARTITION_DESIGNATOR_MAX; i++) dissected_partition_done(m->partitions + i); + /* Second, free decrypted images. This must be after dissected_partition_done(), as freeing + * DecryptedImage may try to deactivate partitions. */ + decrypted_image_unref(m->decrypted_image); + free(m->image_name); free(m->hostname); strv_free(m->machine_info); @@ -2096,7 +2101,8 @@ int dissected_image_decrypt( return -EINVAL; if (!m->encrypted && !m->verity_ready) { - *ret = NULL; + if (ret) + *ret = NULL; return 0; } @@ -2130,7 +2136,9 @@ int dissected_image_decrypt( } } - *ret = TAKE_PTR(d); + m->decrypted_image = TAKE_PTR(d); + if (ret) + *ret = decrypted_image_ref(m->decrypted_image); return 1; #else diff --git a/src/shared/dissect-image.h b/src/shared/dissect-image.h index 6dd5246042..7308798493 100644 --- a/src/shared/dissect-image.h +++ b/src/shared/dissect-image.h @@ -211,6 +211,7 @@ struct DissectedImage { bool single_file_system:1; /* MBR/GPT or single file system */ DissectedPartition partitions[_PARTITION_DESIGNATOR_MAX]; + DecryptedImage *decrypted_image; /* Meta information extracted from /etc/os-release and similar */ char *image_name; From 36d5eb0bffc3cc7b8e4be1e41ee3cbd4ddd8c870 Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Sun, 11 Sep 2022 22:41:03 +0900 Subject: [PATCH 3/4] loop-util: introduce reference counter for LoopDevice --- src/shared/loop-util.c | 6 +++++- src/shared/loop-util.h | 2 ++ 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/src/shared/loop-util.c b/src/shared/loop-util.c index 49f4b2bf6e..54251f0fb7 100644 --- a/src/shared/loop-util.c +++ b/src/shared/loop-util.c @@ -369,6 +369,7 @@ static int loop_configure( return -ENOMEM; *d = (LoopDevice) { + .n_ref = 1, .fd = TAKE_FD(loop_with_fd), .lock_fd = TAKE_FD(lock_fd), .node = TAKE_PTR(node), @@ -624,7 +625,7 @@ int loop_device_make_by_path( return loop_device_make_internal(path, fd, open_flags, 0, 0, loop_flags, lock_op, ret); } -LoopDevice* loop_device_unref(LoopDevice *d) { +static LoopDevice* loop_device_free(LoopDevice *d) { _cleanup_close_ int control = -1; int r; @@ -696,6 +697,8 @@ LoopDevice* loop_device_unref(LoopDevice *d) { return mfree(d); } +DEFINE_TRIVIAL_REF_UNREF_FUNC(LoopDevice, loop_device, loop_device_free); + void loop_device_relinquish(LoopDevice *d) { assert(d); @@ -796,6 +799,7 @@ int loop_device_open_full( return -ENOMEM; *d = (LoopDevice) { + .n_ref = 1, .fd = TAKE_FD(fd), .lock_fd = TAKE_FD(lock_fd), .nr = nr, diff --git a/src/shared/loop-util.h b/src/shared/loop-util.h index cb0183ba07..756041adaa 100644 --- a/src/shared/loop-util.h +++ b/src/shared/loop-util.h @@ -11,6 +11,7 @@ typedef struct LoopDevice LoopDevice; /* Some helpers for setting up loopback block devices */ struct LoopDevice { + unsigned n_ref; int fd; int lock_fd; int nr; /* The loopback device index (i.e. 4 for /dev/loop4); if this object encapsulates a non-loopback block device, set to -1 */ @@ -34,6 +35,7 @@ static inline int loop_device_open(const char *loop_path, int open_flags, int lo return loop_device_open_full(loop_path, -1, open_flags, lock_op, ret); } +LoopDevice* loop_device_ref(LoopDevice *d); LoopDevice* loop_device_unref(LoopDevice *d); DEFINE_TRIVIAL_CLEANUP_FUNC(LoopDevice*, loop_device_unref); From 1e63dc4f1cbec8a2d2bc053b49db23fe9d47a524 Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Sun, 11 Sep 2022 22:46:39 +0900 Subject: [PATCH 4/4] dissect-image: take a reference of LoopDevice into DissectedImage To make LoopDevice object freed after DissectedImage is freed. At least currently, this should not change anything. Preparation for later commits. --- src/shared/dissect-image.c | 29 ++++++++++++++++++++++++++++- src/shared/dissect-image.h | 8 +++----- 2 files changed, 31 insertions(+), 6 deletions(-) diff --git a/src/shared/dissect-image.c b/src/shared/dissect-image.c index e97c22d796..ab8813447a 100644 --- a/src/shared/dissect-image.c +++ b/src/shared/dissect-image.c @@ -1120,6 +1120,10 @@ DissectedImage* dissected_image_unref(DissectedImage *m) { * DecryptedImage may try to deactivate partitions. */ decrypted_image_unref(m->decrypted_image); + /* Third, unref LoopDevice. This must be called after the above two, as freeing LoopDevice may try to + * remove existing partitions on the loopback block device. */ + loop_device_unref(m->loop); + free(m->image_name); free(m->hostname); strv_free(m->machine_info); @@ -2794,8 +2798,31 @@ finish: return r; } +int dissect_loop_device( + LoopDevice *loop, + const VeritySettings *verity, + const MountOptions *mount_options, + DissectImageFlags flags, + DissectedImage **ret) { + + _cleanup_(dissected_image_unrefp) DissectedImage *m = NULL; + int r; + + assert(loop); + assert(ret); + + r = dissect_image(loop->fd, loop->node, loop->backing_file ?: loop->node, verity, mount_options, flags, &m); + if (r < 0) + return r; + + m->loop = loop_device_ref(loop); + + *ret = TAKE_PTR(m); + return 0; +} + int dissect_loop_device_and_warn( - const LoopDevice *loop, + LoopDevice *loop, const VeritySettings *verity, const MountOptions *mount_options, DissectImageFlags flags, diff --git a/src/shared/dissect-image.h b/src/shared/dissect-image.h index 7308798493..efddea80c7 100644 --- a/src/shared/dissect-image.h +++ b/src/shared/dissect-image.h @@ -210,6 +210,7 @@ struct DissectedImage { bool verity_sig_ready:1; /* verity signature logic, fully specified and usable */ bool single_file_system:1; /* MBR/GPT or single file system */ + LoopDevice *loop; DissectedPartition partitions[_PARTITION_DESIGNATOR_MAX]; DecryptedImage *decrypted_image; @@ -262,11 +263,8 @@ int dissect_image( const MountOptions *mount_options, DissectImageFlags flags, DissectedImage **ret); -static inline int dissect_loop_device(const LoopDevice *loop, const VeritySettings *verity, const MountOptions *mount_options, DissectImageFlags flags, DissectedImage **ret) { - assert(loop); - return dissect_image(loop->fd, loop->node, loop->backing_file ?: loop->node, verity, mount_options, flags, ret); -} -int dissect_loop_device_and_warn(const LoopDevice *loop, const VeritySettings *verity, const MountOptions *mount_options, DissectImageFlags flags, DissectedImage **ret); +int dissect_loop_device(LoopDevice *loop, const VeritySettings *verity, const MountOptions *mount_options, DissectImageFlags flags, DissectedImage **ret); +int dissect_loop_device_and_warn(LoopDevice *loop, const VeritySettings *verity, const MountOptions *mount_options, DissectImageFlags flags, DissectedImage **ret); DissectedImage* dissected_image_unref(DissectedImage *m); DEFINE_TRIVIAL_CLEANUP_FUNC(DissectedImage*, dissected_image_unref);