Linux-EROFS Archive on lore.kernel.org
 help / color / mirror / Atom feed
From: Yifan Zhao <stopire@gmail.com>
To: linux-erofs@lists.ozlabs.org
Cc: Yifan Zhao <stopire@gmail.com>
Subject: [PATCH 8/8] erofs-utils: fix read error and short read handling
Date: Thu, 12 Nov 2026 20:47:25 +0800	[thread overview]
Message-ID: <20261112124725.2774244-9-stopire@gmail.com> (raw)
In-Reply-To: <20261112124725.2774244-1-stopire@gmail.com>

Several erofs_io_read() and erofs_io_pread() callers mishandle negative
errors or unexpected short reads, potentially reporting success or
looping at EOF.

Propagate negative errors, reject unexpected short reads and premature
EOF, and preserve the result reported by the ublk handler.

Also cap OCI blob copies at the requested length.

Assisted-by: Codex:gpt-6-astra
Assisted-by: Claude Code:deepseek-v4.1-flash-1017
Signed-off-by: Yifan Zhao <stopire@gmail.com>
---
 lib/backends/fanotify.c |  3 ++-
 lib/backends/nbd.c      |  2 ++
 lib/backends/ublk.c     |  2 +-
 lib/compress.c          |  2 +-
 lib/fragments.c         |  2 +-
 lib/inode.c             | 11 +++++------
 lib/remotes/oci.c       |  1 +
 lib/super.c             |  2 +-
 mount/main.c            | 10 +++++-----
 9 files changed, 19 insertions(+), 16 deletions(-)

diff --git a/lib/backends/fanotify.c b/lib/backends/fanotify.c
index cf8b616..898ea84 100644
--- a/lib/backends/fanotify.c
+++ b/lib/backends/fanotify.c
@@ -169,7 +169,8 @@ static int erofs_fanotify_handle_range(struct erofs_fanotify_ctx *ctx,
 		  (unsigned long long)(offset + length));
 
 	read_len = erofs_io_pread(&ctx->vd, ctx->fetch_buf, length, offset);
