diff --git a/WHATS_NEW_DM b/WHATS_NEW_DM index a4e90fb5c..28484e2c1 100644 --- a/WHATS_NEW_DM +++ b/WHATS_NEW_DM @@ -1,5 +1,6 @@ Version 1.02.74 - ================================ + Check whether device names are properly mangled on ioctl return. Deactivation of failed thin check on thin pool returns success. Version 1.02.73 - 3rd March 2012 diff --git a/libdm/ioctl/libdm-iface.c b/libdm/ioctl/libdm-iface.c index e8bde2940..0e3dab5ed 100644 --- a/libdm/ioctl/libdm-iface.c +++ b/libdm/ioctl/libdm-iface.c @@ -1550,41 +1550,47 @@ static const char *_sanitise_message(char *message) return sanitised_message; } -static void _do_dm_ioctl_unmangle_name(char *name) +static int _do_dm_ioctl_unmangle_name(char *name) { dm_string_mangling_t mode = dm_get_name_mangling_mode(); char buf[DM_NAME_LEN]; int r; if (mode == DM_STRING_MANGLING_NONE) - return; + return 1; if ((r = unmangle_name(name, DM_NAME_LEN, buf, sizeof(buf), - dm_get_name_mangling_mode())) < 0) + dm_get_name_mangling_mode())) < 0) { log_debug("_do_dm_ioctl_unmangle_name: failed to " "unmangle \"%s\"", name); - else if (r) + return 0; + } else if (r) memcpy(name, buf, strlen(buf) + 1); + + return 1; } -static void _dm_ioctl_unmangle_names(int type, struct dm_ioctl *dmi) +static int _dm_ioctl_unmangle_names(int type, struct dm_ioctl *dmi) { struct dm_names *names; unsigned next = 0; char *name; + int r = 1; if ((name = dmi->name)) - _do_dm_ioctl_unmangle_name(name); + r = _do_dm_ioctl_unmangle_name(name); if (type == DM_DEVICE_LIST && ((names = ((struct dm_names *) ((char *)dmi + dmi->data_start)))) && names->dev) { do { names = (struct dm_names *)((char *) names + next); - _do_dm_ioctl_unmangle_name(names->name); + r = _do_dm_ioctl_unmangle_name(names->name); next = names->next; } while (next); } + + return r; } static struct dm_ioctl *_do_dm_ioctl(struct dm_task *dmt, unsigned command, @@ -1703,8 +1709,7 @@ static struct dm_ioctl *_do_dm_ioctl(struct dm_task *dmt, unsigned command, */ *retryable = errno == EBUSY; - _dm_zfree_dmi(dmi); - return NULL; + goto error; } } @@ -1715,11 +1720,16 @@ static struct dm_ioctl *_do_dm_ioctl(struct dm_task *dmt, unsigned command, _udev_complete(dmt); } - (void) _dm_ioctl_unmangle_names(dmt->type, dmi); + if (!_dm_ioctl_unmangle_names(dmt->type, dmi)) + goto error; #else /* Userspace alternative for testing */ #endif return dmi; + +error: + _dm_zfree_dmi(dmi); + return NULL; } void dm_task_update_nodes(void) diff --git a/libdm/libdm-common.c b/libdm/libdm-common.c index 2d793bd67..260343670 100644 --- a/libdm/libdm-common.c +++ b/libdm/libdm-common.c @@ -421,6 +421,7 @@ bad2: int unmangle_name(const char *str, size_t len, char *buf, size_t buf_len, dm_string_mangling_t mode) { + int strict = mode != DM_STRING_MANGLING_NONE; char str_rest[DM_NAME_LEN]; size_t i, j; int code; @@ -439,6 +440,13 @@ int unmangle_name(const char *str, size_t len, char *buf, } for (i = 0, j = 0; str[i]; i++, j++) { + if (strict && !(_is_whitelisted_char(str[i]) || str[i]=='\\')) { + log_error("The name \"%s\" should be mangled but " + "it contains blacklisted characters.", str); + j=0; r=-1; + goto out; + } + if (str[i] == '\\' && str[i+1] == 'x') { if (!sscanf(&str[i+2], "%2x%s", &code, str_rest)) { log_debug("Hex encoding mismatch detected in \"%s\" "