From: Karel Zak Date: Mon, 26 Nov 2012 15:24:28 +0000 (+0100) Subject: lib/canonicalize: add canonicalize_path_restricted() to canonicalize without suid... X-Git-Tag: v2.22.2~20 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=d342b443d5daec2c55734e93ba3b81a60ae6075f;p=thirdparty%2Futil-linux.git lib/canonicalize: add canonicalize_path_restricted() to canonicalize without suid permisssions Signed-off-by: Karel Zak --- diff --git a/include/canonicalize.h b/include/canonicalize.h index f26df18c2b..c149738029 100644 --- a/include/canonicalize.h +++ b/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 */ diff --git a/lib/canonicalize.c b/lib/canonicalize.c index ab32c10431..1e8aff4f2b 100644 --- a/lib/canonicalize.c +++ b/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)