Fix memleak in os.getrandom()

Issue #27778: Fix a memory leak in os.getrandom() when the getrandom() is
interrupted by a signal and a signal handler raises a Python exception.

Modify also os_getrandom_impl() to avoid the temporary buffer, use directly a
Python bytes object.
diff --git a/Misc/NEWS b/Misc/NEWS
index 97f669d..bda0576 100644
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -32,6 +32,9 @@
 Library
 -------
 
+- Issue #27778: Fix a memory leak in os.getrandom() when the getrandom() is
+  interrupted by a signal and a signal handler raises a Python exception.
+
 - Issue #28200: Fix memory leak on Windows in the os module (fix
   path_converter() function).
 
diff --git a/Modules/posixmodule.c b/Modules/posixmodule.c
index 470ee92..28d30b0 100644
--- a/Modules/posixmodule.c
+++ b/Modules/posixmodule.c
@@ -12047,42 +12047,50 @@
 os_getrandom_impl(PyObject *module, Py_ssize_t size, int flags)
 /*[clinic end generated code: output=b3a618196a61409c input=59bafac39c594947]*/
 {
-    char *buffer;
-    Py_ssize_t n;
     PyObject *bytes;
+    Py_ssize_t n;
 
     if (size < 0) {
         errno = EINVAL;
         return posix_error();
     }
 
-    buffer = PyMem_Malloc(size);
-    if (buffer == NULL) {
+    bytes = PyBytes_FromStringAndSize(NULL, size);
+    if (bytes == NULL) {
         PyErr_NoMemory();
         return NULL;
     }
 
     while (1) {
-        n = syscall(SYS_getrandom, buffer, size, flags);
+        n = syscall(SYS_getrandom,
+                    PyBytes_AS_STRING(bytes),
+                    PyBytes_GET_SIZE(bytes),
+                    flags);
         if (n < 0 && errno == EINTR) {
             if (PyErr_CheckSignals() < 0) {
-                return NULL;
+                goto error;
             }
+
+            /* getrandom() was interrupted by a signal: retry */
             continue;
         }
         break;
     }
 
     if (n < 0) {
-        PyMem_Free(buffer);
         PyErr_SetFromErrno(PyExc_OSError);
-        return NULL;
+        goto error;
     }
 
-    bytes = PyBytes_FromStringAndSize(buffer, n);
-    PyMem_Free(buffer);
+    if (n != size) {
+        _PyBytes_Resize(&bytes, n);
+    }
 
     return bytes;
+
+error:
+    Py_DECREF(bytes);
+    return NULL;
 }
 #endif   /* HAVE_GETRANDOM_SYSCALL */