nvmet-rdma: reject inline data with a nonzero offset#926
Open
blktests-ci[bot] wants to merge 1 commit into
Open
nvmet-rdma: reject inline data with a nonzero offset#926blktests-ci[bot] wants to merge 1 commit into
blktests-ci[bot] wants to merge 1 commit into
Conversation
nvmet_rdma_map_sgl_inline() takes a host-controlled offset and length
from the inline SGL descriptor and bounds-checks them against the
per-port inline_data_size:
u64 off = le64_to_cpu(sgl->addr);
u32 len = le32_to_cpu(sgl->length);
...
if (off + len > rsp->queue->dev->inline_data_size)
return NVME_SC_SGL_INVALID_OFFSET | NVME_STATUS_DNR;
This is unsound whenever the offset is nonzero:
- "off + len" is evaluated in u64 and wraps modulo 2^64. A descriptor
with addr = 0xfffffffffffffe00 and length = 0x1000 wraps the sum to
0xe00 and passes the check. nvmet_rdma_use_inline_sg() then stores
the offset into scatterlist::offset (unsigned int) and the block
layer reads out of bounds of the inline page; a large len also makes
num_pages(len) exceed NVMET_RDMA_MAX_INLINE_SGE and overruns the
fixed-size inline_sg[] array.
- Even computed without wrapping, inline_data_size is configurable up
to max(SZ_16K, PAGE_SIZE). An offset in (PAGE_SIZE, inline_data_size]
passes the bound and then "PAGE_SIZE - off" in
nvmet_rdma_use_inline_sg() underflows, leaving scatterlist::length at
~4 GiB and the offset pointing past the first inline page.
A nonzero inline offset is never legitimate here. nvmet advertises
icdoff = 0, nvme_rdma_setup_ctrl() refuses to use a controller that
reports a nonzero icdoff ("icdoff is not supported!"), and
nvme_rdma_map_sg_inline() sets the inline descriptor addr to icdoff, so
a compliant initiator always sends offset 0. nvmet_rdma_use_inline_sg()
likewise assumes the inline data begins at the start of the first inline
page (the RNIC DMAs it to page offset 0); any nonzero offset also
mis-describes the scatterlist even when it is in bounds.
Reject a nonzero offset directly. This closes the u64 overflow, the
inline_sg[] overrun and the PAGE_SIZE - off underflow together, and is
simpler than bounding the offset.
Fixes: 0d5ee2b ("nvmet-rdma: support max(16KB, PAGE_SIZE) inline data")
Cc: stable@vger.kernel.org
Reported-by: Bryam Vargas <hexlabsecurity@proton.me>
Signed-off-by: Bryam Vargas <hexlabsecurity@proton.me>
Author
|
Upstream branch: ba3e43a |
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.
Pull request for series with
subject: nvmet-rdma: reject inline data with a nonzero offset
version: 1
url: https://patchwork.kernel.org/project/linux-block/list/?series=1105801