[m-rev.] for post-commit review; fix system RNG handles for non-unrandom C implementations

Julien Fischer jfischer at opturion.com
Sat Feb 20 01:11:50 AEDT 2021


Fix system RNG handles for non-urandom C implementations.

Ensure it is not possible to use a system RNG handle after it has been closed
with the arc4random() and rand_s() based implementations.

library/random.system_rng.m:
     As above.

Julien.

diff --git a/library/random.system_rng.m b/library/random.system_rng.m
index 7e7339f1c..b16ce3b83 100644
--- a/library/random.system_rng.m
+++ b/library/random.system_rng.m
@@ -178,14 +178,14 @@
      #define ML_SYSRAND_IMPL_NONE
  #endif

-#if defined(ML_SYSRAND_IMPL_URANDOM)
-    struct ML_SystemRandomHandle_Struct {
+struct ML_SystemRandomHandle_Struct {
+    #if defined(ML_SYSRAND_IMPL_URANDOM)
          int ML_srh_fd;
-    };
-    typedef struct ML_SystemRandomHandle_Struct *ML_SystemRandomHandle;
-#else
-    typedef MR_Unsigned ML_SystemRandomHandle;
-#endif
+    #else
+        MR_Bool ML_srh_is_open;
+    #endif
+};
+typedef struct ML_SystemRandomHandle_Struct *ML_SystemRandomHandle;

  // When succeeded is MR_TRUE, returns a handle through which the system
  // RNG can be accessed; err_msg will point to the empty string in this case.
@@ -796,24 +796,40 @@ ML_random_generate_bytes(ML_SystemRandomHandle handle,
  ML_SystemRandomHandle
  ML_random_open(MR_Bool *succeeded, MR_String *err_msg)
  {
+    ML_SystemRandomHandle handle =
+        MR_GC_NEW(struct ML_SystemRandomHandle_Struct);
+    handle->ML_srh_is_open = MR_TRUE;
      *succeeded = MR_TRUE;
      *err_msg = MR_make_string_const(\"\");
-    return 0;
+    return handle;
  }

  MR_Bool
  ML_random_close(ML_SystemRandomHandle handle, MR_String *err_msg)
  {
-    *err_msg = MR_make_string_const(\"\");
-    return MR_TRUE;
+    if (handle->ML_srh_is_open) {
+        handle->ML_srh_is_open = MR_FALSE;
+        *err_msg = MR_make_string_const(\"\");
+        return MR_TRUE;
+    } else {
+        *err_msg =
+            MR_make_string_const(\"system RNG handle is already closed\");
+        return MR_FALSE;
+    }
  }

  MR_Bool
  ML_random_generate_bytes(ML_SystemRandomHandle handle,
      unsigned char *buffer, size_t len, MR_String *err_msg)
  {
-    arc4random_buf(buffer, len);
-    return MR_TRUE;
+    if (handle->ML_srh_is_open) {
+        arc4random_buf(buffer, len);
+        *err_msg = MR_make_string_const(\"\");
+        return MR_TRUE;
+    } else {
+        *err_msg = MR_make_string_const(\"system RNG handle is closed\");
+        return MR_FALSE;
+    }
  }

  #elif defined(ML_SYSRAND_IMPL_RAND_S)
@@ -821,16 +837,26 @@ ML_random_generate_bytes(ML_SystemRandomHandle handle,
  ML_SystemRandomHandle
  ML_random_open(MR_Bool *succeeded, MR_String *err_msg)
  {
+    ML_SystemRandomHandle handle =
+        MR_GC_NEW(struct ML_SystemRandomHandle_Struct);
+    handle->ML_srh_is_open = MR_TRUE;
      *succeeded = MR_TRUE;
      *err_msg = MR_make_string_const(\"\");
-    return 0;
+    return handle;
  }

  MR_Bool
  ML_random_close(ML_SystemRandomHandle handle, MR_String *err_msg)
  {
-    *err_msg = MR_make_string_const(\"\");
-    return MR_TRUE;
+    if (handle->MR_srh_is_open) {
+        handle->ML_srh_is_open = MR_FALSE;
+        *err_msg = MR_make_string_const(\"\");
+        return MR_TRUE;
+    } else {
+        *err_msg =
+            MR_make_string_const(\"system RNG handle is already closed\");
+        return MR_FALSE;
+    }
  }

  MR_Bool
@@ -841,6 +867,11 @@ ML_random_generate_bytes(ML_SystemRandomHandle handle,
      unsigned int n;
      size_t num_to_read = len;

+    if (!handle->ML_srh_is_open) {
+        *err_msg = MR_make_string_const(\"system RNG handle is closed\");
+        return MR_FALSE;
+    }
+
      while (num_to_read > 0) {
          if (num_to_read < 4) {
              err = rand_s(&n);



More information about the reviews mailing list