From b0f1cc5e22e87a3ef1655643116991673dd1b531 Mon Sep 17 00:00:00 2001 From: Bill Richardson Date: Wed, 24 Sep 2014 00:23:56 -0700 Subject: futility: do traversal of a buffer, not a file We have been traversing things by passing a file descriptor. Now the caller should mmap the file first. This will allow the caller to determine the file type before traversing into it, so we can check args. BUG=none BRANCH=ToT TEST=make runtests Signed-off-by: Bill Richardson Change-Id: If69799bde0133689dc9fb5111e6ecb5ac61639c7 Reviewed-on: https://chromium-review.googlesource.com/219649 Reviewed-by: Randall Spangler --- futility/cmd_show.c | 15 ++++++++-- futility/cmd_sign.c | 12 +++++++- futility/traversal.c | 78 ++++++++++++++++++++++++++++++++++------------------ futility/traversal.h | 22 ++++++++++++--- 4 files changed, 93 insertions(+), 34 deletions(-) diff --git a/futility/cmd_show.c b/futility/cmd_show.c index 8f8ebb5c..9fc0a328 100644 --- a/futility/cmd_show.c +++ b/futility/cmd_show.c @@ -417,6 +417,8 @@ static int do_show(int argc, char *argv[]) int ifd, i; int errorcnt = 0; struct futil_traverse_state_s state; + uint8_t *buf; + uint32_t buf_len; opterr = 0; /* quiet, you */ while ((i = getopt_long(argc, argv, short_opts, long_opts, 0)) != -1) { @@ -473,15 +475,24 @@ static int do_show(int argc, char *argv[]) errorcnt++; fprintf(stderr, "Can't open %s: %s\n", infile, strerror(errno)); - return 1; + continue; + } + + if (0 != futil_map_file(ifd, MAP_RO, &buf, &buf_len)) { + errorcnt++; + goto boo; } memset(&state, 0, sizeof(state)); state.in_filename = infile ? infile : ""; state.op = FUTIL_OP_SHOW; - errorcnt += futil_traverse(ifd, &state, MAP_RO); + errorcnt += futil_traverse(buf, buf_len, &state, + FILE_TYPE_UNKNOWN); + + errorcnt += futil_unmap_file(ifd, MAP_RO, buf, buf_len); +boo: if (close(ifd)) { errorcnt++; fprintf(stderr, "Error when closing %s: %s\n", diff --git a/futility/cmd_sign.c b/futility/cmd_sign.c index a983a222..dd28aec4 100644 --- a/futility/cmd_sign.c +++ b/futility/cmd_sign.c @@ -330,6 +330,8 @@ static int do_sign(int argc, char *argv[]) int errorcnt = 0; struct futil_traverse_state_s state; char *e = 0; + uint8_t *buf; + uint32_t buf_len; opterr = 0; /* quiet, you */ while ((i = getopt_long(argc, argv, short_opts, long_opts, 0)) != -1) { @@ -465,12 +467,20 @@ static int do_sign(int argc, char *argv[]) return 1; } + if (0 != futil_map_file(fd, MAP_RW, &buf, &buf_len)) { + errorcnt++; + goto boo; + } + memset(&state, 0, sizeof(state)); state.in_filename = outfile ? outfile : ""; state.op = FUTIL_OP_SIGN; - errorcnt += futil_traverse(fd, &state, MAP_RW); + errorcnt += futil_traverse(buf, buf_len, &state, FILE_TYPE_UNKNOWN); + + errorcnt += futil_unmap_file(fd, MAP_RO, buf, buf_len); +boo: if (close(fd)) { errorcnt++; fprintf(stderr, "Error when closing %s: %s\n", diff --git a/futility/traversal.c b/futility/traversal.c index d7ecf201..b392fa97 100644 --- a/futility/traversal.c +++ b/futility/traversal.c @@ -191,7 +191,7 @@ static int invoke_callback(struct futil_traverse_state_s *state, return 0; } -static enum futil_file_type what_is_this(uint8_t *buf, uint32_t len) +enum futil_file_type futil_what_file_type_buf(uint8_t *buf, uint32_t len) { VbPublicKey *pubkey = (VbPublicKey *)buf; VbKeyBlockHeader *key_block = (VbKeyBlockHeader *)buf; @@ -243,16 +243,57 @@ static enum futil_file_type what_is_this(uint8_t *buf, uint32_t len) return FILE_TYPE_UNKNOWN; } -static int traverse_buffer(uint8_t *buf, uint32_t len, - struct futil_traverse_state_s *state) +enum futil_file_type futil_what_file_type(const char *filename) +{ + enum futil_file_type type; + int ifd; + uint8_t *buf; + uint32_t buf_len; + + ifd = open(filename, O_RDONLY); + if (ifd < 0) { + fprintf(stderr, "Can't open %s: %s\n", + filename, strerror(errno)); + exit(1); + } + + if (0 != futil_map_file(ifd, MAP_RO, &buf, &buf_len)) { + close(ifd); + exit(1); + } + + type = futil_what_file_type_buf(buf, buf_len); + + if (0 != futil_unmap_file(ifd, MAP_RO, buf, buf_len)) { + close(ifd); + exit(1); + } + + if (close(ifd)) { + fprintf(stderr, "Error when closing %s: %s\n", + filename, strerror(errno)); + exit(1); + } + + return type; +} + +int futil_traverse(uint8_t *buf, uint32_t len, + struct futil_traverse_state_s *state, + enum futil_file_type type) { FmapHeader *fmap; FmapAreaHeader *ah = 0; const struct bios_area_s *area; - enum futil_file_type type; int retval = 0; - type = what_is_this(buf, len); + if (state->op < 0 || state->op >= NUM_FUTIL_OPS) { + fprintf(stderr, "Invalid op %d\n", state->op); + return 1; + } + + if (type == FILE_TYPE_UNKNOWN) + type = futil_what_file_type_buf(buf, len); state->in_type = type; state->errors = retval; @@ -265,6 +306,9 @@ static int traverse_buffer(uint8_t *buf, uint32_t len, case FILE_TYPE_KEYBLOCK: case FILE_TYPE_FW_PREAMBLE: case FILE_TYPE_GBB: + case FILE_TYPE_KERN_PREAMBLE: + case FILE_TYPE_RAW_FIRMWARE: + case FILE_TYPE_RAW_KERNEL: retval |= invoke_callback(state, direct_callback[type].component, direct_callback[type].name, @@ -305,6 +349,8 @@ static int traverse_buffer(uint8_t *buf, uint32_t len, break; default: + Debug("%s:%d unhandled type %s\n", __FILE__, __LINE__, + futil_file_type_str[type]); retval = 1; } @@ -312,25 +358,3 @@ static int traverse_buffer(uint8_t *buf, uint32_t len, 0, buf, len); return retval; } - -int futil_traverse(int ifd, struct futil_traverse_state_s *state, - int writeable) -{ - uint8_t *mmap_ptr = 0; - uint32_t len; - int errorcnt = 0; - - if (state->op < 0 || state->op >= NUM_FUTIL_OPS) { - fprintf(stderr, "Invalid op %d\n", state->op); - return 1; - } - - if (0 != futil_map_file(ifd, writeable, &mmap_ptr, &len)) - return 1; - - errorcnt |= traverse_buffer(mmap_ptr, len, state); - - errorcnt |= futil_unmap_file(ifd, writeable, mmap_ptr, len); - - return errorcnt; -} diff --git a/futility/traversal.h b/futility/traversal.h index 74c88f5d..531ad6aa 100644 --- a/futility/traversal.h +++ b/futility/traversal.h @@ -89,12 +89,26 @@ struct futil_traverse_state_s { int errors; }; + +/* + * This tries to match the buffer content to one of the known file types. + */ +enum futil_file_type futil_what_file_type_buf(uint8_t *buf, uint32_t len); + +/* + * This opens a file and tries to match it to one of the known file types. It + * fails only if it can't open and scan the file. It's not an error if it + * returns FILE_TYPE_UKNOWN. + */ +enum futil_file_type futil_what_file_type(const char *filename); + /* - * Traverse the input file using the provided state - * Return nonzero (but no details) if there were any errors. + * Traverse the buffer using the provided state, which should be initialized + * before calling. Returns nonzero (but no details) if there were any errors. */ -int futil_traverse(int ifd, struct futil_traverse_state_s *state, - int writeable); +int futil_traverse(uint8_t *buf, uint32_t len, + struct futil_traverse_state_s *state, + enum futil_file_type type_hint); /* These are invoked by the traversal. They also return nonzero on error. */ int futil_cb_show_begin(struct futil_traverse_state_s *state); -- cgit v1.2.1