[libvirt] [PATCH] util: fix libvirtd crash caused by virStorageNetHostTransportTypeFromString
Peter Krempa
pkrempa at redhat.com
Wed Oct 29 09:50:35 UTC 2014
On 10/27/14 07:40, Shanzhi Yu wrote:
>
> On 10/25/2014 03:12 AM, Eric Blake wrote:
>> On 10/24/2014 01:01 PM, Shanzhi Yu wrote:
>>> When split uri->scheme into two strings with "+", the second one will be
>> s/split/splitting/
>>
>>> "rdma://server/..", pass it to virStorageNetHostTransportTypeFromString
>>> will lead libvirtd crash. So a second virStringSplit call is needed.
>> Can you show the FULL string that is being passed into this function,
>> and not just the string after the first split on '+'? That is, showing
>> an easy formula of how to reproduce the bug makes it easier to know if
>> the solution is right.
>
> Seem the solution is not right. I misunderstand uri->scheme as
> "gluster+tcp://NetHostIP/path/to/volume"
> The scheme should be "gluster+tcp" or "gluster+rdma" ?
> ..
>
> if (!(uri = virURIParse(path))) {
> virReportError(VIR_ERR_INTERNAL_ERROR,
> _("failed to parse backing file location '%s'"),
> path);
> goto cleanup;
> }
>
> if (!(scheme = virStringSplit(uri->scheme, "+", 2)))
> goto cleanup;
> ..
>
> But it is easy to reproduce this crash
>
> Steps:
>
> 1) Create a volume with "gluster+tcp" or "gluster+rmda" as backend
> # qemu-img create -f qcow2 /var/lib/libvirt/images/tcp.img -b
> gluster+tcp://10.66.6.111/gluster-vol1/rhel65.img -o backing_fmt=raw 1G
> Formatting '/var/lib/libvirt/images/tcp.img', fmt=qcow2 size=1073741824
> backing_file='gluster+tcp://10.66.6.111/gluster-vol1/rhel65.img'
> backing_fmt='raw' encryption=off cluster_size=65536 lazy_refcounts=off
>
> 2) Refresh pool default (target pach /var/lib/libvirt/images)
> # virsh pool-refresh default
>
> Libvirtd will crash
>
> ..
> Program received signal SIGSEGV, Segmentation fault.
> [Switching to Thread 0x7f5df5e4d700 (LWP 23916)]
> virStorageSourceParseBackingURI (path=<optimized out>,
> src=0x7f5de0009130) at util/virstoragefile.c:2126
> 2126 (src->hosts->transport =
> virStorageNetHostTransportTypeFromString(scheme[1])) < 0) {
> (gdb)
>
> ..
>
>
>>
>>> Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1156288
>> You have to assume that not everyone will click through this link.
>>
>>> Signed-off-by: Shanzhi Yu <shyu at redhat.com>
>>> ---
>>> src/util/virstoragefile.c | 3 +++
>>> 1 file changed, 3 insertions(+)
>>>
>>> diff --git a/src/util/virstoragefile.c b/src/util/virstoragefile.c
>>> index 960aa23..795c188 100644
>>> --- a/src/util/virstoragefile.c
>>> +++ b/src/util/virstoragefile.c
>>> @@ -2144,6 +2144,9 @@
>>> virStorageSourceParseBackingURI(virStorageSourcePtr src,
>>> goto cleanup;
>>> }
>>> + if (!(scheme = virStringSplit(scheme[1], ":", 2)))
>> Ouch. Memory leak. You are overwriting the contents of malloc'd scheme
>> with a new pointer. You'll need to send a v2.
>
> As talk before, seem the solution is wrong. But I do escape the crash
> with below patch
>
The patch below avoids the crash as it avoids parsing the scheme at all.
The problem is different though:
> diff --git a/src/util/virstoragefile.c b/src/util/virstoragefile.c
> index 960aa23..a8373af 100644
> --- a/src/util/virstoragefile.c
> +++ b/src/util/virstoragefile.c
> @@ -2124,6 +2124,7 @@
> virStorageSourceParseBackingURI(virStorageSourcePtr src,
> {
> virURIPtr uri = NULL;
> char **scheme = NULL;
> + char **scheme1 = NULL;
> int ret = -1;
>
> if (!(uri = virURIParse(path))) {
> @@ -2144,11 +2145,14 @@
> virStorageSourceParseBackingURI(virStorageSourcePtr src,
> goto cleanup;
> }
>
> - if (scheme[1] &&
> - (src->hosts->transport =
> virStorageNetHostTransportTypeFromString(scheme[1])) <
> + if (scheme[1] && !(scheme1 = virStringSplit(scheme[1], ":", 2)))
> + goto cleanup;
The scheme doesn't contain the colon thus scheme1 will always have only
one element
> +
> + if (scheme1[1] &&
and thus never trigger this condition.
> + (src->hosts->transport =
The real problem is here though. src->hosts is not allocated and thus
dereferencing it crashes libvirt. The code that allocates it is a bit
below and needs to be moved upwards.
I'll be sending a patch shortly. Please make sure that you are fixing
the right problem next time.
> virStorageNetHostTransportTypeFromString(scheme1[1]))
> virReportError(VIR_ERR_INTERNAL_ERROR,
> _("invalid protocol transport type '%s'"),
> - scheme[1]);
> + scheme1[1]);
> goto cleanup;
> }
>
> @@ -2201,6 +2205,8 @@
> virStorageSourceParseBackingURI(virStorageSourcePtr src,
> cleanup:
> virURIFree(uri);
> virStringFreeList(scheme);
> + if (!scheme1)
> + virStringFreeList(scheme1);
> return ret;
> }
>
>
>
>>> + goto cleanup;
>>> +
>>> if (scheme[1] &&
>>> (src->hosts->transport =
>>> virStorageNetHostTransportTypeFromString(scheme[1])) < 0) {
>>> virReportError(VIR_ERR_INTERNAL_ERROR,
>>>
>
Peter
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 819 bytes
Desc: OpenPGP digital signature
URL: <http://listman.redhat.com/archives/libvir-list/attachments/20141029/4401f6f5/attachment-0001.sig>
More information about the libvir-list
mailing list