[libvirt] [PATCH] Fix oversized stack allocation

john.levon at sun.com john.levon at sun.com
Wed Jan 14 15:22:18 UTC 2009


# HG changeset patch
# User John Levon <john.levon at sun.com>
# Date 1231946129 28800
# Node ID c7538cb7fab4e6f3aa6714fdd4126dcf2f0371b4
# Parent  cfe04caba5de61620fa6d1c2bff85cfd62255c1d
Fix oversized stack allocation

REMOTE_MESSAGE_MAX is a whopping 262Kb and shouldn't be allocated on the
stack.

Signed-off-by: Ryan Scott <ryan.scott at sun.com>

diff --git a/src/remote_internal.c b/src/remote_internal.c
--- a/src/remote_internal.c
+++ b/src/remote_internal.c
@@ -4797,10 +4797,11 @@ call (virConnectPtr conn, struct private
       xdrproc_t args_filter, char *args,
       xdrproc_t ret_filter, char *ret)
 {
-    char buffer[REMOTE_MESSAGE_MAX];
+    char *buffer = NULL;
     char buffer2[4];
     struct remote_message_header hdr;
     XDR xdr;
+    int err = -1;
     int len;
     struct remote_error rerror;
 
@@ -4814,18 +4815,23 @@ call (virConnectPtr conn, struct private
     hdr.serial = serial;
     hdr.status = REMOTE_OK;
 
+    if ((buffer = malloc(REMOTE_MESSAGE_MAX)) == NULL) {
+        error (conn, VIR_ERR_SYSTEM_ERROR, strerror (errno));
+        goto out;
+    }
+
     /* Serialise header followed by args. */
-    xdrmem_create (&xdr, buffer, sizeof buffer, XDR_ENCODE);
+    xdrmem_create (&xdr, buffer, REMOTE_MESSAGE_MAX, XDR_ENCODE);
     if (!xdr_remote_message_header (&xdr, &hdr)) {
         error (flags & REMOTE_CALL_IN_OPEN ? NULL : conn,
                VIR_ERR_RPC, _("xdr_remote_message_header failed"));
-        return -1;
+        goto out;
     }
 
     if (!(*args_filter) (&xdr, args)) {
         error (flags & REMOTE_CALL_IN_OPEN ? NULL : conn, VIR_ERR_RPC,
                _("marshalling args"));
-        return -1;
+        goto out;
     }
 
     /* Get the length stored in buffer. */
@@ -4842,25 +4848,25 @@ call (virConnectPtr conn, struct private
     if (!xdr_int (&xdr, &len)) {
         error (flags & REMOTE_CALL_IN_OPEN ? NULL : conn, VIR_ERR_RPC,
                _("xdr_int (length word)"));
-        return -1;
+        goto out;
     }
     xdr_destroy (&xdr);
 
     /* Send length word followed by header+args. */
     if (really_write (conn, priv, flags & REMOTE_CALL_IN_OPEN, buffer2, sizeof buffer2) == -1 ||
         really_write (conn, priv, flags & REMOTE_CALL_IN_OPEN, buffer, len-4) == -1)
-        return -1;
+        goto out;
 
 retry_read:
     /* Read and deserialise length word. */
     if (really_read (conn, priv, flags & REMOTE_CALL_IN_OPEN, buffer2, sizeof buffer2) == -1)
-        return -1;
+        goto out;
 
     xdrmem_create (&xdr, buffer2, sizeof buffer2, XDR_DECODE);
     if (!xdr_int (&xdr, &len)) {
         error (flags & REMOTE_CALL_IN_OPEN ? NULL : conn,
                VIR_ERR_RPC, _("xdr_int (length word, reply)"));
-        return -1;
+        goto out;
     }
     xdr_destroy (&xdr);
 
@@ -4870,20 +4876,25 @@ retry_read:
     if (len < 0 || len > REMOTE_MESSAGE_MAX) {
         error (flags & REMOTE_CALL_IN_OPEN ? NULL : conn,
                VIR_ERR_RPC, _("packet received from server too large"));
-        return -1;
     }
 
     /* Read reply header and what follows (either a ret or an error). */
     if (really_read (conn, priv, flags & REMOTE_CALL_IN_OPEN, buffer, len) == -1)
-        return -1;
+        goto out;
 
     /* Deserialise reply header. */
     xdrmem_create (&xdr, buffer, len, XDR_DECODE);
     if (!xdr_remote_message_header (&xdr, &hdr)) {
         error (flags & REMOTE_CALL_IN_OPEN ? NULL : conn,
                VIR_ERR_RPC, _("invalid header in reply"));
-        return -1;
-    }
+        goto out;
+    }
+
+    /*
+     * Although the previous lines were the last references to buffer in this
+     * function, we can't free it yet, as the xdr struct still has some
+     * pointers to it.
+     */
 
     /* Check program, version, etc. are what we expect. */
     if (hdr.prog != REMOTE_PROGRAM) {
@@ -4892,7 +4903,7 @@ retry_read:
                          VIR_ERR_RPC, VIR_ERR_ERROR, NULL, NULL, NULL, 0, 0,
                          _("unknown program (received %x, expected %x)"),
                          hdr.prog, REMOTE_PROGRAM);
-        return -1;
+        goto out;
     }
     if (hdr.vers != REMOTE_PROTOCOL_VERSION) {
         virRaiseError (flags & REMOTE_CALL_IN_OPEN ? NULL : conn,
@@ -4900,7 +4911,7 @@ retry_read:
                          VIR_ERR_RPC, VIR_ERR_ERROR, NULL, NULL, NULL, 0, 0,
                          _("unknown protocol version (received %x, expected %x)"),
                          hdr.vers, REMOTE_PROTOCOL_VERSION);
-        return -1;
+        goto out;
     }
 
     if (hdr.proc == REMOTE_PROC_DOMAIN_EVENT &&
@@ -4923,7 +4934,7 @@ retry_read:
                          VIR_ERR_RPC, VIR_ERR_ERROR, NULL, NULL, NULL, 0, 0,
                          _("unknown procedure (received %x, expected %x)"),
                          hdr.proc, proc_nr);
-        return -1;
+        goto out;
     }
     if (hdr.direction != REMOTE_REPLY) {
         virRaiseError (flags & REMOTE_CALL_IN_OPEN ? NULL : conn,
@@ -4931,14 +4942,14 @@ retry_read:
                          VIR_ERR_RPC, VIR_ERR_ERROR, NULL, NULL, NULL, 0, 0,
                          _("unknown direction (received %x, expected %x)"),
                          hdr.direction, REMOTE_REPLY);
-        return -1;
+        goto out;
     }
     if (hdr.serial != serial) {
         virRaiseError (flags & REMOTE_CALL_IN_OPEN ? NULL : conn, NULL, NULL, VIR_FROM_REMOTE,
                          VIR_ERR_RPC, VIR_ERR_ERROR, NULL, NULL, NULL, 0, 0,
                          _("unknown serial (received %x, expected %x)"),
                          hdr.serial, serial);
-        return -1;
+        goto out;
     }
 
     /* Status is either REMOTE_OK (meaning that what follows is a ret
@@ -4950,17 +4961,18 @@ retry_read:
         if (!(*ret_filter) (&xdr, ret)) {
             error (flags & REMOTE_CALL_IN_OPEN ? NULL : conn, VIR_ERR_RPC,
                    _("unmarshalling ret"));
-            return -1;
+            goto out;
         }
         xdr_destroy (&xdr);
-        return 0;
+        err = 0;
+        goto out;
 
     case REMOTE_ERROR:
         memset (&rerror, 0, sizeof rerror);
         if (!xdr_remote_error (&xdr, &rerror)) {
             error (flags & REMOTE_CALL_IN_OPEN ? NULL : conn,
                    VIR_ERR_RPC, _("unmarshalling remote_error"));
-            return -1;
+            goto out;
         }
         xdr_destroy (&xdr);
         /* See if caller asked us to keep quiet about missing RPCs
@@ -4970,11 +4982,12 @@ retry_read:
             rerror.code == VIR_ERR_RPC &&
             rerror.level == VIR_ERR_ERROR &&
             STRPREFIX(*rerror.message, "unknown procedure")) {
-            return -2;
+            err = -2;
+            goto out;
         }
         server_error (flags & REMOTE_CALL_IN_OPEN ? NULL : conn, &rerror);
         xdr_free ((xdrproc_t) xdr_remote_error, (char *) &rerror);
-        return -1;
+        goto out;
 
     default:
         virRaiseError (flags & REMOTE_CALL_IN_OPEN ? NULL : conn, NULL, NULL, VIR_FROM_REMOTE,
@@ -4982,8 +4995,12 @@ retry_read:
                          _("unknown status (received %x)"),
                          hdr.status);
         xdr_destroy (&xdr);
-        return -1;
-    }
+        goto out;
+    }
+
+out:
+    VIR_FREE (buffer);
+    return err;
 }
 
 static int
@@ -5551,7 +5568,7 @@ remoteDomainEventFired(int watch,
                        int event,
                        void *opaque)
 {
-    char buffer[REMOTE_MESSAGE_MAX];
+    char *buffer = NULL;
     char buffer2[4];
     struct remote_message_header hdr;
     XDR xdr;
@@ -5566,22 +5583,22 @@ remoteDomainEventFired(int watch,
          DEBUG("%s : VIR_EVENT_HANDLE_HANGUP or "
                "VIR_EVENT_HANDLE_ERROR encountered", __FUNCTION__);
          virEventRemoveHandle(watch);
-         return;
+         goto out;
     }
 
     if (fd != priv->sock) {
         virEventRemoveHandle(watch);
-        return;
+        goto out;
     }
 
     /* Read and deserialise length word. */
     if (really_read (conn, priv, 0, buffer2, sizeof buffer2) == -1)
