From 9b98929ec1d8fc1ec37d699b0735d60cb13308ce Mon Sep 17 00:00:00 2001 From: Kees Cook Date: Tue, 21 Aug 2012 14:59:25 -0700 Subject: mount-encrypted: explicitly use uint64_t for sizes On very large HDDs, the sector count was wrapping around. Switch most calculations to bytes using uint64_t, and use BLKGETSIZE64 for checking the loopback device size. BUG=chrome-os-partner:12705 TEST=parrot build, manual testing STATUS=Fixed Change-Id: I1f7aea81151ed5cc130b1f6a05fda83f7a85150f Signed-off-by: Kees Cook Reviewed-on: https://gerrit.chromium.org/gerrit/31073 Reviewed-by: Elly Jones --- utility/mount-encrypted.c | 40 ++++++++++++++++----------------- utility/mount-helpers.c | 56 ++++++++++++++++++++++++----------------------- utility/mount-helpers.h | 12 +++++----- 3 files changed, 55 insertions(+), 53 deletions(-) diff --git a/utility/mount-encrypted.c b/utility/mount-encrypted.c index 26f1542c..f5d79aa5 100644 --- a/utility/mount-encrypted.c +++ b/utility/mount-encrypted.c @@ -15,6 +15,7 @@ #include #include #include +#include #include #include #include @@ -53,9 +54,9 @@ static const uint32_t kLockboxIndex = 0x20000004; static const uint32_t kLockboxSizeV1 = 0x2c; static const uint32_t kLockboxSizeV2 = 0x45; static const uint32_t kLockboxSaltOffset = 0x5; -static const size_t kSectorSize = 512; -static const size_t kExt4BlockSize = 4096; -static const size_t kExt4MinBytes = 16 * 1024 * 1024; +static const uint64_t kSectorSize = 512; +static const uint64_t kExt4BlockSize = 4096; +static const uint64_t kExt4MinBytes = 16 * 1024 * 1024; static const char * const kStaticKeyDefault = "default unsafe static key"; static const char * const kStaticKeyFactory = "factory unsafe static key"; static const char * const kStaticKeyFinalizationNeeded = "needs finalization"; @@ -673,14 +674,14 @@ static int finalize_from_cmdline(char *key) return EXIT_SUCCESS; } -static void spawn_resizer(const char *device, size_t blocks, - size_t blocks_max) +static void spawn_resizer(const char *device, uint64_t blocks, + uint64_t blocks_max) { pid_t pid; /* Skip resize before forking, if it's not going to happen. */ if (blocks >= blocks_max) { - INFO("Resizing skipped. blocks:%zu >= blocks_max:%zu", + INFO("Resizing skipped. blocks:%" PRIu64 " >= blocks_max:%" PRIu64, blocks, blocks_max); return; } @@ -723,11 +724,11 @@ static int setup_encrypted(int mode) char *encryption_key = NULL; int migrate_allowed = 0, migrate_needed = 0, rebuild = 0; gchar *lodev = NULL; - size_t sectors; + uint64_t sectors; struct bind_mount *bind; int sparsefd; struct statvfs stateful_statbuf; - size_t blocks_min, blocks_max; + uint64_t blocks_min, blocks_max; /* Use the "system key" to decrypt the "encryption key" stored in * the stateful partition. @@ -764,7 +765,7 @@ static int setup_encrypted(int mode) } if (rebuild) { - off_t fs_bytes_max; + uint64_t fs_bytes_max; /* Wipe out the old files, and ignore errors. */ unlink(key_path); @@ -779,8 +780,8 @@ static int setup_encrypted(int mode) fs_bytes_max *= kSizePercent; fs_bytes_max *= stateful_statbuf.f_frsize; - INFO("Creating sparse backing file with size %llu.", - (unsigned long long)fs_bytes_max); + INFO("Creating sparse backing file with size %" PRIu64 ".", + fs_bytes_max); /* Create the sparse file. */ sparsefd = sparse_create(block_path, fs_bytes_max); @@ -805,7 +806,7 @@ static int setup_encrypted(int mode) } /* Get size as seen by block device. */ - sectors = get_sectors(lodev); + sectors = blk_size(lodev) / kSectorSize; if (!sectors) { ERROR("Failed to read device size"); goto lo_cleanup; @@ -848,8 +849,8 @@ static int setup_encrypted(int mode) blocks_max = sectors / (kExt4BlockSize / kSectorSize); blocks_min = kExt4MinBytes / kExt4BlockSize; if (migrate_needed && migrate_allowed) { - off_t fs_bytes_min; - size_t calc_blocks_min; + uint64_t fs_bytes_min; + uint64_t calc_blocks_min; /* When doing a migration, the new filesystem must be * large enough to hold what we're going to migrate. * Instead of walking the bind mount sources, which would @@ -863,8 +864,7 @@ static int setup_encrypted(int mode) fs_bytes_min = stateful_statbuf.f_blocks - stateful_statbuf.f_bfree; fs_bytes_min *= stateful_statbuf.f_frsize; - DEBUG("Stateful bytes used: %llu", - (unsigned long long)fs_bytes_min); + DEBUG("Stateful bytes used: %" PRIu64 "", fs_bytes_min); fs_bytes_min *= kMigrationSizeMultiplier; /* Minimum blocks needed for that many bytes. */ @@ -876,15 +876,15 @@ static int setup_encrypted(int mode) else if (calc_blocks_min < blocks_min) calc_blocks_min = blocks_min; - DEBUG("Maximum fs blocks: %zu", blocks_max); - DEBUG("Minimum fs blocks: %zu", blocks_min); - DEBUG("Migration blocks chosen: %zu", calc_blocks_min); + DEBUG("Maximum fs blocks: %" PRIu64 "", blocks_max); + DEBUG("Minimum fs blocks: %" PRIu64 "", blocks_min); + DEBUG("Migration blocks chosen: %" PRIu64 "", calc_blocks_min); blocks_min = calc_blocks_min; } if (rebuild) { INFO("Building filesystem on %s " - "(blocksize:%zu, min:%zu, max:%zu).", + "(blocksize:%" PRIu64 ", min:%" PRIu64 ", max:%" PRIu64 ").", dmcrypt_dev, kExt4BlockSize, blocks_min, blocks_max); if (!filesystem_build(dmcrypt_dev, kExt4BlockSize, blocks_min, blocks_max)) diff --git a/utility/mount-helpers.c b/utility/mount-helpers.c index 7647ffab..29db21cf 100644 --- a/utility/mount-helpers.c +++ b/utility/mount-helpers.c @@ -15,6 +15,7 @@ #include #include #include +#include #include #include #include @@ -38,10 +39,10 @@ static const gchar * const kLoopTemplate = "/dev/loop%d"; static const int kLoopMajor = 7; static const int kLoopMax = 8; static const unsigned int kResizeStepSeconds = 2; -static const size_t kResizeBlocks = 32768 * 10; -static const size_t kBlocksPerGroup = 32768; -static const size_t kInodeRatioDefault = 16384; -static const size_t kInodeRatioMinimum = 2048; +static const uint64_t kResizeBlocks = 32768 * 10; +static const uint64_t kBlocksPerGroup = 32768; +static const uint64_t kInodeRatioDefault = 16384; +static const uint64_t kInodeRatioMinimum = 2048; static const gchar * const kExt4ExtendedOptions = "discard,lazy_itable_init"; int remove_tree(const char *tree) @@ -54,20 +55,20 @@ int remove_tree(const char *tree) return runcmd(rm, NULL); } -size_t get_sectors(const char *device) +uint64_t blk_size(const char *device) { - size_t sectors; + uint64_t bytes; int fd; if ((fd = open(device, O_RDONLY | O_NOFOLLOW)) < 0) { PERROR("open(%s)", device); return 0; } - if (ioctl(fd, BLKGETSIZE, §ors)) { - PERROR("ioctl(%s, BLKGETSIZE)", device); + if (ioctl(fd, BLKGETSIZE64, &bytes)) { + PERROR("ioctl(%s, BLKGETSIZE64)", device); return 0; } close(fd); - return sectors; + return bytes; } int runcmd(const gchar *argv[], gchar **output) @@ -342,11 +343,11 @@ failed: return 0; } -int dm_setup(size_t sectors, const gchar *encryption_key, const char *name, +int dm_setup(uint64_t sectors, const gchar *encryption_key, const char *name, const gchar *device, const char *path, int discard) { /* Mount loopback device with dm-crypt using the encryption key. */ - gchar *table = g_strdup_printf("0 %zu crypt " \ + gchar *table = g_strdup_printf("0 %" PRIu64 " crypt " \ "aes-cbc-essiv:sha256 %s " \ "0 %s 0%s", sectors, @@ -425,7 +426,7 @@ char *dm_get_key(const gchar *device) return key; } -int sparse_create(const char *path, size_t size) +int sparse_create(const char *path, uint64_t bytes) { int sparsefd; @@ -434,7 +435,7 @@ int sparse_create(const char *path, size_t size) if (sparsefd < 0) goto out; - if (ftruncate(sparsefd, size)) { + if (ftruncate(sparsefd, bytes)) { int saved_errno = errno; close(sparsefd); @@ -460,8 +461,9 @@ out: * ------------------------------------------------------------------ * ceil(size_max / inode-ratio_max) * ceil(blocks_mkfs / group-ratio) */ -static size_t get_inode_ratio(size_t block_bytes_in, size_t blocks_mkfs_in, - size_t blocks_max_in) +static uint64_t get_inode_ratio(uint64_t block_bytes_in, + uint64_t blocks_mkfs_in, + uint64_t blocks_max_in) { double block_bytes = (double)block_bytes_in; double blocks_mkfs = (double)blocks_mkfs_in; @@ -491,7 +493,7 @@ static size_t get_inode_ratio(size_t block_bytes_in, size_t blocks_mkfs_in, if (inode_ratio_mkfs < kInodeRatioMinimum) goto failure; - return (size_t)inode_ratio_mkfs; + return (uint64_t)inode_ratio_mkfs; failure: return kInodeRatioDefault; @@ -505,20 +507,20 @@ failure: * * Returns 1 on success, 0 on failure. */ -int filesystem_build(const char *device, size_t block_bytes, size_t blocks_min, - size_t blocks_max) +int filesystem_build(const char *device, uint64_t block_bytes, + uint64_t blocks_min, uint64_t blocks_max) { int rc = 0; - size_t inode_ratio; + uint64_t inode_ratio; - gchar *blocksize = g_strdup_printf("%zu", block_bytes); + gchar *blocksize = g_strdup_printf("%" PRIu64, block_bytes); if (!blocksize) { PERROR("g_strdup_printf"); goto out; } gchar *blocks_str; - blocks_str = g_strdup_printf("%zu", blocks_min); + blocks_str = g_strdup_printf("%" PRIu64, blocks_min); if (!blocks_str) { PERROR("g_strdup_printf"); goto free_blocksize; @@ -526,7 +528,7 @@ int filesystem_build(const char *device, size_t block_bytes, size_t blocks_min, gchar *extended; if (blocks_min < blocks_max) { - extended = g_strdup_printf("%s,resize=%zu", + extended = g_strdup_printf("%s,resize=%" PRIu64, kExt4ExtendedOptions, blocks_max); } else { extended = g_strdup_printf("%s", kExt4ExtendedOptions); @@ -537,7 +539,7 @@ int filesystem_build(const char *device, size_t block_bytes, size_t blocks_min, } inode_ratio = get_inode_ratio(block_bytes, blocks_min, blocks_max); - gchar *inode_ratio_str = g_strdup_printf("%zu", inode_ratio); + gchar *inode_ratio_str = g_strdup_printf("%" PRIu64, inode_ratio); if (!inode_ratio_str) { PERROR("g_strdup_printf"); goto free_extended; @@ -582,11 +584,11 @@ out: } /* Spawns a filesystem resizing process. */ -int filesystem_resize(const char *device, size_t blocks, size_t blocks_max) +int filesystem_resize(const char *device, uint64_t blocks, uint64_t blocks_max) { /* Ignore resizing if we know the filesystem was built to max size. */ if (blocks >= blocks_max) { - INFO("Resizing aborted. blocks:%zu >= blocks_max:%zu", + INFO("Resizing aborted. blocks:%" PRIu64 " >= blocks_max:%" PRIu64, blocks, blocks_max); return 1; } @@ -609,7 +611,7 @@ int filesystem_resize(const char *device, size_t blocks, size_t blocks_max) if (blocks > blocks_max) blocks = blocks_max; - blocks_str = g_strdup_printf("%zu", blocks); + blocks_str = g_strdup_printf("%" PRIu64, blocks); if (!blocks_str) { PERROR("g_strdup_printf"); return 0; @@ -623,7 +625,7 @@ int filesystem_resize(const char *device, size_t blocks, size_t blocks_max) NULL }; - INFO("Resizing filesystem on %s to %zu.", device, blocks); + INFO("Resizing filesystem on %s to %" PRIu64 ".", device, blocks); if (runcmd(resize, NULL)) { ERROR("resize2fs failed"); return 0; diff --git a/utility/mount-helpers.h b/utility/mount-helpers.h index c5554b36..d2aa1795 100644 --- a/utility/mount-helpers.h +++ b/utility/mount-helpers.h @@ -8,7 +8,7 @@ #define _MOUNT_HELPERS_H_ /* General utility functions. */ -size_t get_sectors(const char *device); +uint64_t blk_size(const char *device); int remove_tree(const char *tree); int runcmd(const gchar *argv[], gchar **output); int same_vfs(const char *mnt_a, const char *mnt_b); @@ -22,18 +22,18 @@ int loop_detach(const gchar *loopback); int loop_detach_name(const char *name); /* Encrypted device mapper setup/teardown. */ -int dm_setup(size_t sectors, const gchar *encryption_key, const char *name, +int dm_setup(uint64_t bytes, const gchar *encryption_key, const char *name, const gchar *device, const char *path, int discard); int dm_teardown(const gchar *device); char *dm_get_key(const gchar *device); /* Sparse file creation. */ -int sparse_create(const char *path, size_t size); +int sparse_create(const char *path, uint64_t bytes); /* Filesystem creation. */ -int filesystem_build(const char *device, size_t block_bytes, size_t blocks_min, - size_t blocks_max); -int filesystem_resize(const char *device, size_t blocks, size_t blocks_max); +int filesystem_build(const char *device, uint64_t block_bytes, + uint64_t blocks_min, uint64_t blocks_max); +int filesystem_resize(const char *device, uint64_t blocks, uint64_t blocks_max); /* Encrypted keyfile handling. */ char *keyfile_read(const char *keyfile, uint8_t *system_key); -- cgit v1.2.1