Commit 7287e355 authored by Peter Maydell's avatar Peter Maydell
Browse files

Merge remote-tracking branch 'remotes/gkurz/tags/cve-2016-9602-for-upstream' into staging



This pull request have all the fixes for CVE-2016-9602, so that it can
be easily picked up by downstreams, as suggested by Michel Tokarev.

# gpg: Signature made Tue 28 Feb 2017 10:21:32 GMT
# gpg:                using DSA key 0x02FC3AEB0101DBC2
# gpg: Good signature from "Greg Kurz <groug@kaod.org>"
# gpg:                 aka "Greg Kurz <groug@free.fr>"
# gpg:                 aka "Greg Kurz <gkurz@linux.vnet.ibm.com>"
# gpg:                 aka "Gregory Kurz (Groug) <groug@free.fr>"
# gpg:                 aka "[jpeg image of size 3330]"
# gpg: WARNING: This key is not certified with a trusted signature!
# gpg:          There is no indication that the signature belongs to the owner.
# Primary key fingerprint: 2BD4 3B44 535E C0A7 9894  DBA2 02FC 3AEB 0101 DBC2

* remotes/gkurz/tags/cve-2016-9602-for-upstream: (28 commits)
  9pfs: local: drop unused code
  9pfs: local: open2: don't follow symlinks
  9pfs: local: mkdir: don't follow symlinks
  9pfs: local: mknod: don't follow symlinks
  9pfs: local: symlink: don't follow symlinks
  9pfs: local: chown: don't follow symlinks
  9pfs: local: chmod: don't follow symlinks
  9pfs: local: link: don't follow symlinks
  9pfs: local: improve error handling in link op
  9pfs: local: rename: use renameat
  9pfs: local: renameat: don't follow symlinks
  9pfs: local: lstat: don't follow symlinks
  9pfs: local: readlink: don't follow symlinks
  9pfs: local: truncate: don't follow symlinks
  9pfs: local: statfs: don't follow symlinks
  9pfs: local: utimensat: don't follow symlinks
  9pfs: local: remove: don't follow symlinks
  9pfs: local: unlinkat: don't follow symlinks
  9pfs: local: lremovexattr: don't follow symlinks
  9pfs: local: lsetxattr: don't follow symlinks
  ...

Signed-off-by: default avatarPeter Maydell <peter.maydell@linaro.org>
parents e3280ffb c23d5f1d
Loading
Loading
Loading
Loading
+557 −466

File changed.

Preview size limit exceeded, changes collapsed.

hw/9pfs/9p-local.h

0 → 100644
+20 −0
Original line number Diff line number Diff line
/*
 * 9p local backend utilities
 *
 * Copyright IBM, Corp. 2017
 *
 * Authors:
 *  Greg Kurz <groug@kaod.org>
 *
 * This work is licensed under the terms of the GNU GPL, version 2 or later.
 * See the COPYING file in the top-level directory.
 */

#ifndef QEMU_9P_LOCAL_H
#define QEMU_9P_LOCAL_H

int local_open_nofollow(FsContext *fs_ctx, const char *path, int flags,
                        mode_t mode);
int local_opendir_nofollow(FsContext *fs_ctx, const char *path);

#endif
+8 −36
Original line number Diff line number Diff line
@@ -25,13 +25,7 @@
static ssize_t mp_pacl_getxattr(FsContext *ctx, const char *path,
                                const char *name, void *value, size_t size)
{
    char *buffer;
    ssize_t ret;

    buffer = rpath(ctx, path);
    ret = lgetxattr(buffer, MAP_ACL_ACCESS, value, size);
    g_free(buffer);
    return ret;
    return local_getxattr_nofollow(ctx, path, MAP_ACL_ACCESS, value, size);
}

