dm-devel.redhat.com archive mirror
 help / color / mirror / Atom feed
From: "Benjamin Marzinski" <bmarzins@redhat.com>
To: device-mapper development <dm-devel@redhat.com>
Cc: Christophe Varoqui <christophe.varoqui@gmail.com>
Subject: [PATCH v2 12/18] kpartx: verify partition devices
Date: Thu,  7 Apr 2016 18:20:06 -0500	[thread overview]
Message-ID: <1460071212-21018-13-git-send-email-bmarzins@redhat.com> (raw)
In-Reply-To: <1460071212-21018-1-git-send-email-bmarzins@redhat.com>

When kpartx is modifies devices (either by removing them, or
reloading them), it doesn't first verify that the device really
is a partition of the expected device.  If a dm device just happens
to have the same name as a kpartx created device would, kpartx can
either delete that device or remap it, causing all sorts of problems.

This patch makes kpartx check the uuid to verify that the device it is
modifying really is a partition device for the correct dm device.

Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
---
 kpartx/devmapper.c | 17 ++++++++++---
 kpartx/devmapper.h |  2 +-
 kpartx/kpartx.c    | 70 ++++++++++++++++++++++++++++++++++++++++++++++++++----
 3 files changed, 81 insertions(+), 8 deletions(-)

diff --git a/kpartx/devmapper.c b/kpartx/devmapper.c
index 82be990..e006bc3 100644
--- a/kpartx/devmapper.c
+++ b/kpartx/devmapper.c
@@ -167,12 +167,16 @@ addout:
 }
 
 extern int
-dm_map_present (char * str)
+dm_map_present (char * str, char **uuid)
 {
 	int r = 0;
 	struct dm_task *dmt;
+	const char *uuidtmp;
 	struct dm_info info;
 
+	if (uuid)
+		*uuid = NULL;
+
 	if (!(dmt = dm_task_create(DM_DEVICE_INFO)))
 		return 0;
 
@@ -187,8 +191,15 @@ dm_map_present (char * str)
 	if (!dm_task_get_info(dmt, &info))
 		goto out;
 
-	if (info.exists)
-		r = 1;
+	if (!info.exists)
+		goto out;
+
+	r = 1;
+	if (uuid) {
+		uuidtmp = dm_task_get_uuid(dmt);
+		if (uuidtmp && strlen(uuidtmp))
+			*uuid = strdup(uuidtmp);
+	}
 out:
 	dm_task_destroy(dmt);
 	return r;
diff --git a/kpartx/devmapper.h b/kpartx/devmapper.h
index ac1d5d9..436efe1 100644
--- a/kpartx/devmapper.h
+++ b/kpartx/devmapper.h
@@ -13,7 +13,7 @@ int dm_prereq (char *, int, int, int);
 int dm_simplecmd (int, const char *, int, uint16_t);
 int dm_addmap (int, const char *, const char *, const char *, uint64_t,
 	       int, const char *, int, mode_t, uid_t, gid_t);
-int dm_map_present (char *);
+int dm_map_present (char *, char **);
 char * dm_mapname(int major, int minor);
 dev_t dm_get_first_dep(char *devname);
 char * dm_mapuuid(int major, int minor);
diff --git a/kpartx/kpartx.c b/kpartx/kpartx.c
index 8047698..e8c35d4 100644
--- a/kpartx/kpartx.c
+++ b/kpartx/kpartx.c
@@ -191,6 +191,21 @@ get_hotplug_device(void)
 	return device;
 }
 
