>From a23969a4505a7cfb8d741b81e70ab23a868862c7 Mon Sep 17 00:00:00 2001 From: "Richard W.M. Jones" Date: Mon, 1 Apr 2019 16:36:15 +0100 Subject: [PATCH] lib: qemu: rbd: Properly escape IPv6 addresses. Each ':' character in the address must be escaped from qemu. Thanks: Jonathan Wright --- common/utils/guestfs-utils.h | 1 + common/utils/utils.c | 47 ++++++++++++++++++++++++++++++++++++ lib/qemu.c | 37 +++++++++------------------- 3 files changed, 60 insertions(+), 25 deletions(-) diff --git a/common/utils/guestfs-utils.h b/common/utils/guestfs-utils.h index 1459a4c3c..52aeca012 100644 --- a/common/utils/guestfs-utils.h +++ b/common/utils/guestfs-utils.h @@ -47,6 +47,7 @@ extern char *guestfs_int_concat_strings (char *const *); extern char **guestfs_int_copy_string_list (char *const *); extern char *guestfs_int_join_strings (const char *sep, char *const *); extern char **guestfs_int_split_string (char sep, const char *); +extern char *guestfs_int_replace_string (const char *str, const char *s1, const char *s2); extern char *guestfs_int_exit_status_to_string (int status, const char *cmd_name, char *buffer, size_t buflen); extern int guestfs_int_random_string (char *ret, size_t len); extern char *guestfs_int_drive_name (size_t index, char *ret); diff --git a/common/utils/utils.c b/common/utils/utils.c index 48e7ed4d1..18725f693 100644 --- a/common/utils/utils.c +++ b/common/utils/utils.c @@ -214,6 +214,53 @@ guestfs_int_split_string (char sep, const char *str) return ret; } +/** + * Replace every instance of C appearing in C with C. A + * newly allocated string is returned which must be freed by the + * caller. If allocation fails this can return C. + * + * For example: + * + * replace_string ("abcabb", "ab", "a"); + * + * would return C<"acab">. + */ +char * +guestfs_int_replace_string (const char *str, const char *s1, const char *s2) +{ + const size_t len = strlen (str), s1len = strlen (s1), s2len = strlen (s2); + size_t i, n; + char *ret; + + /* Count the size of the final string. */ + n = 0; + for (i = 0; i < len; ++i) { + if (strncmp (&str[i], s1, s1len) == 0) + n += s2len; + else + n++; + } + + ret = malloc (n+1); + if (ret == NULL) + return NULL; + + n = 0; + for (i = 0; i < len; ++i) { + if (strncmp (&str[i], s1, s1len) == 0) { + strcpy (&ret[n], s2); + n += s2len; + } + else { + ret[n] = str[i]; + n++; + } + } + ret[n] = '\0'; + + return ret; +} + /** * Translate a wait/system exit status into a printable string. */ diff --git a/lib/qemu.c b/lib/qemu.c index 2f3493217..21450f996 100644 --- a/lib/qemu.c +++ b/lib/qemu.c @@ -903,37 +903,24 @@ guestfs_int_drive_source_qemu_param (guestfs_h *g, } case drive_protocol_rbd: { + CLEANUP_FREE_STRING_LIST char **hosts = NULL; CLEANUP_FREE char *mon_host = NULL, *username = NULL, *secret = NULL; const char *auth; - size_t n = 0; - size_t i, j; + size_t i; - /* build the list of all the mon hosts */ - for (i = 0; i < src->nr_servers; i++) { - n += strlen (src->servers[i].u.hostname); - n += 8; /* for slashes, colons, & port numbers */ - } - n++; /* for \0 */ - mon_host = safe_malloc (g, n); - n = 0; - for (i = 0; i < src->nr_servers; i++) { - CLEANUP_FREE char *port = NULL; + /* Build the list of all the mon hosts. */ + hosts = safe_calloc (g, src->nr_servers + 1, sizeof (char *)); - for (j = 0; j < strlen (src->servers[i].u.hostname); j++) - mon_host[n++] = src->servers[i].u.hostname[j]; - mon_host[n++] = '\\'; - mon_host[n++] = ':'; - port = safe_asprintf (g, "%d", src->servers[i].port); - for (j = 0; j < strlen (port); j++) - mon_host[n++] = port[j]; + for (i = 0; i < src->nr_servers; i++) { + CLEANUP_FREE char *escaped_host; - /* join each host with \; */ - if (i != src->nr_servers - 1) { - mon_host[n++] = '\\'; - mon_host[n++] = ';'; - } + escaped_host = + guestfs_int_replace_string (src->servers[i].u.hostname, ":", "\\:"); + if (escaped_host == NULL) g->abort_cb (); + hosts[i] = + safe_asprintf (g, "%s\\:%d", escaped_host, src->servers[i].port); } - mon_host[n] = '\0'; + mon_host = guestfs_int_join_strings ("\\;", hosts); if (src->username) username = safe_asprintf (g, ":id=%s", src->username); -- 2.20.1