qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
From: Laurent Vivier <laurent@vivier.eu>
To: qemu-devel@nongnu.org
Cc: Owen Anderson <oanderso@google.com>, Laurent Vivier <laurent@vivier.eu>
Subject: [PULL 09/12] fd-trans: Fix race condition on reallocation of the translation table.
Date: Tue, 13 Jul 2021 15:41:49 +0200	[thread overview]
Message-ID: <20210713134152.288423-10-laurent@vivier.eu> (raw)
In-Reply-To: <20210713134152.288423-1-laurent@vivier.eu>

From: Owen Anderson <oanderso@google.com>

The mapping from file-descriptors to translator functions is not guarded
on realloc which may cause invalid function pointers to be read from a
previously deallocated mapping.

Signed-off-by: Owen Anderson <oanderso@google.com>
Reviewed-by: Laurent Vivier <laurent@vivier.eu>
Message-Id: <20210701221255.107976-1-oanderso@google.com>
Signed-off-by: Laurent Vivier <laurent@vivier.eu>
---
 linux-user/fd-trans.c |  1 +
 linux-user/fd-trans.h | 55 +++++++++++++++++++++++++++++++++++++------
 linux-user/main.c     |  3 +++
 3 files changed, 52 insertions(+), 7 deletions(-)

diff --git a/linux-user/fd-trans.c b/linux-user/fd-trans.c
index 23adaca83639..86b6f484d30b 100644
--- a/linux-user/fd-trans.c
+++ b/linux-user/fd-trans.c
@@ -267,6 +267,7 @@ enum {
 };
 
 TargetFdTrans **target_fd_trans;
+QemuMutex target_fd_trans_lock;
 unsigned int target_fd_max;
 
 static void tswap_nlmsghdr(struct nlmsghdr *nlh)
diff --git a/linux-user/fd-trans.h b/linux-user/fd-trans.h
index a3fcdaabc758..1b9fa2041c06 100644
--- a/linux-user/fd-trans.h
+++ b/linux-user/fd-trans.h
@@ -16,6 +16,8 @@
 #ifndef FD_TRANS_H
 #define FD_TRANS_H
 
