@@ -335,6 +335,49 @@ class PacRetAnalysis
335335 });
336336 }
337337
338+ BitVector getClobberedRegs (const MCInst &Point) const {
339+ BitVector Clobbered (NumRegs, false );
340+ // Assume a call can clobber all registers, including callee-saved
341+ // registers. There's a good chance that callee-saved registers will be
342+ // saved on the stack at some point during execution of the callee.
343+ // Therefore they should also be considered as potentially modified by an
344+ // attacker/written to.
345+ // Also, not all functions may respect the AAPCS ABI rules about
346+ // caller/callee-saved registers.
347+ if (BC.MIB ->isCall (Point))
348+ Clobbered.set ();
349+ else
350+ BC.MIB ->getClobberedRegs (Point, Clobbered);
351+ return Clobbered;
352+ }
353+
354+ // Returns all registers that can be treated as if they are written by an
355+ // authentication instruction.
356+ SmallVector<MCPhysReg> getRegsMadeSafeToDeref (const MCInst &Point,
357+ const State &Cur) const {
358+ SmallVector<MCPhysReg> Regs;
359+ const MCPhysReg NoReg = BC.MIB ->getNoRegister ();
360+
361+ // A signed pointer can be authenticated, or
362+ ErrorOr<MCPhysReg> AutReg = BC.MIB ->getAuthenticatedReg (Point);
363+ if (AutReg && *AutReg != NoReg)
364+ Regs.push_back (*AutReg);
365+
366+ // ... a safe address can be materialized, or
367+ MCPhysReg NewAddrReg = BC.MIB ->getMaterializedAddressRegForPtrAuth (Point);
368+ if (NewAddrReg != NoReg)
369+ Regs.push_back (NewAddrReg);
370+
371+ // ... an address can be updated in a safe manner, producing the result
372+ // which is as trusted as the input address.
373+ if (auto DstAndSrc = BC.MIB ->analyzeAddressArithmeticsForPtrAuth (Point)) {
374+ if (Cur.SafeToDerefRegs [DstAndSrc->second ])
375+ Regs.push_back (DstAndSrc->first );
376+ }
377+
378+ return Regs;
379+ }
380+
338381 State computeNext (const MCInst &Point, const State &Cur) {
339382 PacStatePrinter P (BC);
340383 LLVM_DEBUG ({
@@ -355,37 +398,35 @@ class PacRetAnalysis
355398 return State ();
356399 }
357400
401+ // First, compute various properties of the instruction, taking the state
402+ // before its execution into account, if necessary.
403+
404+ BitVector Clobbered = getClobberedRegs (Point);
405+ SmallVector<MCPhysReg> NewSafeToDerefRegs =
406+ getRegsMadeSafeToDeref (Point, Cur);
407+
408+ // Then, compute the state after this instruction is executed.
358409 State Next = Cur;
359- BitVector Clobbered (NumRegs, false );
360- // Assume a call can clobber all registers, including callee-saved
361- // registers. There's a good chance that callee-saved registers will be
362- // saved on the stack at some point during execution of the callee.
363- // Therefore they should also be considered as potentially modified by an
364- // attacker/written to.
365- // Also, not all functions may respect the AAPCS ABI rules about
366- // caller/callee-saved registers.
367- if (BC.MIB ->isCall (Point))
368- Clobbered.set ();
369- else
370- BC.MIB ->getClobberedRegs (Point, Clobbered);
410+
371411 Next.SafeToDerefRegs .reset (Clobbered);
372412 // Keep track of this instruction if it writes to any of the registers we
373413 // need to track that for:
374414 for (MCPhysReg Reg : RegsToTrackInstsFor.getRegisters ())
375415 if (Clobbered[Reg])
376416 lastWritingInsts (Next, Reg) = {&Point};
377417
378- ErrorOr<MCPhysReg> AutReg = BC.MIB ->getAuthenticatedReg (Point);
379- if (AutReg && *AutReg != BC.MIB ->getNoRegister ()) {
380- // The sub-registers of *AutReg are also trusted now, but not its
381- // super-registers (as they retain untrusted register units).
382- BitVector AuthenticatedSubregs =
383- BC.MIB ->getAliases (*AutReg, /* OnlySmaller=*/ true );
384- for (MCPhysReg Reg : AuthenticatedSubregs.set_bits ()) {
385- Next.SafeToDerefRegs .set (Reg);
386- if (RegsToTrackInstsFor.isTracked (Reg))
387- lastWritingInsts (Next, Reg).clear ();
388- }
418+ // After accounting for clobbered registers in general, override the state
419+ // according to authentication and other *special cases* of clobbering.
420+
421+ // The sub-registers are also safe-to-dereference now, but not their
422+ // super-registers (as they retain untrusted register units).
423+ BitVector NewSafeSubregs (NumRegs);
424+ for (MCPhysReg SafeReg : NewSafeToDerefRegs)
425+ NewSafeSubregs |= BC.MIB ->getAliases (SafeReg, /* OnlySmaller=*/ true );
426+ for (MCPhysReg Reg : NewSafeSubregs.set_bits ()) {
427+ Next.SafeToDerefRegs .set (Reg);
428+ if (RegsToTrackInstsFor.isTracked (Reg))
429+ lastWritingInsts (Next, Reg).clear ();
389430 }
390431
391432 LLVM_DEBUG ({
@@ -402,7 +443,7 @@ class PacRetAnalysis
402443public:
403444 std::vector<MCInstReference>
404445 getLastClobberingInsts (const MCInst &Inst, BinaryFunction &BF,
405- const ArrayRef<MCPhysReg> UsedDirtyRegs) {
446+ const ArrayRef<MCPhysReg> UsedDirtyRegs) const {
406447 if (RegsToTrackInstsFor.empty ())
407448 return {};
408449 auto MaybeState = getStateBefore (Inst);
0 commit comments