~ chicken-core (chicken-5) 93012bb389d919ee3d575289be1f29d9a5701d8c
commit 93012bb389d919ee3d575289be1f29d9a5701d8c
Author: Peter Bex <peter@more-magic.net>
AuthorDate: Fri Dec 1 21:29:17 2017 +0100
Commit: felix <felix@call-with-current-continuation.org>
CommitDate: Sun Dec 3 00:06:59 2017 +0100
Fix calls to C_reclaim to use the number of saved objects (#1428)
When the argvector change was introduced, several C_reclaim calls were
incorrectly changed to use the size of the argvector to the C function
that would invoke C_reclaim. In many cases we don't save all the
arguments, which means "c" would be larger than the size of the
temporary stack.
The value of "c" gets set to C_restart_c, which will be used in the
setjmp trampoline as the size of the buffer to set aside for the
re-invoked closure's argvector. Then, we read C_restart_c words from
the stack top, which might overshoot the temporary stack bottom, which
means we're potentially reading beyond malloced memory.
Finally, CHICKEN_initialize would save 2 objects on the temp stack but
neglected to set C_restart_c to the correct value. This appeared to
work only because CHICKEN_run happened to look at the effective stack
size rather than the restart count. Now, we use the restart count and
also assert that it's always identical to the stack size. Any
mismatch must be due to a bug.
This is not an exploitable bug because the copied bytes are
inaccessible: they're lying just beyond the highest argument in the
argvector, which is inaccessible from Scheme. The worst that can
happen is that we try to read from a page that doesn't belong to us
and we'll segfault.
Signed-off-by: felix <felix@call-with-current-continuation.org>
diff --git a/NEWS b/NEWS
index 10d677b9..f3b00b40 100644
--- a/NEWS
+++ b/NEWS
@@ -167,6 +167,8 @@
- Correctly calculate memory requirements of Scheme objects produced
from foreign types with "const" qualifiers, avoiding memory
corruption (#1424, thanks to Vasilij Schneidermann and Lemonboy)
+ - Do not read beyond temporary stack buffer, which could lead to
+ a crash when returning from a foreign callback (#1428).
4.12.0
diff --git a/runtime.c b/runtime.c
index 499fc922..ba79a917 100644
--- a/runtime.c
+++ b/runtime.c
@@ -845,6 +845,7 @@ int CHICKEN_initialize(int heap, int stack, int symbols, void *toplevel)
C_set_block_item(k0, 0, (C_word)termination_continuation);
C_save(k0);
C_save(C_SCHEME_UNDEFINED);
+ C_restart_c = 2;
return 1;
}
@@ -1536,10 +1537,9 @@ C_word CHICKEN_run(void *toplevel)
/* We must copy the argvector onto the stack, because
* any subsequent save() will otherwise clobber it.
*/
- int argcount = C_temporary_stack_bottom - C_temporary_stack;
- C_word *p = C_alloc(argcount);
-
- C_memcpy(p, C_temporary_stack, argcount * sizeof(C_word));
+ C_word *p = C_alloc(C_restart_c);
+ assert(C_restart_c == (C_temporary_stack_bottom - C_temporary_stack));
+ C_memcpy(p, C_temporary_stack, C_restart_c * sizeof(C_word));
C_temporary_stack = C_temporary_stack_bottom;
((C_proc)C_restart_trampoline)(C_restart_c, p);
}
@@ -2115,6 +2115,7 @@ C_word C_fcall C_callback(C_word closure, int argc)
* any subsequent save() will otherwise clobber it.
*/
C_word *p = C_alloc(C_restart_c);
+ assert(C_restart_c == (C_temporary_stack_bottom - C_temporary_stack));
C_memcpy(p, C_temporary_stack, C_restart_c * sizeof(C_word));
C_temporary_stack = C_temporary_stack_bottom;
((C_proc)C_restart_trampoline)(C_restart_c, p);
@@ -9421,7 +9422,7 @@ void C_ccall C_gc(C_word c, C_word *av)
}
else if(f) C_fromspace_top = C_fromspace_limit;
- C_reclaim((void *)gc_2, c);
+ C_reclaim((void *)gc_2, 1);
}
@@ -10740,7 +10741,7 @@ void C_ccall C_ensure_heap_reserve(C_word c, C_word *av)
C_save(k);
if(!C_demand(C_bytestowords(C_unfix(n))))
- C_reclaim((void *)generic_trampoline, c);
+ C_reclaim((void *)generic_trampoline, 1);
p = C_temporary_stack;
C_temporary_stack = C_temporary_stack_bottom;
@@ -10764,7 +10765,7 @@ void C_ccall C_return_to_host(C_word c, C_word *av)
return_to_host = 1;
C_save(k);
- C_reclaim((void *)generic_trampoline, c);
+ C_reclaim((void *)generic_trampoline, 1);
}
@@ -12245,7 +12246,7 @@ void C_ccall C_dump_heap_state(C_word c, C_word *av)
/* make sure heap is compacted */
C_save(k);
C_fromspace_top = C_fromspace_limit; /* force major GC */
- C_reclaim((void *)dump_heap_state_2, c);
+ C_reclaim((void *)dump_heap_state_2, 1);
}
@@ -12473,7 +12474,7 @@ void C_ccall C_filter_heap_objects(C_word c, C_word *av)
C_save(userarg);
C_save(func);
C_fromspace_top = C_fromspace_limit; /* force major GC */
- C_reclaim((void *)filter_heap_objects_2, c);
+ C_reclaim((void *)filter_heap_objects_2, 4);
}
C_regparm C_word C_fcall C_i_process_sleep(C_word n)
Trap