mirror of https://github.com/xqemu/xqemu.git
9pfs: local: rename: use renameat
The local_rename() callback is vulnerable to symlink attacks because it uses rename() which follows symbolic links in all path elements but the rightmost one. This patch simply transforms local_rename() into a wrapper around local_renameat() which is symlink-attack safe. This partly fixes CVE-2016-9602. Signed-off-by: Greg Kurz <groug@kaod.org> Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
This commit is contained in:
parent
99f2cf4b2d
commit
d2767edec5
|
@ -964,36 +964,6 @@ static int local_truncate(FsContext *ctx, V9fsPath *fs_path, off_t size)
|
|||
return ret;
|
||||
}
|
||||
|
||||
static int local_rename(FsContext *ctx, const char *oldpath,
|
||||
const char *newpath)
|
||||
{
|
||||
int err;
|
||||
char *buffer, *buffer1;
|
||||
|
||||
if (ctx->export_flags & V9FS_SM_MAPPED_FILE) {
|
||||
err = local_create_mapped_attr_dir(ctx, newpath);
|
||||
if (err < 0) {
|
||||
return err;
|
||||
}
|
||||
/* rename the .virtfs_metadata files */
|
||||
buffer = local_mapped_attr_path(ctx, oldpath);
|
||||
buffer1 = local_mapped_attr_path(ctx, newpath);
|
||||
err = rename(buffer, buffer1);
|
||||
g_free(buffer);
|
||||
g_free(buffer1);
|
||||
if (err < 0 && errno != ENOENT) {
|
||||
return err;
|
||||
}
|
||||
}
|
||||
|
||||
buffer = rpath(ctx, oldpath);
|
||||
buffer1 = rpath(ctx, newpath);
|
||||
err = rename(buffer, buffer1);
|
||||
g_free(buffer);
|
||||
g_free(buffer1);
|
||||
return err;
|
||||
}
|
||||
|
||||
static int local_chown(FsContext *fs_ctx, V9fsPath *fs_path, FsCred *credp)
|
||||
{
|
||||
char *buffer;
|
||||
|
@ -1254,6 +1224,33 @@ out:
|
|||
return ret;
|
||||
}
|
||||
|
||||
static void v9fs_path_init_dirname(V9fsPath *path, const char *str)
|
||||
{
|
||||
path->data = g_path_get_dirname(str);
|
||||
path->size = strlen(path->data) + 1;
|
||||
}
|
||||
|
||||
static int local_rename(FsContext *ctx, const char *oldpath,
|
||||
const char *newpath)
|
||||
{
|
||||
int err;
|
||||
char *oname = g_path_get_basename(oldpath);
|
||||
char *nname = g_path_get_basename(newpath);
|
||||
V9fsPath olddir, newdir;
|
||||
|
||||
v9fs_path_init_dirname(&olddir, oldpath);
|
||||
v9fs_path_init_dirname(&newdir, newpath);
|
||||
|
||||
err = local_renameat(ctx, &olddir, oname, &newdir, nname);
|
||||
|
||||
v9fs_path_free(&newdir);
|
||||
v9fs_path_free(&olddir);
|
||||
g_free(nname);
|
||||
g_free(oname);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
static int local_unlinkat(FsContext *ctx, V9fsPath *dir,
|
||||
const char *name, int flags)
|
||||
{
|
||||
|
|
Loading…
Reference in New Issue