@@ -335,6 +335,50 @@ 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> 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
+
338
382
State computeNext (const MCInst &Point , const State &Cur) {
339
383
PacStatePrinter P (BC);
340
384
LLVM_DEBUG ({
@@ -355,37 +399,39 @@ class PacRetAnalysis
355
399
return State ();
356
400
}
357
401
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.
358
414
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
+
371
416
Next.SafeToDerefRegs .reset (Clobbered);
372
417
// Keep track of this instruction if it writes to any of the registers we
373
418
// need to track that for:
374
419
for (MCPhysReg Reg : RegsToTrackInstsFor.getRegisters ())
375
420
if (Clobbered[Reg])
376
421
lastWritingInsts (Next, Reg) = {&Point };
377
422
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 ();
389
435
}
390
436
391
437
LLVM_DEBUG ({
0 commit comments