[PATCH 1/3] erofs-utils: fsck: fix unsigned integer overflow in symlink extraction

Gao Xiang <[email protected]>
Newsgroups org.ozlabs.lists.linux-erofs
Message-ID <[email protected]>
erofs_extract_symlink() allocates a buffer using malloc(i_size + 1)
where i_size is a 64-bit value read directly from the on-disk inode
with no upper bound validation. When i_size equals UINT64_MAX, the
addition wraps to zero, and malloc(0) returns a minimal allocation.
The subsequent erofs_pread() writes i_size bytes into this tiny
buffer.

Reported-by: Tristan <[email protected]>
Closes: https://lore.kernel.org/r/CAA1XrhPMekMqAnRkC-jV9rTsO4LHjzh=kxn6zQKMgBrqfrnp8A@mail.gmail.com/5-symlink-integer-overflow.txt
Signed-off-by: Gao Xiang <[email protected]>
---
 fsck/main.c          | 5 +++--
 include/erofs/defs.h | 9 +++++++++
 2 files changed, 12 insertions(+), 2 deletions(-)

diff --git a/fsck/main.c b/fsck/main.c
index 21ada195edab..f7f1387fe642 100644
--- a/fsck/main.c
+++ b/fsck/main.c
@@ -784,6 +784,7 @@ static inline int erofs_extract_symlink(struct erofs_inode *inode)
 {
 	struct erofs_vfile vf;
 	bool tryagain = true;
+	erofs_off_t bufsz;
 	int ret;
 	char *buf = NULL;
 
@@ -794,8 +795,8 @@ static inline int erofs_extract_symlink(struct erofs_inode *inode)
 	if (ret)
 		return ret;
 
-	buf = malloc(inode->i_size + 1);
-	if (!buf) {
+	if (check_add_overflow(inode->i_size, (erofs_off_t)1, &bufsz) ||
+	    (buf = malloc(bufsz))) {
 		ret = -ENOMEM;
 		goto out;
 	}
diff --git a/include/erofs/defs.h b/include/erofs/defs.h
index 8151b76ad0f5..fabd867d159c 100644
--- a/include/erofs/defs.h
+++ b/include/erofs/defs.h
@@ -392,6 +392,15 @@ unsigned long __roundup_pow_of_two(unsigned long n)
 #define __erofs_stringify_1(x...)	#x
 #define __erofs_stringify(x...)		__erofs_stringify_1(x)
 
+#define check_add_overflow(a, b, d) ({		\
+	typeof(a) __a = (a);			\
+	typeof(b) __b = (b);			\
+	typeof(d) __d = (d);			\
+	(void) (&__a == &__b);			\
+	(void) (&__a == __d);			\
+	__builtin_add_overflow(__a, __b, __d);	\
+})
+
 #define check_sub_overflow(a, b, d) ({		\
 	typeof(a) __a = (a);			\
 	typeof(b) __b = (b);			\
-- 
2.43.5
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.