From f6d16b6bbd5b8b7ac238c3d2148bebf4e91140a2 Mon Sep 17 00:00:00 2001 From: Shreenidhi Shedi Date: Sun, 8 Aug 2021 12:33:40 +0530 Subject: [PATCH] fix(skipcpio): improve error checking Some other minor tweaks Signed-off-by: Shreenidhi Shedi --- src/skipcpio/skipcpio.c | 180 +++++++++++++++++++++++----------------- 1 file changed, 106 insertions(+), 74 deletions(-) diff --git a/src/skipcpio/skipcpio.c b/src/skipcpio/skipcpio.c index fd9b4e46ad..89cc354915 100644 --- a/src/skipcpio/skipcpio.c +++ b/src/skipcpio/skipcpio.c @@ -1,4 +1,4 @@ -/* dracut-install.c -- install files and executables +/* skipcpio.c Copyright (C) 2012 Harald Hoyer Copyright (C) 2012 Red Hat, Inc. All rights reserved. @@ -28,11 +28,18 @@ #include #define CPIO_MAGIC "070701" + #define CPIO_END "TRAILER!!!" #define CPIO_ENDLEN (sizeof(CPIO_END) - 1) #define CPIO_ALIGNMENT 4 +#define ALIGN_UP(n, a) (((n) + (a) - 1) & (~((a) - 1))) + +#define pr_err(fmt, ...) \ + fprintf(stderr, "ERROR: %s:%d:%s(): " fmt, __FILE__, __LINE__, \ + __func__, ##__VA_ARGS__) + struct cpio_header { char c_magic[6]; char c_ino[8]; @@ -62,110 +69,135 @@ union buf_union { static union buf_union buf; -#define ALIGN_UP(n, a) (((n) + (a) - 1) & (~((a) - 1))) - int main(int argc, char **argv) { - FILE *f; size_t s; + long pos = 0; + FILE *f = NULL; + char *fname = NULL; + int ret = EXIT_FAILURE; + unsigned long filesize; + unsigned long filename_length; if (argc != 2) { fprintf(stderr, "Usage: %s \n", argv[0]); - exit(1); + goto end; } - f = fopen(argv[1], "r"); - + fname = argv[1]; + f = fopen(fname, "r"); if (f == NULL) { - fprintf(stderr, "Cannot open file '%s'\n", argv[1]); - exit(1); + pr_err("Cannot open file '%s'\n", fname); + goto end; } - s = fread(&buf.cpio, sizeof(buf.cpio), 1, f); - if (s <= 0) { - fprintf(stderr, "Read error from file '%s'\n", argv[1]); - fclose(f); - exit(1); + if ((fread(&buf.cpio, sizeof(buf.cpio), 1, f) != 1) || + ferror(f)) { + pr_err("Read error from file '%s'\n", fname); + goto end; } - fseek(f, 0, SEEK_SET); - - /* check, if this is a cpio archive */ - if (memcmp(buf.cpio.h.c_magic, CPIO_MAGIC, 6) == 0) { - long pos = 0; + if (fseek(f, 0, SEEK_SET)) { + pr_err("fseek error on file '%s'\n", fname); + goto end; + } - unsigned long filesize; - unsigned long filename_length; + /* check, if this is a cpio archive */ + if (memcmp(buf.cpio.h.c_magic, CPIO_MAGIC, 6)) { + goto cat_rest; + } - do { - // zero string, spilling into next unused field, to use strtol - buf.cpio.h.c_chksum[0] = 0; - filename_length = strtoul(buf.cpio.h.c_namesize, NULL, 16); - pos = ALIGN_UP(pos + sizeof(struct cpio_header) + filename_length, CPIO_ALIGNMENT); - - // zero string, spilling into next unused field, to use strtol - buf.cpio.h.c_dev_maj[0] = 0; - filesize = strtoul(buf.cpio.h.c_filesize, NULL, 16); - pos = ALIGN_UP(pos + filesize, CPIO_ALIGNMENT); - - if (filename_length == (CPIO_ENDLEN + 1) - && strncmp(buf.cpio.filename, CPIO_END, CPIO_ENDLEN) == 0) { - fseek(f, pos, SEEK_SET); - break; + do { + // zero string, spilling into next unused field, to use strtol + buf.cpio.h.c_chksum[0] = 0; + filename_length = strtoul(buf.cpio.h.c_namesize, NULL, 16); + pos = ALIGN_UP(pos + sizeof(struct cpio_header) + filename_length, CPIO_ALIGNMENT); + + // zero string, spilling into next unused field, to use strtol + buf.cpio.h.c_dev_maj[0] = 0; + filesize = strtoul(buf.cpio.h.c_filesize, NULL, 16); + pos = ALIGN_UP(pos + filesize, CPIO_ALIGNMENT); + + if (filename_length == (CPIO_ENDLEN + 1) + && strncmp(buf.cpio.filename, CPIO_END, CPIO_ENDLEN) == 0) { + if (fseek(f, pos, SEEK_SET)) { + pr_err("fseek\n"); + goto end; } + break; + } - if (fseek(f, pos, SEEK_SET) != 0) { - perror("fseek"); - exit(1); - } + if (fseek(f, pos, SEEK_SET)) { + pr_err("fseek\n"); + goto end; + } - if (fread(&buf.cpio, sizeof(buf.cpio), 1, f) != 1) { - perror("fread"); - exit(1); - } + if ((fread(&buf.cpio, sizeof(buf.cpio), 1, f) != 1) || + ferror(f)) { + pr_err("fread\n"); + goto end; + } - if (memcmp(buf.cpio.h.c_magic, CPIO_MAGIC, 6) != 0) { - fprintf(stderr, "Corrupt CPIO archive!\n"); - exit(1); - } - } while (!feof(f)); + if (memcmp(buf.cpio.h.c_magic, CPIO_MAGIC, 6)) { + pr_err("Corrupt CPIO archive!\n"); + goto end; + } + } while (!feof(f)); - if (feof(f)) { - /* CPIO_END not found, just cat the whole file */ - fseek(f, 0, SEEK_SET); - } else { - /* skip zeros */ - do { - size_t i; + if (feof(f)) { + /* CPIO_END not found, just cat the whole file */ + if (fseek(f, 0, SEEK_SET)) { + pr_err("fseek\n"); + goto end; + } + } else { + /* skip zeros */ + do { + size_t i; - s = fread(buf.copy_buffer, 1, sizeof(buf.copy_buffer) - 1, f); - if (s <= 0) - break; + s = fread(buf.copy_buffer, 1, sizeof(buf.copy_buffer) - 1, f); + if (ferror(f)) { + pr_err("fread\n"); + goto end; + } - for (i = 0; (i < s) && (buf.copy_buffer[i] == 0); i++) ; + for (i = 0; (i < s) && (buf.copy_buffer[i] == 0); i++) ; - if (buf.copy_buffer[i] != 0) { - pos += i; + if (buf.copy_buffer[i]) { + pos += i; - fseek(f, pos, SEEK_SET); - break; + if (fseek(f, pos, SEEK_SET)) { + pr_err("fseek\n"); + goto end; } + break; + } - pos += s; - } while (!feof(f)); - } + pos += s; + } while (!feof(f)); } + +cat_rest: /* cat out the rest */ while (!feof(f)) { s = fread(buf.copy_buffer, 1, sizeof(buf.copy_buffer), f); - if (s <= 0) - break; + if (ferror(f)) { + pr_err("fread\n"); + goto end; + } - s = fwrite(buf.copy_buffer, 1, s, stdout); - if (s <= 0) - break; + if (fwrite(buf.copy_buffer, 1, s, stdout) != s) { + pr_err("fwrite\n"); + goto end; + } + } + + ret = EXIT_SUCCESS; + +end: + if (f) { + fclose(f); } - fclose(f); - return EXIT_SUCCESS; + return ret; }