| Index: src/trusted/validator/x86/ncval_seg_sfi/ncvalidate.c
|
| ===================================================================
|
| --- src/trusted/validator/x86/ncval_seg_sfi/ncvalidate.c (revision 7726)
|
| +++ src/trusted/validator/x86/ncval_seg_sfi/ncvalidate.c (working copy)
|
| @@ -405,8 +405,8 @@
|
| NCSetAdrTable(ioffset, vstate->vttable);
|
| }
|
|
|
| -static void RememberTP(const NaClPcAddress src, NaClPcAddress target,
|
| - struct NCValidatorState *vstate) {
|
| +static void RememberTP(const NCDecoderInst *dinst, const NaClPcAddress src,
|
| + NaClPcAddress target, struct NCValidatorState *vstate) {
|
| const NaClMemorySize ioffset = target - vstate->iadrbase;
|
|
|
| if (NCAddressInMemoryRange(target, vstate)) {
|
| @@ -414,8 +414,18 @@
|
| }
|
| else if ((target & vstate->alignmask) == 0) {
|
| /* Allow bundle-aligned jumps. */
|
| - }
|
| - else {
|
| + } else if (dinst->unchanged) {
|
| + /* If we are replacing this instruction during dynamic code modification
|
| + * and it has not changed, the jump target must be valid because the
|
| + * instruction has been previously validated. However, we may be only
|
| + * replacing a subsection of the code segment and therefore may not have
|
| + * information about instruction boundries outside of the code being
|
| + * replaced. Therefore, we allow unaligned direct jumps outside of the code
|
| + * being validated if and only if the instruction is unchanged.
|
| + * If dynamic code replacement is not being performed, inst->unchanged
|
| + * should always be false.
|
| + */
|
| + } else {
|
| ValidatePrintError(src, "JUMP TARGET out of range", vstate);
|
| NCStatsBadTarget(vstate);
|
| }
|
| @@ -510,7 +520,7 @@
|
| NaClPcAddress target =
|
| dinst->vpc + dinst->inst.bytes.length + offset;
|
| NCStatsCheckTarget(vstate);
|
| - RememberTP(dinst->vpc, target, vstate);
|
| + RememberTP(dinst, dinst->vpc, target, vstate);
|
| }
|
|
|
| static void ValidateJmpz(const NCDecoderInst *dinst) {
|
| @@ -542,7 +552,7 @@
|
| if (opcode0 == 0xe8) ValidateCallAlignment(dinst);
|
| }
|
| target = dinst->vpc + dinst->inst.bytes.length + offset;
|
| - RememberTP(dinst->vpc, target, vstate);
|
| + RememberTP(dinst, dinst->vpc, target, vstate);
|
| }
|
|
|
| /*
|
| @@ -895,18 +905,13 @@
|
| static Bool ValidateInstReplacement(NCDecoderStatePair* tthis,
|
| NCDecoderInst *dinst_old,
|
| NCDecoderInst *dinst_new) {
|
| +
|
| +
|
| /* Only validate individual instructions that have changed. */
|
| - if (memcmp(dinst_old->inst.bytes.byte,
|
| - dinst_new->inst.bytes.byte,
|
| - dinst_new->inst.bytes.length)) {
|
| - /* Call single instruction validator first, will call ValidateIndirect5() */
|
| - ValidateInst(dinst_new);
|
| - } else {
|
| - /* Still need to record there is an intruction here for NCValidateFinish()
|
| - * to verify basic block alignment.
|
| - */
|
| - RememberIP(dinst_new->vpc, NCVALIDATOR_STATE_DOWNCAST(dinst_new->dstate));
|
| - }
|
| + dinst_new->unchanged = memcmp(dinst_old->inst.bytes.byte,
|
| + dinst_new->inst.bytes.byte,
|
| + dinst_new->inst.bytes.length) == 0;
|
| + ValidateInst(dinst_new);
|
|
|
| if (dinst_old->opinfo->insttype == NACLi_INDIRECT
|
| || dinst_new->opinfo->insttype == NACLi_INDIRECT) {
|
|
|