static ssize_t mp_pacl_listxattr(FsContext *ctx, const char *path,
@@ -56,23 +50,16 @@ static ssize_t mp_pacl_listxattr(FsContext *ctx, const char *path,
static int mp_pacl_setxattr(FsContext *ctx, const char *path, const char *name,
                            void *value, size_t size, int flags)
{
    char *buffer;
    int ret;

    buffer = rpath(ctx, path);
    ret = lsetxattr(buffer, MAP_ACL_ACCESS, value, size, flags);
    g_free(buffer);
    return ret;
    return local_setxattr_nofollow(ctx, path, MAP_ACL_ACCESS, value, size,
                                   flags);
}

static int mp_pacl_removexattr(FsContext *ctx,
                               const char *path, const char *name)
{
    int ret;
    char *buffer;

    buffer = rpath(ctx, path);
    ret  = lremovexattr(buffer, MAP_ACL_ACCESS);
    ret = local_removexattr_nofollow(ctx, path, MAP_ACL_ACCESS);
    if (ret == -1 && errno == ENODATA) {
        /*
         * We don't get ENODATA error when trying to remove a
@@ -82,20 +69,13 @@ static int mp_pacl_removexattr(FsContext *ctx,
        errno = 0;
        ret = 0;
    }
    g_free(buffer);
    return ret;
}

static ssize_t mp_dacl_getxattr(FsContext *ctx, const char *path,
                                const char *name, void *value, size_t size)
{
    char *buffer;
    ssize_t ret;

    buffer = rpath(ctx, path);
    ret = lgetxattr(buffer, MAP_ACL_DEFAULT, value, size);
    g_free(buffer);
    return ret;
    return local_getxattr_nofollow(ctx, path, MAP_ACL_DEFAULT, value, size);
}

static ssize_t mp_dacl_listxattr(FsContext *ctx, const char *path,
@@ -120,23 +100,16 @@ static ssize_t mp_dacl_listxattr(FsContext *ctx, const char *path,
static int mp_dacl_setxattr(FsContext *ctx, const char *path, const char *name,
                            void *value, size_t size, int flags)
{
    char *buffer;
    int ret;

    buffer = rpath(ctx, path);
    ret = lsetxattr(buffer, MAP_ACL_DEFAULT, value, size, flags);
    g_free(buffer);
    return ret;
    return local_setxattr_nofollow(ctx, path, MAP_ACL_DEFAULT, value, size,
                                   flags);
}

static int mp_dacl_removexattr(FsContext *ctx,
                               const char *path, const char *name)
{
    int ret;
    char *buffer;

    buffer = rpath(ctx, path);
    ret  = lremovexattr(buffer, MAP_ACL_DEFAULT);
    ret = local_removexattr_nofollow(ctx, path, MAP_ACL_DEFAULT);
    if (ret == -1 && errno == ENODATA) {
        /*
         * We don't get ENODATA error when trying to remove a
@@ -146,7 +119,6 @@ static int mp_dacl_removexattr(FsContext *ctx,
        errno = 0;
        ret = 0;
    }
    g_free(buffer);
    return ret;
}

hw/9pfs/9p-util.c

0 → 100644
+69 −0
Original line number Diff line number Diff line
/*
 * 9p utilities
 *
 * Copyright IBM, Corp. 2017
 *
 * Authors:
 *  Greg Kurz <groug@kaod.org>
 *
 * This work is licensed under the terms of the GNU GPL, version 2 or later.
 * See the COPYING file in the top-level directory.
 */

#include "qemu/osdep.h"
#include "qemu/xattr.h"
#include "9p-util.h"

int relative_openat_nofollow(int dirfd, const char *path, int flags,
                             mode_t mode)
{
    int fd;

    fd = dup(dirfd);
    if (fd == -1) {
        return -1;
    }

    while (*path) {
        const char *c;
        int next_fd;
        char *head;

        /* Only relative paths without consecutive slashes */
        assert(path[0] != '/');

        head = g_strdup(path);
        c = strchr(path, '/');
        if (c) {
            head[c - path] = 0;
            next_fd = openat_dir(fd, head);
        } else {
            next_fd = openat_file(fd, head, flags, mode);
        }
        g_free(head);
        if (next_fd == -1) {
            close_preserve_errno(fd);
            return -1;
        }
        close(fd);
        fd = next_fd;

        if (!c) {
            break;
        }
        path = c + 1;
    }

    return fd;
}

ssize_t fgetxattrat_nofollow(int dirfd, const char *filename, const char *name,
                             void *value, size_t size)
{
    char *proc_path = g_strdup_printf("/proc/self/fd/%d/%s", dirfd, filename);
    int ret;

    ret = lgetxattr(proc_path, name, value, size);
    g_free(proc_path);
    return ret;
}

hw/9pfs/9p-util.h

0 → 100644
+54 −0
Original line number Diff line number Diff line
/*
 * 9p utilities
 *
 * Copyright IBM, Corp. 2017
 *
 * Authors:
 *  Greg Kurz <groug@kaod.org>
 *
 * This work is licensed under the terms of the GNU GPL, version 2 or later.
 * See the COPYING file in the top-level directory.
 */

#ifndef QEMU_9P_UTIL_H
#define QEMU_9P_UTIL_H

static inline void close_preserve_errno(int fd)
{
    int serrno = errno;
    close(fd);
    errno = serrno;
}

static inline int openat_dir(int dirfd, const char *name)
{
    return openat(dirfd, name, O_DIRECTORY | O_RDONLY | O_PATH);
}

static inline int openat_file(int dirfd, const char *name, int flags,
                              mode_t mode)
{
    int fd, serrno, ret;

    fd = openat(dirfd, name, flags | O_NOFOLLOW | O_NOCTTY | O_NONBLOCK,
                mode);
    if (fd == -1) {
        return -1;
    }

    serrno = errno;
    /* O_NONBLOCK was only needed to open the file. Let's drop it. */
    ret = fcntl(fd, F_SETFL, flags);
    assert(!ret);
    errno = serrno;
    return fd;
}

int relative_openat_nofollow(int dirfd, const char *path, int flags,
                             mode_t mode);
ssize_t fgetxattrat_nofollow(int dirfd, const char *path, const char *name,
                             void *value, size_t size);
int fsetxattrat_nofollow(int dirfd, const char *path, const char *name,
                         void *value, size_t size, int flags);

#endif
Loading