summaryrefslogtreecommitdiffstats
path: root/lib/canonicalize.c
diff options
context:
space:
mode:
authorKarel Zak2012-11-26 16:24:28 +0100
committerKarel Zak2012-11-26 16:24:28 +0100
commit33c5fd0c5a774458470c86f9d318d8c48a9c9ccb (patch)
treecd27c68eb080de1ab123ef2941364c1ab891821c /lib/canonicalize.c
parentlibmount: make debug stuff more robust (diff)
downloadkernel-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/canonicalize.c')
-rw-r--r--lib/canonicalize.c42
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)