[Qemu-devel] [PATCH for 2.10 28/35] syscall: check dup/dup2/dup3() errors, return EBADFD/EINVAL if required

Philippe Mathieu-Daudé posted 35 patches 8 years, 3 months ago
There is a newer version of this series
[Qemu-devel] [PATCH for 2.10 28/35] syscall: check dup/dup2/dup3() errors, return EBADFD/EINVAL if required
Posted by Philippe Mathieu-Daudé 8 years, 3 months ago
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é <f4bug@amsat.org>
---
 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


Re: [Qemu-devel] [PATCH for 2.10 28/35] syscall: check dup/dup2/dup3() errors, return EBADFD/EINVAL if required
Posted by Laurent Vivier 8 years, 3 months ago
Le 24/07/2017 à 20:27, Philippe Mathieu-Daudé a écrit :
> 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é <f4bug@amsat.org>
> ---
>  linux-user/syscall.c | 32 +++++++++++++++++++++++---------
>  1 file changed, 23 insertions(+), 9 deletions(-)
> 


I don't understand why we need that: the dup()/dup2()/dup3() functions
will return the good error number.

Could you be more explicit on the reason?

Thanks,
Laurent