Message ID | 1465994350-12256-1-git-send-email-pbonzini@redhat.com (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
On 06/15/16 14:39, Paolo Bonzini wrote: > Avoid duplicated code between esp_do_dma and handle_ti. esp_do_dma > has the same code that handle_ti contains after the call to esp_do_dma; > but the code in handle_ti is never reached (... never reached after esp_do_dma() is called -- it is reached in general... but splitting hairs about this is not important) > because it is in an "else if". > Remove the else and also the pointless return. Yes, this looks correct. > esp_do_dma also has a partially dead assignment of the to_device > variable. Sink it to the point where it's actually used. You could sink it a bit more, I think, to just before the first use. > Finally, assert that the other caller of esp_do_dma (esp_transfer_data) > only transfers data and not a command. This is true because get_cmd > cancels the old request synchronously before its caller handle_satn_stop > sets do_cmd to 1. I didn't try to verify why the claim is true, but if the claim is true, then the assert() is valid, and fits in with the changes in esp_do_dma() and handle_ti() -- the logic taken over by handle_ti() from esp_do_dma() is not reached when esp_do_dma() is called by esp_transfer_data(), but then again, on that call path, the original logic was never reached anyway. (If the claim is wrong, we'll quickly find out with the assert() :)) ... So, I think if you wish, you could lower the "to_device" assignment a bit more. Either way: Reviewed-by: Laszlo Ersek <lersek@redhat.com> And I guess Prasad will submit a new version of the buffer overflow fix, on top of this patch, according to your previous message <http://thread.gmane.org/gmane.comp.emulators.qemu/419113/focus=419155>. Thanks Laszlo > > Signed-off-by: Paolo Bonzini <pbonzini@redhat.com> > --- > hw/scsi/esp.c | 11 ++++------- > 1 file changed, 4 insertions(+), 7 deletions(-) > > diff --git a/hw/scsi/esp.c b/hw/scsi/esp.c > index 3f08598..2bc5076 100644 > --- a/hw/scsi/esp.c > +++ b/hw/scsi/esp.c > @@ -245,21 +245,17 @@ static void esp_do_dma(ESPState *s) > uint32_t len; > int to_device; > > - to_device = (s->ti_size < 0); > len = s->dma_left; > if (s->do_cmd) { > trace_esp_do_dma(s->cmdlen, len); > s->dma_memory_read(s->dma_opaque, &s->cmdbuf[s->cmdlen], len); > - s->ti_size = 0; > - s->cmdlen = 0; > - s->do_cmd = 0; > - do_cmd(s, s->cmdbuf); > return; > } > if (s->async_len == 0) { > /* Defer until data is available. */ > return; > } > + to_device = (s->ti_size < 0); > if (len > s->async_len) { > len = s->async_len; > } > @@ -318,6 +314,7 @@ void esp_transfer_data(SCSIRequest *req, uint32_t len) > { > ESPState *s = req->hba_private; > > + assert(!s->do_cmd); > trace_esp_transfer_data(s->dma_left, s->ti_size); > s->async_len = len; > s->async_buf = scsi_req_get_buf(req); > @@ -358,13 +355,13 @@ static void handle_ti(ESPState *s) > s->dma_left = minlen; > s->rregs[ESP_RSTAT] &= ~STAT_TC; > esp_do_dma(s); > - } else if (s->do_cmd) { > + } > + if (s->do_cmd) { > trace_esp_handle_ti_cmd(s->cmdlen); > s->ti_size = 0; > s->cmdlen = 0; > s->do_cmd = 0; > do_cmd(s, s->cmdbuf); > - return; > } > } > >
On 15/06/2016 15:16, Laszlo Ersek wrote: > On 06/15/16 14:39, Paolo Bonzini wrote: >> Finally, assert that the other caller of esp_do_dma (esp_transfer_data) >> only transfers data and not a command. This is true because get_cmd >> cancels the old request synchronously before its caller handle_satn_stop >> sets do_cmd to 1. > > I didn't try to verify why the claim is true, but if the claim is true, > then the assert() is valid, and fits in with the changes in esp_do_dma() > and handle_ti() -- the logic taken over by handle_ti() from esp_do_dma() > is not reached when esp_do_dma() is called by esp_transfer_data(), but > then again, on that call path, the original logic was never reached anyway. > > (If the claim is wrong, we'll quickly find out with the assert() :)) Correct. :) > ... So, I think if you wish, you could lower the "to_device" assignment > a bit more. Will do, thanks. Paolo
+-- On Wed, 15 Jun 2016, Laszlo Ersek wrote --+ | And I guess Prasad will submit a new version of the buffer overflow fix, | on top of this patch, according to your previous message | <http://thread.gmane.org/gmane.comp.emulators.qemu/419113/focus=419155>. Yes, I'm preparing an update. -- Prasad J Pandit / Red Hat Product Security Team 47AF CE69 3A90 54AA 9045 1053 DD13 3D32 FE5B 041F
diff --git a/hw/scsi/esp.c b/hw/scsi/esp.c index 3f08598..2bc5076 100644 --- a/hw/scsi/esp.c +++ b/hw/scsi/esp.c @@ -245,21 +245,17 @@ static void esp_do_dma(ESPState *s) uint32_t len; int to_device; - to_device = (s->ti_size < 0); len = s->dma_left; if (s->do_cmd) { trace_esp_do_dma(s->cmdlen, len); s->dma_memory_read(s->dma_opaque, &s->cmdbuf[s->cmdlen], len); - s->ti_size = 0; - s->cmdlen = 0; - s->do_cmd = 0; - do_cmd(s, s->cmdbuf); return; } if (s->async_len == 0) { /* Defer until data is available. */ return; } + to_device = (s->ti_size < 0); if (len > s->async_len) { len = s->async_len; } @@ -318,6 +314,7 @@ void esp_transfer_data(SCSIRequest *req, uint32_t len) { ESPState *s = req->hba_private; + assert(!s->do_cmd); trace_esp_transfer_data(s->dma_left, s->ti_size); s->async_len = len; s->async_buf = scsi_req_get_buf(req); @@ -358,13 +355,13 @@ static void handle_ti(ESPState *s) s->dma_left = minlen; s->rregs[ESP_RSTAT] &= ~STAT_TC; esp_do_dma(s); - } else if (s->do_cmd) { + } + if (s->do_cmd) { trace_esp_handle_ti_cmd(s->cmdlen); s->ti_size = 0; s->cmdlen = 0; s->do_cmd = 0; do_cmd(s, s->cmdbuf); - return; } }
Avoid duplicated code between esp_do_dma and handle_ti. esp_do_dma has the same code that handle_ti contains after the call to esp_do_dma; but the code in handle_ti is never reached because it is in an "else if". Remove the else and also the pointless return. esp_do_dma also has a partially dead assignment of the to_device variable. Sink it to the point where it's actually used. Finally, assert that the other caller of esp_do_dma (esp_transfer_data) only transfers data and not a command. This is true because get_cmd cancels the old request synchronously before its caller handle_satn_stop sets do_cmd to 1. Signed-off-by: Paolo Bonzini <pbonzini@redhat.com> --- hw/scsi/esp.c | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-)