-	if (read_len < 0) {
+	if (read_len != length) {
+		read_len = read_len < 0 ? read_len : -EIO;
 		erofs_err("Failed to fetch range [%llu, %llu): %s",
 			  (unsigned long long)offset,
 			  (unsigned long long)(offset + length),
diff --git a/lib/backends/nbd.c b/lib/backends/nbd.c
index db0df44..81506b1 100644
--- a/lib/backends/nbd.c
+++ b/lib/backends/nbd.c
@@ -600,6 +600,8 @@ int erofs_nbd_get_request(int skfd, struct erofs_nbd_request *rq)
 	int err;
 
 	err = erofs_io_read(&vf, rq, sizeof(*rq));
+	if (err < 0)
+		return err;
 	if (err < sizeof(*rq))
 		return -EPIPE;
 
diff --git a/lib/backends/ublk.c b/lib/backends/ublk.c
index d2c5e19..7fa88d9 100644
--- a/lib/backends/ublk.c
+++ b/lib/backends/ublk.c
@@ -630,7 +630,7 @@ static int ublk_handle_io(struct erofs_ublk_queue *q, int tag)
 		if (ret < 0)
 			io->result = ret;
 		else
-			io->result = req.nr_sectors << 9;
+			io->result = req.result;
 	} else {
 		io->result = -EOPNOTSUPP;
 	}
diff --git a/lib/compress.c b/lib/compress.c
index b5f75ca..e764e44 100644
--- a/lib/compress.c
+++ b/lib/compress.c
@@ -1386,7 +1386,7 @@ int z_erofs_compress_segment(struct z_erofs_compress_sctx *ctx,
 			erofs_io_pread(vf, ctx->queue + ctx->tail, rx,
 				       ictx->fpos + offset));
 		if (ret != rx)
-			return -errno;
+			return ret < 0 ? ret : -EIO;
 
 		ctx->remaining -= rx;
 		ctx->tail += rx;
diff --git a/lib/fragments.c b/lib/fragments.c
index 3398888..2313daf 100644
--- a/lib/fragments.c
+++ b/lib/fragments.c
@@ -148,7 +148,7 @@ int erofs_fragment_findmatch(struct erofs_inode *inode,
 	ret = erofs_io_pread(vf, data, s1, fpos + inode->i_size - s1);
 	if (ret != s1) {
 		free(data);
-		return -errno;
+		return ret < 0 ? ret : -EIO;
 	}
 	e1 = s1 - EROFS_TOF_HASHLEN;
 	deduped = 0;
diff --git a/lib/inode.c b/lib/inode.c
index f687857..c9f8dd6 100644
--- a/lib/inode.c
+++ b/lib/inode.c
@@ -2024,18 +2024,17 @@ static int erofs_set_inode_fingerprint(struct erofs_inode *inode, int fd,
 	if (!ishare_xattr_prefix_id)
 		return 0;
 	erofs_sha256_init(&md);
-	do {
+	while (remaining) {
 		u8 buf[32768];
 
 		ret = erofs_io_pread(&vf, buf,
 				     min_t(u64, remaining, sizeof(buf)), pos);
-		if (ret < 0)
-			return ret;
-		if (ret > 0)
-			erofs_sha256_process(&md, buf, ret);
+		if (ret <= 0)
+			return ret < 0 ? ret : -EIO;
+		erofs_sha256_process(&md, buf, ret);
 		remaining -= ret;
 		pos += ret;
-	} while (remaining);
+	}
 	erofs_sha256_done(&md, out + sizeof("sha256:") - 1);
 #if defined(_WIN32) && !defined(__CYGWIN__)
 	ret = erofs_io_lseek(&vf, pos - inode->i_size, SEEK_SET);
diff --git a/lib/remotes/oci.c b/lib/remotes/oci.c
index 948d699..3e86e91 100644
--- a/lib/remotes/oci.c
+++ b/lib/remotes/oci.c
@@ -1491,6 +1491,7 @@ static ssize_t ocierofs_io_pread(struct erofs_vfile *vf, void *buf, size_t len,
 		return ret;
 
 	if (download_buf && download_size > 0) {
+		download_size = min_t(size_t, download_size, len);
 		memcpy(buf, download_buf, download_size);
 		free(download_buf);
 		return download_size;
diff --git a/lib/super.c b/lib/super.c
index 694a3e9..c6a9230 100644
--- a/lib/super.c
+++ b/lib/super.c
@@ -89,7 +89,7 @@ int erofs_read_superblock(struct erofs_sb_info *sbi)
 		return 0;
 
 	read = erofs_io_pread(&sbi->bdev, data, EROFS_MAX_BLOCK_SIZE, 0);
-	if (read < EROFS_SUPER_OFFSET + sizeof(*dsb)) {
+	if (read < 0 || read < EROFS_SUPER_OFFSET + sizeof(*dsb)) {
 		ret = read < 0 ? read : -EIO;
 		erofs_err("cannot read erofs superblock: %s",
 			  erofs_strerror(ret));
diff --git a/mount/main.c b/mount/main.c
index 347a71b..345053b 100644
--- a/mount/main.c
+++ b/mount/main.c
@@ -591,8 +591,8 @@ static ssize_t erofsmount_tarindex_pread(struct erofs_vfile *vf, void *buf,
 	if (index_part) {
 		local_read = erofs_io_pread(&tp->tarindex_vf, buf,
 					    index_part, offset);
-		if (local_read < 0)
-			return local_read;
+		if (local_read != index_part)
+			return local_read < 0 ? local_read : -EIO;
 	}
 	if (tardata_part) {
 		remote_read = erofs_io_pread(tp->zinfo_vf, buf + local_read,
@@ -1460,9 +1460,9 @@ static int erofsmount_ublk_handler(void *ctx, struct erofs_ublk_request *rq)
 
 	ret = erofs_io_pread(vf, rq->buf, rq->nr_sectors << 9,
 			     rq->start_sector << 9);
-	if (ret < 0) {
-		rq->result = -EIO;
-		return (int)ret;
+	if (ret != (rq->nr_sectors << 9)) {
+		rq->result = ret < 0 ? ret : -EIO;
+		return rq->result;
 	}
 	rq->result = ret;
 	return 0;
-- 
2.56.0



  parent reply	other threads:[~2026-11-12 12:48 UTC|newest]

Thread overview: 11+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-11-12 12:47 [PATCH 0/8] erofs-utils: fix issues found by LLMs Yifan Zhao
2026-11-12 12:47 ` [PATCH 1/8] erofs-utils: lib: fix arithmetic overflow in large file handling Yifan Zhao
2026-11-12 12:47 ` [PATCH 2/8] erofs-utils: mkfs: fix incremental superblock stack overread Yifan Zhao
2026-11-12 12:47 ` [PATCH 3/8] erofs-utils: tar: fix out-of-bounds access when trimming PAX paths Yifan Zhao
2026-11-12 12:47 ` [PATCH 4/8] erofs-utils: lib: fix buffer leaks in error paths Yifan Zhao
2026-11-12 23:20   ` Gao Xiang
2026-11-12 12:47 ` [PATCH 5/8] erofs-utils: exclude: fix stack overflow when checking long paths Yifan Zhao
2026-11-12 12:47 ` [PATCH 6/8] erofs-utils: lib: fix gzran EOF handling and state leaks Yifan Zhao
2026-11-12 12:47 ` [PATCH 7/8] erofs-utils: lib: fix metabox inline data reads Yifan Zhao
2026-11-12 12:47 ` Yifan Zhao [this message]
2026-11-12 23:41   ` [PATCH 8/8] erofs-utils: fix read error and short read handling Gao Xiang

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=20261112124725.2774244-9-stopire@gmail.com \
    --to=stopire@gmail.com \
    --cc=linux-erofs@lists.ozlabs.org \
    /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