kernel: Add mechanism in IOBuffer & IORequest to clamp the last iovec.
This is needed by CreateSubRequest, which creates a sub-request using some subset of the passed IO vectors. In the case that the last vector will not be fully used, we need to clamp its size in the sub-request to the remaining length. do_iterative_fd_io, used by vfs_read_pages (which is in turn used by the file cache) used this to split up requests into their constituent block-run requests. So, previously, the invalid IO requests created by this could, under one possible interpretation, overwrite valid file data and cause disk corruption. It is slightly unfortunate that generic_size_t has no unsigned equivalent, so we are left with 0 as the magic number here, instead of -1. However, the passed "length" remains unchanged, so any callers that pass the wrong value for lastVecSize will be trapped by the assert added in the previous commit Fixes #15912 (the assert added in the previous commit), and potentially disk corruption caused by this.
This commit is contained in:
parent
d939cacf6b
commit
c1c239fefb
@ -112,8 +112,8 @@ IOBuffer::Delete()
|
||||
|
||||
|
||||
void
|
||||
IOBuffer::SetVecs(generic_size_t firstVecOffset, const generic_io_vec* vecs,
|
||||
uint32 count, generic_size_t length, uint32 flags)
|
||||
IOBuffer::SetVecs(generic_size_t firstVecOffset, generic_size_t lastVecSize,
|
||||
const generic_io_vec* vecs, uint32 count, generic_size_t length, uint32 flags)
|
||||
{
|
||||
memcpy(fVecs, vecs, sizeof(generic_io_vec) * count);
|
||||
|
||||
@ -121,6 +121,8 @@ IOBuffer::SetVecs(generic_size_t firstVecOffset, const generic_io_vec* vecs,
|
||||
fVecs[0].base += firstVecOffset;
|
||||
fVecs[0].length -= firstVecOffset;
|
||||
}
|
||||
if (lastVecSize > 0)
|
||||
fVecs[count - 1].length = lastVecSize;
|
||||
|
||||
fVecCount = count;
|
||||
fLength = length;
|
||||
@ -750,8 +752,8 @@ IORequest::Init(off_t offset, generic_addr_t buffer, generic_size_t length,
|
||||
|
||||
status_t
|
||||
IORequest::Init(off_t offset, generic_size_t firstVecOffset,
|
||||
const generic_io_vec* vecs, size_t count, generic_size_t length, bool write,
|
||||
uint32 flags)
|
||||
generic_size_t lastVecSize, const generic_io_vec* vecs, size_t count,
|
||||
generic_size_t length, bool write, uint32 flags)
|
||||
{
|
||||
ASSERT(offset >= 0);
|
||||
|
||||
@ -759,7 +761,7 @@ IORequest::Init(off_t offset, generic_size_t firstVecOffset,
|
||||
if (fBuffer == NULL)
|
||||
return B_NO_MEMORY;
|
||||
|
||||
fBuffer->SetVecs(firstVecOffset, vecs, count, length, flags);
|
||||
fBuffer->SetVecs(firstVecOffset, lastVecSize, vecs, count, length, flags);
|
||||
|
||||
fOwner = NULL;
|
||||
fOffset = offset;
|
||||
@ -825,8 +827,9 @@ IORequest::CreateSubRequest(off_t parentOffset, off_t offset,
|
||||
if (subRequest == NULL)
|
||||
return B_NO_MEMORY;
|
||||
|
||||
status_t error = subRequest->Init(offset, vecOffset, vecs + startVec,
|
||||
endVec - startVec + 1, length, fIsWrite, fFlags & ~B_DELETE_IO_REQUEST);
|
||||
status_t error = subRequest->Init(offset, vecOffset, remainingLength,
|
||||
vecs + startVec, endVec - startVec + 1, length, fIsWrite,
|
||||
fFlags & ~B_DELETE_IO_REQUEST);
|
||||
if (error != B_OK) {
|
||||
delete subRequest;
|
||||
return error;
|
||||
|
@ -40,6 +40,7 @@ public:
|
||||
bool IsUser() const { return fUser; }
|
||||
|
||||
void SetVecs(generic_size_t firstVecOffset,
|
||||
generic_size_t lastVecSize,
|
||||
const generic_io_vec* vecs, uint32 count,
|
||||
generic_size_t length, uint32 flags);
|
||||
|
||||
@ -219,10 +220,11 @@ struct IORequest : IORequestChunk, DoublyLinkedListLinkImpl<IORequest> {
|
||||
status_t Init(off_t offset, const generic_io_vec* vecs,
|
||||
size_t count, generic_size_t length,
|
||||
bool write, uint32 flags)
|
||||
{ return Init(offset, 0, vecs, count,
|
||||
{ return Init(offset, 0, 0, vecs, count,
|
||||
length, write, flags); }
|
||||
status_t Init(off_t offset,
|
||||
generic_size_t firstVecOffset,
|
||||
generic_size_t lastVecSize,
|
||||
const generic_io_vec* vecs, size_t count,
|
||||
generic_size_t length, bool write,
|
||||
uint32 flags);
|
||||
|
Loading…
Reference in New Issue
Block a user