qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
* [Qemu-devel] [PATCH 0/3] rdma: validate remote provided RDMAControlHeader::len
@ 2013-08-07  2:26 Isaku Yamahata
  2013-08-07  2:26 ` [Qemu-devel] [PATCH 1/3] rdma: use resp.len after validation in qemu_rdma_registration_stop Isaku Yamahata
                   ` (6 more replies)
  0 siblings, 7 replies; 8+ messages in thread
From: Isaku Yamahata @ 2013-08-07  2:26 UTC (permalink / raw)
  To: qemu-devel; +Cc: owasserm, pbonzini, mrhines, quintela

RDMAControlHeader::len is remote-provided. So validate the value before use.

Isaku Yamahata (3):
  rdma: use resp.len after validation in qemu_rdma_registration_stop
  rdma: validate RDMAControlHeader::len
  rdma: check if RDMAControlHeader::len match transferred byte

 migration-rdma.c |   44 ++++++++++++++++++++++++++++++--------------
 1 file changed, 30 insertions(+), 14 deletions(-)

-- 
1.7.10.4

^ permalink raw reply	[flat|nested] 8+ messages in thread

* [Qemu-devel] [PATCH 1/3] rdma: use resp.len after validation in qemu_rdma_registration_stop
  2013-08-07  2:26 [Qemu-devel] [PATCH 0/3] rdma: validate remote provided RDMAControlHeader::len Isaku Yamahata
@ 2013-08-07  2:26 ` Isaku Yamahata
  2013-08-07  2:26 ` [Qemu-devel] [PATCH 2/3] rdma: validate RDMAControlHeader::len Isaku Yamahata
                   ` (5 subsequent siblings)
  6 siblings, 0 replies; 8+ messages in thread
From: Isaku Yamahata @ 2013-08-07  2:26 UTC (permalink / raw)
  To: qemu-devel; +Cc: owasserm, pbonzini, mrhines, quintela

resp.len is given from remote host. So should be validated before use.
Otherwise memcpy can access beyond the buffer.

Cc: Michael R. Hines <mrhines@us.ibm.com>
Signed-off-by: Isaku Yamahata <yamahata@private.email.ne.jp>
---
 migration-rdma.c |    7 +++----
 1 file changed, 3 insertions(+), 4 deletions(-)

diff --git a/migration-rdma.c b/migration-rdma.c
index 3a380d4..6721266 100644
--- a/migration-rdma.c
+++ b/migration-rdma.c
@@ -3045,10 +3045,6 @@ static int qemu_rdma_registration_stop(QEMUFile *f, void *opaque,
             return ret;
         }
 
-        qemu_rdma_move_header(rdma, reg_result_idx, &resp);
-        memcpy(rdma->block,
-            rdma->wr_data[reg_result_idx].control_curr, resp.len);
-
         nb_remote_blocks = resp.len / sizeof(RDMARemoteBlock);
 
         /*
@@ -3070,6 +3066,9 @@ static int qemu_rdma_registration_stop(QEMUFile *f, void *opaque,
             return -EINVAL;
         }
 
+        qemu_rdma_move_header(rdma, reg_result_idx, &resp);
+        memcpy(rdma->block,
+            rdma->wr_data[reg_result_idx].control_curr, resp.len);
         for (i = 0; i < nb_remote_blocks; i++) {
             network_to_remote_block(&rdma->block[i]);
 
-- 
1.7.10.4

^ permalink raw reply related	[flat|nested] 8+ messages in thread

* [Qemu-devel] [PATCH 2/3] rdma: validate RDMAControlHeader::len
  2013-08-07  2:26 [Qemu-devel] [PATCH 0/3] rdma: validate remote provided RDMAControlHeader::len Isaku Yamahata
  2013-08-07  2:26 ` [Qemu-devel] [PATCH 1/3] rdma: use resp.len after validation in qemu_rdma_registration_stop Isaku Yamahata
