# HG changeset patch # User John Levon <john.levon@xxxxxxx> # 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@xxxxxxx> 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 -- Libvir-list mailing list Libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list