summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMarius Vollmer <mvollmer@redhat.com>2013-02-01 11:27:38 +0200
committerDavid Zeuthen <zeuthen@gmail.com>2013-02-17 13:47:51 -0800
commit0a34a0847d9542269991dee3986a8b7c3a748cbc (patch)
tree847eea049b7ab4554bebe7483c63f50159df6821
parent201b23a2ddf0abc5b371a8381b25758d3544450e (diff)
Make sure logical partitions stay within the extended partition.
Signed-off-by: David Zeuthen <zeuthen@gmail.com>
-rw-r--r--src/udiskslinuxpartitiontable.c60
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...