假设我在沙盒的受信任部分中有以下伪代码,可以防止不受信任的代码调用和mprotect()
直接(无法从沙盒内存访问 mutext) ......mmap()
ptrace()
//src and dest are user controlled but must be valid.
TrustedPart_for_safe_jit(void * mutext, uint8_t *src,uint8_t *dest, uint32_t size) // in the current case, *dest targets a PROT_NONE memory region
{
MutexLock(mutext);
ValidateOpcodesOrCrash(src,size); // uses calls to mmap on size internally. Contains many different loops and use several 10k thousands lines of codes in the trusted part of the sandbox : this is the longest part. Please also note that src is write protected while being in this function.
unwriteprotect(dest,size); // calls many sandbox’s internal functions
SafeMemcpy(src,dest,size); // THIS IS the function which contains the race condition
asm("mfence");
unEXECprotect(dest,size); // involve write protecting as well as allowing reading
MutexUnlock(mutext);
}
SafeMemcpy(uint8_t *src,uint8_t *dest, uint32_t size) // the data to be copied cannot exceed 128Mb
{
if(!CheckUserTargetPointToValidMemroyRange(dest,size) {
uint8_t *src_ptr=src;
uint8_t *dest_ptr=dest;
uint8_t *end_ptr=des+size;
while (dest_ptr < end_ptr) { // that loop should execute very fast
*(uint32_t *) dest_ptr = *(uint32_t *) src_ptr;
dest_ptr += 4;
src_ptr += 4;
}
}
}
该部分负责允许不受信任的代码使用ᴊɪᴛ编译。
关键是不受信任的线程没有被挂起。
如您所知,当 2 个线程使用memcpy()
相同的目的地时,它们会生成随机数据。在这种情况下,此类数据可能包含类似的指令int 0x80
,从而允许逃离沙箱。
到目前为止我想到的事情:
- 将数据写入文件并通过沙箱使用 read 系统调用读取它。如果内存仍处于写保护状态,则程序不会崩溃。这将涉及循环,即使要复制的数据可以是 128Mb 大,由于系统调用开销,我不确定它是否会起作用。
另一种方法是多次创建代码并尝试使用多个时间读取,但我不知道如何选择初始时间窗口。 - 使用 futex... 但是我找不到 futex 是否可以用来检查未分配内存的值。我也不确定线程是否可以在内存被写保护之前唤醒。
那么,是否可以为 memcpy 竞争条件计划时间窗口?