summaryrefslogtreecommitdiff
path: root/src/shared/dm-util.c
diff options
context:
space:
mode:
authorLuca Boccassi <luca.boccassi@microsoft.com>2020-07-08 19:57:31 +0100
committerLuca Boccassi <luca.boccassi@microsoft.com>2020-07-21 23:42:03 +0100
commitac1f3ad05f7476ae58981dcba45dfeb2c0006824 (patch)
tree3df9b81faac4c8112c8470925b4289e8c0f49beb /src/shared/dm-util.c
parent536879480a5ec4d4be10941aa837791ddd68edc2 (diff)
downloadsystemd-ac1f3ad05f7476ae58981dcba45dfeb2c0006824.tar.gz
verity: re-use already open devices if the hashes match
Opening a verity device is an expensive operation. The kernelspace operations are mostly sequential with a global lock held regardless of which device is being opened. In userspace jumps in and out of multiple libraries are required. When signatures are used, there's the additional cryptographic checks. We know when two devices are identical: they have the same root hash. If libcrypsetup returns EEXIST, double check that the hashes are really the same, and that either both or none have a signature, and if everything matches simply remount the already open device. The kernel will do reference counting for us. In order to quickly and reliably discover if a device is already open, change the node naming scheme from '/dev/mapper/major:minor-verity' to '/dev/mapper/$roothash-verity'. Unfortunately libdevmapper is not 100% reliable, so in some case it will say that the device already exists and it is active, but in reality it is not usable. Fallback to an individually-activated unique device name in those cases for robustness.
Diffstat (limited to 'src/shared/dm-util.c')
-rw-r--r--src/shared/dm-util.c36
1 files changed, 36 insertions, 0 deletions
diff --git a/src/shared/dm-util.c b/src/shared/dm-util.c
index 9ffa427027..7efcb6b2aa 100644
--- a/src/shared/dm-util.c
+++ b/src/shared/dm-util.c
@@ -5,3 +5,39 @@
#include "dm-util.h"
#include "fd-util.h"
#include "string-util.h"
+
+int dm_deferred_remove_cancel(const char *name) {
+ _cleanup_close_ int fd = -1;
+ struct message {
+ struct dm_ioctl dm_ioctl;
+ struct dm_target_msg dm_target_msg;
+ char msg_text[STRLEN("@cancel_deferred_remove") + 1];
+ } _packed_ message = {
+ .dm_ioctl = {
+ .version = {
+ DM_VERSION_MAJOR,
+ DM_VERSION_MINOR,
+ DM_VERSION_PATCHLEVEL
+ },
+ .data_size = sizeof(struct message),
+ .data_start = sizeof(struct dm_ioctl),
+ },
+ .msg_text = "@cancel_deferred_remove",
+ };
+
+ assert(name);
+
+ if (strlen(name) >= sizeof(message.dm_ioctl.name))
+ return -ENODEV; /* A device with a name longer than this cannot possibly exist */
+
+ strncpy_exact(message.dm_ioctl.name, name, sizeof(message.dm_ioctl.name));
+
+ fd = open("/dev/mapper/control", O_RDWR|O_CLOEXEC);
+ if (fd < 0)
+ return -errno;
+
+ if (ioctl(fd, DM_TARGET_MSG, &message))
+ return -errno;
+
+ return 0;
+}