Commit 3e6c3b0f authored by Sebastian Sanchez's avatar Sebastian Sanchez Committed by Doug Ledford

IB/hfi1: Fix SGE length for misaligned PIO copy

When trying to align the source pointer and there's a byte carry
in an SGE copy, bytes are borrowed from the next quad-word X to
complete the required quad-word copy. Then, the SGE length is
reduced by the number of borrowed bytes. After this, if the
remaining number of bytes from quad-word X (extra bytes) is
greater than the new SGE length, the number of extra bytes needs
to be updated to the new SGE length. Otherwise, when the
SGE length gets updated again after the extra bytes are read to
create the new byte carry, it goes negative, which then becomes
a very large number as the SGE length is an unsigned integer.
This causes SGE buffer to be over-read.
Reviewed-by: default avatarDean Luick <dean.luick@intel.com>
Signed-off-by: default avatarSebastian Sanchez <sebastian.sanchez@intel.com>
Signed-off-by: default avatarDennis Dalessandro <dennis.dalessandro@intel.com>
Signed-off-by: default avatarDoug Ledford <dledford@redhat.com>
parent dbdf7d4e
...@@ -771,6 +771,9 @@ void seg_pio_copy_mid(struct pio_buf *pbuf, const void *from, size_t nbytes) ...@@ -771,6 +771,9 @@ void seg_pio_copy_mid(struct pio_buf *pbuf, const void *from, size_t nbytes)
read_extra_bytes(pbuf, from, to_fill); read_extra_bytes(pbuf, from, to_fill);
from += to_fill; from += to_fill;
nbytes -= to_fill; nbytes -= to_fill;
/* may not be enough valid bytes left to align */
if (extra > nbytes)
extra = nbytes;
/* ...now write carry */ /* ...now write carry */
dest = pbuf->start + (pbuf->qw_written * sizeof(u64)); dest = pbuf->start + (pbuf->qw_written * sizeof(u64));
...@@ -798,6 +801,15 @@ void seg_pio_copy_mid(struct pio_buf *pbuf, const void *from, size_t nbytes) ...@@ -798,6 +801,15 @@ void seg_pio_copy_mid(struct pio_buf *pbuf, const void *from, size_t nbytes)
read_low_bytes(pbuf, from, extra); read_low_bytes(pbuf, from, extra);
from += extra; from += extra;
nbytes -= extra; nbytes -= extra;
/*
* If no bytes are left, return early - we are done.
* NOTE: This short-circuit is *required* because
* "extra" may have been reduced in size and "from"
* is not aligned, as required when leaving this
* if block.
*/
if (nbytes == 0)
return;
} }
/* at this point, from is QW aligned */ /* at this point, from is QW aligned */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment