From: Lennart Poettering Date: Mon, 19 Sep 2022 12:23:02 +0000 (+0200) Subject: blockdev-util: make sure get_block_device_fd() works reliably for O_PATH, too X-Git-Tag: v252-rc1~132^2~5 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=13879c54d4f8b912e1f8c57e0ff7b516dd2a6f52;p=thirdparty%2Fsystemd.git blockdev-util: make sure get_block_device_fd() works reliably for O_PATH, too --- diff --git a/src/shared/blockdev-util.c b/src/shared/blockdev-util.c index 12d4b549526..4402b7a97c0 100644 --- a/src/shared/blockdev-util.c +++ b/src/shared/blockdev-util.c @@ -131,7 +131,21 @@ int get_block_device_fd(int fd, dev_t *ret) { return 1; } - r = btrfs_get_block_device_fd(fd, ret); + r = fcntl(fd, F_GETFL); + if (r < 0) + return -errno; + if (FLAGS_SET(r, O_PATH) && (S_ISREG(st.st_mode) || S_ISDIR(st.st_mode))) { + _cleanup_close_ int real_fd = -1; + + /* The fstat() above we can execute on an O_PATH fd. But the btrfs ioctl we cannot. Hence + * acquire a "real" fd first, without the O_PATH flag. */ + + real_fd = fd_reopen(fd, O_RDONLY|O_CLOEXEC); + if (real_fd < 0) + return real_fd; + r = btrfs_get_block_device_fd(real_fd, ret); + } else + r = btrfs_get_block_device_fd(fd, ret); if (r > 0) return 1; if (r != -ENOTTY) /* not btrfs */