[libvirt] [PATCH] Allocate buffer to hold xend response
Jim Fehlig
jfehlig at novell.com
Thu Jun 3 22:51:40 UTC 2010
Jim Meyering wrote:
> Jim Fehlig wrote:
> ...
>
>> Subject: [PATCH] Allocate buffer to hold xend response
>>
>> There are cases when a response from xend can exceed 4096 bytes, in
>> which case anything beyond 4096 is ignored. This patch changes the
>> current fixed-size, stack-allocated buffer to a dynamically allocated
>> buffer based on Content-Length in HTTP header.
>> ---
>> src/xen/xend_internal.c | 80 ++++++++++++++++++++++++-----------------------
>> 1 files changed, 41 insertions(+), 39 deletions(-)
>>
>> diff --git a/src/xen/xend_internal.c b/src/xen/xend_internal.c
>> index e763bad..0c1a738 100644
>> --- a/src/xen/xend_internal.c
>> +++ b/src/xen/xend_internal.c
>> @@ -302,17 +302,19 @@ istartswith(const char *haystack, const char *needle)
>> * xend_req:
>> * @fd: the file descriptor
>> * @content: the buffer to store the content
>> - * @n_content: the size of the buffer
>> *
>> * Read the HTTP response from a Xen Daemon request.
>> + * If the response contains content, memory is allocated to
>> + * hold the content.
>> *
>> - * Returns the HTTP return code.
>> + * Returns the HTTP return code and @content is set to the
>> + * allocated memory containing HTTP content.
>> */
>> static int
>> -xend_req(int fd, char *content, size_t n_content)
>> +xend_req(int fd, char **content)
>> {
>> char buffer[4096];
>> - int content_length = -1;
>> + int content_length = 0;
>> int retcode = 0;
>>
>> while (sreads(fd, buffer, sizeof(buffer)) > 0) {
>> @@ -325,19 +327,17 @@ xend_req(int fd, char *content, size_t n_content)
>> retcode = atoi(buffer + 9);
>> }
>>
>> - if (content_length > -1) {
>> + if (content_length > 0) {
>> ssize_t ret;
>>
>> - if ((unsigned int) content_length > (n_content + 1))
>> - content_length = n_content - 1;
>> + if (VIR_ALLOC_N(*content, content_length) < 0 ) {
>> + virReportOOMError();
>> + return -1;
>> + }
>>
>> - ret = sread(fd, content, content_length);
>> + ret = sread(fd, *content, content_length);
>> if (ret < 0)
>> return -1;
>> -
>> - content[ret] = 0;
>> - } else {
>> - content[0] = 0;
>> }
>>
>
> Hi Jim,
>
> The above removes the code that guarantees the content buffer is
> NUL-terminated, yet I don't see where the requirement for NUL-termination
> has been dropped.
I removed that since VIR_ALLOC_N fills the memory with zeros. Correct?
> Even if the content payload we receive typically ends
> in a NUL, we cannot guarantee that (i.e., content may be corrupted or
> malicious), so we have to verify the assumption or add a NUL byte of
> our own.
>
> While your change does adjust the xend_req caller to handle NULL
> "content", here it will read beyond end of buffer when "*content" has
> no trailing NUL byte:
>
> virXendError(VIR_ERR_GET_FAILED,
> _("%d status from xen daemon: %s:%s"),
> - ret, path, content);
> + ret, path,
> + content ? *content: "NULL");
>
> BTW, please add a space before the ":".
>
Ok.
> Also, now that we'll get the buffer length from an untrusted
> source, it would be good to ensure that it's not outrageously
> large before using it as the size of the buffer we allocate,
> assuming there is some reasonably low upper bound on the maximum
> payload size. That could save us from potential DoS abuse.
>
Good point. Suggestions on the limit?
BTW, I pushed the patch after Eric's ACK. I'll role another to address
these issues, once I get confirmation on the NUL-termination.
Thanks,
Jim
More information about the libvir-list
mailing list