]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/commit
Fix a buffer overrun which may lead to data corruption, introduced in
authorXin LI <delphij@FreeBSD.org>
Sat, 29 Aug 2015 09:22:32 +0000 (09:22 +0000)
committerXin LI <delphij@FreeBSD.org>
Sat, 29 Aug 2015 09:22:32 +0000 (09:22 +0000)
commit9053fe148ba7ebd03c2fec44f8560666d6bc7e13
treefebadb7647a7259922400bd179f6155df571c729
parente92c2a8d6a59fe2586b1efaf84637be10290db15
Fix a buffer overrun which may lead to data corruption, introduced in
r286951 by reinstating changes in r274628.

In l2arc_compress_buf(), we allocate a buffer to stash away the compressed
data in 'cdata', allocated of l2hdr->b_asize bytes.

We then ask zio_compress_data() to compress the buffer, b_l1hdr.b_tmp_cdata,
which is of l2hdr->b_asize bytes, and have the compressed size (or original
size, if compress didn't gain enough) stored in csize.

To pad the buffer to fit the optimal write size, we round up the compressed
size to L2 device's vdev_ashift.

Illumos code rounds up the size by at most SPA_MINBLOCKSIZE.  Because we
know csize <= b_asize, and b_asize is integer multiple of SPA_MINBLOCKSIZE,
we are guaranteed that the rounded up csize would be <= b_asize. However,
this is not necessarily true when we round up to 1 << vdev_ashift, because
it could be larger than SPA_MINBLOCKSIZE.

So, in the worst case scenario, we are overwriting at most

(1 << vdev_ashift - SPA_MINBLOCKSIZE)

bytes of memory next to the compressed data buffer.

Andriy's original change in r274628 reorganized the code a little bit,
by moving the padding to after we determined that the compression was
beneficial.  At which point, we would check rounded size against the
allocated buffer size, and the buffer overrun would not be possible.
sys/cddl/contrib/opensolaris/uts/common/fs/zfs/arc.c