From a0745dce6bf173eb72bbaa174d0bf3e172ebb7f5 Mon Sep 17 00:00:00 2001 From: Kai Kang Date: Thu, 18 Nov 2021 09:53:36 +0800 Subject: squashfs-tools: fix CVE-2021-41072 Backport patches to fix CVE-2021-41072. And update context for verison 4.4 at same time. CVE: CVE-2021-41072 Ref: * https://nvd.nist.gov/vuln/detail/CVE-2021-41072 (From OE-Core rev: e95ccf6f7fe5a42fffcfa5e43087ff964622e26c) Signed-off-by: Kai Kang Signed-off-by: Anuj Mittal Signed-off-by: Richard Purdie --- .../files/CVE-2021-41072-requisite-3.patch | 330 +++++++++++++++++++++ 1 file changed, 330 insertions(+) create mode 100644 meta/recipes-devtools/squashfs-tools/files/CVE-2021-41072-requisite-3.patch (limited to 'meta/recipes-devtools/squashfs-tools/files/CVE-2021-41072-requisite-3.patch') diff --git a/meta/recipes-devtools/squashfs-tools/files/CVE-2021-41072-requisite-3.patch b/meta/recipes-devtools/squashfs-tools/files/CVE-2021-41072-requisite-3.patch new file mode 100644 index 0000000000..fad5898f13 --- /dev/null +++ b/meta/recipes-devtools/squashfs-tools/files/CVE-2021-41072-requisite-3.patch @@ -0,0 +1,330 @@ +The commit is required by the fix for CVE-2021-41072. Update context for +version 4.4. + +Upstream-Status: Backport [https://github.com/plougher/squashfs-tools/commit/9938154] + +Signed-off-by: Kai Kang + +From 9938154174756ee48a94ea0b076397a2944b028d Mon Sep 17 00:00:00 2001 +From: Phillip Lougher +Date: Sun, 12 Sep 2021 22:58:11 +0100 +Subject: [PATCH] unsquashfs: use linked list to store directory names + +This should bring higher performance, and it allows sorting +if necessary (1.x and 2.0 filesystems). + +Signed-off-by: Phillip Lougher +--- + squashfs-tools/unsquash-1.c | 30 +++++++++++++++--------------- + squashfs-tools/unsquash-1234.c | 12 ++++++++---- + squashfs-tools/unsquash-2.c | 29 +++++++++++++++-------------- + squashfs-tools/unsquash-3.c | 29 +++++++++++++++-------------- + squashfs-tools/unsquash-4.c | 29 +++++++++++++++-------------- + squashfs-tools/unsquashfs.c | 16 ++++++++++------ + squashfs-tools/unsquashfs.h | 3 ++- + 7 files changed, 80 insertions(+), 68 deletions(-) + +diff --git a/squashfs-tools/unsquash-1.c b/squashfs-tools/unsquash-1.c +index d0121c6..b604434 100644 +--- a/squashfs-tools/unsquash-1.c ++++ b/squashfs-tools/unsquash-1.c +@@ -207,7 +207,7 @@ static struct dir *squashfs_opendir(unsi + long long start; + int bytes; + int dir_count, size; +- struct dir_ent *new_dir; ++ struct dir_ent *ent, *cur_ent = NULL; + struct dir *dir; + + TRACE("squashfs_opendir: inode start block %d, offset %d\n", +@@ -220,7 +220,7 @@ static struct dir *squashfs_opendir(unsi + EXIT_UNSQUASH("squashfs_opendir: malloc failed!\n"); + + dir->dir_count = 0; +- dir->cur_entry = 0; ++ dir->cur_entry = NULL; + dir->mode = (*i)->mode; + dir->uid = (*i)->uid; + dir->guid = (*i)->gid; +@@ -295,19 +295,20 @@ static struct dir *squashfs_opendir(unsi + TRACE("squashfs_opendir: directory entry %s, inode " + "%d:%d, type %d\n", dire->name, + dirh.start_block, dire->offset, dire->type); +- if((dir->dir_count % DIR_ENT_SIZE) == 0) { +- new_dir = realloc(dir->dirs, (dir->dir_count + +- DIR_ENT_SIZE) * sizeof(struct dir_ent)); +- if(new_dir == NULL) +- EXIT_UNSQUASH("squashfs_opendir: " +- "realloc failed!\n"); +- dir->dirs = new_dir; +- } +- dir->dirs[dir->dir_count].name = strdup(dire->name); +- dir->dirs[dir->dir_count].start_block = +- dirh.start_block; +- dir->dirs[dir->dir_count].offset = dire->offset; +- dir->dirs[dir->dir_count].type = dire->type; ++ ent = malloc(sizeof(struct dir_ent)); ++ if(ent == NULL) ++ MEM_ERROR(); ++ ++ ent->name = strdup(dire->name); ++ ent->start_block = dirh.start_block; ++ ent->offset = dire->offset; ++ ent->type = dire->type; ++ ent->next = NULL; ++ if(cur_ent == NULL) ++ dir->dirs = ent; ++ else ++ cur_ent->next = ent; ++ cur_ent = ent; + dir->dir_count ++; + bytes += dire->size + 1; + } +diff --git a/squashfs-tools/unsquash-1234.c b/squashfs-tools/unsquash-1234.c +index ac46d9d..e389f8d 100644 +--- a/squashfs-tools/unsquash-1234.c ++++ b/squashfs-tools/unsquash-1234.c +@@ -60,11 +60,15 @@ int check_name(char *name, int size) + + void squashfs_closedir(struct dir *dir) + { +- int i; ++ struct dir_ent *ent = dir->dirs; + +- for(i = 0; i < dir->dir_count; i++) +- free(dir->dirs[i].name); ++ while(ent) { ++ struct dir_ent *tmp = ent; ++ ++ ent = ent->next; ++ free(tmp->name); ++ free(tmp); ++ } + +- free(dir->dirs); + free(dir); + } +diff --git a/squashfs-tools/unsquash-2.c b/squashfs-tools/unsquash-2.c +index e847980..956f96f 100644 +--- a/squashfs-tools/unsquash-2.c ++++ b/squashfs-tools/unsquash-2.c +@@ -308,7 +308,7 @@ static struct dir *squashfs_opendir(unsi + long long start; + int bytes; + int dir_count, size; +- struct dir_ent *new_dir; ++ struct dir_ent *ent, *cur_ent = NULL; + struct dir *dir; + + TRACE("squashfs_opendir: inode start block %d, offset %d\n", +@@ -321,7 +321,7 @@ static struct dir *squashfs_opendir(unsi + EXIT_UNSQUASH("squashfs_opendir: malloc failed!\n"); + + dir->dir_count = 0; +- dir->cur_entry = 0; ++ dir->cur_entry = NULL; + dir->mode = (*i)->mode; + dir->uid = (*i)->uid; + dir->guid = (*i)->gid; +@@ -396,19 +396,20 @@ static struct dir *squashfs_opendir(unsi + TRACE("squashfs_opendir: directory entry %s, inode " + "%d:%d, type %d\n", dire->name, + dirh.start_block, dire->offset, dire->type); +- if((dir->dir_count % DIR_ENT_SIZE) == 0) { +- new_dir = realloc(dir->dirs, (dir->dir_count + +- DIR_ENT_SIZE) * sizeof(struct dir_ent)); +- if(new_dir == NULL) +- EXIT_UNSQUASH("squashfs_opendir: " +- "realloc failed!\n"); +- dir->dirs = new_dir; +- } +- dir->dirs[dir->dir_count].name = strdup(dire->name); +- dir->dirs[dir->dir_count].start_block = +- dirh.start_block; +- dir->dirs[dir->dir_count].offset = dire->offset; +- dir->dirs[dir->dir_count].type = dire->type; ++ ent = malloc(sizeof(struct dir_ent)); ++ if(ent == NULL) ++ MEM_ERROR(); ++ ++ ent->name = strdup(dire->name); ++ ent->start_block = dirh.start_block; ++ ent->offset = dire->offset; ++ ent->type = dire->type; ++ ent->next = NULL; ++ if(cur_ent == NULL) ++ dir->dirs = ent; ++ else ++ cur_ent->next = ent; ++ cur_ent = ent; + dir->dir_count ++; + bytes += dire->size + 1; + } +diff --git a/squashfs-tools/unsquash-3.c b/squashfs-tools/unsquash-3.c +index 8223f27..835a574 100644 +--- a/squashfs-tools/unsquash-3.c ++++ b/squashfs-tools/unsquash-3.c +@@ -334,7 +334,7 @@ static struct dir *squashfs_opendir(unsi + long long start; + int bytes; + int dir_count, size; +- struct dir_ent *new_dir; ++ struct dir_ent *ent, *cur_ent = NULL; + struct dir *dir; + + TRACE("squashfs_opendir: inode start block %d, offset %d\n", +@@ -347,7 +347,7 @@ static struct dir *squashfs_opendir(unsi + EXIT_UNSQUASH("squashfs_opendir: malloc failed!\n"); + + dir->dir_count = 0; +- dir->cur_entry = 0; ++ dir->cur_entry = NULL; + dir->mode = (*i)->mode; + dir->uid = (*i)->uid; + dir->guid = (*i)->gid; +@@ -423,19 +423,20 @@ static struct dir *squashfs_opendir(unsi + TRACE("squashfs_opendir: directory entry %s, inode " + "%d:%d, type %d\n", dire->name, + dirh.start_block, dire->offset, dire->type); +- if((dir->dir_count % DIR_ENT_SIZE) == 0) { +- new_dir = realloc(dir->dirs, (dir->dir_count + +- DIR_ENT_SIZE) * sizeof(struct dir_ent)); +- if(new_dir == NULL) +- EXIT_UNSQUASH("squashfs_opendir: " +- "realloc failed!\n"); +- dir->dirs = new_dir; +- } +- dir->dirs[dir->dir_count].name = strdup(dire->name); +- dir->dirs[dir->dir_count].start_block = +- dirh.start_block; +- dir->dirs[dir->dir_count].offset = dire->offset; +- dir->dirs[dir->dir_count].type = dire->type; ++ ent = malloc(sizeof(struct dir_ent)); ++ if(ent == NULL) ++ MEM_ERROR(); ++ ++ ent->name = strdup(dire->name); ++ ent->start_block = dirh.start_block; ++ ent->offset = dire->offset; ++ ent->type = dire->type; ++ ent->next = NULL; ++ if(cur_ent == NULL) ++ dir->dirs = ent; ++ else ++ cur_ent->next = ent; ++ cur_ent = ent; + dir->dir_count ++; + bytes += dire->size + 1; + } +diff --git a/squashfs-tools/unsquash-4.c b/squashfs-tools/unsquash-4.c +index 1e199a7..694783d 100644 +--- a/squashfs-tools/unsquash-4.c ++++ b/squashfs-tools/unsquash-4.c +@@ -281,7 +281,7 @@ static struct dir *squashfs_opendir(unsi + long long start; + long long bytes; + int dir_count, size; +- struct dir_ent *new_dir; ++ struct dir_ent *ent, *cur_ent = NULL; + struct dir *dir; + + TRACE("squashfs_opendir: inode start block %d, offset %d\n", +@@ -294,7 +294,7 @@ static struct dir *squashfs_opendir(unsi + EXIT_UNSQUASH("squashfs_opendir: malloc failed!\n"); + + dir->dir_count = 0; +- dir->cur_entry = 0; ++ dir->cur_entry = NULL; + dir->mode = (*i)->mode; + dir->uid = (*i)->uid; + dir->guid = (*i)->gid; +@@ -359,19 +359,20 @@ static struct dir *squashfs_opendir(unsi + TRACE("squashfs_opendir: directory entry %s, inode " + "%d:%d, type %d\n", dire->name, + dirh.start_block, dire->offset, dire->type); +- if((dir->dir_count % DIR_ENT_SIZE) == 0) { +- new_dir = realloc(dir->dirs, (dir->dir_count + +- DIR_ENT_SIZE) * sizeof(struct dir_ent)); +- if(new_dir == NULL) +- EXIT_UNSQUASH("squashfs_opendir: " +- "realloc failed!\n"); +- dir->dirs = new_dir; +- } +- dir->dirs[dir->dir_count].name = strdup(dire->name); +- dir->dirs[dir->dir_count].start_block = +- dirh.start_block; +- dir->dirs[dir->dir_count].offset = dire->offset; +- dir->dirs[dir->dir_count].type = dire->type; ++ ent = malloc(sizeof(struct dir_ent)); ++ if(ent == NULL) ++ MEM_ERROR(); ++ ++ ent->name = strdup(dire->name); ++ ent->start_block = dirh.start_block; ++ ent->offset = dire->offset; ++ ent->type = dire->type; ++ ent->next = NULL; ++ if(cur_ent == NULL) ++ dir->dirs = ent; ++ else ++ cur_ent->next = ent; ++ cur_ent = ent; + dir->dir_count ++; + bytes += dire->size + 1; + } +diff --git a/squashfs-tools/unsquashfs.c b/squashfs-tools/unsquashfs.c +index 04be53c..fee28ec 100644 +--- a/squashfs-tools/unsquashfs.c ++++ b/squashfs-tools/unsquashfs.c +@@ -1277,14 +1277,18 @@ failed: + int squashfs_readdir(struct dir *dir, char **name, unsigned int *start_block, + unsigned int *offset, unsigned int *type) + { +- if(dir->cur_entry == dir->dir_count) ++ if(dir->cur_entry == NULL) ++ dir->cur_entry = dir->dirs; ++ else ++ dir->cur_entry = dir->cur_entry->next; ++ ++ if(dir->cur_entry == NULL) + return FALSE; + +- *name = dir->dirs[dir->cur_entry].name; +- *start_block = dir->dirs[dir->cur_entry].start_block; +- *offset = dir->dirs[dir->cur_entry].offset; +- *type = dir->dirs[dir->cur_entry].type; +- dir->cur_entry ++; ++ *name = dir->cur_entry->name; ++ *start_block = dir->cur_entry->start_block; ++ *offset = dir->cur_entry->offset; ++ *type = dir->cur_entry->type; + + return TRUE; + } +diff --git a/squashfs-tools/unsquashfs.h b/squashfs-tools/unsquashfs.h +index 583fbe4..f8cf78c 100644 +--- a/squashfs-tools/unsquashfs.h ++++ b/squashfs-tools/unsquashfs.h +@@ -169,17 +169,18 @@ struct dir_ent { + unsigned int start_block; + unsigned int offset; + unsigned int type; ++ struct dir_ent *next; + }; + + struct dir { + int dir_count; +- int cur_entry; + unsigned int mode; + uid_t uid; + gid_t guid; + unsigned int mtime; + unsigned int xattr; + struct dir_ent *dirs; ++ struct dir_ent *cur_entry; + }; + + struct file_entry { +-- +2.17.1 + -- cgit v1.2.3-54-g00ecf