From 1423c95eb62afcad29c6a1946de63e5b6a1e804a Mon Sep 17 00:00:00 2001 From: Ariadne Conill Date: Fri, 2 Apr 2021 13:22:14 -0600 Subject: [PATCH] archive: more strictly validate tarball headers --- src/archive.c | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/src/archive.c b/src/archive.c index 81821dc..80677d0 100644 --- a/src/archive.c +++ b/src/archive.c @@ -60,6 +60,7 @@ struct apk_tar_digest_info { #define GET_OCTAL(s) get_octal(s, sizeof(s)) #define PUT_OCTAL(s,v) put_octal(s, sizeof(s), v) +#define HAS_NULLTERM(a) memchr(a, '\0', sizeof(a)) static unsigned int get_octal(char *s, size_t l) { @@ -193,6 +194,27 @@ static void handle_extended_header(struct apk_file_info *fi, apk_blob_t hdr) } } +static int validate_tar_header(struct tar_header *buf) +{ + /* Ensure that fields which should be null-terminated + * are null-terminated to use string functions on them. */ + if (!HAS_NULLTERM(buf->uname) || !HAS_NULLTERM(buf->gname) || + !HAS_NULLTERM(buf->linkname) || !HAS_NULLTERM(buf->magic) || + !HAS_NULLTERM(buf->name) || !HAS_NULLTERM(buf->prefix)) { + return FALSE; + } + + /* Validate the typeflag field. */ + if (!strchr("KLgx01234567", buf->typeflag)) + return FALSE; + + /* Validate the size field. */ + if (GET_OCTAL(buf->size) >= SSIZE_MAX - 512) + return FALSE; + + return TRUE; +} + int apk_tar_parse(struct apk_istream *is, apk_archive_entry_parser parser, void *ctx, int soft_checksums, struct apk_id_cache *idc) { @@ -216,7 +238,12 @@ int apk_tar_parse(struct apk_istream *is, apk_archive_entry_parser parser, memset(&entry, 0, sizeof(entry)); entry.name = buf.name; while ((r = apk_istream_read(is, &buf, 512)) == 512) { + if (!validate_tar_header(&buf)) { + goto err; + } + offset += 512; + if (buf.name[0] == '\0') { if (end) break; end++; -- 2.31.0