void NCValidateSegment(uint8_t *mbase, NaClPcAddress vbase, size_t sz, struct NCValidatorState *vstate) { if (sz == 0) { ValidatePrintError(0, "Bad text segment (zero size)", vstate); Stats_SegFault(vstate); return; } GetCPUFeatures(&(vstate->cpufeatures)); /* The name of the flag is misleading; f_386 requires not just */ /* 386 instructions but also the CPUID instruction is supported. */ if (!vstate->cpufeatures.f_386) { ValidatePrintError(0, "CPU does not support CPUID", vstate); Stats_BadCPU(vstate); return; } #if (0) /* TODO(bradchen): enable this check */ if (!vstate->cpufeatures.f_whitelisted) { ValidatePrintError(0, "CPU does not support CPUID", vstate); Stats_BadCPU(vstate); return; } #endif NCDecodeSegment(mbase, vbase, sz, vstate); }
static void BadInstructionError(const struct NCDecoderState *mstate, const char *msg) { ValidatePrintError(mstate->inst.vaddr, msg, mstate->vstate); if (mstate->vstate->do_stub_out) { memset(mstate->inst.maddr, kNaClFullStop, mstate->inst.length); } }
static void ValidateCallAlignment(const struct NCDecoderState *mstate) { NaClPcAddress fallthru = mstate->inst.vaddr + mstate->inst.length; if (fallthru & mstate->vstate->alignmask) { ValidatePrintError(mstate->inst.vaddr, "Bad call alignment", mstate->vstate); /* This makes bad call alignment a fatal error. */ Stats_BadAlignment(mstate->vstate); } }
static void ForgetIP(const NaClPcAddress ip, struct NCValidatorState *vstate) { NaClMemorySize ioffset = ip - vstate->iadrbase; if (ip < vstate->iadrbase || ip >= vstate->iadrlimit) { ValidatePrintError(ip, "JUMP TARGET out of range in ForgetIP", vstate); Stats_BadTarget(vstate); return; } ClearAdrTable(ioffset, vstate->vttable); }
int NCValidateFinish(struct NCValidatorState *vstate) { uint32_t offset; if (vstate == NULL) { vprint(("validator not initialized. Did you call ncvalidate_init()?\n")); /* non-zero indicates failure */ return 1; } dprint(("CheckTargets: %x-%x\n", vstate->iadrbase, vstate->iadrlimit)); for (offset = 0; offset < vstate->iadrlimit - vstate->iadrbase; offset += 1) { if (GetAdrTable(offset, vstate->kttable)) { /* printf("CheckTarget %x\n", offset + iadrbase); */ Stats_CheckTarget(vstate); if (!GetAdrTable(offset, vstate->vttable)) { ValidatePrintError(vstate->iadrbase + offset, "Bad jump target", vstate); Stats_BadTarget(vstate); } } } /* check basic block boundaries */ if (vstate->iadrbase & vstate->alignmask) { /* This should never happen because the alignment of iadrbase is */ /* checked in NCValidateInit(). */ ValidatePrintError(vstate->iadrbase, "Bad base address alignment", vstate); Stats_BadAlignment(vstate); } for (offset = 0; offset < vstate->iadrlimit - vstate->iadrbase; offset += vstate->alignment) { if (!GetAdrTable(offset, vstate->vttable)) { ValidatePrintError(vstate->iadrbase + offset, "Bad basic block alignment", vstate); Stats_BadAlignment(vstate); } } fflush(stdout); /* Now that all the work is done, generate return code. */ /* Return zero if there are no problems. */ return (vstate->stats.sawfailure); }
/* * (Same as NCValidateSegment, but operates on a pair of instructions.) * Validates that instructions at mbase_new may replace mbase_old. */ void NCValidateSegmentPair(uint8_t *mbase_old, uint8_t *mbase_new, NaClPcAddress vbase, size_t sz, struct NCValidatorState *vstate) { if (sz == 0) { ValidatePrintError(0, "Bad text segment (zero size)", vstate); Stats_SegFault(vstate); return; } GetCPUFeatures(&(vstate->cpufeatures)); /* The name of the flag is misleading; f_386 requires not just */ /* 386 instructions but also the CPUID instruction is supported. */ if (!vstate->cpufeatures.f_386) { ValidatePrintError(0, "CPU does not support CPUID", vstate); Stats_BadCPU(vstate); return; } NCDecodeSegmentPair(mbase_old, mbase_new, vbase, sz, vstate, ValidateInstReplacement); }
static void RememberTP(const NaClPcAddress src, NaClPcAddress target, struct NCValidatorState *vstate) { const NaClMemorySize ioffset = target - vstate->iadrbase; if (vstate->iadrbase <= target && target < vstate->iadrlimit) { /* Remember address for checking later. */ SetAdrTable(ioffset, vstate->kttable); } else if ((target & vstate->alignmask) == 0) { /* Allow bundle-aligned jumps. */ } else { ValidatePrintError(src, "JUMP TARGET out of range", vstate); Stats_BadTarget(vstate); } }
static void RememberIP(const NaClPcAddress ip, struct NCValidatorState *vstate) { const NaClMemorySize ioffset = ip - vstate->iadrbase; if (ip < vstate->iadrbase || ip >= vstate->iadrlimit) { ValidatePrintError(ip, "JUMP TARGET out of range in RememberIP", vstate); Stats_BadTarget(vstate); return; } if (GetAdrTable(ioffset, vstate->vttable)) { vprint(("RememberIP: Saw inst at %"NACL_PRIxNaClPcAddressAll " twice\n", ip)); Stats_InternalError(vstate); return; } Stats_Inst(vstate); SetAdrTable(ioffset, vstate->vttable); }
static void ValidatePrintOffsetError(const NaClPcAddress addr, const char *msg, struct NCValidatorState *vstate) { ValidatePrintError(vstate->iadrbase + addr, msg, vstate); }
static void ValidatePrintInstructionError(const struct NCDecoderInst *dinst, const char *msg, struct NCValidatorState *vstate) { ValidatePrintError(NCPrintableInstructionAddress(dinst), msg, vstate); }