From: Yu Watanabe Date: Mon, 19 Sep 2022 23:43:45 +0000 (+0900) Subject: blockdev-util: reopen file descriptor only when O_PATH is set X-Git-Tag: v252-rc1~49^2~4 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=446f8db66bf5e0fbf71bd42423d865c207082388;p=thirdparty%2Fsystemd.git blockdev-util: reopen file descriptor only when O_PATH is set Prompted by 13879c54d4f8b912e1f8c57e0ff7b516dd2a6f52. --- diff --git a/src/shared/blockdev-util.c b/src/shared/blockdev-util.c index b90a5223ccf..d9921681702 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)