Browse Source

[LibOS] Test syscall arguments during parsing (in inline-debug mode)

Dmitrii Kuvaiskii 6 years ago
parent
commit
b89903da4b
1 changed files with 50 additions and 8 deletions
  1. 50 8
      LibOS/shim/src/shim_parser.c

+ 50 - 8
LibOS/shim/src/shim_parser.c

@@ -433,7 +433,16 @@ static inline int is_pointer (const char * type)
 
 static inline void parse_string_arg (va_list * ap)
 {
-    VPRINTF("\"%s\"", ap);
+    va_list ap_test_arg;
+    va_copy(ap_test_arg, *ap);
+    const char* test_arg = va_arg(ap_test_arg, const char*);
+    if (!test_user_string(test_arg)) {
+        VPRINTF("\"%s\"", ap);
+    } else {
+        /* invalid memory region, print arg as ptr not string */
+        VPRINTF("\"(invalid-addr %p)\"", ap);
+    }
+    va_end(ap_test_arg);
 }
 
 static inline void parse_pointer_arg (va_list * ap)
@@ -732,7 +741,17 @@ static void parse_exec_args (const char * type, va_list * ap)
 
     PUTS("[");
 
-    for (; *args ; args++) {
+    for (; ; args++) {
+        if (test_user_memory(args, sizeof(*args), false)) {
+            PRINTF("(invalid-argv %p)", args);
+            break;
+        }
+        if (*args == NULL)
+            break;
+        if (test_user_string(*args)) {
+            PRINTF("(invalid-addr %p),", *args);
+            continue;
+        }
         PUTS(*args);
         PUTS(",");
     }
@@ -749,15 +768,23 @@ static void parse_exec_envp (const char * type, va_list * ap)
         return;
     }
 
-    int cnt = 0;
-
     PUTS("[");
 
-    for (; *envp ; envp++)
-        if (cnt++ < 2) {
-            PUTS(*envp);
-            PUTS(",");
+    int cnt = 0;
+    for (; cnt < 2; cnt++, envp++) {
+        if (test_user_memory(envp, sizeof(*envp), false)) {
+            PRINTF("(invalid-envp %p)", envp);
+            break;
+        }
+        if (*envp == NULL)
+            break;
+        if (test_user_string(*envp)) {
+            PRINTF("(invalid-addr %p),", *envp);
+            continue;
         }
+        PUTS(*envp);
+        PUTS(",");
+    }
 
     if (cnt > 2)
         PRINTF("(%d more)", cnt);
@@ -830,6 +857,11 @@ static void parse_sigmask (const char * type, va_list * ap)
         return;
     }
 
+    if (test_user_memory(sigset, sizeof(*sigset), false)) {
+        PRINTF("(invalid-addr %p)", sigset);
+        return;
+    }
+
     PUTS("[");
 
     for (int signum = 1 ; signum <= sizeof(sigset) * 8 ; signum++)
@@ -870,6 +902,11 @@ static void parse_timespec (const char * type, va_list * ap)
         return;
     }
 
+    if (test_user_memory((void*)tv, sizeof(*tv), false)) {
+        PRINTF("(invalid-addr %p)", tv);
+        return;
+    }
+
     PRINTF("[%ld,%ld]", tv->tv_sec, tv->tv_nsec);
 }
 
@@ -882,6 +919,11 @@ static void parse_sockaddr (const char * type, va_list *ap)
         return;
     }
 
+    if (test_user_memory((void*)addr, sizeof(*addr), false)) {
+        PRINTF("(invalid-addr %p)", addr);
+        return;
+    }
+
     switch (addr->sa_family) {
         case AF_INET: {
             struct sockaddr_in * a = (void *) addr;