Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 312e0e7b authored by Abhishek Arpure's avatar Abhishek Arpure Committed by Tom Marshall
Browse files

Integer overflow observed while formatting volume

While calculating volume size, get_block_device_size() returns
u64 value but the returned value is assigned in ssize_t variable.
This may cause integer overflow if the volume size is beyond
ssize_t limit.

Use int64_t instead of ssize_t in get_file_size() and explicitly check
for overflow to fix the issue.

Bug: 65001754
Test: mmma bootable/recovery
Change-Id: I91eb30bff0bf7dcc48678efc2f414d2b79af6d0d
(cherry picked from commit 4fec8e9e)
parent 409a4472
Loading
Loading
Loading
Loading
+12 −5
Original line number Diff line number Diff line
@@ -18,6 +18,7 @@

#include <ctype.h>
#include <fcntl.h>
#include <stdint.h>
#include <dirent.h>
#include <stdlib.h>
#include <sys/mount.h>
@@ -282,16 +283,22 @@ static int exec_cmd(const char* path, char* const argv[]) {
    return WEXITSTATUS(status);
}

static ssize_t get_file_size(int fd, uint64_t reserve_len) {
static int64_t get_file_size(int fd, uint64_t reserve_len) {
  struct stat buf;
  int ret = fstat(fd, &buf);
  if (ret) return 0;

  ssize_t computed_size;
  int64_t computed_size;
  if (S_ISREG(buf.st_mode)) {
    computed_size = buf.st_size - reserve_len;
  } else if (S_ISBLK(buf.st_mode)) {
    computed_size = get_block_device_size(fd) - reserve_len;
    uint64_t block_device_size = get_block_device_size(fd);
    if (block_device_size < reserve_len ||
        block_device_size > std::numeric_limits<int64_t>::max()) {
      computed_size = 0;
    } else {
      computed_size = block_device_size - reserve_len;
    }
  } else {
    computed_size = 0;
  }
@@ -339,13 +346,13 @@ int format_volume(const char* volume, const char* directory) {
            close(fd);
        }

        ssize_t length = 0;
        int64_t length = 0;
        if (v->length != 0) {
            length = v->length;
        } else if (v->key_loc != NULL && strcmp(v->key_loc, "footer") == 0) {
          android::base::unique_fd fd(open(v->blk_device, O_RDONLY));
          if (fd < 0) {
            PLOG(ERROR) << "get_file_size: failed to open " << v->blk_device;
            PLOG(ERROR) << "format_volume: failed to open " << v->blk_device;
            return -1;
          }
          length = get_file_size(fd.get(), CRYPT_FOOTER_OFFSET);