fix(ext2): read sparse holes as zeros and return 0 at EOF - #267
Merged
Conversation
Two boundary defects of the ext2 read path: - Sparse holes inside i_size failed to read: a resolved block pointer of zero is a legal hole, but ext2_read_inode_block treated it as an error (and rejected any block beyond the allocated count), so any read touching a hole returned -1. Holes now read as a block of zeros, and the block range check is based on the file size instead of the allocated block count (issue #192). - Reads at or beyond EOF returned -1 (or worse): without a guard, offsets past i_size hit unallocated tail blocks or computed wrapping copy lengths in unsigned arithmetic. Additionally, when the read end was block-aligned, end_block overshot by one and end_size wrapped the last copy length. Reads at EOF now return 0, zero-length reads return 0, and the end block is derived from the last byte actually read (issue #242). Update the t_shebang sparse-script case, which pinned the old #192 failure (EIO): the shebang read of the sparse script now succeeds and the exec outcome is governed by the open #222 interpreter-path bug (ENOENT today, success once #222 is fixed).
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Fix two related boundary defects in the EXT2 read path:
The existing sparse-script regression in
t_shebangis also updated because it previously depended on the broken sparse-hole behavior.Fixes #192.
Fixes #242.
Problem / motivation
#192 — sparse holes were treated as invalid blocks
EXT2 sparse files may contain a zero block pointer inside the logical file size. Such a block is a hole and must read as zeros.
Previously,
ext2_read_inode_block()validated the requested logical block against the number of physically allocated blocks.That is incorrect for sparse files: a file can logically cover more blocks than it physically allocates.
After resolving the logical block, a sparse hole produced a physical block index of
0, which eventually reachedext2_read_block()and failed as an invalid block.This made any read touching a hole fail entirely.
#242 — EOF reads could enter invalid block arithmetic
ext2_read_inode_data()did not reject reads whose offset was already at or beyondinode->size.Depending on the offset and file layout, this could cause:
-1instead of0.There was also a related end-block calculation problem for reads ending exactly on a block boundary:
When
end_offsetwas block-aligned, this selected the block after the final byte actually requested.Changes
Sparse-file reads
ext2_read_inode_block()now:inode->size, notinode->blocks_count;0as a sparse hole;This preserves the distinction between:
EOF handling
ext2_read_inode_data()now returns0immediately when:or when:
The end block is now calculated from the last byte actually included in the read:
so an exact block-boundary end no longer advances into the following block.
t_shebangThe sparse-script case previously expected
EIObecause its shebang read crossed a sparse hole and therefore exercised #192.With sparse reads fixed, that I/O failure is no longer valid behavior.
The test now accepts the outcomes that can legitimately follow a successful sparse-file read:
ENOENTwith the current execve: the whole shebang line is used as the interpreter path, so scripts with an interpreter argument always fail #222 interpreter-line parsing bug;It specifically no longer accepts a sparse-read failure.
Validation
git diff --checkValidation details:
Scope
This fixes the EXT2 root cause originally tracked by #192. The historical secondary
execve()crash propagation described there has already been addressed separately by the transactional executable-loading work.The unrelated test-address randomization and low-user-address mapping problems discovered during verification are intentionally left out of this change and will be tracked separately.
Related issues
Fixes #192.
Fixes #242.
Related: #56, #222.