summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSami Kerola2015-06-24 10:15:14 +0200
committerKarel Zak2015-07-30 11:39:15 +0200
commita232cfdc0a3d40239e0f0a3bbfda0a9a92c880b6 (patch)
tree0c6e2121b61841bbd78329209f76dc7404e211c1
parentmkfs.minix: check user input carefully (diff)
downloadkernel-qcow2-util-linux-a232cfdc0a3d40239e0f0a3bbfda0a9a92c880b6.tar.gz
kernel-qcow2-util-linux-a232cfdc0a3d40239e0f0a3bbfda0a9a92c880b6.tar.xz
kernel-qcow2-util-linux-a232cfdc0a3d40239e0f0a3bbfda0a9a92c880b6.zip
mkfs.minix: check requested blocks will not exceed available on device
Earlier user could define more blocks than device, or backing file for loopback file system, had available. That lead to a system crash with following commands; fallocate --length 64KiB test-file mkfs.minix -3 -i 842160 test-file 104882174 mkdir test-file.d mount test-file test-file.d cp /etc/service test-file.d Killed sudo umount test-file.d The minix driver should probably not hang the whole kernel, but the least that mkfs.minix ought to do is not to let users to get that condition quite as easily. Signed-off-by: Sami Kerola <kerolasa@iki.fi>
-rw-r--r--disk-utils/mkfs.minix.c64
1 files changed, 34 insertions, 30 deletions
diff --git a/disk-utils/mkfs.minix.c b/disk-utils/mkfs.minix.c
index 59e1674ec..c2ab6644c 100644
--- a/disk-utils/mkfs.minix.c
+++ b/disk-utils/mkfs.minix.c
@@ -656,6 +656,39 @@ static int find_super_magic(const struct fs_control *ctl)
}
}
+static void determine_device_blocks(struct fs_control *ctl, const struct stat *statbuf)
+{
+ unsigned long long dev_blocks;
+
+ if (S_ISBLK(statbuf->st_mode)) {
+ int sectorsize;
+
+ if (blkdev_get_sector_size(ctl->device_fd, &sectorsize) == -1)
+ sectorsize = DEFAULT_SECTOR_SIZE; /* kernel < 2.3.3 */
+ if (blkdev_is_misaligned(ctl->device_fd))
+ warnx(_("%s: device is misaligned"), ctl->device_name);
+ if (MINIX_BLOCK_SIZE < sectorsize)
+ errx(MKFS_EX_ERROR, _("block size smaller than physical "
+ "sector size of %s"), ctl->device_name);
+ if (blkdev_get_size(ctl->device_fd, &dev_blocks) == -1)
+ errx(MKFS_EX_ERROR, _("cannot determine size of %s"), ctl->device_name);
+ dev_blocks /= MINIX_BLOCK_SIZE;
+ } else if (!S_ISBLK(statbuf->st_mode))
+ dev_blocks = statbuf->st_size / MINIX_BLOCK_SIZE;
+ if (!ctl->fs_blocks)
+ ctl->fs_blocks = dev_blocks;
+ else if (dev_blocks < ctl->fs_blocks)
+ errx(MKFS_EX_ERROR,
+ _("%s: requested blocks (%llu) exceeds available (%llu) blocks\n"),
+ ctl->device_name, ctl->fs_blocks, dev_blocks);
+ if (ctl->fs_blocks < 10)
+ errx(MKFS_EX_ERROR, _("%s: number of blocks too small"), ctl->device_name);
+ if (fs_version == 1 && ctl->fs_blocks > MINIX_MAX_INODES)
+ ctl->fs_blocks = MINIX_MAX_INODES;
+ if (ctl->fs_blocks > MINIX_MAX_INODES * BITS_PER_BLOCK)
+ ctl->fs_blocks = MINIX_MAX_INODES * BITS_PER_BLOCK; /* Utter maximum: Clip. */
+}
+
static void check_user_instructions(struct fs_control *ctl)
{
switch (fs_version) {
@@ -782,38 +815,9 @@ int main(int argc, char ** argv)
ctl.device_fd = open(ctl.device_name, O_RDWR | O_EXCL);
else
ctl.device_fd = open(ctl.device_name, O_RDWR);
-
if (ctl.device_fd < 0)
err(MKFS_EX_ERROR, _("cannot open %s"), ctl.device_name);
-
- if (S_ISBLK(statbuf.st_mode)) {
- int sectorsize;
-
- if (blkdev_get_sector_size(ctl.device_fd, &sectorsize) == -1)
- sectorsize = DEFAULT_SECTOR_SIZE; /* kernel < 2.3.3 */
-
- if (blkdev_is_misaligned(ctl.device_fd))
- warnx(_("%s: device is misaligned"), ctl.device_name);
-
- if (MINIX_BLOCK_SIZE < sectorsize)
- errx(MKFS_EX_ERROR, _("block size smaller than physical "
- "sector size of %s"), ctl.device_name);
- if (!ctl.fs_blocks) {
- if (blkdev_get_size(ctl.device_fd, &ctl.fs_blocks) == -1)
- errx(MKFS_EX_ERROR, _("cannot determine size of %s"),
- ctl.device_name);
- ctl.fs_blocks /= MINIX_BLOCK_SIZE;
- }
- } else if (!S_ISBLK(statbuf.st_mode)) {
- if (!ctl.fs_blocks)
- ctl.fs_blocks = statbuf.st_size / MINIX_BLOCK_SIZE;
- }
- if (ctl.fs_blocks < 10)
- errx(MKFS_EX_ERROR, _("%s: number of blocks too small"), ctl.device_name);
- if (fs_version == 1 && ctl.fs_blocks > MINIX_MAX_INODES)
- ctl.fs_blocks = MINIX_MAX_INODES;
- if (ctl.fs_blocks > MINIX_MAX_INODES * BITS_PER_BLOCK)
- ctl.fs_blocks = MINIX_MAX_INODES * BITS_PER_BLOCK; /* Utter maximum: Clip. */
+ determine_device_blocks(&ctl, &statbuf);
setup_tables(&ctl);
if (ctl.check_blocks)
check_blocks(&ctl);