I'm please to announce that the first Native Client exploit from outside Google has been submitted as
Issue 23 to the project site. User defend.the.world found an inner-sandbox escape due to a defect in the validator. The validator was checking for calls through registers, as in this two-byte call:
83 e2 e0 and $0xffffffe0,%edx
ff d2 call %edx
but erroneously permitting similar calls through memory using this addressing mode:
83 e2 e0 and $0xffffffe0,%edx
ff 12 call *(%edx)
The
and mask required by the validator aligns the address in the register, but not the address in the memory location pointed to by the register, thereby allowing a control transfer to an arbitrary byte location in the untrusted text segment. For example, it could transfer control to a syscall instruction embedded in the middle of an instruction previously identified by the validator.
Fixing this defect is relatively simple via a patch to ncv/ncvalidate.c to restrict the addressing modes allowed for this kind of call or jump:
bash-3.2$ diff -Naur ORIG/ncvalidate.c ncvalidate.c
--- ORIG/ncvalidate.c 2008-12-12 22:28:16.000000000 -0800
+++ ncvalidate.c 2008-12-12 22:38:04.000000000 -0800
@@ -482,6 +482,10 @@
/* check all the opcodes. */
if (jmpopcode[0] != 0xff) break;
if ((modrm_reg(mrm) != 2) && (modrm_reg(mrm) != 4)) break;
+ /* Issue 32: disallow unsafe call/jump indirection */
+ /* example: ff 12 call (*edx) */
+ /* Reported by defend.the.world on 11 Dec 2008 */
+ if (modrm_mod(mrm) != 3) break;
if (oropcode[0] != 0x81) break;
if (andopcode[0] != 0x81) break;
/* check modrm bytes of or and and instructions */
@@ -536,6 +540,10 @@
/* In GROUP5, 2 => call, 4 => jmp */
if (jmpopcode[0] != 0xff) break;
if ((modrm_reg(mrm) != 2) && (modrm_reg(mrm) != 4)) break;
+ /* Issue 32: disallow unsafe call/jump indirection */
+ /* example: ff 12 call (*edx) */
+ /* Reported by defend.the.world on 11 Dec 2008 */
+ if (modrm_mod(mrm) != 3) break;
if (targetreg == kReg_ESP) break;
if (andopcode[0] != 0x83) break;
/* check modrm bytes of or and and instructions */
bash-3.2$
Note that we are fixing both the five and 14-byte versions of ValidateIndirect, even though only the five-byte version is used. This fix will be included in our next set of downloads.
Congratulations to defend.the.world!
Brad Chen