diff options
author | Karel Zak | 2011-03-30 13:00:03 +0200 |
---|---|---|
committer | Karel Zak | 2011-03-30 13:00:03 +0200 |
commit | 66bb8267103df6658ee984a89f1d8445f42d072e (patch) | |
tree | 821ab7bffcc6ca2f1e9f3240e4c4f4ce1ef9f1af /shlibs/mount/src/context_umount.c | |
parent | libmount: fix test (diff) | |
download | kernel-qcow2-util-linux-66bb8267103df6658ee984a89f1d8445f42d072e.tar.gz kernel-qcow2-util-linux-66bb8267103df6658ee984a89f1d8445f42d072e.tar.xz kernel-qcow2-util-linux-66bb8267103df6658ee984a89f1d8445f42d072e.zip |
libmount: use chdir() and NOFOLLOW umount flag for umount operation
Signed-off-by: Karel Zak <kzak@redhat.com>
Diffstat (limited to 'shlibs/mount/src/context_umount.c')
-rw-r--r-- | shlibs/mount/src/context_umount.c | 41 |
1 files changed, 39 insertions, 2 deletions
diff --git a/shlibs/mount/src/context_umount.c b/shlibs/mount/src/context_umount.c index cdf919854..0e69fe5f9 100644 --- a/shlibs/mount/src/context_umount.c +++ b/shlibs/mount/src/context_umount.c @@ -424,10 +424,25 @@ int mnt_context_umount_setopt(struct libmnt_context *cxt, int c, char *arg) return rc; } +/* Check whether the kernel supports UMOUNT_NOFOLLOW flag */ +static int umount_nofollow_support(void) +{ + int res = umount2("", UMOUNT_UNUSED); + if (res != -1 || errno != EINVAL) + return 0; + + res = umount2("", UMOUNT_NOFOLLOW); + if (res != -1 || errno != ENOENT) + return 0; + + return 1; +} + static int do_umount(struct libmnt_context *cxt) { int rc = 0, flags = 0; const char *src, *target; + char *tgtbuf = NULL; assert(cxt); assert(cxt->fs); @@ -446,16 +461,38 @@ static int do_umount(struct libmnt_context *cxt) if (cxt->flags & MNT_FL_FAKE) return 0; + DBG(CXT, mnt_debug_h(cxt, "do umount")); + + if (cxt->restricted) { + /* + * extra paranoa for non-root users + * -- chdir to the parent of the mountpoint and use NOFOLLOW + * flag to avoid races and symlink attacks. + */ + if (umount_nofollow_support()) + flags |= UMOUNT_NOFOLLOW; + + rc = mnt_chdir_to_parent(target, &tgtbuf); + if (rc) + return rc; + target = tgtbuf; + } + if (cxt->flags & MNT_FL_LAZY) flags |= MNT_DETACH; else if (cxt->flags & MNT_FL_FORCE) flags |= MNT_FORCE; - rc = flasg ? umount2(target, flags) : umount(target); + DBG(CXT, mnt_debug_h(cxt, "umount(2) [target='%s', flags=0x%08x]", + target, flags)); + + rc = flags ? umount2(target, flags) : umount(target); if (rc < 0) cxt->syscall_status = -errno; + free(tgtbuf); + /* * try remount read-only */ @@ -468,7 +505,7 @@ static int do_umount(struct libmnt_context *cxt) "umount(2) failed [errno=%d] -- tring remount read-only", -cxt->syscall_status)); - rc = mount(src, target, NULL, + rc = mount(src, mnt_fs_get_target(cxt->fs), NULL, MS_MGC_VAL | MS_REMOUNT | MS_RDONLY, NULL); if (rc < 0) { cxt->syscall_status = -errno; |