summaryrefslogtreecommitdiffstats
path: root/libmount/src/utils.c
diff options
context:
space:
mode:
authorKarel Zak2011-11-08 21:47:23 +0100
committerKarel Zak2011-11-08 21:47:23 +0100
commit6107377322d5d6866c3aa363def656fdf68311e6 (patch)
treea9c52aef130a125ea0d0651c981f9543e467c546 /libmount/src/utils.c
parentdocs: refresh TODO file (diff)
downloadkernel-qcow2-util-linux-6107377322d5d6866c3aa363def656fdf68311e6.tar.gz
kernel-qcow2-util-linux-6107377322d5d6866c3aa363def656fdf68311e6.tar.xz
kernel-qcow2-util-linux-6107377322d5d6866c3aa363def656fdf68311e6.zip
libmount: fix chdir to parent for restricted (user) umounts
Reported-by: Petr Uzel <petr.uzel@suse.cz> Signed-off-by: Karel Zak <kzak@redhat.com>
Diffstat (limited to 'libmount/src/utils.c')
-rw-r--r--libmount/src/utils.c41
1 files changed, 25 insertions, 16 deletions
diff --git a/libmount/src/utils.c b/libmount/src/utils.c
index f3a174ff1..239e587fe 100644
--- a/libmount/src/utils.c
+++ b/libmount/src/utils.c
@@ -80,34 +80,40 @@ static char *stripoff_last_component(char *path)
if (!p)
return NULL;
*p = '\0';
- return ++p;
+ return p + 1;
}
-/* Note that the @target has to be absolute path (so at least "/")
+/*
+ * Note that the @target has to be absolute path (so at least "/"). The
+ * @filename returns allocated buffer with last path component, for example:
+ *
+ * mnt_chdir_to_parent("/mnt/test", &buf) ==> chdir("/mnt"), buf="test"
*/
int mnt_chdir_to_parent(const char *target, char **filename)
{
- char *path, *last = NULL;
+ char *buf, *parent, *last = NULL;
char cwd[PATH_MAX];
int rc = -EINVAL;
if (!target || *target != '/')
return -EINVAL;
- path = strdup(target);
- if (!path)
+ DBG(UTILS, mnt_debug("moving to %s parent", target));
+
+ buf = strdup(target);
+ if (!buf)
return -ENOMEM;
- if (*(path + 1) != '\0') {
- last = stripoff_last_component(path);
+ if (*(buf + 1) != '\0') {
+ last = stripoff_last_component(buf);
if (!last)
goto err;
}
- if (!*path)
- *path = '/'; /* root */
- if (chdir(path) == -1) {
- DBG(UTILS, mnt_debug("failed to chdir to %s: %m", path));
+ parent = buf && *buf ? buf : "/";
+
+ if (chdir(parent) == -1) {
+ DBG(UTILS, mnt_debug("failed to chdir to %s: %m", parent));
rc = -errno;
goto err;
}
@@ -116,14 +122,17 @@ int mnt_chdir_to_parent(const char *target, char **filename)
rc = -errno;
goto err;
}
- if (strcmp(cwd, path) != 0) {
- DBG(UTILS, mnt_debug("path moved (%s -> %s)", path, cwd));
+ if (strcmp(cwd, parent) != 0) {
+ DBG(UTILS, mnt_debug(
+ "unexpected chdir (expected=%s, cwd=%s)", parent, cwd));
goto err;
}
- DBG(CXT, mnt_debug("current directory moved to %s", path));
+ DBG(CXT, mnt_debug(
+ "current directory moved to %s [last_component='%s']",
+ parent, last));
- *filename = path;
+ *filename = buf;
if (!last || !*last)
memcpy(*filename, ".", 2);
@@ -131,7 +140,7 @@ int mnt_chdir_to_parent(const char *target, char **filename)
memcpy(*filename, last, strlen(last) + 1);
return 0;
err:
- free(path);
+ free(buf);
return rc;
}