@ 2013-08-07  2:26 ` Isaku Yamahata
  2013-08-07  2:26 ` [Qemu-devel] [PATCH 3/3] rdma: check if RDMAControlHeader::len match transferred byte Isaku Yamahata
                   ` (4 subsequent siblings)
  6 siblings, 0 replies; 8+ messages in thread
From: Isaku Yamahata @ 2013-08-07  2:26 UTC (permalink / raw)
  To: qemu-devel; +Cc: owasserm, pbonzini, mrhines, quintela

RMDAControlHeader::len is provided from remote, so validate it.

Cc: Michael R. Hines <mrhines@us.ibm.com>
Signed-off-by: Isaku Yamahata <yamahata@private.email.ne.jp>
---
 migration-rdma.c |    5 +++++
 1 file changed, 5 insertions(+)

diff --git a/migration-rdma.c b/migration-rdma.c
index 6721266..ebe1f55 100644
--- a/migration-rdma.c
+++ b/migration-rdma.c
@@ -1424,6 +1424,7 @@ static int qemu_rdma_post_send_control(RDMAContext *rdma, uint8_t *buf,
      * The copy makes the RDMAControlHeader simpler to manipulate
      * for the time being.
      */
+    assert(head->len <= RDMA_CONTROL_MAX_BUFFER - sizeof(*head));
     memcpy(wr->control, head, sizeof(RDMAControlHeader));
     control_to_network((void *) wr->control);
 
@@ -1504,6 +1505,10 @@ static int qemu_rdma_exchange_get_response(RDMAContext *rdma,
                 control_desc[head->type], head->type, head->len);
         return -EIO;
     }
+    if (head->len > RDMA_CONTROL_MAX_BUFFER - sizeof(*head)) {
+        fprintf(stderr, "too long length: %d\n", head->len);
+        return -EINVAL;
+    }
 
     return 0;
 }
-- 
1.7.10.4

^ permalink raw reply related	[flat|nested] 8+ messages in thread

* [Qemu-devel] [PATCH 3/3] rdma: check if RDMAControlHeader::len match transferred byte
  2013-08-07  2:26 [Qemu-devel] [PATCH 0/3] rdma: validate remote provided RDMAControlHeader::len Isaku Yamahata
  2013-08-07  2:26 ` [Qemu-devel] [PATCH 1/3] rdma: use resp.len after validation in qemu_rdma_registration_stop Isaku Yamahata
  2013-08-07  2:26 ` [Qemu-devel] [PATCH 2/3] rdma: validate RDMAControlHeader::len Isaku Yamahata
@ 2013-08-07  2:26 ` Isaku Yamahata
  2013-08-07  7:40 ` [Qemu-devel] [PATCH 0/3] rdma: validate remote provided RDMAControlHeader::len Paolo Bonzini
                   ` (3 subsequent siblings)
  6 siblings, 0 replies; 8+ messages in thread
From: Isaku Yamahata @ 2013-08-07  2:26 UTC (permalink / raw)
  To: qemu-devel; +Cc: owasserm, pbonzini, mrhines, quintela

RDMAControlHeader::len is provided from remote, so check if the value
match the actual transferred byte_len.

Cc: Michael R. Hines <mrhines@us.ibm.com>
Signed-off-by: Isaku Yamahata <yamahata@private.email.ne.jp>
---
 migration-rdma.c |   32 ++++++++++++++++++++++----------
 1 file changed, 22 insertions(+), 10 deletions(-)

diff --git a/migration-rdma.c b/migration-rdma.c
index ebe1f55..30e08cd 100644
--- a/migration-rdma.c
+++ b/migration-rdma.c
@@ -1214,7 +1214,8 @@ static void qemu_rdma_signal_unregister(RDMAContext *rdma, uint64_t index,
  * (of any kind) has completed.
  * Return the work request ID that completed.
  */
-static uint64_t qemu_rdma_poll(RDMAContext *rdma, uint64_t *wr_id_out)
+static uint64_t qemu_rdma_poll(RDMAContext *rdma, uint64_t *wr_id_out,
+                               uint32_t *byte_len)
 {
     int ret;
     struct ibv_wc wc;
@@ -1285,6 +1286,9 @@ static uint64_t qemu_rdma_poll(RDMAContext *rdma, uint64_t *wr_id_out)
     }
 
     *wr_id_out = wc.wr_id;
+    if (byte_len) {
+        *byte_len = wc.byte_len;
+    }
 
     return  0;
 }
