summaryrefslogtreecommitdiffstats
path: root/lib
diff options
context:
space:
mode:
authorKarel Zak2014-05-20 10:11:57 +0200
committerKarel Zak2014-05-20 10:11:57 +0200
commit1dbbd85b9498536ab38758a03c9ec20362f1c572 (patch)
tree68c6e9f425e7132df226ca59873868ef148273b3 /lib
parentmount: fix tiny typo in man page (diff)
downloadkernel-qcow2-util-linux-1dbbd85b9498536ab38758a03c9ec20362f1c572.tar.gz
kernel-qcow2-util-linux-1dbbd85b9498536ab38758a03c9ec20362f1c572.tar.xz
kernel-qcow2-util-linux-1dbbd85b9498536ab38758a03c9ec20362f1c572.zip
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 Signed-off-by: Karel Zak <kzak@redhat.com>
Diffstat (limited to 'lib')
-rw-r--r--lib/canonicalize.c45
1 files changed, 30 insertions, 15 deletions
diff --git a/lib/canonicalize.c b/lib/canonicalize.c
index cac60d7a4..49ac80246 100644
--- a/lib/canonicalize.c
+++ b/lib/canonicalize.c
@@ -48,9 +48,27 @@ char *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, *p;
+ char *canonical, *dmname;
if (!path || !*path)
return NULL;
@@ -59,9 +77,8 @@ char *canonicalize_path(const char *path)
if (!canonical)
return strdup(path);
- p = strrchr(canonical, '/');
- if (p && strncmp(p, "/dm-", 4) == 0 && isdigit(*(p + 4))) {
- char *dm = canonicalize_dm_name(p + 1);
+ if (is_dm_devname(canonical, &dmname)) {
+ char *dm = canonicalize_dm_name(dmname);
if (dm) {
free(canonical);
return dm;
@@ -73,7 +90,7 @@ char *canonicalize_path(const char *path)
char *canonicalize_path_restricted(const char *path)
{
- char *canonical, *p = NULL;
+ char *canonical, *dmname;
int errsv;
uid_t euid;
gid_t egid;
@@ -91,17 +108,15 @@ char *canonicalize_path_restricted(const char *path)
errsv = errno = 0;
canonical = realpath(path, NULL);
- if (canonical) {
- p = strrchr(canonical, '/');
- if (p && strncmp(p, "/dm-", 4) == 0 && isdigit(*(p + 4))) {
- char *dm = canonicalize_dm_name(p + 1);
- if (dm) {
- free(canonical);
- canonical = dm;
- }
- }
- } else
+ if (!canonical)
errsv = errno;
+ else if (is_dm_devname(canonical, &dmname)) {
+ char *dm = canonicalize_dm_name(dmname);
+ if (dm) {
+ free(canonical);
+ canonical = dm;
+ }
+ }
/* restore */
if (setegid(egid) < 0 || seteuid(euid) < 0) {