+static int
+check_uuid(char *uuid, char *part_uuid, char **err_msg) {
+	char *map_uuid = strchr(part_uuid, '-');
+	if (!map_uuid || strncmp(part_uuid, "part", 4) != 0) {
+		*err_msg = "not a kpartx partition";
+		return -1;
+	}
+	map_uuid++;
+	if (strcmp(uuid, map_uuid) != 0) {
+		*err_msg = "a partition of a different device";
+		return -1;
+	}
+	return 0;
+}
+
 int
 main(int argc, char **argv){
 	int i, j, m, n, op, off, arg, c, d, ro=0;
@@ -432,6 +447,8 @@ main(int argc, char **argv){
 
 		case DELETE:
 			for (j = MAXSLICES-1; j >= 0; j--) {
+				char *part_uuid, *reason;
+
 				if (safe_sprintf(partname, "%s%s%d",
 					     mapname, delim, j+1)) {
 					fprintf(stderr, "partname too small\n");
@@ -439,9 +456,18 @@ main(int argc, char **argv){
 				}
 				strip_slash(partname);
 
-				if (!dm_map_present(partname))
+				if (!dm_map_present(partname, &part_uuid))
 					continue;
 
+				if (part_uuid && uuid) {
+					if (check_uuid(uuid, part_uuid, &reason) != 0) {
+						fprintf(stderr, "%s is %s. Not removing\n", partname, reason);
+						free(part_uuid);
+						continue;
+					}
+					free(part_uuid);
+				}
+
 				if (!dm_simplecmd(DM_DEVICE_REMOVE, partname,
 						  0, 0)) {
 					r++;
@@ -466,6 +492,8 @@ main(int argc, char **argv){
 		case UPDATE:
 			/* ADD and UPDATE share the same code that adds new partitions. */
 			for (j = 0, c = 0; j < n; j++) {
+				char *part_uuid, *reason;
+
 				if (slices[j].size == 0)
 					continue;
 
@@ -488,9 +516,19 @@ main(int argc, char **argv){
 					exit(1);
 				}
 
-				op = (dm_map_present(partname) ?
+				op = (dm_map_present(partname, &part_uuid) ?
 					DM_DEVICE_RELOAD : DM_DEVICE_CREATE);
 
+				if (part_uuid && uuid) {
+					if (check_uuid(uuid, part_uuid, &reason) != 0) {
+						fprintf(stderr, "%s is already in use, and %s\n", partname, reason);
+						r++;
+						free(part_uuid);
+						continue;
+					}
+					free(part_uuid);
+				}
+
 				if (!dm_addmap(op, partname, DM_TARGET, params,
 					       slices[j].size, ro, uuid, j+1,
 					       buf.st_mode & 0777, buf.st_uid,
@@ -498,6 +536,7 @@ main(int argc, char **argv){
 					fprintf(stderr, "create/reload failed on %s\n",
 						partname);
 					r++;
+					continue;
 				}
 				if (op == DM_DEVICE_RELOAD &&
 				    !dm_simplecmd(DM_DEVICE_RESUME, partname,
@@ -505,6 +544,7 @@ main(int argc, char **argv){
 					fprintf(stderr, "resume failed on %s\n",
 						partname);
 					r++;
+					continue;
 				}
 
 				dm_devn(partname, &slices[j].major,
@@ -520,6 +560,7 @@ main(int argc, char **argv){
 			d = c;
 			while (c) {
 				for (j = 0; j < n; j++) {
+					char *part_uuid, *reason;
 					int k = slices[j].container - 1;
 
 					if (slices[j].size == 0)
@@ -552,9 +593,19 @@ main(int argc, char **argv){
 						exit(1);
 					}
 
-					op = (dm_map_present(partname) ?
+					op = (dm_map_present(partname,
+							     &part_uuid) ?
 					      DM_DEVICE_RELOAD : DM_DEVICE_CREATE);
 
+					if (part_uuid && uuid) {
+						if (check_uuid(uuid, part_uuid, &reason) != 0) {
+							fprintf(stderr, "%s is already in use, and %s\n", partname, reason);
+							free(part_uuid);
+							continue;
+						}
+						free(part_uuid);
+					}
+
 					dm_addmap(op, partname, DM_TARGET, params,
 						  slices[j].size, ro, uuid, j+1,
 						  buf.st_mode & 0777,
@@ -584,6 +635,7 @@ main(int argc, char **argv){
 			}
 
 			for (j = MAXSLICES-1; j >= 0; j--) {
+				char *part_uuid, *reason;
 				if (safe_sprintf(partname, "%s%s%d",
 					     mapname, delim, j+1)) {
 					fprintf(stderr, "partname too small\n");
@@ -591,9 +643,19 @@ main(int argc, char **argv){
 				}
 				strip_slash(partname);
 
-				if (slices[j].size || !dm_map_present(partname))
+				if (slices[j].size ||
+				    !dm_map_present(partname, &part_uuid))
 					continue;
 
+				if (part_uuid && uuid) {
+					if (check_uuid(uuid, part_uuid, &reason) != 0) {
+						fprintf(stderr, "%s is %s. Not removing\n", partname, reason);
+						free(part_uuid);
+						continue;
+					}
+					free(part_uuid);
+				}
+
 				if (!dm_simplecmd(DM_DEVICE_REMOVE,
 						  partname, 1, 0)) {
 					r++;
-- 
1.8.3.1

  parent reply	other threads:[~2016-04-07 23:20 UTC|newest]

Thread overview: 22+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2016-04-07 23:19 [PATCH v2 00/18] Multipath patch sync Benjamin Marzinski
2016-04-07 23:19 ` [PATCH v2 01/18] multipathd: use /run instead of /var/run Benjamin Marzinski
2016-04-07 23:19 ` [PATCH v2 02/18] retrigger uevents to try and get the uid through udev Benjamin Marzinski
2016-04-07 23:19 ` [PATCH v2 03/18] Fix issues with user_friendly_names initramfs bindings Benjamin Marzinski
2016-04-07 23:19 ` [PATCH v2 04/18] Add libmpathcmd library and use it internally Benjamin Marzinski
2016-04-07 23:19 ` [PATCH v2 05/18] libmultipath: add ignore_new_boot_devs option Benjamin Marzinski
2016-04-07 23:20 ` [PATCH v2 06/18] libmultipath: fix PAD and PRINT macros Benjamin Marzinski
2016-04-07 23:20 ` [PATCH v2 07/18] libmultipath: Cut down on alua prioritizer ioctls Benjamin Marzinski
2016-04-07 23:20 ` [PATCH v2 08/18] multipathd: fail if pidfile can't be created Benjamin Marzinski
2016-04-07 23:20 ` [PATCH v2 09/18] libmultipath: check correct function for define Benjamin Marzinski
2016-04-07 23:20 ` [PATCH v2 10/18] multipathd: delay reloads during creation Benjamin Marzinski
2016-04-08  8:36   ` Zdenek Kabelac
2016-04-08 21:53     ` Benjamin Marzinski
2016-04-07 23:20 ` [PATCH v2 11/18] multipath: Fix minor text issues Benjamin Marzinski
2016-04-07 23:20 ` Benjamin Marzinski [this message]
2016-04-07 23:20 ` [PATCH v2 13/18] multipath: add exclusive_pref_bit for alua prio Benjamin Marzinski
2016-04-07 23:20 ` [PATCH v2 14/18] multipathd: print "fail" when remove fails Benjamin Marzinski
2016-04-07 23:20 ` [PATCH v2 15/18] multipath: check partitions unused before removing Benjamin Marzinski
2016-04-07 23:20 ` [PATCH v2 16/18] multipathd.service: remove blk-availability Requires Benjamin Marzinski
2016-04-07 23:20 ` [PATCH v2 17/18] multipathd: use 64-bit int for command key Benjamin Marzinski
2016-04-07 23:20 ` [PATCH v2 18/18] multipath: add wwn keyword to weightedpath prio Benjamin Marzinski
2016-04-18  9:36 ` [PATCH v2 00/18] Multipath patch sync Christophe Varoqui

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1460071212-21018-13-git-send-email-bmarzins@redhat.com \
    --to=bmarzins@redhat.com \
    --cc=christophe.varoqui@gmail.com \
    --cc=dm-devel@redhat.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).