[scudo] Descriptive Fucshia errors
authorCaslyn Tonelli <caslyn@google.com>
Sun, 16 Apr 2023 02:03:58 +0000 (02:03 +0000)
committerCaslyn Tonelli <caslyn@google.com>
Mon, 17 Apr 2023 17:38:06 +0000 (17:38 +0000)
`dieOnError` in fuchsia.cpp takes the syscall name, status code, and
relevant size parameter to describe what failed, the reason, and size
context. Several different Fuchsia syscalls can fail underlying Scudo's
map operation and gets hidden if using `dieOnMapUnmapError`.

The reason for this change is to provide an error status code and more
helpful information to debug failures.

compiler-rt/lib/scudo/standalone/fuchsia.cpp

index ef93542..0788c41 100644 (file)
@@ -19,6 +19,7 @@
 #include <zircon/compiler.h>
 #include <zircon/process.h>
 #include <zircon/sanitizer.h>
+#include <zircon/status.h>
 #include <zircon/syscalls.h>
 
 namespace scudo {
@@ -31,6 +32,16 @@ void NORETURN die() { __builtin_trap(); }
 // with ZX_HANDLE_INVALID.
 static_assert(ZX_HANDLE_INVALID == 0, "");
 
+static void NORETURN dieOnError(zx_status_t Status, const char *FnName,
+                                uptr Size) {
+  char Error[128];
+  formatString(Error, sizeof(Error),
+               "SCUDO ERROR: %s failed with size %zuKB (%s)", FnName,
+               Size >> 10, zx_status_get_string(Status));
+  outputRaw(Error);
+  die();
+}
+
 static void *allocateVmar(uptr Size, MapPlatformData *Data, bool AllowNoMem) {
   // Only scenario so far.
   DCHECK(Data);
@@ -42,7 +53,7 @@ static void *allocateVmar(uptr Size, MapPlatformData *Data, bool AllowNoMem) {
       Size, &Data->Vmar, &Data->VmarBase);
   if (UNLIKELY(Status != ZX_OK)) {
     if (Status != ZX_ERR_NO_MEMORY || !AllowNoMem)
-      dieOnMapUnmapError(Status == ZX_ERR_NO_MEMORY ? Size : 0);
+      dieOnError(Status, "zx_vmar_allocate", Size);
     return nullptr;
   }
   return reinterpret_cast<void *>(Data->VmarBase);
@@ -73,7 +84,7 @@ void *map(void *Addr, uptr Size, const char *Name, uptr Flags,
     Status = _zx_vmo_set_size(Vmo, VmoSize + Size);
     if (Status != ZX_OK) {
       if (Status != ZX_ERR_NO_MEMORY || !AllowNoMem)
-        dieOnMapUnmapError(Status == ZX_ERR_NO_MEMORY ? Size : 0);
+        dieOnError(Status, "zx_vmo_set_size", VmoSize + Size);
       return nullptr;
     }
   } else {
@@ -81,7 +92,7 @@ void *map(void *Addr, uptr Size, const char *Name, uptr Flags,
     Status = _zx_vmo_create(Size, ZX_VMO_RESIZABLE, &Vmo);
     if (UNLIKELY(Status != ZX_OK)) {
       if (Status != ZX_ERR_NO_MEMORY || !AllowNoMem)
-        dieOnMapUnmapError(Status == ZX_ERR_NO_MEMORY ? Size : 0);
+        dieOnError(Status, "zx_vmo_create", Size);
       return nullptr;
     }
     _zx_object_set_property(Vmo, ZX_PROP_NAME, Name, strlen(Name));
@@ -99,7 +110,7 @@ void *map(void *Addr, uptr Size, const char *Name, uptr Flags,
   Status = _zx_vmar_map(Vmar, MapFlags, Offset, Vmo, VmoSize, Size, &P);
   if (UNLIKELY(Status != ZX_OK)) {
     if (Status != ZX_ERR_NO_MEMORY || !AllowNoMem)
-      dieOnMapUnmapError(Status == ZX_ERR_NO_MEMORY ? Size : 0);
+      dieOnError(Status, "zx_vmar_map", Size);
     return nullptr;
   }
 
@@ -120,7 +131,7 @@ void *map(void *Addr, uptr Size, const char *Name, uptr Flags,
   }
   if (UNLIKELY(Status != ZX_OK)) {
     if (Status != ZX_ERR_NO_MEMORY || !AllowNoMem)
-      dieOnMapUnmapError(Status == ZX_ERR_NO_MEMORY ? Size : 0);
+      dieOnError(Status, "zx_vmar_op_range", Size);
     return nullptr;
   }
 
@@ -145,7 +156,7 @@ void unmap(void *Addr, uptr Size, uptr Flags, MapPlatformData *Data) {
     const zx_status_t Status =
         _zx_vmar_unmap(Vmar, reinterpret_cast<uintptr_t>(Addr), Size);
     if (UNLIKELY(Status != ZX_OK))
-      dieOnMapUnmapError();
+      dieOnError(Status, "zx_vmar_unmap", Size);
   }
   if (Data) {
     if (Data->Vmo != ZX_HANDLE_INVALID)
@@ -160,8 +171,9 @@ void setMemoryPermission(UNUSED uptr Addr, UNUSED uptr Size, UNUSED uptr Flags,
       (Flags & MAP_NOACCESS) ? 0 : (ZX_VM_PERM_READ | ZX_VM_PERM_WRITE);
   DCHECK(Data);
   DCHECK_NE(Data->Vmar, ZX_HANDLE_INVALID);
-  if (_zx_vmar_protect(Data->Vmar, Prot, Addr, Size) != ZX_OK)
-    dieOnMapUnmapError();
+  const zx_status_t Status = _zx_vmar_protect(Data->Vmar, Prot, Addr, Size);
+  if (Status != ZX_OK)
+    dieOnError(Status, "zx_vmar_protect", Size);
 }
 
 void releasePagesToOS(UNUSED uptr BaseAddress, uptr Offset, uptr Size,