@@ -335,6 +335,50 @@ 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> getAuthenticatedRegs (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 ->getSafelyMaterializedAddressReg (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+ MCPhysReg ArithResult, ArithSrc;
374+ std::tie (ArithResult, ArithSrc) =
375+ BC.MIB ->analyzeSafeAddressArithmetics (Point);
376+ if (ArithResult != NoReg && Cur.SafeToDerefRegs [ArithSrc])
377+ Regs.push_back (ArithResult);
378+
379+ return Regs;
380+ }
381+
338382 State computeNext (const MCInst &Point, const State &Cur) {
339383 PacStatePrinter P (BC);
340384 LLVM_DEBUG ({
@@ -355,37 +399,39 @@ class PacRetAnalysis
355399 return State ();
356400 }
357401
402+ // First, compute various properties of the instruction, taking the state
403+ // before its execution into account, if necessary.
404+
405+ BitVector Clobbered = getClobberedRegs (Point);
406+ // Compute the set of registers that can be considered as written by
407+ // an authentication instruction. This includes operations that are
408+ // *strictly better* than authentication, such as materializing a
409+ // PC-relative constant.
410+ SmallVector<MCPhysReg> AuthenticatedOrBetter =
411+ getAuthenticatedRegs (Point, Cur);
412+
413+ // Then, compute the state after this instruction is executed.
358414 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);
415+
371416 Next.SafeToDerefRegs .reset (Clobbered);
372417 // Keep track of this instruction if it writes to any of the registers we
373418 // need to track that for:
374419 for (MCPhysReg Reg : RegsToTrackInstsFor.getRegisters ())
375420 if (Clobbered[Reg])
376421 lastWritingInsts (Next, Reg) = {&Point};
377422
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- }
423+ // After accounting for clobbered registers in general, override the state
424+ // according to authentication and other *special cases* of clobbering.
425+
426+ // The sub-registers of each authenticated register are also trusted now,
427+ // but not their super-registers (as they retain untrusted register units).
428+ BitVector AuthenticatedSubregs (NumRegs);
429+ for (MCPhysReg AutReg : AuthenticatedOrBetter)
430+ AuthenticatedSubregs |= BC.MIB ->getAliases (AutReg, /* OnlySmaller=*/ true );
431+ for (MCPhysReg Reg : AuthenticatedSubregs.set_bits ()) {
432+ Next.SafeToDerefRegs .set (Reg);
433+ if (RegsToTrackInstsFor.isTracked (Reg))
434+ lastWritingInsts (Next, Reg).clear ();
389435 }
390436
391437 LLVM_DEBUG ({
0 commit comments