Re: [libvirt] [PATCH v3 2/3] conf: add check if migration_host is a localhost address
This patch has triggered a Coverity RESOURCE_LEAK (3 actually) On 10/08/2014 09:54 PM, Chen, Fan wrote: On Wed, 2014-10-08 at 12:33 +0200, Ján Tomko wrote: On 10/07/2014 06:07 AM, Chen Fan wrote: Signed-off-by: Chen Fan chen.fan.f...@cn.fujitsu.com diff --git a/src/util/virsocketaddr.c b/src/util/virsocketaddr.c index 6d36689..a19e3af 100644 --- a/src/util/virsocketaddr.c +++ b/src/util/virsocketaddr.c @@ -889,15 +889,24 @@ virSocketAddrNumericFamily(const char *address) * false otherwise */ bool -virSocketAddrIsNumericLocalhost(const virSocketAddr *addr) +virSocketAddrIsNumericLocalhost(const char *addr) { +struct addrinfo *res; struct in_addr tmp = { .s_addr = htonl(INADDR_LOOPBACK) }; -switch (addr-data.stor.ss_family) { +struct sockaddr_in *inet4; +struct sockaddr_in6 *inet6; + +if (virSocketAddrParseInternal(res, addr, AF_UNSPEC, false) 0) +return false; + 'res' allocates something that must be free'd +switch (res-ai_addr-sa_family) { case AF_INET: -return memcmp(addr-data.inet4.sin_addr.s_addr, tmp.s_addr, - sizeof(addr-data.inet4.sin_addr.s_addr)) == 0; +inet4 = (struct sockaddr_in*) res-ai_addr; Leak #1 +return memcmp(inet4-sin_addr.s_addr, tmp.s_addr, + sizeof(inet4-sin_addr.s_addr)) == 0; case AF_INET6: -return IN6_IS_ADDR_LOOPBACK(addr-data.inet6.sin6_addr); +inet6 = (struct sockaddr_in6*) res-ai_addr; Leak #2 +return IN6_IS_ADDR_LOOPBACK((inet6-sin6_addr)); } Leak #3 return false; Other callers will call 'freeaddrinfo(res);' In order to resolve - you probably need to create a local ret = false, then assign ret = to either memcmp/IN6_IS_ADDR_LOOPBACK return, then call freeaddrinfo() before return ret John -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
Re: [libvirt] [PATCH v3 2/3] conf: add check if migration_host is a localhost address
On Wed, 2014-10-15 at 04:46 -0400, John Ferlan wrote: This patch has triggered a Coverity RESOURCE_LEAK (3 actually) Right, I will make a patch to fix it. Thank you for catching that. On 10/08/2014 09:54 PM, Chen, Fan wrote: On Wed, 2014-10-08 at 12:33 +0200, Ján Tomko wrote: On 10/07/2014 06:07 AM, Chen Fan wrote: Signed-off-by: Chen Fan chen.fan.f...@cn.fujitsu.com diff --git a/src/util/virsocketaddr.c b/src/util/virsocketaddr.c index 6d36689..a19e3af 100644 --- a/src/util/virsocketaddr.c +++ b/src/util/virsocketaddr.c @@ -889,15 +889,24 @@ virSocketAddrNumericFamily(const char *address) * false otherwise */ bool -virSocketAddrIsNumericLocalhost(const virSocketAddr *addr) +virSocketAddrIsNumericLocalhost(const char *addr) { +struct addrinfo *res; struct in_addr tmp = { .s_addr = htonl(INADDR_LOOPBACK) }; -switch (addr-data.stor.ss_family) { +struct sockaddr_in *inet4; +struct sockaddr_in6 *inet6; + +if (virSocketAddrParseInternal(res, addr, AF_UNSPEC, false) 0) +return false; + 'res' allocates something that must be free'd +switch (res-ai_addr-sa_family) { case AF_INET: -return memcmp(addr-data.inet4.sin_addr.s_addr, tmp.s_addr, - sizeof(addr-data.inet4.sin_addr.s_addr)) == 0; +inet4 = (struct sockaddr_in*) res-ai_addr; Leak #1 +return memcmp(inet4-sin_addr.s_addr, tmp.s_addr, + sizeof(inet4-sin_addr.s_addr)) == 0; case AF_INET6: -return IN6_IS_ADDR_LOOPBACK(addr-data.inet6.sin6_addr); +inet6 = (struct sockaddr_in6*) res-ai_addr; Leak #2 +return IN6_IS_ADDR_LOOPBACK((inet6-sin6_addr)); } Leak #3 return false; Other callers will call 'freeaddrinfo(res);' In order to resolve - you probably need to create a local ret = false, then assign ret = to either memcmp/IN6_IS_ADDR_LOOPBACK return, then call freeaddrinfo() before return ret John -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
Re: [libvirt] [PATCH v3 2/3] conf: add check if migration_host is a localhost address
On 10/07/2014 06:07 AM, Chen Fan wrote: Signed-off-by: Chen Fan chen.fan.f...@cn.fujitsu.com --- src/libvirt_private.syms | 1 + src/qemu/qemu_conf.c | 50 src/qemu/qemu_conf.h | 2 ++ src/util/virsocketaddr.c | 24 +++ src/util/virsocketaddr.h | 2 ++ 5 files changed, 79 insertions(+) diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms index 8ab1394..a104bc6 100644 --- a/src/libvirt_private.syms +++ b/src/libvirt_private.syms @@ -1911,6 +1911,7 @@ virSocketAddrGetIpPrefix; virSocketAddrGetPort; virSocketAddrGetRange; virSocketAddrIsNetmask; +virSocketAddrIsNumericLocalhost; virSocketAddrIsPrivate; virSocketAddrIsWildcard; virSocketAddrMask; diff --git a/src/qemu/qemu_conf.c b/src/qemu/qemu_conf.c index adc6caf..6b0ac5c 100644 --- a/src/qemu/qemu_conf.c +++ b/src/qemu/qemu_conf.c @@ -707,6 +707,15 @@ int virQEMUDriverConfigLoadFile(virQEMUDriverConfigPtr cfg, GET_VALUE_LONG(seccomp_sandbox, cfg-seccompSandbox); GET_VALUE_STR(migration_host, cfg-migrateHost); +if (cfg-migrateHost +qemuCheckLocalhost(cfg-migrateHost)) { +virReportError(VIR_ERR_CONF_SYNTAX, + _(migration_host must not be the address of + the local machine: %s), + cfg-migrateHost); +goto cleanup; +} + GET_VALUE_STR(migration_address, cfg-migrationAddress); GET_VALUE_BOOL(log_timestamp, cfg-logTimestamp); @@ -1371,3 +1380,44 @@ qemuGetDefaultHugepath(virHugeTLBFSPtr hugetlbfs, return qemuGetHugepagePath(hugetlbfs[i]); } + +bool +qemuCheckLocalhost(const char *addrStr) +{ +virSocketAddr addr; +char *hostname, *tmp; +bool encloseAddress = false; +int family; +bool ret = true; + +if (VIR_STRDUP(hostname, addrStr) 0) +return false; + +tmp = hostname; + +if (STRPREFIX(hostname, [)) { +char *end = strchr(hostname, ']'); +if (end) { +*end = '\0'; +hostname++; +encloseAddress = true; +} +} We don't format the qemu.conf back and we don't need the brackets for anything. We can just store the migration host without them in cfg-migrationHost + +if (STRPREFIX(hostname, localhost)) +goto cleanup; + +family = virSocketAddrNumericFamily(hostname); +if ((family == AF_INET !encloseAddress) || +family == AF_INET6) { +if (virSocketAddrParse(addr, hostname, family) 0 +virSocketAddrIsNumericLocalhost(addr)) { +goto cleanup; +} +} There's no need to check for family upfront. + +ret = false; +cleanup: +VIR_FREE(tmp); +return ret; +} diff --git a/src/qemu/qemu_conf.h b/src/qemu/qemu_conf.h index cb01fb6..c9ce53c 100644 --- a/src/qemu/qemu_conf.h +++ b/src/qemu/qemu_conf.h @@ -322,4 +322,6 @@ int qemuTranslateSnapshotDiskSourcePool(virConnectPtr conn, char * qemuGetHugepagePath(virHugeTLBFSPtr hugepage); char * qemuGetDefaultHugepath(virHugeTLBFSPtr hugetlbfs, size_t nhugetlbfs); + +bool qemuCheckLocalhost(const char *addrStr); #endif /* __QEMUD_CONF_H */ diff --git a/src/util/virsocketaddr.c b/src/util/virsocketaddr.c index 7fe7a15..6d36689 100644 --- a/src/util/virsocketaddr.c +++ b/src/util/virsocketaddr.c @@ -878,3 +878,27 @@ virSocketAddrNumericFamily(const char *address) freeaddrinfo(res); return family; } + +/** + * virSocketAddrIsNumericLocalhost: + * @address: address to check + * + * Check if passed address is a numeric 'localhost' address. + * + * Returns: true if @address is a numeric 'localhost' address, + * false otherwise + */ +bool +virSocketAddrIsNumericLocalhost(const virSocketAddr *addr) I've rewritten this function to take a 'const char *' argument. Along with the virStringStripIPv6Brackets function I've sent for review separately, this removes the need for a separate qemuCheckLocalhost function and it can be inlined. +{ +struct in_addr tmp = { .s_addr = htonl(INADDR_LOOPBACK) }; +switch (addr-data.stor.ss_family) { +case AF_INET: +return memcmp(addr-data.inet4.sin_addr.s_addr, tmp.s_addr, + sizeof(addr-data.inet4.sin_addr.s_addr)) == 0; +case AF_INET6: +return IN6_IS_ADDR_LOOPBACK(addr-data.inet6.sin6_addr); +} +return false; + +} The diff I'll squash into this patch before pushing (after virStringStripIPv6Brackets is sorted out): --- a/src/qemu/qemu_conf.c +++ b/src/qemu/qemu_conf.c @@ -707,8 +707,10 @@ int virQEMUDriverConfigLoadFile(virQEMUDriverConfigPtr cfg, GET_VALUE_LONG(seccomp_sandbox, cfg-seccompSandbox); GET_VALUE_STR(migration_host, cfg-migrateHost); +virStringStripIPv6Brackets(cfg-migrateHost); if (cfg-migrateHost -
Re: [libvirt] [PATCH v3 2/3] conf: add check if migration_host is a localhost address
On Wed, 2014-10-08 at 12:33 +0200, Ján Tomko wrote: On 10/07/2014 06:07 AM, Chen Fan wrote: Signed-off-by: Chen Fan chen.fan.f...@cn.fujitsu.com --- src/libvirt_private.syms | 1 + src/qemu/qemu_conf.c | 50 src/qemu/qemu_conf.h | 2 ++ src/util/virsocketaddr.c | 24 +++ src/util/virsocketaddr.h | 2 ++ 5 files changed, 79 insertions(+) diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms index 8ab1394..a104bc6 100644 --- a/src/libvirt_private.syms +++ b/src/libvirt_private.syms @@ -1911,6 +1911,7 @@ virSocketAddrGetIpPrefix; virSocketAddrGetPort; virSocketAddrGetRange; virSocketAddrIsNetmask; +virSocketAddrIsNumericLocalhost; virSocketAddrIsPrivate; virSocketAddrIsWildcard; virSocketAddrMask; diff --git a/src/qemu/qemu_conf.c b/src/qemu/qemu_conf.c index adc6caf..6b0ac5c 100644 --- a/src/qemu/qemu_conf.c +++ b/src/qemu/qemu_conf.c @@ -707,6 +707,15 @@ int virQEMUDriverConfigLoadFile(virQEMUDriverConfigPtr cfg, GET_VALUE_LONG(seccomp_sandbox, cfg-seccompSandbox); GET_VALUE_STR(migration_host, cfg-migrateHost); +if (cfg-migrateHost +qemuCheckLocalhost(cfg-migrateHost)) { +virReportError(VIR_ERR_CONF_SYNTAX, + _(migration_host must not be the address of + the local machine: %s), + cfg-migrateHost); +goto cleanup; +} + GET_VALUE_STR(migration_address, cfg-migrationAddress); GET_VALUE_BOOL(log_timestamp, cfg-logTimestamp); @@ -1371,3 +1380,44 @@ qemuGetDefaultHugepath(virHugeTLBFSPtr hugetlbfs, return qemuGetHugepagePath(hugetlbfs[i]); } + +bool +qemuCheckLocalhost(const char *addrStr) +{ +virSocketAddr addr; +char *hostname, *tmp; +bool encloseAddress = false; +int family; +bool ret = true; + +if (VIR_STRDUP(hostname, addrStr) 0) +return false; + +tmp = hostname; + +if (STRPREFIX(hostname, [)) { +char *end = strchr(hostname, ']'); +if (end) { +*end = '\0'; +hostname++; +encloseAddress = true; +} +} We don't format the qemu.conf back and we don't need the brackets for anything. We can just store the migration host without them in cfg-migrationHost + +if (STRPREFIX(hostname, localhost)) +goto cleanup; + +family = virSocketAddrNumericFamily(hostname); +if ((family == AF_INET !encloseAddress) || +family == AF_INET6) { +if (virSocketAddrParse(addr, hostname, family) 0 +virSocketAddrIsNumericLocalhost(addr)) { +goto cleanup; +} +} There's no need to check for family upfront. + +ret = false; +cleanup: +VIR_FREE(tmp); +return ret; +} diff --git a/src/qemu/qemu_conf.h b/src/qemu/qemu_conf.h index cb01fb6..c9ce53c 100644 --- a/src/qemu/qemu_conf.h +++ b/src/qemu/qemu_conf.h @@ -322,4 +322,6 @@ int qemuTranslateSnapshotDiskSourcePool(virConnectPtr conn, char * qemuGetHugepagePath(virHugeTLBFSPtr hugepage); char * qemuGetDefaultHugepath(virHugeTLBFSPtr hugetlbfs, size_t nhugetlbfs); + +bool qemuCheckLocalhost(const char *addrStr); #endif /* __QEMUD_CONF_H */ diff --git a/src/util/virsocketaddr.c b/src/util/virsocketaddr.c index 7fe7a15..6d36689 100644 --- a/src/util/virsocketaddr.c +++ b/src/util/virsocketaddr.c @@ -878,3 +878,27 @@ virSocketAddrNumericFamily(const char *address) freeaddrinfo(res); return family; } + +/** + * virSocketAddrIsNumericLocalhost: + * @address: address to check + * + * Check if passed address is a numeric 'localhost' address. + * + * Returns: true if @address is a numeric 'localhost' address, + * false otherwise + */ +bool +virSocketAddrIsNumericLocalhost(const virSocketAddr *addr) I've rewritten this function to take a 'const char *' argument. Along with the virStringStripIPv6Brackets function I've sent for review separately, this removes the need for a separate qemuCheckLocalhost function and it can be inlined. +{ +struct in_addr tmp = { .s_addr = htonl(INADDR_LOOPBACK) }; +switch (addr-data.stor.ss_family) { +case AF_INET: +return memcmp(addr-data.inet4.sin_addr.s_addr, tmp.s_addr, + sizeof(addr-data.inet4.sin_addr.s_addr)) == 0; +case AF_INET6: +return IN6_IS_ADDR_LOOPBACK(addr-data.inet6.sin6_addr); +} +return false; + +} The diff I'll squash into this patch before pushing (after virStringStripIPv6Brackets is sorted out): I had tested this diff and it works fine. Thanks, Chen --- a/src/qemu/qemu_conf.c +++ b/src/qemu/qemu_conf.c @@ -707,8 +707,10 @@ int