From 446f8db66bf5e0fbf71bd42423d865c207082388 Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Tue, 20 Sep 2022 08:43:45 +0900 Subject: [PATCH] blockdev-util: reopen file descriptor only when O_PATH is set Prompted by 13879c54d4f8b912e1f8c57e0ff7b516dd2a6f52. --- src/shared/blockdev-util.c | 22 ++++++++++++++++------ 1 file changed, 16 insertions(+), 6 deletions(-) diff --git a/src/shared/blockdev-util.c b/src/shared/blockdev-util.c index b90a5223cc..d992168170 100644 --- a/src/shared/blockdev-util.c +++ b/src/shared/blockdev-util.c @@ -40,16 +40,26 @@ static int fd_get_devnum(int fd, bool backing, dev_t *ret) { else if (major(st.st_dev) != 0) devnum = st.st_dev; else { - _cleanup_close_ int regfd = -1; - /* If major(st.st_dev) is zero, this might mean we are backed by btrfs, which needs special * handing, to get the backing device node. */ - regfd = fd_reopen(fd, O_RDONLY|O_CLOEXEC|O_NONBLOCK|O_NOCTTY); - if (regfd < 0) - return regfd; + r = fcntl(fd, F_GETFL); + if (r < 0) + return -errno; + + if (FLAGS_SET(r, O_PATH)) { + _cleanup_close_ int regfd = -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. */ + + regfd = fd_reopen(fd, O_RDONLY|O_CLOEXEC|O_NONBLOCK|O_NOCTTY); + if (regfd < 0) + return regfd; - r = btrfs_get_block_device_fd(regfd, &devnum); + r = btrfs_get_block_device_fd(regfd, &devnum); + } else + r = btrfs_get_block_device_fd(fd, &devnum); if (r == -ENOTTY) /* not btrfs */ return -ENOTBLK; if (r < 0) -- 2.25.1