[PATCH] arc4random: Fix incorrect usage of TEMP_FAILURE_RETRY

Xi Ruoyao xry111@xry111.site
Thu Jan 4 00:54:12 GMT 2024


The _nocancel functions returns errors as negative values, i. e. -EINTR
for interrupted system call.  But TEMP_FAILURE_RETRY expects the errors
as errno, thus using TEMP_FAILURE_RETRY is incorrect here.

Add a customized TEMP_FAILURE_RETRY_NEG macro and use it instead of
TEMP_FAILURE_RETRY to fix the issue.

Signed-off-by: Xi Ruoyao <xry111@xry111.site>
---
 stdlib/arc4random.c | 19 ++++++++++++++-----
 1 file changed, 14 insertions(+), 5 deletions(-)

diff --git a/stdlib/arc4random.c b/stdlib/arc4random.c
index 3ae8fc1302..41f24c124c 100644
--- a/stdlib/arc4random.c
+++ b/stdlib/arc4random.c
@@ -30,6 +30,15 @@ arc4random_getrandom_failure (void)
   __libc_fatal ("Fatal glibc error: cannot get entropy for arc4random\n");
 }
 
+/* Special version of TEMP_FAILURE_RETRY for error values as negative
+   values.  */
+#define TEMP_FAILURE_RETRY_NEG(expression)	\
+  (__extension__				\
+    ({ long int __result;			\
+       do __result = (long int) (expression);	\
+       while (__result == -EINTR);		\
+       __result; }))
+
 void
 __arc4random_buf (void *p, size_t n)
 {
@@ -42,7 +51,7 @@ __arc4random_buf (void *p, size_t n)
 
   for (;;)
     {
-      l = TEMP_FAILURE_RETRY (__getrandom_nocancel (p, n, 0));
+      l = TEMP_FAILURE_RETRY_NEG (__getrandom_nocancel (p, n, 0));
       if (l > 0)
 	{
 	  if ((size_t) l == n)
@@ -60,24 +69,24 @@ __arc4random_buf (void *p, size_t n)
     {
       /* Poll /dev/random as an approximation of RNG initialization.  */
       struct pollfd pfd = { .events = POLLIN };
-      pfd.fd = TEMP_FAILURE_RETRY (
+      pfd.fd = TEMP_FAILURE_RETRY_NEG (
 	  __open64_nocancel ("/dev/random", O_RDONLY | O_CLOEXEC | O_NOCTTY));
       if (pfd.fd < 0)
 	arc4random_getrandom_failure ();
-      if (TEMP_FAILURE_RETRY (__poll_infinity_nocancel (&pfd, 1)) < 0)
+      if (TEMP_FAILURE_RETRY_NEG (__poll_infinity_nocancel (&pfd, 1)) < 0)
 	arc4random_getrandom_failure ();
       if (__close_nocancel (pfd.fd) < 0)
 	arc4random_getrandom_failure ();
       atomic_store_relaxed (&seen_initialized, 1);
     }
 
-  fd = TEMP_FAILURE_RETRY (
+  fd = TEMP_FAILURE_RETRY_NEG (
       __open64_nocancel ("/dev/urandom", O_RDONLY | O_CLOEXEC | O_NOCTTY));
   if (fd < 0)
     arc4random_getrandom_failure ();
   for (;;)
     {
-      l = TEMP_FAILURE_RETRY (__read_nocancel (fd, p, n));
+      l = TEMP_FAILURE_RETRY_NEG (__read_nocancel (fd, p, n));
       if (l <= 0)
 	arc4random_getrandom_failure ();
       if ((size_t) l == n)
-- 
2.43.0



More information about the Libc-alpha mailing list