Browse files

fixing clone() race condition leading to a deadlock

libc's clone() makes a 'call *%gs:0x10' before executing child
function. Unfortunately, at this moment, we already hijacked the
%gs:0x10 page but the companion was not yet ready to process
this kind of event.

From now on, we hook the VDSO page only when the child has really been
started and we are sure he can handle requests.

Thanks Fabrice Desclaux for this debugging session :)
  • Loading branch information...
1 parent 01cde21 commit 69fe3f2f5ce0e35c24e9285cfc4931087673a9d2 @nbareil committed Feb 1, 2011
Showing with 20 additions and 1 deletion.
  1. +20 −1 inject.c
View
21 inject.c
@@ -17,6 +17,9 @@
#include "companion.h"
#include "mm.h"
+
+#include <linux/unistd.h>
+
char junk[JUNK_SIZE];
static void hijack_vdso_gate(void) {
@@ -43,6 +46,17 @@ unsigned int la_version(unsigned int version) {
return version;
}
+volatile unsigned int is_son_ready_to_hook_vdso = 0;
+void * sync_companion(void *t) {
+ /*
+ * from now on, the libc has done every function calls needed, we can safely
+ * let the child hook the VDSO
+ */
+ is_son_ready_to_hook_vdso=1;
+ companion_routine();
+
+}
+
void la_preinit(uintptr_t *cookie) {
char dummy_stack[512];
struct sharepoint *sharedmemory;
@@ -83,12 +97,17 @@ void la_preinit(uintptr_t *cookie) {
ptr = (void *)sharedmemory->retarray;
asm("movd %0, %%mm3\n" : : "m" (ptr));
- ret = clone(companion_routine, dummy_stack+sizeof dummy_stack, CLONE_FILES |CLONE_VM, 12);
+ ret = clone(sync_companion, dummy_stack+sizeof dummy_stack, CLONE_FILES |CLONE_VM, 12);
if (ret == -1) {
perror("clone(trusted)");
exit(1);
}
enter_seccomp_mode();
+
+ while (! is_son_ready_to_hook_vdso)
+ /* waiting for that every libc calls' son have been done before hooking vdso */
+ /* do nothing */ ;
+
hijack_vdso_gate();
}

0 comments on commit 69fe3f2

Please sign in to comment.