diff --git a/devicemodel/core/sw_load_bzimage.c b/devicemodel/core/sw_load_bzimage.c index d4f0fb918..93c33f154 100644 --- a/devicemodel/core/sw_load_bzimage.c +++ b/devicemodel/core/sw_load_bzimage.c @@ -97,8 +97,8 @@ static char ramdisk_path[STR_LEN]; static char kernel_path[STR_LEN]; static int with_ramdisk; static int with_kernel; -static int ramdisk_size; -static int kernel_size; +static size_t ramdisk_size; +static size_t kernel_size; static int acrn_get_bzimage_setup_size(struct vmctx *ctx) @@ -133,7 +133,7 @@ acrn_parse_kernel(char *arg) if (len < STR_LEN) { strncpy(kernel_path, arg, len + 1); - if (check_image(kernel_path) != 0){ + if (check_image(kernel_path, 0, &kernel_size) != 0){ fprintf(stderr, "SW_LOAD: check_image failed for '%s'\n", kernel_path); exit(10); /* Non-zero */ @@ -154,7 +154,7 @@ acrn_parse_ramdisk(char *arg) if (len < STR_LEN) { strncpy(ramdisk_path, arg, len + 1); - if (check_image(ramdisk_path) != 0){ + if (check_image(ramdisk_path, 0, &ramdisk_size) != 0){ fprintf(stderr, "SW_LOAD: check_image failed for '%s'\n", ramdisk_path); exit(11); /* Non-zero */ @@ -171,7 +171,8 @@ static int acrn_prepare_ramdisk(struct vmctx *ctx) { FILE *fp; - int len, read; + long len; + size_t read; fp = fopen(ramdisk_path, "r"); if (fp == NULL) { @@ -182,26 +183,33 @@ acrn_prepare_ramdisk(struct vmctx *ctx) fseek(fp, 0, SEEK_END); len = ftell(fp); + + if (len != ramdisk_size) { + fprintf(stderr, + "SW_LOAD ERR: ramdisk file changed\n"); + fclose(fp); + return -1; + } + if (len > (BOOTARGS_LOAD_OFF(ctx) - RAMDISK_LOAD_OFF(ctx))) { printf("SW_LOAD ERR: the size of ramdisk file is too big" - " file len=0x%x, limit is 0x%lx\n", len, + " file len=0x%lx, limit is 0x%lx\n", len, BOOTARGS_LOAD_OFF(ctx) - RAMDISK_LOAD_OFF(ctx)); fclose(fp); return -1; } - ramdisk_size = len; fseek(fp, 0, SEEK_SET); read = fread(ctx->baseaddr + RAMDISK_LOAD_OFF(ctx), sizeof(char), len, fp); if (read < len) { printf("SW_LOAD ERR: could not read the whole ramdisk file," - " file len=%d, read %d\n", len, read); + " file len=%ld, read %lu\n", len, read); fclose(fp); return -1; } fclose(fp); - printf("SW_LOAD: ramdisk %s size %d copied to guest 0x%lx\n", + printf("SW_LOAD: ramdisk %s size %lu copied to guest 0x%lx\n", ramdisk_path, ramdisk_size, RAMDISK_LOAD_OFF(ctx)); return 0; @@ -211,7 +219,8 @@ static int acrn_prepare_kernel(struct vmctx *ctx) { FILE *fp; - int len, read; + long len; + size_t read; fp = fopen(kernel_path, "r"); if (fp == NULL) { @@ -222,24 +231,31 @@ acrn_prepare_kernel(struct vmctx *ctx) fseek(fp, 0, SEEK_END); len = ftell(fp); + + if (len != kernel_size) { + fprintf(stderr, + "SW_LOAD ERR: kernel file changed\n"); + fclose(fp); + return -1; + } + if ((len + KERNEL_LOAD_OFF(ctx)) > RAMDISK_LOAD_OFF(ctx)) { printf("SW_LOAD ERR: need big system memory to fit image\n"); fclose(fp); return -1; } - kernel_size = len; fseek(fp, 0, SEEK_SET); read = fread(ctx->baseaddr + KERNEL_LOAD_OFF(ctx), sizeof(char), len, fp); if (read < len) { printf("SW_LOAD ERR: could not read the whole kernel file," - " file len=%d, read %d\n", len, read); + " file len=%ld, read %lu\n", len, read); fclose(fp); return -1; } fclose(fp); - printf("SW_LOAD: kernel %s size %d copied to guest 0x%lx\n", + printf("SW_LOAD: kernel %s size %lu copied to guest 0x%lx\n", kernel_path, kernel_size, KERNEL_LOAD_OFF(ctx)); return 0; diff --git a/devicemodel/core/sw_load_common.c b/devicemodel/core/sw_load_common.c index 95f8faf39..337161502 100644 --- a/devicemodel/core/sw_load_common.c +++ b/devicemodel/core/sw_load_common.c @@ -117,15 +117,32 @@ get_bootargs(void) } int -check_image(char *path) +check_image(char *path, size_t size_limit, size_t *size) { FILE *fp; + long len; fp = fopen(path, "r"); - if (fp == NULL) + + if (fp == NULL) { + fprintf(stderr, + "SW_LOAD ERR: image file failed to open\n"); return -1; + } + + fseek(fp, 0, SEEK_END); + len = ftell(fp); + + if (len == 0 || (size_limit && len > size_limit)) { + fprintf(stderr, + "SW_LOAD ERR: file is %s\n", + len ? "too large" : "empty"); + fclose(fp); + return -1; + } fclose(fp); + *size = len; return 0; } diff --git a/devicemodel/core/sw_load_elf.c b/devicemodel/core/sw_load_elf.c index b89033429..3d0c933c0 100644 --- a/devicemodel/core/sw_load_elf.c +++ b/devicemodel/core/sw_load_elf.c @@ -96,10 +96,11 @@ int acrn_parse_elf(char *arg) { size_t len = strnlen(arg, STR_LEN); + size_t elfsz; if (len < STR_LEN) { strncpy(elf_path, arg, len + 1); - assert(check_image(elf_path) == 0); + assert(check_image(elf_path, 0, &elfsz) == 0); elf_file_name = elf_path; diff --git a/devicemodel/core/sw_load_vsbl.c b/devicemodel/core/sw_load_vsbl.c index bcc494e62..583738b79 100644 --- a/devicemodel/core/sw_load_vsbl.c +++ b/devicemodel/core/sw_load_vsbl.c @@ -104,11 +104,11 @@ struct vsbl_para { }; static char guest_part_info_path[STR_LEN]; -static int guest_part_info_size; +static size_t guest_part_info_size; static bool with_guest_part_info; static char vsbl_path[STR_LEN]; -static int vsbl_size; +static size_t vsbl_size; static int boot_blk_bdf; @@ -125,11 +125,13 @@ vsbl_set_bdf(int bnum, int snum, int fnum) int acrn_parse_guest_part_info(char *arg) { + int error; size_t len = strlen(arg); if (len < STR_LEN) { strncpy(guest_part_info_path, arg, len + 1); - assert(check_image(guest_part_info_path) == 0); + error = check_image(guest_part_info_path, 0, &guest_part_info_size); + assert(!error); with_guest_part_info = true; @@ -144,7 +146,8 @@ static int acrn_prepare_guest_part_info(struct vmctx *ctx) { FILE *fp; - int len, read; + long len; + size_t read; fp = fopen(guest_part_info_path, "r"); if (fp == NULL) { @@ -156,6 +159,14 @@ acrn_prepare_guest_part_info(struct vmctx *ctx) fseek(fp, 0, SEEK_END); len = ftell(fp); + + if (len != guest_part_info_size) { + fprintf(stderr, + "SW_LOAD ERR: partition blob changed\n"); + fclose(fp); + return -1; + } + if ((len + GUEST_PART_INFO_OFF(ctx)) > BOOTARGS_OFF(ctx)) { fprintf(stderr, "SW_LOAD ERR: too large partition blob\n"); @@ -163,8 +174,6 @@ acrn_prepare_guest_part_info(struct vmctx *ctx) return -1; } - guest_part_info_size = len; - fseek(fp, 0, SEEK_SET); read = fread(ctx->baseaddr + GUEST_PART_INFO_OFF(ctx), sizeof(char), len, fp); @@ -175,7 +184,7 @@ acrn_prepare_guest_part_info(struct vmctx *ctx) return -1; } fclose(fp); - printf("SW_LOAD: partition blob %s size %d copy to guest 0x%lx\n", + printf("SW_LOAD: partition blob %s size %lu copy to guest 0x%lx\n", guest_part_info_path, guest_part_info_size, GUEST_PART_INFO_OFF(ctx)); @@ -185,11 +194,13 @@ acrn_prepare_guest_part_info(struct vmctx *ctx) int acrn_parse_vsbl(char *arg) { + int error; size_t len = strlen(arg); if (len < STR_LEN) { strncpy(vsbl_path, arg, len + 1); - assert(check_image(vsbl_path) == 0); + error = check_image(vsbl_path, 8 * MB, &vsbl_size); + assert(!error); vsbl_file_name = vsbl_path; @@ -204,7 +215,7 @@ static int acrn_prepare_vsbl(struct vmctx *ctx) { FILE *fp; - int len, read; + size_t read; fp = fopen(vsbl_path, "r"); if (fp == NULL) { @@ -215,27 +226,25 @@ acrn_prepare_vsbl(struct vmctx *ctx) } fseek(fp, 0, SEEK_END); - len = ftell(fp); - if (len > (8*MB)) { + + if (ftell(fp) != vsbl_size) { fprintf(stderr, - "SW_LOAD ERR: too large vsbl file\n"); + "SW_LOAD ERR: vsbl file changed\n"); fclose(fp); return -1; } - vsbl_size = len; - fseek(fp, 0, SEEK_SET); read = fread(ctx->baseaddr + VSBL_TOP(ctx) - vsbl_size, - sizeof(char), len, fp); - if (read < len) { + sizeof(char), vsbl_size, fp); + if (read < vsbl_size) { fprintf(stderr, "SW_LOAD ERR: could not read whole partition blob\n"); fclose(fp); return -1; } fclose(fp); - printf("SW_LOAD: partition blob %s size %d copy to guest 0x%lx\n", + printf("SW_LOAD: partition blob %s size %lu copy to guest 0x%lx\n", vsbl_path, vsbl_size, VSBL_TOP(ctx) - vsbl_size); return 0; diff --git a/devicemodel/include/sw_load.h b/devicemodel/include/sw_load.h index 9d8fb90ee..83b70242e 100644 --- a/devicemodel/include/sw_load.h +++ b/devicemodel/include/sw_load.h @@ -65,7 +65,7 @@ int acrn_parse_guest_part_info(char *arg); char *get_bootargs(void); void vsbl_set_bdf(int bnum, int snum, int fnum); -int check_image(char *path); +int check_image(char *path, size_t size_limit, size_t *size); uint32_t acrn_create_e820_table(struct vmctx *ctx, struct e820_entry *e820); int add_e820_entry(struct e820_entry *e820, int len, uint64_t start, uint64_t size, uint32_t type);