[clang] [PAC] Implement function pointer re-signing (PR #98847)

Daniil Kovalev via cfe-commits cfe-commits at lists.llvm.org
Mon Jul 15 06:48:42 PDT 2024


================
@@ -165,6 +166,88 @@ CGPointerAuthInfo CodeGenModule::getPointerAuthInfoForType(QualType T) {
   return ::getPointerAuthInfoForType(*this, T);
 }
 
+static bool isZeroConstant(llvm::Value *value) {
+  if (auto ci = dyn_cast<llvm::ConstantInt>(value))
+    return ci->isZero();
+  return false;
+}
+
+static bool equalAuthPolicies(const CGPointerAuthInfo &left,
+                              const CGPointerAuthInfo &right) {
+  if (left.isSigned() != right.isSigned())
+    return false;
+  assert(left.isSigned() && right.isSigned() &&
+         "should only be called with non-null auth policies");
+  return left.getKey() == right.getKey() &&
+         left.getAuthenticationMode() == right.getAuthenticationMode();
+}
+
+llvm::Value *CodeGenFunction::EmitPointerAuthResign(
+    llvm::Value *value, QualType type, const CGPointerAuthInfo &curAuthInfo,
+    const CGPointerAuthInfo &newAuthInfo, bool isKnownNonNull) {
+  // Fast path: if neither schema wants a signature, we're done.
+  if (!curAuthInfo && !newAuthInfo)
+    return value;
+
+  llvm::Value *null = nullptr;
+  // If the value is obviously null, we're done.
+  if (auto pointerValue = dyn_cast<llvm::PointerType>(value->getType())) {
+    null = CGM.getNullPointer(pointerValue, type);
+  } else {
+    assert(value->getType()->isIntegerTy());
+    null = llvm::ConstantInt::get(IntPtrTy, 0);
+  }
+  if (value == null) {
+    return value;
+  }
+
+  // If both schemas sign the same way, we're done.
+  if (equalAuthPolicies(curAuthInfo, newAuthInfo)) {
+    auto curD = curAuthInfo.getDiscriminator();
+    auto newD = newAuthInfo.getDiscriminator();
+    if (curD == newD)
+      return value;
+
+    if ((curD == nullptr && isZeroConstant(newD)) ||
+        (newD == nullptr && isZeroConstant(curD)))
+      return value;
+  }
+
+  llvm::BasicBlock *initBB = Builder.GetInsertBlock();
+  llvm::BasicBlock *resignBB = nullptr, *contBB = nullptr;
+
+  // Null pointers have to be mapped to null, and the ptrauth_resign
+  // intrinsic doesn't do that.
+  if (!isKnownNonNull && !llvm::isKnownNonZero(value, CGM.getDataLayout())) {
+    contBB = createBasicBlock("resign.cont");
+    resignBB = createBasicBlock("resign.nonnull");
+
+    auto isNonNull = Builder.CreateICmpNE(value, null);
+    Builder.CreateCondBr(isNonNull, resignBB, contBB);
+    EmitBlock(resignBB);
+  }
+
+  // Perform the auth/sign/resign operation.
+  if (!newAuthInfo) {
+    value = EmitPointerAuthAuth(curAuthInfo, value);
+  } else if (!curAuthInfo) {
+    value = EmitPointerAuthSign(newAuthInfo, value);
+  } else {
+    value = EmitPointerAuthResignCall(value, curAuthInfo, newAuthInfo);
+  }
+
+  // Clean up with a phi if we branched before.
+  if (contBB) {
+    EmitBlock(contBB);
+    auto phi = Builder.CreatePHI(value->getType(), 2);
----------------
kovdan01 wrote:

Nit: either

```suggestion
    auto *phi = Builder.CreatePHI(value->getType(), 2);
```
or
```suggestion
    PHINode *phi = Builder.CreatePHI(value->getType(), 2);
```

https://github.com/llvm/llvm-project/pull/98847


More information about the cfe-commits mailing list