summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--WHATS_NEW_DM1
-rw-r--r--libdm/ioctl/libdm-iface.c30
-rw-r--r--libdm/libdm-common.c8
3 files changed, 29 insertions, 10 deletions
diff --git a/WHATS_NEW_DM b/WHATS_NEW_DM
index a4e90fb5..28484e2c 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 e8bde294..0e3dab5e 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 2d793bd6..26034367 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\" "