raster pushed a commit to branch master.

http://git.enlightenment.org/core/efl.git/commit/?id=a5c8e883d8f9b3389e9a6233ba79c47df3bdc420

commit a5c8e883d8f9b3389e9a6233ba79c47df3bdc420
Author: Carsten Haitzler (Rasterman) <ras...@rasterman.com>
Date:   Wed Aug 30 12:03:41 2017 +0900

    eina mmap safety - only map zeropages if it's an eina file that sigbuses
    
    restrict mapping /dev/zero to only eina files having a sigbus
    reported. the mmap was before all our file access used eina_file i
    think thus the raw mmap of it. now walk all eina files and find the
    candidate and only then if it exists flag is as having a faulty i/o
    backing and map the zerto pages then return, otherwise call abort.
    more restricted mapping and perhaps a fix for not trapping non-efl
    issues.
    
    @fix
---
 src/lib/eina/eina_file.c    | 15 +++++++--------
 src/lib/eina/eina_mmap.c    | 43 ++++++++++++++++++++++++++-----------------
 src/lib/eina/eina_private.h |  2 +-
 3 files changed, 34 insertions(+), 26 deletions(-)

diff --git a/src/lib/eina/eina_file.c b/src/lib/eina/eina_file.c
index 7e154db0a0..c2c7f8f4aa 100644
--- a/src/lib/eina/eina_file.c
+++ b/src/lib/eina/eina_file.c
@@ -418,30 +418,28 @@ _eina_file_mmap_faulty_one(void *addr, long page_size,
    return EINA_FALSE;
 }
 
-void
+Eina_Bool
 eina_file_mmap_faulty(void *addr, long page_size)
 {
    Eina_File_Map *m;
    Eina_File *f;
    Eina_Iterator *itf;
    Eina_Iterator *itm;
+   Eina_Bool faulty = EINA_FALSE;
 
-   /* NOTE: I actually don't know if other thread are running, I will try to 
take the lock.
-      It may be possible that if other thread are not running and they were in 
the middle of
-      accessing an Eina_File this lock are still taken and we will result as a 
deadlock. */
    eina_lock_take(&_eina_file_lock_cache);
 
    itf = eina_hash_iterator_data_new(_eina_file_cache);
    EINA_ITERATOR_FOREACH(itf, f)
      {
-        Eina_Bool faulty = EINA_FALSE;
-
         eina_lock_take(&f->lock);
 
         if (f->global_map != MAP_FAILED)
           {
-             if ((unsigned char *) addr < (((unsigned char *)f->global_map) + 
f->length) &&
-                 (((unsigned char *) addr) + page_size) >= (unsigned char *) 
f->global_map)
+             if ((unsigned char *)addr <
+                 (((unsigned char *)f->global_map) + f->length) &&
+                 (((unsigned char *)addr) + page_size) >=
+                  (unsigned char *)f->global_map)
                {
                   f->global_faulty = EINA_TRUE;
                   faulty = EINA_TRUE;
@@ -477,6 +475,7 @@ eina_file_mmap_faulty(void *addr, long page_size)
    eina_iterator_free(itf);
 
    eina_lock_release(&_eina_file_lock_cache);
+   return faulty;
 }
 
 /* ================================================================ *
diff --git a/src/lib/eina/eina_mmap.c b/src/lib/eina/eina_mmap.c
index d6d5281515..11d8804759 100644
--- a/src/lib/eina/eina_mmap.c
+++ b/src/lib/eina/eina_mmap.c
@@ -129,26 +129,35 @@ _eina_mmap_safe_sigbus(int sig, siginfo_t *siginfo, void 
*ptr)
                }
           }
      }
-   /* send this to stderr - not eina_log. Specifically want this on stderr */
-   fprintf(stderr,
-           "EINA: Data at address 0x%lx is invalid. Replacing with zero 
page.\n",
-           (unsigned long)addr);
-   /* align address to the lower page boundary */
-   addr = (unsigned char *)((long)addr & (~(_eina_mmap_pagesize - 1)));
-   /* mmap a pzge of zero's from /dev/zero in there */
-   if (mmap(addr, _eina_mmap_pagesize,
-            PROT_READ | PROT_WRITE | PROT_EXEC,
-            MAP_PRIVATE | MAP_FIXED,
-            _eina_mmap_zero_fd, 0) == MAP_FAILED)
+   // Look into mmaped Eina_File if it was one of them, mark it as having
+   // I/O errors and then mmap a zero page in place here
+   if (eina_file_mmap_faulty(addr, _eina_mmap_pagesize))
      {
-        /* mmap of /dev/zero failed :( */
-        perror("mmap");
-        ERR("Failed to mmap() /dev/zero in place of page. SIGBUS!!!");
-        errno = perrno;
+        // Send this to stderr not eina_log. Specifically want this on stderr
+        fprintf(stderr,
+                "EINA: Data at address 0x%lx is invalid. "
+                "Replacing with zero page.\n",
+                (unsigned long)addr);
+        /* align address to the lower page boundary */
+        addr = (unsigned char *)((long)addr & (~(_eina_mmap_pagesize - 1)));
+        /* mmap a pzge of zero's from /dev/zero in there */
+        if (mmap(addr, _eina_mmap_pagesize,
+                 PROT_READ | PROT_WRITE | PROT_EXEC,
+                 MAP_PRIVATE | MAP_FIXED,
+                 _eina_mmap_zero_fd, 0) == MAP_FAILED)
+          {
+             /* mmap of /dev/zero failed :( */
+             perror("mmap");
+             ERR("Failed to mmap() /dev/zero in place of page. SIGBUS!!!");
+             errno = perrno;
+             abort();
+          }
+     }
+   else
+     {
+        ERR("Regular SIGBUS not in an eina_file mmaped file");
         abort();
      }
-   /* Look into mmaped Eina_File if it was one of them, just to remember for 
later request */
-   eina_file_mmap_faulty(addr, _eina_mmap_pagesize);
    /* restore previous errno */
    errno = perrno;
 }
diff --git a/src/lib/eina/eina_private.h b/src/lib/eina/eina_private.h
index d032f84fbd..745364a2e5 100644
--- a/src/lib/eina/eina_private.h
+++ b/src/lib/eina/eina_private.h
@@ -136,7 +136,7 @@ void eina_log_threads_shutdown(void);
 
 void eina_cpu_count_internal(void);
 
-void eina_file_mmap_faulty(void *addr, long page_size);
+Eina_Bool eina_file_mmap_faulty(void *addr, long page_size);
 
 #ifndef EINA_FREEQ_H_
 typedef struct _Eina_FreeQ Eina_FreeQ;

-- 


Reply via email to