@@ -1302,7 +1306,8 @@ static uint64_t qemu_rdma_poll(RDMAContext *rdma, uint64_t *wr_id_out)
  * completions only need to be recorded, but do not actually
  * need further processing.
  */
-static int qemu_rdma_block_for_wrid(RDMAContext *rdma, int wrid_requested)
+static int qemu_rdma_block_for_wrid(RDMAContext *rdma, int wrid_requested,
+                                    uint32_t *byte_len)
 {
     int num_cq_events = 0, ret = 0;
     struct ibv_cq *cq;
@@ -1314,7 +1319,7 @@ static int qemu_rdma_block_for_wrid(RDMAContext *rdma, int wrid_requested)
     }
     /* poll cq first */
     while (wr_id != wrid_requested) {
-        ret = qemu_rdma_poll(rdma, &wr_id_in);
+        ret = qemu_rdma_poll(rdma, &wr_id_in, byte_len);
         if (ret < 0) {
             return ret;
         }
@@ -1356,7 +1361,7 @@ static int qemu_rdma_block_for_wrid(RDMAContext *rdma, int wrid_requested)
         }
 
         while (wr_id != wrid_requested) {
-            ret = qemu_rdma_poll(rdma, &wr_id_in);
+            ret = qemu_rdma_poll(rdma, &wr_id_in, byte_len);
             if (ret < 0) {
                 goto err_block_for_wrid;
             }
@@ -1442,7 +1447,7 @@ static int qemu_rdma_post_send_control(RDMAContext *rdma, uint8_t *buf,
         return ret;
     }
 
-    ret = qemu_rdma_block_for_wrid(rdma, RDMA_WRID_SEND_CONTROL);
+    ret = qemu_rdma_block_for_wrid(rdma, RDMA_WRID_SEND_CONTROL, NULL);
     if (ret < 0) {
         fprintf(stderr, "rdma migration: send polling control error!\n");
     }
@@ -1483,7 +1488,9 @@ static int qemu_rdma_post_recv_control(RDMAContext *rdma, int idx)
 static int qemu_rdma_exchange_get_response(RDMAContext *rdma,
                 RDMAControlHeader *head, int expecting, int idx)
 {
-    int ret = qemu_rdma_block_for_wrid(rdma, RDMA_WRID_RECV_CONTROL + idx);
+    uint32_t byte_len;
+    int ret = qemu_rdma_block_for_wrid(rdma, RDMA_WRID_RECV_CONTROL + idx,
+                                       &byte_len);
 
     if (ret < 0) {
         fprintf(stderr, "rdma migration: recv polling control error!\n");
@@ -1509,6 +1516,11 @@ static int qemu_rdma_exchange_get_response(RDMAContext *rdma,
         fprintf(stderr, "too long length: %d\n", head->len);
         return -EINVAL;
     }
+    if (sizeof(*head) + head->len != byte_len) {
+        fprintf(stderr, "Malformed length: %d byte_len %d\n",
+                head->len, byte_len);
+        return -EINVAL;
+    }
 
     return 0;
 }
@@ -1738,7 +1750,7 @@ retry:
                 count++, current_index, chunk,
                 sge.addr, length, rdma->nb_sent, block->nb_chunks);
 
-        ret = qemu_rdma_block_for_wrid(rdma, RDMA_WRID_RDMA_WRITE);
+        ret = qemu_rdma_block_for_wrid(rdma, RDMA_WRID_RDMA_WRITE, NULL);
 
         if (ret < 0) {
             fprintf(stderr, "Failed to Wait for previous write to complete "
@@ -1882,7 +1894,7 @@ retry:
 
     if (ret == ENOMEM) {
         DDPRINTF("send queue is full. wait a little....\n");
-        ret = qemu_rdma_block_for_wrid(rdma, RDMA_WRID_RDMA_WRITE);
+        ret = qemu_rdma_block_for_wrid(rdma, RDMA_WRID_RDMA_WRITE, NULL);
         if (ret < 0) {
             fprintf(stderr, "rdma migration: failed to make "
                             "room in full send queue! %d\n", ret);
@@ -2471,7 +2483,7 @@ static int qemu_rdma_drain_cq(QEMUFile *f, RDMAContext *rdma)
     }
 
     while (rdma->nb_sent) {
-        ret = qemu_rdma_block_for_wrid(rdma, RDMA_WRID_RDMA_WRITE);
+        ret = qemu_rdma_block_for_wrid(rdma, RDMA_WRID_RDMA_WRITE, NULL);
         if (ret < 0) {
             fprintf(stderr, "rdma migration: complete polling error!\n");
             return -EIO;
@@ -2607,7 +2619,7 @@ static size_t qemu_rdma_save_page(QEMUFile *f, void *opaque,
      */
     while (1) {
         uint64_t wr_id, wr_id_in;
-        int ret = qemu_rdma_poll(rdma, &wr_id_in);
+        int ret = qemu_rdma_poll(rdma, &wr_id_in, NULL);
         if (ret < 0) {
             fprintf(stderr, "rdma migration: polling error! %d\n", ret);
             goto err;
-- 
1.7.10.4

^ permalink raw reply related	[flat|nested] 8+ messages in thread

* Re: [Qemu-devel] [PATCH 0/3] rdma: validate remote provided RDMAControlHeader::len
  2013-08-07  2:26 [Qemu-devel] [PATCH 0/3] rdma: validate remote provided RDMAControlHeader::len Isaku Yamahata
                   ` (2 preceding siblings ...)
  2013-08-07  2:26 ` [Qemu-devel] [PATCH 3/3] rdma: check if RDMAControlHeader::len match transferred byte Isaku Yamahata
@ 2013-08-07  7:40 ` Paolo Bonzini
  2013-08-07  8:54 ` Orit Wasserman
                   ` (2 subsequent siblings)
  6 siblings, 0 replies; 8+ messages in thread
From: Paolo Bonzini @ 2013-08-07  7:40 UTC (permalink / raw)
  To: Isaku Yamahata; +Cc: owasserm, mrhines, qemu-devel, quintela

> RDMAControlHeader::len is remote-provided. So validate the value before use.
> 
> Isaku Yamahata (3):
>   rdma: use resp.len after validation in qemu_rdma_registration_stop
>   rdma: validate RDMAControlHeader::len
>   rdma: check if RDMAControlHeader::len match transferred byte
> 
>  migration-rdma.c |   44 ++++++++++++++++++++++++++++++--------------
>  1 file changed, 30 insertions(+), 14 deletions(-)

Looks good, thanks!

We will have a mix of assertions and errors after this patch.
Asserting on the destination is probably okay, but as a follow-up
perhaps we can change the assertion(s) to errors.

Paolo

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [Qemu-devel] [PATCH 0/3] rdma: validate remote provided RDMAControlHeader::len
  2013-08-07  2:26 [Qemu-devel] [PATCH 0/3] rdma: validate remote provided RDMAControlHeader::len Isaku Yamahata
                   ` (3 preceding siblings ...)
  2013-08-07  7:40 ` [Qemu-devel] [PATCH 0/3] rdma: validate remote provided RDMAControlHeader::len Paolo Bonzini
@ 2013-08-07  8:54 ` Orit Wasserman
  2013-08-07 15:02 ` Michael R. Hines
  2013-08-14 16:27 ` Anthony Liguori
  6 siblings, 0 replies; 8+ messages in thread
From: Orit Wasserman @ 2013-08-07  8:54 UTC (permalink / raw)
  To: Isaku Yamahata; +Cc: pbonzini, mrhines, qemu-devel, quintela

On 08/07/2013 05:26 AM, Isaku Yamahata wrote:
> RDMAControlHeader::len is remote-provided. So validate the value before use.
> 
> Isaku Yamahata (3):
>   rdma: use resp.len after validation in qemu_rdma_registration_stop
>   rdma: validate RDMAControlHeader::len
>   rdma: check if RDMAControlHeader::len match transferred byte
> 
>  migration-rdma.c |   44 ++++++++++++++++++++++++++++++--------------
>  1 file changed, 30 insertions(+), 14 deletions(-)
> 

Series 
Reviewed-by: Orit Wasserman <owasserm@redhat.com>

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [Qemu-devel] [PATCH 0/3] rdma: validate remote provided RDMAControlHeader::len
  2013-08-07  2:26 [Qemu-devel] [PATCH 0/3] rdma: validate remote provided RDMAControlHeader::len Isaku Yamahata
                   ` (4 preceding siblings ...)
  2013-08-07  8:54 ` Orit Wasserman
@ 2013-08-07 15:02 ` Michael R. Hines
  2013-08-14 16:27 ` Anthony Liguori
  6 siblings, 0 replies; 8+ messages in thread
From: Michael R. Hines @ 2013-08-07 15:02 UTC (permalink / raw)
  To: Isaku Yamahata; +Cc: owasserm, quintela, mrhines, qemu-devel, pbonzini

On 08/06/2013 10:26 PM, Isaku Yamahata wrote:
> RDMAControlHeader::len is remote-provided. So validate the value before use.
>
> Isaku Yamahata (3):
>    rdma: use resp.len after validation in qemu_rdma_registration_stop
>    rdma: validate RDMAControlHeader::len
>    rdma: check if RDMAControlHeader::len match transferred byte
>
>   migration-rdma.c |   44 ++++++++++++++++++++++++++++++--------------
>   1 file changed, 30 insertions(+), 14 deletions(-)
>

Thank you. I will apply to my tree and re-send.

- Michael

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [Qemu-devel] [PATCH 0/3] rdma: validate remote provided RDMAControlHeader::len
  2013-08-07  2:26 [Qemu-devel] [PATCH 0/3] rdma: validate remote provided RDMAControlHeader::len Isaku Yamahata
                   ` (5 preceding siblings ...)
  2013-08-07 15:02 ` Michael R. Hines
@ 2013-08-14 16:27 ` Anthony Liguori
  6 siblings, 0 replies; 8+ messages in thread
From: Anthony Liguori @ 2013-08-14 16:27 UTC (permalink / raw)
  To: Isaku Yamahata, qemu-devel; +Cc: owasserm, quintela, mrhines, pbonzini

Applied.  Thanks.

Regards,

Anthony Liguori

^ permalink raw reply	[flat|nested] 8+ messages in thread

end of thread, other threads:[~2013-08-14 16:28 UTC | newest]

Thread overview: 8+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2013-08-07  2:26 [Qemu-devel] [PATCH 0/3] rdma: validate remote provided RDMAControlHeader::len Isaku Yamahata
2013-08-07  2:26 ` [Qemu-devel] [PATCH 1/3] rdma: use resp.len after validation in qemu_rdma_registration_stop Isaku Yamahata
2013-08-07  2:26 ` [Qemu-devel] [PATCH 2/3] rdma: validate RDMAControlHeader::len Isaku Yamahata
2013-08-07  2:26 ` [Qemu-devel] [PATCH 3/3] rdma: check if RDMAControlHeader::len match transferred byte Isaku Yamahata
2013-08-07  7:40 ` [Qemu-devel] [PATCH 0/3] rdma: validate remote provided RDMAControlHeader::len Paolo Bonzini
2013-08-07  8:54 ` Orit Wasserman
2013-08-07 15:02 ` Michael R. Hines
2013-08-14 16:27 ` Anthony Liguori

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).