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; --