Sign Up
Log In
Log In
or
Sign Up
Places
All Projects
Status Monitor
Collapse sidebar
openSUSE:11.4:Update
kvm.853
kvm-qemu-preXX-block-prevent-snapshot-mode-TMPD...
Overview
Repositories
Revisions
Requests
Users
Attributes
Meta
File kvm-qemu-preXX-block-prevent-snapshot-mode-TMPDIR-symlink-attack.patch of Package kvm.853
From eba25057b9a5e19d10ace2bc7716667a31297169 Mon Sep 17 00:00:00 2001 From: Jim Meyering <jim@meyering.net> Date: Mon, 28 May 2012 09:27:54 +0200 Subject: [PATCH] block: prevent snapshot mode $TMPDIR symlink attack In snapshot mode, bdrv_open creates an empty temporary file without checking for mkstemp or close failure, and ignoring the possibility of a buffer overrun given a surprisingly long $TMPDIR. Change the get_tmp_filename function to return int (not void), so that it can inform its two callers of those failures. Also avoid the risk of buffer overrun and do not ignore mkstemp or close failure. Update both callers (in block.c and vvfat.c) to propagate temp-file-creation failure to their callers. get_tmp_filename creates and closes an empty file, while its callers later open that presumed-existing file with O_CREAT. The problem was that a malicious user could provoke mkstemp failure and race to create a symlink with the selected temporary file name, thus causing the qemu process (usually root owned) to open through the symlink, overwriting an attacker-chosen file. This addresses CVE-2012-2652. http://bugzilla.redhat.com/CVE-2012-2652 Reviewed-by: Stefan Hajnoczi <stefanha@linux.vnet.ibm.com> Signed-off-by: Jim Meyering <meyering@redhat.com> Signed-off-by: Anthony Liguori <aliguori@us.ibm.com> --- block.c | 37 ++++++++++++++++++++++++------------- block/vvfat.c | 7 ++++++- block_int.h | 2 +- 3 files changed, 31 insertions(+), 15 deletions(-) Index: qemu-kvm-0.15.1/block.c =================================================================== --- qemu-kvm-0.15.1.orig/block.c +++ qemu-kvm-0.15.1/block.c @@ -254,28 +254,36 @@ int bdrv_create_file(const char* filenam return bdrv_create(drv, filename, options); } -#ifdef _WIN32 -void get_tmp_filename(char *filename, int size) +/* + * Create a uniquely-named empty temporary file. + * Return 0 upon success, otherwise a negative errno value. + */ +int get_tmp_filename(char *filename, int size) { +#ifdef _WIN32 char temp_dir[MAX_PATH]; - - GetTempPath(MAX_PATH, temp_dir); - GetTempFileName(temp_dir, "qem", 0, filename); -} + /* GetTempFileName requires that its output buffer (4th param) + have length MAX_PATH or greater. */ + assert(size >= MAX_PATH); + return (GetTempPath(MAX_PATH, temp_dir) + && GetTempFileName(temp_dir, "qem", 0, filename) + ? 0 : -GetLastError()); #else -void get_tmp_filename(char *filename, int size) -{ int fd; const char *tmpdir; - /* XXX: race condition possible */ tmpdir = getenv("TMPDIR"); if (!tmpdir) tmpdir = "/tmp"; - snprintf(filename, size, "%s/vl.XXXXXX", tmpdir); + if (snprintf(filename, size, "%s/vl.XXXXXX", tmpdir) >= size) { + return -EOVERFLOW; + } fd = mkstemp(filename); - close(fd); -} + if (fd < 0 || close(fd)) { + return -errno; + } + return 0; #endif +} /* * Detect host devices. By convention, /dev/cdrom[N] is always @@ -555,7 +563,10 @@ int bdrv_open(BlockDriverState *bs, cons bdrv_delete(bs1); - get_tmp_filename(tmp_filename, sizeof(tmp_filename)); + ret = get_tmp_filename(tmp_filename, sizeof(tmp_filename)); + if (ret < 0) { + return ret; + } /* Real path is meaningless for protocols */ if (is_protocol) Index: qemu-kvm-0.15.1/block/vvfat.c =================================================================== --- qemu-kvm-0.15.1.orig/block/vvfat.c +++ qemu-kvm-0.15.1/block/vvfat.c @@ -2795,7 +2795,12 @@ static int enable_write_target(BDRVVVFAT array_init(&(s->commits), sizeof(commit_t)); s->qcow_filename = qemu_malloc(1024); - get_tmp_filename(s->qcow_filename, 1024); + ret = get_tmp_filename(s->qcow_filename, 1024); + if (ret < 0) { + qemu_free(s->qcow_filename); + s->qcow_filename = NULL; + return ret; + } bdrv_qcow = bdrv_find_format("qcow"); options = parse_option_parameters("", bdrv_qcow->create_options, NULL); Index: qemu-kvm-0.15.1/block_int.h =================================================================== --- qemu-kvm-0.15.1.orig/block_int.h +++ qemu-kvm-0.15.1/block_int.h @@ -216,7 +216,7 @@ struct BlockDriverAIOCB { BlockDriverAIOCB *next; }; -void get_tmp_filename(char *filename, int size); +int get_tmp_filename(char *filename, int size); void *qemu_aio_get(AIOPool *pool, BlockDriverState *bs, BlockDriverCompletionFunc *cb, void *opaque);
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