aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid Oberhollenzer <david.oberhollenzer@sigma-star.at>2021-06-24 16:04:57 +0200
committerDavid Oberhollenzer <david.oberhollenzer@sigma-star.at>2021-06-25 15:12:41 +0200
commitb409ddcec8c7ae304a7985e450b723fbb95cf4e9 (patch)
treef5709ed75336cb8fd4ee553c5a0f30425829d12b
parente567e9c5df1b0b9781d9e2a625c22302005cd95e (diff)
libfstree: guard against possible overflow in readlink()
*in theory*, say on a 32 bit system, we could have a 32 bit size_t and a 64 bit off_t. If the filesystem permitted this, we *could* then have a symlink with a target > 4G. Or the target is exacetely 4G, but adding a null-terminator could exceed addressable memory. This commit adds a check to guard against such an overflow and throw an error, instead of silently wrapping around. Signed-off-by: David Oberhollenzer <david.oberhollenzer@sigma-star.at>
-rw-r--r--lib/fstree/fstree_from_dir.c17
1 files changed, 15 insertions, 2 deletions
diff --git a/lib/fstree/fstree_from_dir.c b/lib/fstree/fstree_from_dir.c
index 9f8e3ba..e0ea600 100644
--- a/lib/fstree/fstree_from_dir.c
+++ b/lib/fstree/fstree_from_dir.c
@@ -358,12 +358,25 @@ static int populate_dir(int dir_fd, fstree_t *fs, tree_node_t *root,
continue;
if (S_ISLNK(sb.st_mode)) {
- extra = calloc(1, sb.st_size + 1);
+ size_t size;
+
+ if ((sizeof(sb.st_size) > sizeof(size_t)) &&
+ sb.st_size > SIZE_MAX) {
+ errno = EOVERFLOW;
+ goto fail_rdlink;
+ }
+
+ if (SZ_ADD_OV((size_t)sb.st_size, 1, &size)) {
+ errno = EOVERFLOW;
+ goto fail_rdlink;
+ }
+
+ extra = calloc(1, size);
if (extra == NULL)
goto fail_rdlink;
if (readlinkat(dir_fd, ent->d_name,
- extra, sb.st_size) < 0) {
+ extra, (size_t)sb.st_size) < 0) {
goto fail_rdlink;
}