]> git.proxmox.com Git - pve-qemu.git/commitdiff
d/patches: backport virtiofsd security fix
authorThomas Lamprecht <t.lamprecht@proxmox.com>
Wed, 24 Feb 2021 17:40:28 +0000 (18:40 +0100)
committerThomas Lamprecht <t.lamprecht@proxmox.com>
Wed, 24 Feb 2021 18:02:07 +0000 (19:02 +0100)
Signed-off-by: Thomas Lamprecht <t.lamprecht@proxmox.com>
debian/patches/extra/0004-virtiofsd-extract-lo_do_open-from-lo_open.patch [new file with mode: 0644]
debian/patches/extra/0005-virtiofsd-optionally-return-inode-pointer-from-lo_do.patch [new file with mode: 0644]
debian/patches/extra/0006-virtiofsd-prevent-opening-of-special-files-CVE-2020-.patch [new file with mode: 0644]
debian/patches/extra/0007-virtiofsd-Add-_llseek-to-the-seccomp-whitelist.patch [new file with mode: 0644]
debian/patches/extra/0008-virtiofsd-Add-restart_syscall-to-the-seccomp-whiteli.patch [new file with mode: 0644]
debian/patches/series

diff --git a/debian/patches/extra/0004-virtiofsd-extract-lo_do_open-from-lo_open.patch b/debian/patches/extra/0004-virtiofsd-extract-lo_do_open-from-lo_open.patch
new file mode 100644 (file)
index 0000000..24ea1aa
--- /dev/null
@@ -0,0 +1,143 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Stefan Hajnoczi <stefanha@redhat.com>
+Date: Thu, 4 Feb 2021 18:34:35 +0000
+Subject: [PATCH] virtiofsd: extract lo_do_open() from lo_open()
+
+Both lo_open() and lo_create() have similar code to open a file. Extract
+a common lo_do_open() function from lo_open() that will be used by
+lo_create() in a later commit.
+
+Since lo_do_open() does not otherwise need fuse_req_t req, convert
+lo_add_fd_mapping() to use struct lo_data *lo instead.
+
+Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
+Message-Id: <20210204150208.367837-2-stefanha@redhat.com>
+Reviewed-by: Greg Kurz <groug@kaod.org>
+Signed-off-by: Dr. David Alan Gilbert <dgilbert@redhat.com>
+Signed-off-by: Thomas Lamprecht <t.lamprecht@proxmox.com>
+---
+ tools/virtiofsd/passthrough_ll.c | 73 ++++++++++++++++++++------------
+ 1 file changed, 46 insertions(+), 27 deletions(-)
+
+diff --git a/tools/virtiofsd/passthrough_ll.c b/tools/virtiofsd/passthrough_ll.c
+index 97485b22b4..218e20e9d7 100644
+--- a/tools/virtiofsd/passthrough_ll.c
++++ b/tools/virtiofsd/passthrough_ll.c
+@@ -471,17 +471,17 @@ static void lo_map_remove(struct lo_map *map, size_t key)
+ }
+ /* Assumes lo->mutex is held */
+-static ssize_t lo_add_fd_mapping(fuse_req_t req, int fd)
++static ssize_t lo_add_fd_mapping(struct lo_data *lo, int fd)
+ {
+     struct lo_map_elem *elem;
+-    elem = lo_map_alloc_elem(&lo_data(req)->fd_map);
++    elem = lo_map_alloc_elem(&lo->fd_map);
+     if (!elem) {
+         return -1;
+     }
+     elem->fd = fd;
+-    return elem - lo_data(req)->fd_map.elems;
++    return elem - lo->fd_map.elems;
+ }
+ /* Assumes lo->mutex is held */
+@@ -1661,6 +1661,38 @@ static void update_open_flags(int writeback, int allow_direct_io,
+     }
+ }
++static int lo_do_open(struct lo_data *lo, struct lo_inode *inode,
++                      struct fuse_file_info *fi)
++{
++    char buf[64];
++    ssize_t fh;
++    int fd;
++
++    update_open_flags(lo->writeback, lo->allow_direct_io, fi);
++
++    sprintf(buf, "%i", inode->fd);
++    fd = openat(lo->proc_self_fd, buf, fi->flags & ~O_NOFOLLOW);
++    if (fd == -1) {
++        return errno;
++    }
++
++    pthread_mutex_lock(&lo->mutex);
++    fh = lo_add_fd_mapping(lo, fd);
++    pthread_mutex_unlock(&lo->mutex);
++    if (fh == -1) {
++        close(fd);
++        return ENOMEM;
++    }
++
++    fi->fh = fh;
++    if (lo->cache == CACHE_NONE) {
++        fi->direct_io = 1;
++    } else if (lo->cache == CACHE_ALWAYS) {
++        fi->keep_cache = 1;
++    }
++    return 0;
++}
++
+ static void lo_create(fuse_req_t req, fuse_ino_t parent, const char *name,
+                       mode_t mode, struct fuse_file_info *fi)
+ {
+@@ -1701,7 +1733,7 @@ static void lo_create(fuse_req_t req, fuse_ino_t parent, const char *name,
+         ssize_t fh;
+         pthread_mutex_lock(&lo->mutex);
+-        fh = lo_add_fd_mapping(req, fd);
++        fh = lo_add_fd_mapping(lo, fd);
+         pthread_mutex_unlock(&lo->mutex);
+         if (fh == -1) {
+             close(fd);
+@@ -1892,38 +1924,25 @@ static void lo_fsyncdir(fuse_req_t req, fuse_ino_t ino, int datasync,
+ static void lo_open(fuse_req_t req, fuse_ino_t ino, struct fuse_file_info *fi)
+ {
+-    int fd;
+-    ssize_t fh;
+-    char buf[64];
+     struct lo_data *lo = lo_data(req);
++    struct lo_inode *inode = lo_inode(req, ino);
++    int err;
+     fuse_log(FUSE_LOG_DEBUG, "lo_open(ino=%" PRIu64 ", flags=%d)\n", ino,
+              fi->flags);
+-    update_open_flags(lo->writeback, lo->allow_direct_io, fi);
+-
+-    sprintf(buf, "%i", lo_fd(req, ino));
+-    fd = openat(lo->proc_self_fd, buf, fi->flags & ~O_NOFOLLOW);
+-    if (fd == -1) {
+-        return (void)fuse_reply_err(req, errno);
+-    }
+-
+-    pthread_mutex_lock(&lo->mutex);
+-    fh = lo_add_fd_mapping(req, fd);
+-    pthread_mutex_unlock(&lo->mutex);
+-    if (fh == -1) {
+-        close(fd);
+-        fuse_reply_err(req, ENOMEM);
++    if (!inode) {
++        fuse_reply_err(req, EBADF);
+         return;
+     }
+-    fi->fh = fh;
+-    if (lo->cache == CACHE_NONE) {
+-        fi->direct_io = 1;
+-    } else if (lo->cache == CACHE_ALWAYS) {
+-        fi->keep_cache = 1;
++    err = lo_do_open(lo, inode, fi);
++    lo_inode_put(lo, &inode);
++    if (err) {
++        fuse_reply_err(req, err);
++    } else {
++        fuse_reply_open(req, fi);
+     }
+-    fuse_reply_open(req, fi);
+ }
+ static void lo_release(fuse_req_t req, fuse_ino_t ino,
diff --git a/debian/patches/extra/0005-virtiofsd-optionally-return-inode-pointer-from-lo_do.patch b/debian/patches/extra/0005-virtiofsd-optionally-return-inode-pointer-from-lo_do.patch
new file mode 100644 (file)
index 0000000..713bcc0
--- /dev/null
@@ -0,0 +1,107 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Stefan Hajnoczi <stefanha@redhat.com>
+Date: Thu, 4 Feb 2021 18:34:36 +0000
+Subject: [PATCH] virtiofsd: optionally return inode pointer from
+ lo_do_lookup()
+
+lo_do_lookup() finds an existing inode or allocates a new one. It
+increments nlookup so that the inode stays alive until the client
+releases it.
+
+Existing callers don't need the struct lo_inode so the function doesn't
+return it. Extend the function to optionally return the inode. The next
+commit will need it.
+
+Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
+Reviewed-by: Greg Kurz <groug@kaod.org>
+Message-Id: <20210204150208.367837-3-stefanha@redhat.com>
+Signed-off-by: Dr. David Alan Gilbert <dgilbert@redhat.com>
+Signed-off-by: Thomas Lamprecht <t.lamprecht@proxmox.com>
+---
+ tools/virtiofsd/passthrough_ll.c | 29 +++++++++++++++++++++--------
+ 1 file changed, 21 insertions(+), 8 deletions(-)
+
+diff --git a/tools/virtiofsd/passthrough_ll.c b/tools/virtiofsd/passthrough_ll.c
+index 218e20e9d7..2bd050b620 100644
+--- a/tools/virtiofsd/passthrough_ll.c
++++ b/tools/virtiofsd/passthrough_ll.c
+@@ -843,11 +843,13 @@ static int do_statx(struct lo_data *lo, int dirfd, const char *pathname,
+ }
+ /*
+- * Increments nlookup and caller must release refcount using
+- * lo_inode_put(&parent).
++ * Increments nlookup on the inode on success. unref_inode_lolocked() must be
++ * called eventually to decrement nlookup again. If inodep is non-NULL, the
++ * inode pointer is stored and the caller must call lo_inode_put().
+  */
+ static int lo_do_lookup(fuse_req_t req, fuse_ino_t parent, const char *name,
+-                        struct fuse_entry_param *e)
++                        struct fuse_entry_param *e,
++                        struct lo_inode **inodep)
+ {
+     int newfd;
+     int res;
+@@ -857,6 +859,10 @@ static int lo_do_lookup(fuse_req_t req, fuse_ino_t parent, const char *name,
+     struct lo_inode *inode = NULL;
+     struct lo_inode *dir = lo_inode(req, parent);
++    if (inodep) {
++        *inodep = NULL;
++    }
++
+     /*
+      * name_to_handle_at() and open_by_handle_at() can reach here with fuse
+      * mount point in guest, but we don't have its inode info in the
+@@ -924,7 +930,14 @@ static int lo_do_lookup(fuse_req_t req, fuse_ino_t parent, const char *name,
+         pthread_mutex_unlock(&lo->mutex);
+     }
+     e->ino = inode->fuse_ino;
+-    lo_inode_put(lo, &inode);
++
++    /* Transfer ownership of inode pointer to caller or drop it */
++    if (inodep) {
++        *inodep = inode;
++    } else {
++        lo_inode_put(lo, &inode);
++    }
++
+     lo_inode_put(lo, &dir);
+     fuse_log(FUSE_LOG_DEBUG, "  %lli/%s -> %lli\n", (unsigned long long)parent,
+@@ -959,7 +972,7 @@ static void lo_lookup(fuse_req_t req, fuse_ino_t parent, const char *name)
+         return;
+     }
+-    err = lo_do_lookup(req, parent, name, &e);
++    err = lo_do_lookup(req, parent, name, &e, NULL);
+     if (err) {
+         fuse_reply_err(req, err);
+     } else {
+@@ -1067,7 +1080,7 @@ static void lo_mknod_symlink(fuse_req_t req, fuse_ino_t parent,
+         goto out;
+     }
+-    saverr = lo_do_lookup(req, parent, name, &e);
++    saverr = lo_do_lookup(req, parent, name, &e, NULL);
+     if (saverr) {
+         goto out;
+     }
+@@ -1544,7 +1557,7 @@ static void lo_do_readdir(fuse_req_t req, fuse_ino_t ino, size_t size,
+         if (plus) {
+             if (!is_dot_or_dotdot(name)) {
+-                err = lo_do_lookup(req, ino, name, &e);
++                err = lo_do_lookup(req, ino, name, &e, NULL);
+                 if (err) {
+                     goto error;
+                 }
+@@ -1742,7 +1755,7 @@ static void lo_create(fuse_req_t req, fuse_ino_t parent, const char *name,
+         }
+         fi->fh = fh;
+-        err = lo_do_lookup(req, parent, name, &e);
++        err = lo_do_lookup(req, parent, name, &e, NULL);
+     }
+     if (lo->cache == CACHE_NONE) {
+         fi->direct_io = 1;
diff --git a/debian/patches/extra/0006-virtiofsd-prevent-opening-of-special-files-CVE-2020-.patch b/debian/patches/extra/0006-virtiofsd-prevent-opening-of-special-files-CVE-2020-.patch
new file mode 100644 (file)
index 0000000..338b28f
--- /dev/null
@@ -0,0 +1,296 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Stefan Hajnoczi <stefanha@redhat.com>
+Date: Thu, 4 Feb 2021 18:34:37 +0000
+Subject: [PATCH] virtiofsd: prevent opening of special files (CVE-2020-35517)
+
+A well-behaved FUSE client does not attempt to open special files with
+FUSE_OPEN because they are handled on the client side (e.g. device nodes
+are handled by client-side device drivers).
+
+The check to prevent virtiofsd from opening special files is missing in
+a few cases, most notably FUSE_OPEN. A malicious client can cause
+virtiofsd to open a device node, potentially allowing the guest to
+escape. This can be exploited by a modified guest device driver. It is
+not exploitable from guest userspace since the guest kernel will handle
+special files inside the guest instead of sending FUSE requests.
+
+This patch fixes this issue by introducing the lo_inode_open() function
+to check the file type before opening it. This is a short-term solution
+because it does not prevent a compromised virtiofsd process from opening
+device nodes on the host.
+
+Restructure lo_create() to try O_CREAT | O_EXCL first. Note that O_CREAT
+| O_EXCL does not follow symlinks, so O_NOFOLLOW masking is not
+necessary here. If the file exists and the user did not specify O_EXCL,
+open it via lo_do_open().
+
+Reported-by: Alex Xu <alex@alxu.ca>
+Fixes: CVE-2020-35517
+Reviewed-by: Dr. David Alan Gilbert <dgilbert@redhat.com>
+Reviewed-by: Vivek Goyal <vgoyal@redhat.com>
+Reviewed-by: Greg Kurz <groug@kaod.org>
+Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
+Message-Id: <20210204150208.367837-4-stefanha@redhat.com>
+Signed-off-by: Dr. David Alan Gilbert <dgilbert@redhat.com>
+Signed-off-by: Thomas Lamprecht <t.lamprecht@proxmox.com>
+---
+ tools/virtiofsd/passthrough_ll.c | 144 ++++++++++++++++++++-----------
+ 1 file changed, 92 insertions(+), 52 deletions(-)
+
+diff --git a/tools/virtiofsd/passthrough_ll.c b/tools/virtiofsd/passthrough_ll.c
+index 2bd050b620..03c5e0d13c 100644
+--- a/tools/virtiofsd/passthrough_ll.c
++++ b/tools/virtiofsd/passthrough_ll.c
+@@ -567,6 +567,38 @@ static int lo_fd(fuse_req_t req, fuse_ino_t ino)
+     return fd;
+ }
++/*
++ * Open a file descriptor for an inode. Returns -EBADF if the inode is not a
++ * regular file or a directory.
++ *
++ * Use this helper function instead of raw openat(2) to prevent security issues
++ * when a malicious client opens special files such as block device nodes.
++ * Symlink inodes are also rejected since symlinks must already have been
++ * traversed on the client side.
++ */
++static int lo_inode_open(struct lo_data *lo, struct lo_inode *inode,
++                         int open_flags)
++{
++    g_autofree char *fd_str = g_strdup_printf("%d", inode->fd);
++    int fd;
++
++    if (!S_ISREG(inode->filetype) && !S_ISDIR(inode->filetype)) {
++        return -EBADF;
++    }
++
++    /*
++     * The file is a symlink so O_NOFOLLOW must be ignored. We checked earlier
++     * that the inode is not a special file but if an external process races
++     * with us then symlinks are traversed here. It is not possible to escape
++     * the shared directory since it is mounted as "/" though.
++     */
++    fd = openat(lo->proc_self_fd, fd_str, open_flags & ~O_NOFOLLOW);
++    if (fd < 0) {
++        return -errno;
++    }
++    return fd;
++}
++
+ static void lo_init(void *userdata, struct fuse_conn_info *conn)
+ {
+     struct lo_data *lo = (struct lo_data *)userdata;
+@@ -696,9 +728,9 @@ static void lo_setattr(fuse_req_t req, fuse_ino_t ino, struct stat *attr,
+         if (fi) {
+             truncfd = fd;
+         } else {
+-            sprintf(procname, "%i", ifd);
+-            truncfd = openat(lo->proc_self_fd, procname, O_RDWR);
++            truncfd = lo_inode_open(lo, inode, O_RDWR);
+             if (truncfd < 0) {
++                errno = -truncfd;
+                 goto out_err;
+             }
+         }
+@@ -860,7 +892,7 @@ static int lo_do_lookup(fuse_req_t req, fuse_ino_t parent, const char *name,
+     struct lo_inode *dir = lo_inode(req, parent);
+     if (inodep) {
+-        *inodep = NULL;
++        *inodep = NULL; /* in case there is an error */
+     }
+     /*
+@@ -1674,19 +1706,26 @@ static void update_open_flags(int writeback, int allow_direct_io,
+     }
+ }
++/*
++ * Open a regular file, set up an fd mapping, and fill out the struct
++ * fuse_file_info for it. If existing_fd is not negative, use that fd instead
++ * opening a new one. Takes ownership of existing_fd.
++ *
++ * Returns 0 on success or a positive errno.
++ */
+ static int lo_do_open(struct lo_data *lo, struct lo_inode *inode,
+-                      struct fuse_file_info *fi)
++                      int existing_fd, struct fuse_file_info *fi)
+ {
+-    char buf[64];
+     ssize_t fh;
+-    int fd;
++    int fd = existing_fd;
+     update_open_flags(lo->writeback, lo->allow_direct_io, fi);
+-    sprintf(buf, "%i", inode->fd);
+-    fd = openat(lo->proc_self_fd, buf, fi->flags & ~O_NOFOLLOW);
+-    if (fd == -1) {
+-        return errno;
++    if (fd < 0) {
++        fd = lo_inode_open(lo, inode, fi->flags);
++        if (fd < 0) {
++            return -fd;
++        }
+     }
+     pthread_mutex_lock(&lo->mutex);
+@@ -1709,9 +1748,10 @@ static int lo_do_open(struct lo_data *lo, struct lo_inode *inode,
+ static void lo_create(fuse_req_t req, fuse_ino_t parent, const char *name,
+                       mode_t mode, struct fuse_file_info *fi)
+ {
+-    int fd;
++    int fd = -1;
+     struct lo_data *lo = lo_data(req);
+     struct lo_inode *parent_inode;
++    struct lo_inode *inode = NULL;
+     struct fuse_entry_param e;
+     int err;
+     struct lo_cred old = {};
+@@ -1737,36 +1777,38 @@ static void lo_create(fuse_req_t req, fuse_ino_t parent, const char *name,
+     update_open_flags(lo->writeback, lo->allow_direct_io, fi);
+-    fd = openat(parent_inode->fd, name, (fi->flags | O_CREAT) & ~O_NOFOLLOW,
+-                mode);
++    /* Try to create a new file but don't open existing files */
++    fd = openat(parent_inode->fd, name, fi->flags | O_CREAT | O_EXCL, mode);
+     err = fd == -1 ? errno : 0;
+-    lo_restore_cred(&old);
+-    if (!err) {
+-        ssize_t fh;
++    lo_restore_cred(&old);
+-        pthread_mutex_lock(&lo->mutex);
+-        fh = lo_add_fd_mapping(lo, fd);
+-        pthread_mutex_unlock(&lo->mutex);
+-        if (fh == -1) {
+-            close(fd);
+-            err = ENOMEM;
+-            goto out;
+-        }
++    /* Ignore the error if file exists and O_EXCL was not given */
++    if (err && (err != EEXIST || (fi->flags & O_EXCL))) {
++        goto out;
++    }
+-        fi->fh = fh;
+-        err = lo_do_lookup(req, parent, name, &e, NULL);
++    err = lo_do_lookup(req, parent, name, &e, &inode);
++    if (err) {
++        goto out;
+     }
+-    if (lo->cache == CACHE_NONE) {
+-        fi->direct_io = 1;
+-    } else if (lo->cache == CACHE_ALWAYS) {
+-        fi->keep_cache = 1;
++
++    err = lo_do_open(lo, inode, fd, fi);
++    fd = -1; /* lo_do_open() takes ownership of fd */
++    if (err) {
++        /* Undo lo_do_lookup() nlookup ref */
++        unref_inode_lolocked(lo, inode, 1);
+     }
+ out:
++    lo_inode_put(lo, &inode);
+     lo_inode_put(lo, &parent_inode);
+     if (err) {
++        if (fd >= 0) {
++            close(fd);
++        }
++
+         fuse_reply_err(req, err);
+     } else {
+         fuse_reply_create(req, &e, fi);
+@@ -1780,7 +1822,6 @@ static struct lo_inode_plock *lookup_create_plock_ctx(struct lo_data *lo,
+                                                       pid_t pid, int *err)
+ {
+     struct lo_inode_plock *plock;
+-    char procname[64];
+     int fd;
+     plock =
+@@ -1797,12 +1838,10 @@ static struct lo_inode_plock *lookup_create_plock_ctx(struct lo_data *lo,
+     }
+     /* Open another instance of file which can be used for ofd locks. */
+-    sprintf(procname, "%i", inode->fd);
+-
+     /* TODO: What if file is not writable? */
+-    fd = openat(lo->proc_self_fd, procname, O_RDWR);
+-    if (fd == -1) {
+-        *err = errno;
++    fd = lo_inode_open(lo, inode, O_RDWR);
++    if (fd < 0) {
++        *err = -fd;
+         free(plock);
+         return NULL;
+     }
+@@ -1949,7 +1988,7 @@ static void lo_open(fuse_req_t req, fuse_ino_t ino, struct fuse_file_info *fi)
+         return;
+     }
+-    err = lo_do_open(lo, inode, fi);
++    err = lo_do_open(lo, inode, -1, fi);
+     lo_inode_put(lo, &inode);
+     if (err) {
+         fuse_reply_err(req, err);
+@@ -2005,39 +2044,40 @@ static void lo_flush(fuse_req_t req, fuse_ino_t ino, struct fuse_file_info *fi)
+ static void lo_fsync(fuse_req_t req, fuse_ino_t ino, int datasync,
+                      struct fuse_file_info *fi)
+ {
++    struct lo_inode *inode = lo_inode(req, ino);
++    struct lo_data *lo = lo_data(req);
+     int res;
+     int fd;
+-    char *buf;
+     fuse_log(FUSE_LOG_DEBUG, "lo_fsync(ino=%" PRIu64 ", fi=0x%p)\n", ino,
+              (void *)fi);
+-    if (!fi) {
+-        struct lo_data *lo = lo_data(req);
+-
+-        res = asprintf(&buf, "%i", lo_fd(req, ino));
+-        if (res == -1) {
+-            return (void)fuse_reply_err(req, errno);
+-        }
++    if (!inode) {
++        fuse_reply_err(req, EBADF);
++        return;
++    }
+-        fd = openat(lo->proc_self_fd, buf, O_RDWR);
+-        free(buf);
+-        if (fd == -1) {
+-            return (void)fuse_reply_err(req, errno);
++    if (!fi) {
++        fd = lo_inode_open(lo, inode, O_RDWR);
++        if (fd < 0) {
++            res = -fd;
++            goto out;
+         }
+     } else {
+         fd = lo_fi_fd(req, fi);
+     }
+     if (datasync) {
+-        res = fdatasync(fd);
++        res = fdatasync(fd) == -1 ? errno : 0;
+     } else {
+-        res = fsync(fd);
++        res = fsync(fd) == -1 ? errno : 0;
+     }
+     if (!fi) {
+         close(fd);
+     }
+-    fuse_reply_err(req, res == -1 ? errno : 0);
++out:
++    lo_inode_put(lo, &inode);
++    fuse_reply_err(req, res);
+ }
+ static void lo_read(fuse_req_t req, fuse_ino_t ino, size_t size, off_t offset,
diff --git a/debian/patches/extra/0007-virtiofsd-Add-_llseek-to-the-seccomp-whitelist.patch b/debian/patches/extra/0007-virtiofsd-Add-_llseek-to-the-seccomp-whitelist.patch
new file mode 100644 (file)
index 0000000..1eb919b
--- /dev/null
@@ -0,0 +1,29 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Greg Kurz <groug@kaod.org>
+Date: Thu, 4 Feb 2021 18:34:38 +0000
+Subject: [PATCH] virtiofsd: Add _llseek to the seccomp whitelist
+
+This is how glibc implements lseek(2) on POWER.
+
+BugLink: https://bugzilla.redhat.com/show_bug.cgi?id=1917692
+Signed-off-by: Greg Kurz <groug@kaod.org>
+Message-Id: <20210121171540.1449777-1-groug@kaod.org>
+Reviewed-by: Dr. David Alan Gilbert <dgilbert@redhat.com>
+Signed-off-by: Dr. David Alan Gilbert <dgilbert@redhat.com>
+Signed-off-by: Thomas Lamprecht <t.lamprecht@proxmox.com>
+---
+ tools/virtiofsd/passthrough_seccomp.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/tools/virtiofsd/passthrough_seccomp.c b/tools/virtiofsd/passthrough_seccomp.c
+index 11623f56f2..bb8ef5b17f 100644
+--- a/tools/virtiofsd/passthrough_seccomp.c
++++ b/tools/virtiofsd/passthrough_seccomp.c
+@@ -68,6 +68,7 @@ static const int syscall_whitelist[] = {
+     SCMP_SYS(linkat),
+     SCMP_SYS(listxattr),
+     SCMP_SYS(lseek),
++    SCMP_SYS(_llseek), /* For POWER */
+     SCMP_SYS(madvise),
+     SCMP_SYS(mkdirat),
+     SCMP_SYS(mknodat),
diff --git a/debian/patches/extra/0008-virtiofsd-Add-restart_syscall-to-the-seccomp-whiteli.patch b/debian/patches/extra/0008-virtiofsd-Add-restart_syscall-to-the-seccomp-whiteli.patch
new file mode 100644 (file)
index 0000000..2399eae
--- /dev/null
@@ -0,0 +1,31 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Greg Kurz <groug@kaod.org>
+Date: Thu, 4 Feb 2021 18:34:39 +0000
+Subject: [PATCH] virtiofsd: Add restart_syscall to the seccomp whitelist
+
+This is how linux restarts some system calls after SIGSTOP/SIGCONT.
+This is needed to avoid virtiofsd termination when resuming execution
+under GDB for example.
+
+Signed-off-by: Greg Kurz <groug@kaod.org>
+Message-Id: <20210201193305.136390-1-groug@kaod.org>
+Reviewed-by: Dr. David Alan Gilbert <dgilbert@redhat.com>
+Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
+Signed-off-by: Dr. David Alan Gilbert <dgilbert@redhat.com>
+Signed-off-by: Thomas Lamprecht <t.lamprecht@proxmox.com>
+---
+ tools/virtiofsd/passthrough_seccomp.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/tools/virtiofsd/passthrough_seccomp.c b/tools/virtiofsd/passthrough_seccomp.c
+index bb8ef5b17f..44d75e0e36 100644
+--- a/tools/virtiofsd/passthrough_seccomp.c
++++ b/tools/virtiofsd/passthrough_seccomp.c
+@@ -92,6 +92,7 @@ static const int syscall_whitelist[] = {
+     SCMP_SYS(renameat),
+     SCMP_SYS(renameat2),
+     SCMP_SYS(removexattr),
++    SCMP_SYS(restart_syscall),
+     SCMP_SYS(rt_sigaction),
+     SCMP_SYS(rt_sigprocmask),
+     SCMP_SYS(rt_sigreturn),
index 60567e8fd0051e37781459e2b7394ab002de02ad..6539603e4212e3ee5c5b5a58b937ff219e6b9c68 100644 (file)
@@ -1,6 +1,11 @@
 extra/0001-Revert-qemu-img-convert-Don-t-pre-zero-images.patch
 extra/0002-docs-don-t-install-man-page-if-guest-agent-is-disabl.patch
 extra/0003-migration-only-check-page-size-match-if-RAM-postcopy.patch
+extra/0004-virtiofsd-extract-lo_do_open-from-lo_open.patch
+extra/0005-virtiofsd-optionally-return-inode-pointer-from-lo_do.patch
+extra/0006-virtiofsd-prevent-opening-of-special-files-CVE-2020-.patch
+extra/0007-virtiofsd-Add-_llseek-to-the-seccomp-whitelist.patch
+extra/0008-virtiofsd-Add-restart_syscall-to-the-seccomp-whiteli.patch
 pve/0001-PVE-Config-block-file-change-locking-default-to-off.patch
 pve/0002-PVE-Config-Adjust-network-script-path-to-etc-kvm.patch
 pve/0003-PVE-Config-set-the-CPU-model-to-kvm64-32-instead-of-.patch