From 33c5fd0c5a774458470c86f9d318d8c48a9c9ccb Mon Sep 17 00:00:00 2001 From: Karel Zak 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 Signed-off-by: Petr Uzel --- 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)