-        return;
+        goto out;
 
     xdrmem_create (&xdr, buffer2, sizeof buffer2, XDR_DECODE);
     if (!xdr_int (&xdr, &len)) {
         error (conn, VIR_ERR_RPC, _("xdr_int (length word, reply)"));
-        return;
+        goto out;
     }
     xdr_destroy (&xdr);
 
@@ -5590,20 +5607,25 @@ remoteDomainEventFired(int watch,
 
     if (len < 0 || len > REMOTE_MESSAGE_MAX) {
         error (conn, VIR_ERR_RPC, _("packet received from server too large"));
-        return;
+        goto out;
+    }
+
+    if ((buffer = malloc(REMOTE_MESSAGE_MAX)) == NULL) {
+        error (conn, VIR_ERR_SYSTEM_ERROR, strerror (errno));
+        goto out;
     }
 
     /* Read reply header and what follows (either a ret or an error). */
     if (really_read (conn, priv, 0, buffer, len) == -1) {
         error (conn, VIR_ERR_RPC, _("error reading buffer from memory"));
-        return;
+        goto out;
     }
 
     /* Deserialise reply header. */
     xdrmem_create (&xdr, buffer, len, XDR_DECODE);
     if (!xdr_remote_message_header (&xdr, &hdr)) {
         error (conn, VIR_ERR_RPC, _("invalid header in event firing"));
-        return;
+        goto out;
     }
 
     if (hdr.proc == REMOTE_PROC_DOMAIN_EVENT &&
@@ -5614,6 +5636,9 @@ remoteDomainEventFired(int watch,
         DEBUG0("invalid proc in event firing");
         error (conn, VIR_ERR_RPC, _("invalid proc in event firing"));
     }
+
+out:
+    VIR_FREE (buffer);
 }
 
 void




More information about the libvir-list mailing list