Index: uspace/lib/fdisk/src/fdisk.c
===================================================================
--- uspace/lib/fdisk/src/fdisk.c	(revision ff381a79ad697b23cc01e3f8a66966d2d2cbd7dc)
+++ uspace/lib/fdisk/src/fdisk.c	(revision d85131771379c9537a913b5408ad050c34f2be6b)
@@ -1089,5 +1089,5 @@
 	vpspec->hdr_blocks = hdrb;
 	vpspec->block0 = fblock0 + hdrb;
-	vpspec->nblocks = act_blocks;
+	vpspec->nblocks = act_blocks - hdrb;
 	vpspec->pkind = pspec->pkind;
 
Index: uspace/lib/label/src/gpt.c
===================================================================
--- uspace/lib/label/src/gpt.c	(revision ff381a79ad697b23cc01e3f8a66966d2d2cbd7dc)
+++ uspace/lib/label/src/gpt.c	(revision d85131771379c9537a913b5408ad050c34f2be6b)
@@ -57,4 +57,7 @@
 static int gpt_suggest_ptype(label_t *, label_pcnt_t, label_ptype_t *);
 
+static int gpt_check_free_idx(label_t *, int);
+static int gpt_check_free_range(label_t *, uint64_t, uint64_t);
+
 static void gpt_unused_pte(gpt_entry_t *);
 static int gpt_part_to_pte(label_part_t *, gpt_entry_t *);
@@ -608,7 +611,14 @@
 	}
 
