From: Stefan Kerkmann <s.kerkmann@pengutronix.de>
To: Sascha Hauer <s.hauer@pengutronix.de>,
"open list:BAREBOX" <barebox@lists.infradead.org>
Cc: Stefan Kerkmann <s.kerkmann@pengutronix.de>
Subject: [PATCH 1/2] fs: __read: fix EOF count clamping for negative file sizes
Date: Thu, 03 Sep 2026 18:29:13 +0200 [thread overview]
Message-ID: <20260903-fix-fs_read_write_eof_checks-v1-1-7afd44db1793@pengutronix.de> (raw)
In-Reply-To: <20260903-fix-fs_read_write_eof_checks-v1-0-7afd44db1793@pengutronix.de>
__read() clamps count to the bytes remaining until EOF, but compared
the signed 64-bit f->f_pos/f->f_size (loff_t) against count (size_t),
which is 32-bit on 32-bit arches and 64-bit on 64-bit arches.
This made the comparison type targent dependent, breaking it for
negative file sizes except for the FILE_SIZE_STREAM sentinel.
- On 32-bit arches count is converted to the signed 64-bit type of
f->f_pos, so for e.g. f->f_size = -512 the comparison f->f_pos + count
> f->f_size evaluated true. The clamp then assigned the negative
difference of f->f_size - f->f_pos to the unsigned count, wrapping it
to a value near 2^32 and turning a small read into a huge out of
bounds read request.
- On 64-bit arches size_t cannot be represented by signed 64-bit, so the
arithmetic C conversions turned the whole comparison unsigned:
f->f_size = -512 was reinterpreted as a value near 2^64, the
comparison stayed false and the clamp never ran, leaving count
unclamped and the bogus size undetected.
__read() now rejects negative file sizes (except for the
FILE_SIZE_STREAM sentinel) with -EINVAL. Reads at or past the end of the
file (reachable via pread() with an offset beyond EOF) now return 0.
Remaining reads are clamped to the bytes left until EOF.
Signed-off-by: Stefan Kerkmann <s.kerkmann@pengutronix.de>
---
fs/fs.c | 12 ++++++++++--
1 file changed, 10 insertions(+), 2 deletions(-)
diff --git a/fs/fs.c b/fs/fs.c
index dc6c30802d..a8f2b78294 100644
--- a/fs/fs.c
+++ b/fs/fs.c
@@ -427,8 +427,16 @@ static ssize_t __read(struct file *f, void *buf, size_t count)
if (fsdrv != ramfs_driver)
assert_command_context();
- if (f->f_size != FILE_SIZE_STREAM && f->f_pos + count > f->f_size)
- count = f->f_size - f->f_pos;
+ if (f->f_size != FILE_SIZE_STREAM) {
+ if (f->f_size < 0) {
+ ret = -EINVAL;
+ goto out;
+ }
+ if (f->f_pos > f->f_size)
+ count = 0;
+ else
+ count = min_t(u64, (u64)f->f_size - (u64)f->f_pos, count);
+ }
if (!count)
return 0;
--
2.47.3
next prev parent reply other threads:[~2026-09-03 16:31 UTC|newest]
Thread overview: 4+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-09-03 16:29 [PATCH 0/2] fs: __read/__write: fix EOF checks " Stefan Kerkmann
2026-09-03 16:29 ` Stefan Kerkmann [this message]
2026-09-04 9:20 ` [PATCH 1/2] fs: __read: fix EOF count clamping " Sascha Hauer
2026-09-03 16:29 ` [PATCH 2/2] fs: __write: fix EOF growth checks " Stefan Kerkmann
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20260903-fix-fs_read_write_eof_checks-v1-1-7afd44db1793@pengutronix.de \
--to=s.kerkmann@pengutronix.de \
--cc=barebox@lists.infradead.org \
--cc=s.hauer@pengutronix.de \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox