qemu-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Qemu-devel] [PATCH for 2.10 28/35] syscall: check dup/dup2/dup3() error


From: Philippe Mathieu-Daudé
Subject: [Qemu-devel] [PATCH for 2.10 28/35] syscall: check dup/dup2/dup3() errors, return EBADFD/EINVAL if required
Date: Mon, 24 Jul 2017 15:27:44 -0300

Linux dup(2) manpage:

ERRORS
  EBADF
    newfd is out of the allowed range for file descriptors (like negative)
  EINVAL (dup3())
    oldfd was equal to newfd

Reported-by: Clang Static Analyzer
Signed-off-by: Philippe Mathieu-Daudé <address@hidden>
---
 linux-user/syscall.c | 32 +++++++++++++++++++++++---------
 1 file changed, 23 insertions(+), 9 deletions(-)

diff --git a/linux-user/syscall.c b/linux-user/syscall.c
index e79b5baec4..637270a02d 100644
--- a/linux-user/syscall.c
+++ b/linux-user/syscall.c
@@ -8336,9 +8336,13 @@ abi_long do_syscall(void *cpu_env, int num, abi_long 
arg1,
         break;
 #endif
     case TARGET_NR_dup:
-        ret = get_errno(dup(arg1));
-        if (ret >= 0) {
-            fd_trans_dup(arg1, ret);
+        if (arg1 < 0) {
+            ret = -TARGET_EBADFD;
+        } else {
+            ret = get_errno(dup(arg1));
+            if (ret >= 0) {
+                fd_trans_dup(arg1, ret);
+            }
         }
         break;
 #ifdef TARGET_NR_pipe
@@ -8436,17 +8440,27 @@ abi_long do_syscall(void *cpu_env, int num, abi_long 
arg1,
 #endif
 #ifdef TARGET_NR_dup2
     case TARGET_NR_dup2:
-        ret = get_errno(dup2(arg1, arg2));
-        if (ret >= 0) {
-            fd_trans_dup(arg1, arg2);
+        if (arg1 < 0 || arg2 < 0) {
+            ret = -TARGET_EBADFD;
+        } else {
+            ret = get_errno(dup2(arg1, arg2));
+            if (ret >= 0) {
+                fd_trans_dup(arg1, arg2);
+            }
         }
         break;
 #endif
 #if defined(CONFIG_DUP3) && defined(TARGET_NR_dup3)
     case TARGET_NR_dup3:
-        ret = get_errno(dup3(arg1, arg2, arg3));
-        if (ret >= 0) {
-            fd_trans_dup(arg1, arg2);
+        if (arg1 < 0 || arg2 < 0) {
+            ret = -TARGET_EBADFD;
+        } else if (arg1 == arg2) {
+            ret = -TARGET_EINVAL;
+        } else {
+            ret = get_errno(dup3(arg1, arg2, arg3));
+            if (ret >= 0) {
+                fd_trans_dup(arg1, arg2);
+            }
         }
         break;
 #endif
-- 
2.13.3




reply via email to

[Prev in Thread] Current Thread [Next in Thread]