diff --git a/src/shared/loop-util.c b/src/shared/loop-util.c index b64953c65d..8c92429648 100644 --- a/src/shared/loop-util.c +++ b/src/shared/loop-util.c @@ -431,10 +431,25 @@ static int loop_device_make_internal( int r, f_flags; struct stat st; + assert(fd >= 0); + assert(open_flags < 0 || IN_SET(open_flags, O_RDWR, O_RDONLY)); assert(ret); - assert(IN_SET(open_flags, O_RDWR, O_RDONLY)); - if (fstat(ASSERT_FD(fd), &st) < 0) + f_flags = fcntl(fd, F_GETFL); + if (f_flags < 0) + return -errno; + + if (open_flags < 0) { + /* If open_flags is unset, initialize it from the open fd */ + if (FLAGS_SET(f_flags, O_PATH)) + return log_debug_errno(SYNTHETIC_ERRNO(EBADFD), "Access mode of image file indicates O_PATH, cannot determine read/write flags."); + + open_flags = f_flags & O_ACCMODE_STRICT; + if (!IN_SET(open_flags, O_RDWR, O_RDONLY)) + return log_debug_errno(SYNTHETIC_ERRNO(EBADFD), "Access mode of image file is write only (?)"); + } + + if (fstat(fd, &st) < 0) return -errno; if (S_ISBLK(st.st_mode)) { @@ -461,10 +476,6 @@ static int loop_device_make_internal( return r; } - f_flags = fcntl(fd, F_GETFL); - if (f_flags < 0) - return -errno; - if (FLAGS_SET(loop_flags, LO_FLAGS_DIRECT_IO) != FLAGS_SET(f_flags, O_DIRECT)) { /* If LO_FLAGS_DIRECT_IO is requested, then make sure we have the fd open with O_DIRECT, as * that's required. Conversely, if it's off require that O_DIRECT is off too (that's because