summaryrefslogtreecommitdiff
path: root/exec/exec.c
diff options
context:
space:
mode:
authorRoland McGrath <roland@gnu.org>1995-11-21 21:48:23 +0000
committerRoland McGrath <roland@gnu.org>1995-11-21 21:48:23 +0000
commit0ee6319c279ce3e5bddc73defca40a1f08ef2a8c (patch)
tree956bfba59e0642b713a2ac642bd22c23a438fd7a /exec/exec.c
parentd1b2b630139132b940f69980727807ff7602e89b (diff)
(safe_bzero): New function, broken out of load_section.
(load_section): Call it.
Diffstat (limited to 'exec/exec.c')
-rw-r--r--exec/exec.c60
1 files changed, 33 insertions, 27 deletions
diff --git a/exec/exec.c b/exec/exec.c
index e267c70d..607faeea 100644
--- a/exec/exec.c
+++ b/exec/exec.c
@@ -108,6 +108,37 @@ check_section (bfd *bfd, asection *sec, void *userdata)
#endif
+/* Zero the specified region but don't crash the server if it faults. */
+
+static error_t
+safe_bzero (void *ptr, size_t size)
+{
+ jmp_buf env;
+ void fault (int signo) { longjmp (env, 1); }
+ thread_t thisthread = hurd_thread_self ();
+ volatile error_t error;
+ sighandler_t preempt (thread_t thread, int signo,
+ long int sigcode, int sigerror)
+ {
+ if (thread == thisthread)
+ {
+ error = sigerror ?: EIO;
+ return &fault;
+ }
+ return SIG_DFL;
+ }
+ struct hurd_signal_preempt preempter;
+ hurd_preempt_signals (&preempter, SIGSEGV,
+ (long int) ptr, (long int) (ptr + size),
+ &preempt);
+ error = 0;
+ if (! setjmp (env))
+ bzero (ptr, size);
+ hurd_unpreempt_signals (&preempter, SIGSEGV);
+ return error;
+}
+
+
/* Load or allocate a section. */
static void
load_section (void *section, struct execdata *u)
@@ -392,33 +423,8 @@ load_section (void *section, struct execdata *u)
vm_deallocate (u->task, mapstart, memsz);
return;
}
- {
- /* Zero the appropriate portion of our copy of the page. All
- this rigamorole is in case the memory backing this page is
- bogus and we fault in bzero; we want to return the fault's
- error code to the user, rather than crash the server. */
- jmp_buf env;
- void fault (int signo) { longjmp (env, 1); }
- thread_t thisthread = hurd_thread_self ();
- sighandler_t preempt (thread_t thread, int signo,
- long int sigcode, int sigerror)
- {
- if (thread == thisthread)
- {
- u->error = sigerror ?: EIO;
- return &fault;
- }
- return SIG_DFL;
- }
- struct hurd_signal_preempt preempter;
- hurd_preempt_signals (&preempter, SIGSEGV,
- ourpage, ourpage + vm_page_size,
- &preempt);
- if (! setjmp (env))
- bzero ((void *) (ourpage + (addr - overlap_page)),
- size - (addr - overlap_page));
- hurd_unpreempt_signals (&preempter, SIGSEGV);
- }
+ u->error = safe_bzero ((void *) (ourpage + (addr - overlap_page)),
+ size - (addr - overlap_page));
if (! u->error && !(vm_prot & VM_PROT_WRITE))
u->error = vm_protect (u->task, overlap_page, size,
0, VM_PROT_WRITE);