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