From 2e7dd6682bc9da79d5249caa93ea1bde37a0f315 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Thu, 14 Jul 2022 11:30:27 +0200 Subject: [PATCH 1/3] growfs: insist we open a directory when opening fs mount point This is a simple safety check, since we shouldn't invoke ioctls on fds without being reasonably sure they are of the right type since ioctls are overloaded, and we might be tricked hence to execute an operation on an fd which means something different than what we expect. --- src/partition/growfs.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/partition/growfs.c b/src/partition/growfs.c index 31dcf0ffdf..d7069b8d08 100644 --- a/src/partition/growfs.c +++ b/src/partition/growfs.c @@ -225,7 +225,7 @@ static int run(int argc, char *argv[]) { if (r < 0) return r; - mountfd = open(arg_target, O_RDONLY|O_CLOEXEC); + mountfd = open(arg_target, O_RDONLY|O_CLOEXEC|O_DIRECTORY); if (mountfd < 0) return log_error_errno(errno, "Failed to open \"%s\": %m", arg_target); From 12810f3abbc5e3d0d9a54495b79538cb18714180 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Thu, 14 Jul 2022 11:31:50 +0200 Subject: [PATCH 2/3] growfs: ensure that we operate on a block device before issuing a block ioctl Similar to the previous commit: let's add extra safety so that we don't issue ioctls on the wrong type of inode. --- src/partition/growfs.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/partition/growfs.c b/src/partition/growfs.c index d7069b8d08..cd85946812 100644 --- a/src/partition/growfs.c +++ b/src/partition/growfs.c @@ -198,6 +198,7 @@ static int run(int argc, char *argv[]) { _cleanup_close_ int mountfd = -1, devfd = -1; _cleanup_free_ char *devpath = NULL; uint64_t size, newsize; + struct stat st; dev_t devno; int r; @@ -233,10 +234,15 @@ static int run(int argc, char *argv[]) { if (r < 0) return log_error_errno(r, "Failed to format device major/minor path: %m"); - devfd = open(devpath, O_RDONLY|O_CLOEXEC); + devfd = open(devpath, O_RDONLY|O_CLOEXEC|O_NOCTTY); if (devfd < 0) return log_error_errno(errno, "Failed to open \"%s\": %m", devpath); + if (fstat(devfd, &st) < 0) + return log_error_errno(r, "Failed to stat() device %s: %m", devpath); + if (!S_ISBLK(st.st_mode)) + return log_error_errno(SYNTHETIC_ERRNO(ENOTBLK), "Backing device of file system is not a block device, refusing."); + if (ioctl(devfd, BLKGETSIZE64, &size) != 0) return log_error_errno(errno, "Failed to query size of \"%s\": %m", devpath); From a39cc90d2b78caf774fe9a52c77608d98cada0af Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Thu, 14 Jul 2022 11:34:18 +0200 Subject: [PATCH 3/3] growfs: don't reopen fds unnecessarily Instead, just open the mount fd once, and then operate on fds only. --- src/partition/growfs.c | 23 +++++++++++++++-------- 1 file changed, 15 insertions(+), 8 deletions(-) diff --git a/src/partition/growfs.c b/src/partition/growfs.c index cd85946812..15cb24d151 100644 --- a/src/partition/growfs.c +++ b/src/partition/growfs.c @@ -85,16 +85,23 @@ static int resize_crypt_luks_device(dev_t devno, const char *fstype, dev_t main_ } #endif -static int maybe_resize_underlying_device(const char *mountpath, dev_t main_devno) { +static int maybe_resize_underlying_device( + int mountfd, + const char *mountpath, + dev_t main_devno) { + _cleanup_free_ char *fstype = NULL, *devpath = NULL; dev_t devno; int r; + assert(mountfd >= 0); + assert(mountpath); + #if HAVE_LIBCRYPTSETUP cryptsetup_enable_logging(NULL); #endif - r = get_block_device_harder(mountpath, &devno); + r = get_block_device_harder_fd(mountfd, &devno); if (r < 0) return log_error_errno(r, "Failed to determine underlying block device of \"%s\": %m", mountpath); @@ -214,7 +221,11 @@ static int run(int argc, char *argv[]) { if (r == 0) return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "\"%s\" is not a mount point: %m", arg_target); - r = get_block_device(arg_target, &devno); + mountfd = open(arg_target, O_RDONLY|O_CLOEXEC|O_DIRECTORY); + if (mountfd < 0) + return log_error_errno(errno, "Failed to open \"%s\": %m", arg_target); + + r = get_block_device_fd(mountfd, &devno); if (r == -EUCLEAN) return btrfs_log_dev_root(LOG_ERR, r, arg_target); if (r < 0) @@ -222,14 +233,10 @@ static int run(int argc, char *argv[]) { if (devno == 0) return log_error_errno(SYNTHETIC_ERRNO(ENODEV), "File system \"%s\" not backed by block device.", arg_target); - r = maybe_resize_underlying_device(arg_target, devno); + r = maybe_resize_underlying_device(mountfd, arg_target, devno); if (r < 0) return r; - mountfd = open(arg_target, O_RDONLY|O_CLOEXEC|O_DIRECTORY); - if (mountfd < 0) - return log_error_errno(errno, "Failed to open \"%s\": %m", arg_target); - r = device_path_make_major_minor(S_IFBLK, devno, &devpath); if (r < 0) return log_error_errno(r, "Failed to format device major/minor path: %m");