@@ -335,6 +335,49 @@ class PacRetAnalysis
335
335
});
336
336
}
337
337
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
+
338
381
State computeNext (const MCInst &Point , const State &Cur) {
339
382
PacStatePrinter P (BC);
340
383
LLVM_DEBUG ({
@@ -355,37 +398,35 @@ class PacRetAnalysis
355
398
return State ();
356
399
}
357
400
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.
358
409
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
+
371
411
Next.SafeToDerefRegs .reset (Clobbered);
372
412
// Keep track of this instruction if it writes to any of the registers we
373
413
// need to track that for:
374
414
for (MCPhysReg Reg : RegsToTrackInstsFor.getRegisters ())
375
415
if (Clobbered[Reg])
376
416
lastWritingInsts (Next, Reg) = {&Point };
377
417
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 ();
389
430
}
390
431
391
432
LLVM_DEBUG ({
0 commit comments