From: Tobias Stoeckmann Date: Wed, 18 Feb 2026 17:04:54 +0000 (+0100) Subject: lib/fileeq: Prevent OOB with short read files X-Git-Tag: v2.43-devel~57^2 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=3dad59c05c97d7515053bc0726e5392e0ffb63b8;p=thirdparty%2Futil-linux.git lib/fileeq: Prevent OOB with short read files Using the Linux Crypto API stores hash sums of read chunks in memory. It trusts that get_digest is called as often as "read blocks" exist in file. It becomes an issue with files which have less content than st_size suggests, e.g. files in sysfs. Eventually, the iterator n will be eq->blocksmax, because the EOF is never noticed. Writing this next hash sum into memory would lead to an out of boundary write. Verify that n is less than eq->blocksmax. If this is not true anymore, treat it as an error so files are considered to be not equal. This is much safer than erroneously treating them as equal. Signed-off-by: Tobias Stoeckmann --- diff --git a/lib/fileeq.c b/lib/fileeq.c index 762619563..67c5c747d 100644 --- a/lib/fileeq.c +++ b/lib/fileeq.c @@ -367,9 +367,12 @@ static ssize_t read_block(struct ul_fileeq *eq, struct ul_fileeq_data *data, off_t off = 0; ssize_t rsz; - if (data->is_eof || n > eq->blocksmax) + if (data->is_eof) return 0; + if (n >= eq->blocksmax) + return -EINVAL; + fd = get_fd(eq, data, &off); if (fd < 0) return fd; @@ -406,9 +409,6 @@ static ssize_t get_digest(struct ul_fileeq *eq, struct ul_fileeq_data *data, size_t sz; int fd; - if (n > eq->blocksmax) - return 0; - /* return already cached if available */ if (n < get_cached_nblocks(data)) { DBG(DATA, ul_debugobj(data, " digest cached")); @@ -422,6 +422,9 @@ static ssize_t get_digest(struct ul_fileeq *eq, struct ul_fileeq_data *data, return 0; } + if (n >= eq->blocksmax) + return -EINVAL; + /* read new block */ fd = get_fd(eq, data, &off); if (fd < 0) @@ -438,8 +441,6 @@ static ssize_t get_digest(struct ul_fileeq *eq, struct ul_fileeq_data *data, return -ENOMEM; } - assert(n <= eq->blocksmax); - rsz = sendfile(eq->fd_cip, data->fd, NULL, eq->readsiz); DBG(DATA, ul_debugobj(data, " sent %zu [%zu wanted] to cipher", rsz, eq->readsiz));