Blob Blame History Raw
From 36e285eb912c86b607b752964c85aa6ee4bc25ea Mon Sep 17 00:00:00 2001
From: Karel Zak <kzak@redhat.com>
Date: Tue, 20 May 2014 10:11:57 +0200
Subject: [PATCH 185/185] lib/canonicalize: make DM canonicalization more
 robust

The current code cares about filenames, but it's too fragile, we have
to check the path is really path to the block device.

Addresses: https://github.com/karelzak/util-linux/issues/83
Addresses: https://bugzilla.redhat.com/show_bug.cgi?id=1678451
Upstream: http://github.com/karelzak/util-linux/commit/1dbbd85b9498536ab38758a03c9ec20362f1c572
Signed-off-by: Karel Zak <kzak@redhat.com>
---
 lib/canonicalize.c | 35 ++++++++++++++++++++++++++---------
 1 file changed, 26 insertions(+), 9 deletions(-)

diff --git a/lib/canonicalize.c b/lib/canonicalize.c
index 548e29b75..814ee3dd8 100644
--- a/lib/canonicalize.c
+++ b/lib/canonicalize.c
@@ -26,6 +26,8 @@
 #include <unistd.h>
 #include <errno.h>
 #include <stdlib.h>
+#include <sys/types.h>
+#include <sys/stat.h>
 
 #include "canonicalize.h"
 
@@ -170,10 +172,28 @@ canonicalize_dm_name(const char *ptname)
 	return res;
 }
 
+static int is_dm_devname(char *canonical, char **name)
+{
+	struct stat sb;
+	char *p = strrchr(canonical, '/');
+
+	*name = NULL;
+
+	if (!p
+	    || strncmp(p, "/dm-", 4) != 0
+	    || !isdigit(*(p + 4))
+	    || stat(canonical, &sb) != 0
+	    || !S_ISBLK(sb.st_mode))
+		return 0;
+
+	*name = p + 1;
+	return 1;
+}
+
 char *
 canonicalize_path(const char *path)
 {
-	char canonical[PATH_MAX+2];
+	char canonical[PATH_MAX+2], *dmname;
 	char *p;
 
 	if (!path || !*path)
@@ -182,10 +202,8 @@ canonicalize_path(const char *path)
 	if (!myrealpath(path, canonical, PATH_MAX+1))
 		return strdup(path);
 
-
-	p = strrchr(canonical, '/');
-	if (p && strncmp(p, "/dm-", 4) == 0 && isdigit(*(p + 4))) {
-		p = canonicalize_dm_name(p+1);
+	if (is_dm_devname(canonical, &dmname)) {
+		p = canonicalize_dm_name(dmname);
 		if (p)
 			return p;
 	}
@@ -196,7 +214,7 @@ canonicalize_path(const char *path)
 char *
 canonicalize_path_restricted(const char *path)
 {
-	char canonical[PATH_MAX+2];
+	char canonical[PATH_MAX+2], *dmname;
 	char *p = NULL;
 	int errsv;
 	uid_t euid;
@@ -215,9 +233,8 @@ canonicalize_path_restricted(const char *path)
 	errsv = errno = 0;
 
 	if (myrealpath(path, canonical, PATH_MAX+1)) {
-		p = strrchr(canonical, '/');
-		if (p && strncmp(p, "/dm-", 4) == 0 && isdigit(*(p + 4)))
-			p = canonicalize_dm_name(p+1);
+		if (is_dm_devname(canonical, &dmname))
+			p = canonicalize_dm_name(dmname);
 		else
 			p = NULL;
 		if (!p)
-- 
2.20.1