diff options
author | Marius Vollmer <mvollmer@redhat.com> | 2013-02-01 11:27:38 +0200 |
---|---|---|
committer | David Zeuthen <zeuthen@gmail.com> | 2013-02-17 13:47:51 -0800 |
commit | 0a34a0847d9542269991dee3986a8b7c3a748cbc (patch) | |
tree | 847eea049b7ab4554bebe7483c63f50159df6821 | |
parent | 201b23a2ddf0abc5b371a8381b25758d3544450e (diff) |
Make sure logical partitions stay within the extended partition.
Signed-off-by: David Zeuthen <zeuthen@gmail.com>
-rw-r--r-- | src/udiskslinuxpartitiontable.c | 60 |
1 files changed, 59 insertions, 1 deletions
diff --git a/src/udiskslinuxpartitiontable.c b/src/udiskslinuxpartitiontable.c index 73436c5..17fa518 100644 --- a/src/udiskslinuxpartitiontable.c +++ b/src/udiskslinuxpartitiontable.c @@ -216,6 +216,56 @@ have_partition_in_range (UDisksPartitionTable *table, return ret; } +static UDisksPartition * +find_container_partition (UDisksPartitionTable *table, + UDisksObject *object, + guint64 start, + guint64 end) +{ + UDisksPartition *ret = NULL; + UDisksDaemon *daemon = NULL; + GDBusObjectManager *object_manager = NULL; + const gchar *table_object_path; + GList *objects = NULL, *l; + + daemon = udisks_linux_block_object_get_daemon (UDISKS_LINUX_BLOCK_OBJECT (object)); + object_manager = G_DBUS_OBJECT_MANAGER (udisks_daemon_get_object_manager (daemon)); + + table_object_path = g_dbus_object_get_object_path (G_DBUS_OBJECT (object)); + + objects = g_dbus_object_manager_get_objects (object_manager); + for (l = objects; l != NULL; l = l->next) + { + UDisksObject *i_object = UDISKS_OBJECT (l->data); + UDisksPartition *i_partition = NULL; + + i_partition = udisks_object_get_partition (i_object); + + if (i_partition == NULL) + goto cont; + + if (g_strcmp0 (udisks_partition_get_table (i_partition), table_object_path) != 0) + goto cont; + + if (udisks_partition_get_is_container (i_partition) + && ranges_overlap (start, end - start, + udisks_partition_get_offset (i_partition), + udisks_partition_get_size (i_partition))) + { + ret = i_partition; + goto out; + } + + cont: + g_clear_object (&i_partition); + } + + out: + g_list_foreach (objects, (GFunc) g_object_unref, NULL); + g_list_free (objects); + return ret; +} + /* ---------------------------------------------------------------------------------------------------- */ typedef struct @@ -375,11 +425,14 @@ handle_create_partition (UDisksPartitionTable *table, { guint64 start_mib; guint64 end_bytes; + guint64 max_end_bytes; const gchar *part_type; char *endp; gint type_as_int; gboolean is_logical = FALSE; + max_end_bytes = udisks_block_get_size (block); + if (strlen (name) > 0) { g_dbus_method_invocation_return_error (invocation, UDISKS_ERROR, UDISKS_ERROR_FAILED, @@ -413,8 +466,13 @@ handle_create_partition (UDisksPartitionTable *table, } else { + UDisksPartition *container = find_container_partition (table, object, + offset, offset + size); + g_assert (container != NULL); is_logical = TRUE; part_type = "logical ext2"; + max_end_bytes = (udisks_partition_get_offset(container) + + udisks_partition_get_size(container)); } } else @@ -438,7 +496,7 @@ handle_create_partition (UDisksPartitionTable *table, object, start_mib * MIB_SIZE, end_bytes, is_logical) || - end_bytes > udisks_block_get_size (block))) + end_bytes > max_end_bytes)) { /* TODO: if end_bytes is sufficiently big this could be *a lot* of loop iterations * and thus a potential DoS attack... |