+#include "qemu/lockable.h"
+
 typedef abi_long (*TargetFdDataFunc)(void *, size_t);
 typedef abi_long (*TargetFdAddrFunc)(void *, abi_ulong, socklen_t);
 typedef struct TargetFdTrans {
@@ -25,12 +27,23 @@ typedef struct TargetFdTrans {
 } TargetFdTrans;
 
 extern TargetFdTrans **target_fd_trans;
+extern QemuMutex target_fd_trans_lock;
 
 extern unsigned int target_fd_max;
 
+static inline void fd_trans_init(void)
+{
+    qemu_mutex_init(&target_fd_trans_lock);
+}
+
 static inline TargetFdDataFunc fd_trans_target_to_host_data(int fd)
 {
-    if (fd >= 0 && fd < target_fd_max && target_fd_trans[fd]) {
+    if (fd < 0) {
+        return NULL;
+    }
+
+    QEMU_LOCK_GUARD(&target_fd_trans_lock);
+    if (fd < target_fd_max && target_fd_trans[fd]) {
         return target_fd_trans[fd]->target_to_host_data;
     }
     return NULL;
@@ -38,7 +51,12 @@ static inline TargetFdDataFunc fd_trans_target_to_host_data(int fd)
 
 static inline TargetFdDataFunc fd_trans_host_to_target_data(int fd)
 {
-    if (fd >= 0 && fd < target_fd_max && target_fd_trans[fd]) {
+    if (fd < 0) {
+        return NULL;
+    }
+
+    QEMU_LOCK_GUARD(&target_fd_trans_lock);
+    if (fd < target_fd_max && target_fd_trans[fd]) {
         return target_fd_trans[fd]->host_to_target_data;
     }
     return NULL;
@@ -46,13 +64,19 @@ static inline TargetFdDataFunc fd_trans_host_to_target_data(int fd)
 
 static inline TargetFdAddrFunc fd_trans_target_to_host_addr(int fd)
 {
-    if (fd >= 0 && fd < target_fd_max && target_fd_trans[fd]) {
+    if (fd < 0) {
+        return NULL;
+    }
+
+    QEMU_LOCK_GUARD(&target_fd_trans_lock);
+    if (fd < target_fd_max && target_fd_trans[fd]) {
         return target_fd_trans[fd]->target_to_host_addr;
     }
     return NULL;
 }
 
-static inline void fd_trans_register(int fd, TargetFdTrans *trans)
+static inline void internal_fd_trans_register_unsafe(int fd,
+                                                     TargetFdTrans *trans)
 {
     unsigned int oldmax;
 
@@ -67,18 +91,35 @@ static inline void fd_trans_register(int fd, TargetFdTrans *trans)
     target_fd_trans[fd] = trans;
 }
 
-static inline void fd_trans_unregister(int fd)
+static inline void fd_trans_register(int fd, TargetFdTrans *trans)
+{
+    QEMU_LOCK_GUARD(&target_fd_trans_lock);
+    internal_fd_trans_register_unsafe(fd, trans);
+}
+
+static inline void internal_fd_trans_unregister_unsafe(int fd)
 {
     if (fd >= 0 && fd < target_fd_max) {
         target_fd_trans[fd] = NULL;
     }
 }
 
+static inline void fd_trans_unregister(int fd)
+{
+    if (fd < 0) {
+        return;
+    }
+
+    QEMU_LOCK_GUARD(&target_fd_trans_lock);
+    internal_fd_trans_unregister_unsafe(fd);
+}
+
 static inline void fd_trans_dup(int oldfd, int newfd)
 {
-    fd_trans_unregister(newfd);
+    QEMU_LOCK_GUARD(&target_fd_trans_lock);
+    internal_fd_trans_unregister_unsafe(newfd);
     if (oldfd < target_fd_max && target_fd_trans[oldfd]) {
-        fd_trans_register(newfd, target_fd_trans[oldfd]);
+        internal_fd_trans_register_unsafe(newfd, target_fd_trans[oldfd]);
     }
 }
 
diff --git a/linux-user/main.c b/linux-user/main.c
index 2fb3a366a699..37ed50d98e2e 100644
--- a/linux-user/main.c
+++ b/linux-user/main.c
@@ -48,6 +48,7 @@
 #include "target_elf.h"
 #include "cpu_loop-common.h"
 #include "crypto/init.h"
+#include "fd-trans.h"
 
 #ifndef AT_FLAGS_PRESERVE_ARGV0
 #define AT_FLAGS_PRESERVE_ARGV0_BIT 0
@@ -829,6 +830,8 @@ int main(int argc, char **argv, char **envp)
     cpu->opaque = ts;
     task_settid(ts);
 
+    fd_trans_init();
+
     ret = loader_exec(execfd, exec_path, target_argv, target_environ, regs,
         info, &bprm);
     if (ret != 0) {
-- 
2.31.1



  parent reply	other threads:[~2021-07-13 14:11 UTC|newest]

Thread overview: 14+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2021-07-13 13:41 [PULL 00/12] Linux user for 6.1 patches Laurent Vivier
2021-07-13 13:41 ` [PULL 01/12] linux-user/syscall: Fix RF-kill errno (typo in ERFKILL) Laurent Vivier
2021-07-13 13:41 ` [PULL 02/12] linux-user/sparc: Rename target_errno.h -> target_errno_defs.h Laurent Vivier
2021-07-13 13:41 ` [PULL 03/12] linux-user: Extract target errno to 'target_errno_defs.h' Laurent Vivier
2021-07-13 13:41 ` [PULL 04/12] linux-user/alpha: Move errno definitions " Laurent Vivier
2021-07-13 13:41 ` [PULL 05/12] linux-user/hppa: " Laurent Vivier
2021-07-13 13:41 ` [PULL 06/12] linux-user/mips: " Laurent Vivier
2021-07-13 13:41 ` [PULL 07/12] linux-user: Simplify host <-> target errno conversion using macros Laurent Vivier
2021-07-13 13:41 ` [PULL 08/12] linux-user/syscall: Remove ERRNO_TABLE_SIZE check Laurent Vivier
2021-07-13 13:41 ` Laurent Vivier [this message]
2021-07-13 13:41 ` [PULL 10/12] linux-user: update syscall_nr.h to Linux v5.13 Laurent Vivier
2021-07-13 13:41 ` [PULL 11/12] linux-user, mips: update syscall-args-o32.c.inc " Laurent Vivier
2021-07-13 13:41 ` [PULL 12/12] linux-user: update syscall.tbl " Laurent Vivier
2021-07-13 22:00 ` [PULL 00/12] Linux user for 6.1 patches Peter Maydell

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20210713134152.288423-10-laurent@vivier.eu \
    --to=laurent@vivier.eu \
    --cc=oanderso@google.com \
    --cc=qemu-devel@nongnu.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).