From 33c5fd0c5a774458470c86f9d318d8c48a9c9ccb Mon Sep 17 00:00:00 2001
From: Karel Zak <kzak@redhat.com>
Date: Mon, 26 Nov 2012 16:24:28 +0100
Subject: [PATCH] lib/canonicalize: add canonicalize_path_restricted() to
 canonicalize without suid permisssions

Signed-off-by: Karel Zak <kzak@redhat.com>
Signed-off-by: Petr Uzel <petr.uzel@suse.cz>
---
 include/canonicalize.h |    1 +
 lib/canonicalize.c     |   42 ++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 43 insertions(+)

Index: util-linux-2.21.2/include/canonicalize.h
===================================================================
--- util-linux-2.21.2.orig/include/canonicalize.h
+++ util-linux-2.21.2/include/canonicalize.h
@@ -4,6 +4,7 @@
 #include "c.h"	/* for PATH_MAX */
 
 extern char *canonicalize_path(const char *path);
+extern char *canonicalize_path_restricted(const char *path);
 extern char *canonicalize_dm_name(const char *ptname);
 
 #endif /* CANONICALIZE_H */
Index: util-linux-2.21.2/lib/canonicalize.c
===================================================================
--- util-linux-2.21.2.orig/lib/canonicalize.c
+++ util-linux-2.21.2/lib/canonicalize.c
@@ -188,6 +188,48 @@ canonicalize_path(const char *path)
 	return strdup(canonical);
 }
 
+char *
+canonicalize_path_restricted(const char *path)
+{
+	char canonical[PATH_MAX+2];
+	char *p = NULL;
+	int errsv;
+	uid_t euid;
+	gid_t egid;
+
+	if (path == NULL)
+		return NULL;
+
+	euid = geteuid();
+	egid = getegid();
+
+	/* drop permissions */
+	if (setegid(getgid()) < 0 || seteuid(getuid()) < 0)
+		return NULL;
+
+	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);
+		else
+			p = NULL;
+		if (!p)
+			p = strdup(canonical);
+	} else
+		errsv = errno;
+
+	/* restore */
+	if (setegid(egid) < 0 || seteuid(euid) < 0) {
+		free(p);
+		return NULL;
+	}
+
+	errno = errsv;
+	return p;
+}
+
 
 #ifdef TEST_PROGRAM_CANONICALIZE
 int main(int argc, char **argv)