CVE-2020-8938: Out-of-bounds Write (CWE-787)
value: An arbitrary memory overwrite vulnerability in Asylo versions up to 0.6.0 allows an attacker to make a host call to FromkLinuxSockAddr with attacker controlled content and size of klinux_addr which allows an attacker to write memory values from within the enclave. We recommend upgrading past commit a37fb6a0e7daf30134dbbf357c9a518a1026aa02
CWE description: The product writes data past the end, or before the beginning, of the intended buffer.
CVSS v3 base score: 3.3
Published: 2020-12-15T15:15Z
Repository: https://github.com/google/asylo
Language: C++
Files changed: asylo/platform/system_call/type_conversions/manual_types_functions.cc
Commit date: 2020-09-25 12:27:44 -0700
Commit message: Check input length in FromLinuxSockAddr

PiperOrigin-RevId: 333785506
Change-Id: I1d68fb8954665eebc1018d80ff995cbe9e7ed6a9

Diff: diff --git a/asylo/platform/system_call/type_conversions/manual_types_functions.cc b/asylo/platform/system_call/type_conversions/manual_types_functions.cc
index 7c71b0258..cba54c184 100644
--- a/asylo/platform/system_call/type_conversions/manual_types_functions.cc
+++ b/asylo/platform/system_call/type_conversions/manual_types_functions.cc
@@ -427,10 +427,14 @@ bool FromkLinuxSockAddr(const struct klinux_sockaddr *input,
     return false;
   }
 
   int16_t klinux_family = input->klinux_sa_family;
   if (klinux_family == kLinux_AF_UNIX) {
+    if (input_len < sizeof(struct klinux_sockaddr_un)) {
+      return false;
+    }
+
     struct klinux_sockaddr_un *klinux_sockaddr_un_in =
         const_cast<struct klinux_sockaddr_un *>(
             reinterpret_cast<const struct klinux_sockaddr_un *>(input));
 
     struct sockaddr_un sockaddr_un_out;
@@ -440,10 +444,13 @@ bool FromkLinuxSockAddr(const struct klinux_sockaddr *input,
         sockaddr_un_out.sun_path, klinux_sockaddr_un_in->klinux_sun_path,
         std::min(sizeof(sockaddr_un_out.sun_path),
                  sizeof(klinux_sockaddr_un_in->klinux_sun_path)));
     CopySockaddr(&sockaddr_un_out, sizeof(sockaddr_un_out), output, output_len);
   } else if (klinux_family == kLinux_AF_INET) {
+    if (input_len < sizeof(struct klinux_sockaddr_in)) {
+      return false;
+    }
     struct klinux_sockaddr_in *klinux_sockaddr_in_in =
         const_cast<struct klinux_sockaddr_in *>(
             reinterpret_cast<const struct klinux_sockaddr_in *>(input));
 
     struct sockaddr_in sockaddr_in_out;
@@ -455,10 +462,14 @@ bool FromkLinuxSockAddr(const struct klinux_sockaddr *input,
     InitializeToZeroArray(sockaddr_in_out.sin_zero);
     ReinterpretCopyArray(sockaddr_in_out.sin_zero,
                          klinux_sockaddr_in_in->klinux_sin_zero);
     CopySockaddr(&sockaddr_in_out, sizeof(sockaddr_in_out), output, output_len);
   } else if (klinux_family == kLinux_AF_INET6) {
+    if (input_len < sizeof(struct klinux_sockaddr_in6)) {
+      return false;
+    }
+
     struct klinux_sockaddr_in6 *klinux_sockaddr_in6_in =
         const_cast<struct klinux_sockaddr_in6 *>(
             reinterpret_cast<const struct klinux_sockaddr_in6 *>(input));
 
     struct sockaddr_in6 sockaddr_in6_out;

Fixed code:     if (input_len < sizeof(struct klinux_sockaddr_un)) {
      return false;
    }

    if (input_len < sizeof(struct klinux_sockaddr_in)) {
      return false;
    }
    if (input_len < sizeof(struct klinux_sockaddr_in6)) {
      return false;
    }