]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
loop-util: track CLOCK_MONOTONIC timestamp immediately before attaching a loopback...
authorLennart Poettering <lennart@poettering.net>
Tue, 20 Apr 2021 14:08:43 +0000 (16:08 +0200)
committerLennart Poettering <lennart@poettering.net>
Tue, 20 Apr 2021 15:20:38 +0000 (17:20 +0200)
This is similar to the preceding work to store the uevent seqnum, but
this stores the CLOCK_MONOTONIC timestamp.

Why? This allows to validate udev database entries, to determine if they
were created *after* we attached the device.

The uevent seqnum logic allows us to validate uevent, and the timestamp
database entries, hence together we should be able to validate both
sources of truth for us.

(note that this is all racy, just a bit less racy, since we cannot
atomically attach loopback devices and get the timestamp for it, the
same way we can't get the uevent seqnum. Thus is shortens the race
window, but doesn#t close it).

src/shared/loop-util.c
src/shared/loop-util.h

index 3615995de097065538d8197f23ad018cd4021a06..c038e7aae6c60aae05586765fa8002e6e69908c7 100644 (file)
@@ -132,12 +132,14 @@ static int loop_configure(
                 int nr,
                 const struct loop_config *c,
                 bool *try_loop_configure,
-                uint64_t *ret_seqnum_not_before) {
+                uint64_t *ret_seqnum_not_before,
+                usec_t *ret_timestamp_not_before) {
 
         _cleanup_(sd_device_unrefp) sd_device *d = NULL;
         _cleanup_free_ char *sysname = NULL;
         _cleanup_close_ int lock_fd = -1;
         uint64_t seqnum;
+        usec_t timestamp;
         int r;
 
         assert(fd >= 0);
@@ -195,6 +197,7 @@ static int loop_configure(
                 r = get_current_uevent_seqnum(&seqnum);
                 if (r < 0)
                         return r;
+                timestamp = now(CLOCK_MONOTONIC);
 
                 if (ioctl(fd, LOOP_CONFIGURE, c) < 0) {
                         /* Do fallback only if LOOP_CONFIGURE is not supported, propagate all other
@@ -255,6 +258,8 @@ static int loop_configure(
 
                         if (ret_seqnum_not_before)
                                 *ret_seqnum_not_before = seqnum;
+                        if (ret_timestamp_not_before)
+                                *ret_timestamp_not_before = timestamp;
 
                         return 0;
                 }
@@ -264,6 +269,7 @@ static int loop_configure(
         r = get_current_uevent_seqnum(&seqnum);
         if (r < 0)
                 return r;
+        timestamp = now(CLOCK_MONOTONIC);
 
         /* Since kernel commit 5db470e229e22b7eda6e23b5566e532c96fb5bc3 (kernel v5.0) the LOOP_SET_STATUS64
          * ioctl can return EAGAIN in case we change the lo_offset field, if someone else is accessing the
@@ -294,6 +300,8 @@ static int loop_configure(
 
         if (ret_seqnum_not_before)
                 *ret_seqnum_not_before = seqnum;
+        if (ret_timestamp_not_before)
+                *ret_timestamp_not_before = timestamp;
 
         return 0;
 
@@ -353,6 +361,7 @@ int loop_device_make(
         struct loop_config config;
         LoopDevice *d = NULL;
         uint64_t seqnum = UINT64_MAX;
+        usec_t timestamp = USEC_INFINITY;
         struct stat st;
         int nr = -1, r;
 
@@ -396,6 +405,7 @@ int loop_device_make(
                                 .relinquished = true, /* It's not allocated by us, don't destroy it when this object is freed */
                                 .devno = st.st_rdev,
                                 .uevent_seqnum_not_before = UINT64_MAX,
+                                .timestamp_not_before = USEC_INFINITY,
                         };
 
                         *ret = d;
@@ -443,7 +453,7 @@ int loop_device_make(
                         if (!IN_SET(errno, ENOENT, ENXIO))
                                 return -errno;
                 } else {
-                        r = loop_configure(loop, nr, &config, &try_loop_configure, &seqnum);
+                        r = loop_configure(loop, nr, &config, &try_loop_configure, &seqnum, &timestamp);
                         if (r >= 0) {
                                 loop_with_fd = TAKE_FD(loop);
                                 break;
@@ -481,6 +491,7 @@ int loop_device_make(
                 .nr = nr,
                 .devno = st.st_rdev,
                 .uevent_seqnum_not_before = seqnum,
+                .timestamp_not_before = timestamp,
         };
 
         *ret = d;
@@ -617,6 +628,7 @@ int loop_device_open(const char *loop_path, int open_flags, LoopDevice **ret) {
                 .relinquished = true, /* It's not ours, don't try to destroy it when this object is freed */
                 .devno = st.st_dev,
                 .uevent_seqnum_not_before = UINT64_MAX,
+                .timestamp_not_before = USEC_INFINITY,
         };
 
         *ret = d;
index 6df4f91c2270d85e82a92bc7f6dd558a4af03b6b..e06dfebb7c6656ca39b12deb6298c9cab358f70e 100644 (file)
@@ -2,6 +2,7 @@
 #pragma once
 
 #include "macro.h"
+#include "time-util.h"
 
 typedef struct LoopDevice LoopDevice;
 
@@ -14,6 +15,7 @@ struct LoopDevice {
         char *node;
         bool relinquished;
         uint64_t uevent_seqnum_not_before; /* uevent sequm right before we attached the loopback device, or UINT64_MAX if we don't know */
+        usec_t timestamp_not_before; /* CLOCK_MONOTONIC timestamp taken immediately before attaching the loopback device, or USEC_INFINITY if we don't know */
 };
 
 int loop_device_make(int fd, int open_flags, uint64_t offset, uint64_t size, uint32_t loop_flags, LoopDevice **ret);