forked from enlightenment/efl
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
This commit is contained in:
parent
15cdd9b71b
commit
a5c8e883d8
|
@ -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;
|
||||
}
|
||||
|
||||
/* ================================================================ *
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Reference in New Issue