From 25ef7a7b1a876f491bd361369423d7309358f6c1 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Wed, 11 Oct 2023 15:35:33 +0200 Subject: [PATCH] _create_and_load_v4: propagate ioctl errors back to caller When setting up dm-verity devices with signed root hashes it is very useful to have a recognizable error code when a key is not present in the kernel keyring. Turns out the kernel actually returns ENOKEY in that case, but this gets lost in libdevmapper. This fixes this: in _create_and_load_v4() it copies the error code from the ioctl from the sub-tasks back to the main task field on failure. This is not enough to make libcryptsetup actually propagate the ENOKEY correctly, that also needs a patch to libcryptsetup, but this is part of the puzzle. --- libdm/ioctl/libdm-iface.c | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/libdm/ioctl/libdm-iface.c b/libdm/ioctl/libdm-iface.c index 38b9533a9..ac5fb3add 100644 --- a/libdm/ioctl/libdm-iface.c +++ b/libdm/ioctl/libdm-iface.c @@ -1478,7 +1478,7 @@ static int _create_and_load_v4(struct dm_task *dmt) { struct dm_info info; struct dm_task *task; - int r; + int r, ioctl_errno = 0; uint32_t cookie; /* Use new task struct to create the device */ @@ -1504,8 +1504,10 @@ static int _create_and_load_v4(struct dm_task *dmt) task->cookie_set = dmt->cookie_set; task->add_node = dmt->add_node; - if (!dm_task_run(task)) + if (!dm_task_run(task)) { + ioctl_errno = task->ioctl_errno; goto_bad; + } if (!dm_task_get_info(task, &info) || !info.exists) goto_bad; @@ -1536,6 +1538,8 @@ static int _create_and_load_v4(struct dm_task *dmt) task->ima_measurement = dmt->ima_measurement; r = dm_task_run(task); + if (!r) + ioctl_errno = task->ioctl_errno; task->head = NULL; task->tail = NULL; @@ -1582,12 +1586,18 @@ static int _create_and_load_v4(struct dm_task *dmt) if (!dm_task_run(dmt)) log_error("Failed to revert device creation."); + if (ioctl_errno != 0) + dmt->ioctl_errno = ioctl_errno; + return 0; bad: dm_task_destroy(task); _udev_complete(dmt); + if (ioctl_errno != 0) + dmt->ioctl_errno = ioctl_errno; + return 0; }