diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms index de4ec4d44..43971db67 100644 --- a/src/libvirt_private.syms +++ b/src/libvirt_private.syms @@ -2751,6 +2751,7 @@ virStrcpy; virStrdup; virStringBufferIsPrintable; virStringEncodeBase64; +virStringFilterChars; virStringHasChars; virStringHasControlChars; virStringIsEmpty; diff --git a/src/lxc/lxc_container.c b/src/lxc/lxc_container.c index b7216d6ee..246145fcd 100644 --- a/src/lxc/lxc_container.c +++ b/src/lxc/lxc_container.c @@ -2159,6 +2159,37 @@ static int lxcContainerSetUserGroup(virCommandPtr cmd, return 0; } +static const char hostname_validchars[] = + "abcdefghijklmnopqrstuvwxyz" + "ABCDEFGHIJKLMNOPQRSTUVWXYZ" + "0123456789-"; + +static int lxcContainerSetHostname(virDomainDefPtr def) +{ + int ret = -1; + char *name = NULL; + char *hostname = NULL; + + /* Filter the VM name to get a valid hostname */ + if (VIR_STRDUP(name, def->name) < 0) + goto cleanup; + + /* RFC 1123 allows 0-9 digits as a first character in hostname */ + virStringFilterChars(name, hostname_validchars); + hostname = name; + if (strlen(name) > 0 && name[0] == '-') + hostname = name + 1; + + if (sethostname(hostname, strlen(hostname)) < 0) { + virReportSystemError(errno, "%s", _("Failed to set hostname")); + goto cleanup; + } + ret = 0; + + cleanup: + VIR_FREE(name); + return ret; +} /** * lxcContainerChild: @@ -2269,6 +2300,10 @@ static int lxcContainerChild(void *data) goto cleanup; } + if (lxcContainerSetHostname(vmDef) < 0) + goto cleanup; + + /* drop a set of root capabilities */ if (lxcContainerDropCapabilities(vmDef, !!hasReboot) < 0) goto cleanup; diff --git a/src/util/virstring.c b/src/util/virstring.c index b2ebce27f..b808aff2c 100644 --- a/src/util/virstring.c +++ b/src/util/virstring.c @@ -1293,6 +1293,30 @@ virStringStripControlChars(char *str) str[j] = '\0'; } +/** + * virStringFilterChars: + * @str: the string to strip + * @valid: the valid characters for the string + * + * Modify the string in-place to remove the characters that aren't + * in the list of valid ones. + */ +void +virStringFilterChars(char *str, const char *valid) +{ + size_t len, i, j; + + if (!str) + return; + + len = strlen(str); + for (i = 0, j = 0; i < len; i++) { + if (strchr(valid, str[i])) + str[j++] = str[i]; + } + str[j] = '\0'; +} + /** * virStringToUpper: * @str: string to capitalize diff --git a/src/util/virstring.h b/src/util/virstring.h index b19abaf9f..8af054bce 100644 --- a/src/util/virstring.h +++ b/src/util/virstring.h @@ -293,6 +293,7 @@ bool virStringHasChars(const char *str, const char *chars); bool virStringHasControlChars(const char *str); void virStringStripControlChars(char *str); +void virStringFilterChars(char *str, const char *valid); bool virStringIsPrintable(const char *str); bool virStringBufferIsPrintable(const uint8_t *buf, size_t buflen); diff --git a/tests/virstringtest.c b/tests/virstringtest.c index 320f7a398..e8518ede1 100644 --- a/tests/virstringtest.c +++ b/tests/virstringtest.c @@ -767,6 +767,36 @@ static int testStripControlChars(const void *args) return ret; } +struct testFilterData { + const char *string; + const char *valid; + const char *result; +}; + +static int testFilterChars(const void *args) +{ + const struct testFilterData *data = args; + int ret = -1; + char *res = NULL; + + if (VIR_STRDUP(res, data->string) < 0) + goto cleanup; + + virStringFilterChars(res, data->valid); + + if (STRNEQ_NULLABLE(res, data->result)) { + fprintf(stderr, "Returned '%s', expected '%s'\n", + NULLSTR(res), NULLSTR(data->result)); + goto cleanup; + } + + ret = 0; + + cleanup: + VIR_FREE(res); + return ret; +} + static int mymain(void) { @@ -1085,6 +1115,22 @@ mymain(void) TEST_STRIP_CONTROL_CHARS("\x01H\x02" "E\x03L\x04L\x05O", "HELLO"); TEST_STRIP_CONTROL_CHARS("\x01\x02\x03\x04HELL\x05O", "HELLO"); TEST_STRIP_CONTROL_CHARS("\nhello \x01\x07hello\t", "\nhello hello\t"); + +#define TEST_FILTER_CHARS(str, filter, res) \ + do { \ + struct testFilterData filterData = { \ + .string = str, \ + .valid = filter, \ + .result = res, \ + }; \ + if (virTestRun("Filter chars from " #str, \ + testFilterChars, &filterData) < 0) \ + ret = -1; \ + } while (0) + + TEST_FILTER_CHARS(NULL, NULL, NULL); + TEST_FILTER_CHARS("hello 123 hello", "helo", "hellohello"); + return ret == 0 ? EXIT_SUCCESS : EXIT_FAILURE; }