-	/* XXX Verify index, block0, nblocks */
-
-	if (pspec->index < 1 || pspec->index > label->pri_entries) {
+	/* Verify index is within bounds and free */
+	rc = gpt_check_free_idx(label, pspec->index);
+	if (rc != EOK) {
+		rc = EINVAL;
+		goto error;
+	}
+
+	/* Verify range is within bounds and free */
+	rc = gpt_check_free_range(label, pspec->block0, pspec->nblocks);
+	if (rc != EOK) {
 		rc = EINVAL;
 		goto error;
@@ -711,4 +721,48 @@
 }
 
+/** Verify that the specified index is valid and free. */
+static int gpt_check_free_idx(label_t *label, int index)
+{
+	label_part_t *part;
+
+	if (index < 1 || index > label->pri_entries)
+		return EINVAL;
+
+	part = gpt_part_first(label);
+	while (part != NULL) {
+		if (part->index == index)
+			return EEXIST;
+		part = gpt_part_next(part);
+	}
+
+	return EOK;
+}
+
+/** Determine if two block address ranges overlap. */
+static bool gpt_overlap(uint64_t a0, uint64_t an, uint64_t b0, uint64_t bn)
+{
+	return !(a0 + an <= b0 || b0 + bn <= a0);
+}
+
+static int gpt_check_free_range(label_t *label, uint64_t block0,
+    uint64_t nblocks)
+{
+	label_part_t *part;
+
+	if (block0 < label->ablock0)
+		return EINVAL;
+	if (block0 + nblocks > label->ablock0 + label->anblocks)
+		return EINVAL;
+
+	part = gpt_part_first(label);
+	while (part != NULL) {
+		if (gpt_overlap(block0, nblocks, part->block0, part->nblocks))
+			return EEXIST;
+		part = gpt_part_next(part);
+	}
+
+	return EOK;
+}
+
 static void gpt_unused_pte(gpt_entry_t *pte)
 {
Index: uspace/lib/label/src/mbr.c
===================================================================
--- uspace/lib/label/src/mbr.c	(revision ff381a79ad697b23cc01e3f8a66966d2d2cbd7dc)
+++ uspace/lib/label/src/mbr.c	(revision d85131771379c9537a913b5408ad050c34f2be6b)
@@ -56,4 +56,8 @@
 static int mbr_suggest_ptype(label_t *, label_pcnt_t, label_ptype_t *);
 
+static int mbr_check_free_idx(label_t *, int);
+static int mbr_check_free_pri_range(label_t *, uint64_t, uint64_t);
+static int mbr_check_free_log_range(label_t *, uint64_t, uint64_t, uint64_t);
+
 static void mbr_unused_pte(mbr_pte_t *);
 static int mbr_part_to_pte(label_part_t *, mbr_pte_t *);
@@ -486,4 +490,26 @@
 }
 
+static label_part_t *mbr_pri_part_first(label_t *label)
+{
+	link_t *link;
+
+	link = list_first(&label->pri_parts);
+	if (link == NULL)
+		return NULL;
+
+	return list_get_instance(link, label_part_t, lpri);
+}
+
+static label_part_t *mbr_pri_part_next(label_part_t *part)
+{
+	link_t *link;
+
+	link = list_next(&part->lpri, &part->label->pri_parts);
+	if (link == NULL)
+		return NULL;
+
+	return list_get_instance(link, label_part_t, lpri);
+}
+
 static void mbr_part_get_info(label_part_t *part, label_part_info_t *pinfo)
 {
@@ -515,5 +541,4 @@
 	if (part == NULL)
 		return ENOMEM;
-
 
 	/* XXX Check if index is used */
@@ -551,7 +576,15 @@
 	if (pspec->pkind != lpk_logical) {
 		/* Primary or extended partition */
-		/* XXX Verify index, block0, nblocks */
-
-		if (pspec->index < 1 || pspec->index > label->pri_entries) {
+
+		/* Verify index is within bounds and free */
+		rc = mbr_check_free_idx(label, pspec->index);
+		if (rc != EOK) {
+			rc = EINVAL;
+			goto error;
+		}
+
+		/* Verify range is within bounds and free */
+		rc = mbr_check_free_pri_range(label, pspec->block0, pspec->nblocks);
+		if (rc != EOK) {
 			rc = EINVAL;
 			goto error;
@@ -575,10 +608,27 @@
 		}
 
+		if (pspec->pkind == lpk_extended) {
+			label->ext_part = part;
+
+			/* Create EBR for empty partition chain */
+			rc = mbr_ebr_create(label, NULL);
+			if (rc != EOK) {
+				label->ext_part = NULL;
+				rc = EIO;
+				goto error;
+			}
+		}
+
 		list_append(&part->lparts, &label->parts);
 		list_append(&part->lpri, &label->pri_parts);
-
-		if (pspec->pkind == lpk_extended)
-			label->ext_part = part;
 	} else {
+		/* Verify range is within bounds and free */
+		rc = mbr_check_free_log_range(label, pspec->hdr_blocks,
+		    pspec->block0, pspec->nblocks);
+		if (rc != EOK) {
+			rc = EINVAL;
+			goto error;
+		}
+
 		/* Logical partition */
 		rc = mbr_log_part_insert(label, part);
@@ -736,4 +786,69 @@
 }
 
+/** Determine if two block address ranges overlap. */
+static bool mbr_overlap(uint64_t a0, uint64_t an, uint64_t b0, uint64_t bn)
+{
+	return !(a0 + an <= b0 || b0 + bn <= a0);
+}
+
+/** Verify that the specified index is valid and free. */
+static int mbr_check_free_idx(label_t *label, int index)
+{
+	label_part_t *part;
+
+	if (index < 1 || index > label->pri_entries)
+		return EINVAL;
+
+	part = mbr_pri_part_first(label);
+	while (part != NULL) {
+		if (part->index == index)
+			return EEXIST;
+		part = mbr_pri_part_next(part);
+	}
+
+	return EOK;
+}
+
+static int mbr_check_free_pri_range(label_t *label, uint64_t block0,
+    uint64_t nblocks)
+{
+	label_part_t *part;
+
+	if (block0 < label->ablock0)
+		return EINVAL;
+	if (block0 + nblocks > label->ablock0 + label->anblocks)
+		return EINVAL;
+
+	part = mbr_pri_part_first(label);
+	while (part != NULL) {
+		if (mbr_overlap(block0, nblocks, part->block0, part->nblocks))
+			return EEXIST;
+		part = mbr_pri_part_next(part);
+	}
+
+	return EOK;
+}
+
+static int mbr_check_free_log_range(label_t *label, uint64_t hdr_blocks,
+    uint64_t block0, uint64_t nblocks)
+{
+	label_part_t *part;
+
+	if (block0 - hdr_blocks < label->ext_part->block0)
+		return EINVAL;
+	if (block0 + nblocks > label->ext_part->block0 + label->ext_part->nblocks)
+		return EINVAL;
+
+	part = mbr_log_part_first(label);
+	while (part != NULL) {
+		if (mbr_overlap(block0 - hdr_blocks, nblocks + hdr_blocks,
+		    part->block0 - part->hdr_blocks, part->nblocks + part->hdr_blocks))
+			return EEXIST;
+		part = mbr_log_part_next(part);
+	}
+
+	return EOK;
+}
+
 
 static void mbr_unused_pte(mbr_pte_t *pte)
@@ -924,5 +1039,11 @@
 }
 
-/** Create EBR for partition. */
+/** Create EBR for partition.
+ *
+ * @param label Label
+ * @param part Partition for which to create EBR or @c NULL to create
+ *        EBR for empty partition chain
+ * @return EOK on success or non-zero error code
+ */
 static int mbr_ebr_create(label_t *label, label_part_t *part)
 {
@@ -935,9 +1056,13 @@
 		return ENOMEM;
 
-	mbr_log_part_to_ptes(part, &br->pte[mbr_ebr_pte_this],
-	    &br->pte[mbr_ebr_pte_next]);
+	if (part != NULL) {
+		ba = part->block0 - part->hdr_blocks;
+		mbr_log_part_to_ptes(part, &br->pte[mbr_ebr_pte_this],
+		    &br->pte[mbr_ebr_pte_next]);
+	} else {
+		ba = label->ext_part->block0;
+	}
+
 	br->signature = host2uint16_t_le(mbr_br_signature);
-
-	ba = part->block0 - part->hdr_blocks;
 
 	rc = block_write_direct(label->svc_id, ba, 1, br);
