diff options
author | Samuel Thibault <samuel.thibault@ens-lyon.org> | 2016-11-20 16:22:29 +0100 |
---|---|---|
committer | Samuel Thibault <samuel.thibault@ens-lyon.org> | 2016-11-20 16:22:29 +0100 |
commit | 62953f120bcdc976a3dfb96505066228464a78dd (patch) | |
tree | e7fa77309a920e7b87befcfd208d05254218a059 | |
parent | 484a67719146e819ddad64fbda23b4b23afa3095 (diff) | |
download | hurd-62953f120bcdc976a3dfb96505066228464a78dd.tar.gz hurd-62953f120bcdc976a3dfb96505066228464a78dd.tar.bz2 hurd-62953f120bcdc976a3dfb96505066228464a78dd.zip |
libpager, libstore: Fix crash on ENOSPC while writing data
We need to save blocked signals, otherwise longjmp will not unblock
SIGSEGV/SIGBUS, and thus next exception will kill us. Also, we need to
make sure that the preemptor is set at the right window in main memory
before letting a handler see it.
* libpager/pager-memcpy.c (do_memcpy): Call __sync_synchronize()
between aligning the fault preemptor and actually accessing data.
(fault): Use siglongjmp instead of longjmp.
(pager_memcpy): Use sigsetjmp instead of setjmp.
* libstore/memobj.c (copy, fault, memobj_memcpy): Likewise.
-rw-r--r-- | libpager/pager-memcpy.c | 5 | ||||
-rw-r--r-- | libstore/memobj.c | 5 |
2 files changed, 6 insertions, 4 deletions
diff --git a/libpager/pager-memcpy.c b/libpager/pager-memcpy.c index 7bdc248b..c7a420b2 100644 --- a/libpager/pager-memcpy.c +++ b/libpager/pager-memcpy.c @@ -121,6 +121,7 @@ pager_memcpy (struct pager *pager, memory_object_t memobj, /* Realign the fault preemptor for the new mapping window. */ preemptor->first = window; preemptor->last = window + window_size; + __sync_synchronize(); if (prot == VM_PROT_READ) memcpy (other, (const void *) window + pageoff, copy_count); @@ -176,7 +177,7 @@ pager_memcpy (struct pager *pager, memory_object_t memobj, err = pager_get_error (pager, sigcode - window + offset); n -= sigcode - window; vm_deallocate (mach_task_self (), window, window_size); - longjmp (buf, 1); + siglongjmp (buf, 1); } if (n == 0) @@ -206,7 +207,7 @@ pager_memcpy (struct pager *pager, memory_object_t memobj, window = 0; window_size = 0; - if (setjmp (buf) == 0) + if (sigsetjmp (buf) == 0) hurd_catch_signal (sigmask (SIGSEGV) | sigmask (SIGBUS), window, window + window_size, &do_copy, (sighandler_t) &fault); diff --git a/libstore/memobj.c b/libstore/memobj.c index cc6c7cac..8bbc833d 100644 --- a/libstore/memobj.c +++ b/libstore/memobj.c @@ -83,6 +83,7 @@ memobj_memcpy (memory_object_t memobj, /* Realign the fault preemptor for the new mapping window. */ preemptor->first = window; preemptor->last = window + windowsize; + __sync_synchronize(); if (prot == VM_PROT_READ) memcpy (other, (const void *) window + pageoff, @@ -103,7 +104,7 @@ memobj_memcpy (memory_object_t memobj, assert (scp->sc_error == EKERN_MEMORY_ERROR); err = EIO; to_copy -= sigcode - window; - longjmp (buf, 1); + siglongjmp (buf, 1); } if (to_copy == 0) @@ -111,7 +112,7 @@ memobj_memcpy (memory_object_t memobj, ERR would not be initialized by the copy loop in this case. */ return 0; - if (setjmp (buf) == 0) + if (sigsetjmp (buf) == 0) hurd_catch_signal (sigmask (SIGSEGV) | sigmask (SIGBUS), window, window + windowsize, ©, (sighandler_t) &fault); |