From 36e285eb912c86b607b752964c85aa6ee4bc25ea Mon Sep 17 00:00:00 2001 From: Karel Zak 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 --- 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 #include #include +#include +#include #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