drivers/misc/rwbuffer: fix rwbuffer overflow issue

issue:
in rwb_wrflush():
memmove(rwb->wrbuffer + padblocks * rwb->blocksize,
rwb->wrbuffer, rwb->wrnblocks * rwb->blocksize);

when the offest from rwb->wrblockstart to startblock plus rwb->wrnblocks is greater
than rwb->wralignblocks, it will be causing memory overflow since rwb->wrbuffer is
allocated rwb.wrmaxblock(rwb.wralignblocks) blocks.

fix:
Let us ensure that the wrblockstart in rwbuffer must be aligned according to
wralignblocks after writing, so there is no need to perform memmove when flushing

Signed-off-by: dongjiuzhu1 <dongjiuzhu1@xiaomi.com>
This commit is contained in:
dongjiuzhu1 2024-04-22 14:01:31 +08:00 committed by Xiang Xiao
parent 0d609c451b
commit e2f1ccdefc

View File

@ -141,19 +141,11 @@ static void rwb_wrflush(FAR struct rwbuffer_s *rwb)
{
size_t padblocks;
DEBUGASSERT(rwb->wrblockstart % rwb->wralignblocks == 0);
finfo("Flushing: blockstart=0x%08lx nblocks=%d from buffer=%p\n",
(long)rwb->wrblockstart, rwb->wrnblocks, rwb->wrbuffer);
padblocks = rwb->wrblockstart % rwb->wralignblocks;
if (padblocks)
{
memmove(rwb->wrbuffer + padblocks * rwb->blocksize,
rwb->wrbuffer, rwb->wrnblocks * rwb->blocksize);
rwb->wrblockstart -= padblocks;
rwb->wrnblocks += padblocks;
rwb_read_(rwb, rwb->wrblockstart, padblocks, rwb->wrbuffer);
}
padblocks = rwb->wrnblocks % rwb->wralignblocks;
if (padblocks)
{
@ -326,40 +318,11 @@ static ssize_t rwb_writebuffer(FAR struct rwbuffer_s *rwb,
nblocks -= ncopy;
}
/* 5. We update a portion at the beginning of the write buffer */
else /* if (rwb->wrblockstart >= startblock && wrbend >= newend) */
{
FAR uint8_t *dest;
FAR const uint8_t *src;
size_t ncopy;
DEBUGASSERT(rwb->wrblockstart >= startblock && wrbend >= newend);
/* Move the cached data to the end of the write buffer */
ncopy = rwb->wrblockstart - startblock;
if (ncopy > rwb->wrmaxblocks - rwb->wrnblocks)
{
ncopy = rwb->wrmaxblocks - rwb->wrnblocks;
}
dest = rwb->wrbuffer + ncopy * rwb->blocksize;
memmove(dest, rwb->wrbuffer, ncopy * rwb->blocksize);
rwb->wrblockstart -= ncopy;
rwb->wrnblocks += ncopy;
/* Copy the data from the updating region to the beginning
* of the write buffer.
*/
ncopy = newend - rwb->wrblockstart;
src = wrbuffer + (nblocks - ncopy) * rwb->blocksize;
memcpy(rwb->wrbuffer, src, ncopy * rwb->blocksize);
nblocks -= ncopy;
}
/* 5. We update a portion at the beginning of the write buffer.
* For writes that are ahead of the writerbuffer, we first flush and
* then process the write in the new writebuffer to ensure that each
* wrblockstart is aligned according to wralignblocks.
*/
}
/* Use the block cache unless the buffer size is bigger than block cache */
@ -372,17 +335,42 @@ static ssize_t rwb_writebuffer(FAR struct rwbuffer_s *rwb,
return ret;
}
}
else if (nblocks)
while (nblocks > 0)
{
size_t padblocks;
size_t remain = nblocks;
/* Flush the write buffer */
rwb_wrflush(rwb);
/* Get the alignment padding of startblock, and read the contents
* of the padding area, ensure that wrblockstart is aligned
* according to wralignblocks.
*/
padblocks = startblock % rwb->wralignblocks;
rwb->wrblockstart = startblock - padblocks;
rwb_read_(rwb, rwb->wrblockstart, padblocks, rwb->wrbuffer);
rwb->wrnblocks = padblocks;
if (remain > rwb->wrmaxblocks - padblocks)
{
remain = rwb->wrmaxblocks - padblocks;
}
/* Buffer the data in the write buffer */
memcpy(rwb->wrbuffer, wrbuffer, nblocks * rwb->blocksize);
rwb->wrblockstart = startblock;
rwb->wrnblocks = nblocks;
memcpy(rwb->wrbuffer + padblocks * rwb->blocksize, wrbuffer,
remain * rwb->blocksize);
rwb->wrnblocks += remain;
/* Update remain state of write buffer */
nblocks -= remain;
startblock += remain;
wrbuffer += remain * rwb->blocksize;
}
if (rwb->wrnblocks > 0)