diff options
author | Karel Zak | 2012-11-26 16:24:28 +0100 |
---|---|---|
committer | Karel Zak | 2012-11-26 16:24:28 +0100 |
commit | 33c5fd0c5a774458470c86f9d318d8c48a9c9ccb (patch) | |
tree | cd27c68eb080de1ab123ef2941364c1ab891821c /lib | |
parent | libmount: make debug stuff more robust (diff) | |
download | kernel-qcow2-util-linux-33c5fd0c5a774458470c86f9d318d8c48a9c9ccb.tar.gz kernel-qcow2-util-linux-33c5fd0c5a774458470c86f9d318d8c48a9c9ccb.tar.xz kernel-qcow2-util-linux-33c5fd0c5a774458470c86f9d318d8c48a9c9ccb.zip |
lib/canonicalize: add canonicalize_path_restricted() to canonicalize without suid permisssions
Signed-off-by: Karel Zak <kzak@redhat.com>
Diffstat (limited to 'lib')
-rw-r--r-- | lib/canonicalize.c | 42 |
1 files changed, 42 insertions, 0 deletions
diff --git a/lib/canonicalize.c b/lib/canonicalize.c index ab32c1043..1e8aff4f2 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) |