Sign Up
Log In
Log In
or
Sign Up
Places
All Projects
Status Monitor
Collapse sidebar
SUSE:SLE-12-SP2:GA
qemu.12301
0225-9pfs-local-remove-don-t-follow-syml.patch
Overview
Repositories
Revisions
Requests
Users
Attributes
Meta
File 0225-9pfs-local-remove-don-t-follow-syml.patch of Package qemu.12301
From e0eb2dbe7f7384894a34ac767e3d6308865e415f Mon Sep 17 00:00:00 2001 From: Greg Kurz <groug@kaod.org> Date: Sun, 26 Feb 2017 23:43:08 +0100 Subject: [PATCH] 9pfs: local: remove: don't follow symlinks The local_remove() callback is vulnerable to symlink attacks because it calls: (1) lstat() which follows symbolic links in all path elements but the rightmost one (2) remove() which follows symbolic links in all path elements but the rightmost one This patch converts local_remove() to rely on opendir_nofollow(), fstatat(AT_SYMLINK_NOFOLLOW) to fix (1) and unlinkat() to fix (2). This partly fixes CVE-2016-9602. Signed-off-by: Greg Kurz <groug@kaod.org> Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com> (cherry picked from commit a0e640a87210b1e986bcd4e7f7de03beb3db0a4a) [BR: Fix and/or infrastructure for BSC#1020427 CVE-2016-9602] Signed-off-by: Bruce Rogers <brogers@suse.com> --- hw/9pfs/9p-local.c | 64 +++++++++++++++------------------------------- 1 file changed, 21 insertions(+), 43 deletions(-) diff --git a/hw/9pfs/9p-local.c b/hw/9pfs/9p-local.c index ec99e4f6b8..8ed16905b9 100644 --- a/hw/9pfs/9p-local.c +++ b/hw/9pfs/9p-local.c @@ -1017,54 +1017,32 @@ err_out: static int local_remove(FsContext *ctx, const char *path) { - int err; struct stat stbuf; - char *buffer; + char *dirpath = g_path_get_dirname(path); + char *name = g_path_get_basename(path); + int flags = 0; + int dirfd; + int err = -1; - if (ctx->export_flags & V9FS_SM_MAPPED_FILE) { - buffer = rpath(ctx, path); - err = lstat(buffer, &stbuf); - g_free(buffer); - if (err) { - goto err_out; - } - /* - * If directory remove .virtfs_metadata contained in the - * directory - */ - if (S_ISDIR(stbuf.st_mode)) { - buffer = g_strdup_printf("%s/%s/%s", ctx->fs_root, - path, VIRTFS_META_DIR); - err = remove(buffer); - g_free(buffer); - if (err < 0 && errno != ENOENT) { - /* - * We didn't had the .virtfs_metadata file. May be file created - * in non-mapped mode ?. Ignore ENOENT. - */ - goto err_out; - } - } - /* - * Now remove the name from parent directory - * .virtfs_metadata directory - */ - buffer = local_mapped_attr_path(ctx, path); - err = remove(buffer); - g_free(buffer); - if (err < 0 && errno != ENOENT) { - /* - * We didn't had the .virtfs_metadata file. May be file created - * in non-mapped mode ?. Ignore ENOENT. - */ - goto err_out; - } + dirfd = local_opendir_nofollow(ctx, dirpath); + if (dirfd) { + goto out; } - buffer = rpath(ctx, path); - err = remove(buffer); - g_free(buffer); + if (fstatat(dirfd, path, &stbuf, AT_SYMLINK_NOFOLLOW) < 0) { + goto err_out; + } + + if (S_ISDIR(stbuf.st_mode)) { + flags |= AT_REMOVEDIR; + } + + err = local_unlinkat_common(ctx, dirfd, name, flags); err_out: + close_preserve_errno(dirfd); +out: + g_free(name); + g_free(dirpath); return err; }
Locations
Projects
Search
Status Monitor
Help
OpenBuildService.org
Documentation
API Documentation
Code of Conduct
Contact
Support
@OBShq
Terms
openSUSE Build Service is sponsored by
The Open Build Service is an
openSUSE project
.
Sign Up
Log In
Places
Places
All Projects
Status Monitor