The MAP_FAILED check for rtable was placed after get_routing_table
and memset had already dereferenced the pointer.  If mmap failed
under memory pressure, pfinet would crash.  Move the check to
immediately after mmap, release global_lock and return ENOMEM.
Also defer setting *dealloc_data until after confirming mmap
succeeded.

* pfinet/pfinet-ops.c (S_pfinet_getroutes): Check rtable for
MAP_FAILED right after mmap; set *dealloc_data only on success.
---
 pfinet/pfinet-ops.c | 21 +++++++++------------
 1 file changed, 9 insertions(+), 12 deletions(-)

diff --git a/pfinet/pfinet-ops.c b/pfinet/pfinet-ops.c
index 8ebbb676..612a2ce1 100644
--- a/pfinet/pfinet-ops.c
+++ b/pfinet/pfinet-ops.c
@@ -159,6 +159,12 @@ S_pfinet_getroutes (io_t port,
         {
          rtable = (ifrtreq_t *) mmap (0, amount * sizeof(ifrtreq_t), 
PROT_READ|PROT_WRITE,
                                       MAP_ANON, 0, 0);
+         if (rtable == MAP_FAILED)
+           {
+             pthread_mutex_unlock(&global_lock);
+             /* Should use errno here, but glue headers #undef errno */    
+             return ENOMEM;
+           }
          if (dealloc_data)
            *dealloc_data = TRUE;
        }
@@ -170,18 +176,9 @@ S_pfinet_getroutes (io_t port,
         memset(&rtable[n], 0, (amount - n) * sizeof(ifrtreq_t));
     }
 
-  if (rtable == MAP_FAILED)
-    {
-      /* Should use errno here, but glue headers #undef errno */
-      err = ENOMEM;
-      *len = 0;
-    }
-  else
-    {
-      *len = n * sizeof(ifrtreq_t);
-      *routes = (char *)rtable;
-    }
+  *len = n * sizeof(ifrtreq_t);
+  *routes = (char *)rtable;
 
   pthread_mutex_unlock (&global_lock);
-  return err;
+  return 0;
 }
-- 
2.54.0


Reply via email to