[clang] c8048c7 - [attributes] Generalize attribute 'enforce_tcb' to Objective-C methods.

Artem Dergachev via cfe-commits cfe-commits at lists.llvm.org
Mon Mar 28 15:08:58 PDT 2022


Author: Pierre d'Herbemont
Date: 2022-03-28T15:08:47-07:00
New Revision: c8048c7c42ffd1731149b0abe15b9081dd27c789

URL: https://github.com/llvm/llvm-project/commit/c8048c7c42ffd1731149b0abe15b9081dd27c789
DIFF: https://github.com/llvm/llvm-project/commit/c8048c7c42ffd1731149b0abe15b9081dd27c789.diff

LOG: [attributes] Generalize attribute 'enforce_tcb' to Objective-C methods.

Calling an ObjC method from a C function marked with the 'enforce_tcb'
attribute did not produce a warning. Now it does, and on top of that
Objective-C methods can participate in TCBs themselves.

Differential Revision: https://reviews.llvm.org/D122343

Added: 
    clang/test/Sema/attr-enforce-tcb-errors.m
    clang/test/Sema/attr-enforce-tcb.m

Modified: 
    clang/include/clang/Basic/Attr.td
    clang/include/clang/Sema/Sema.h
    clang/lib/Sema/SemaChecking.cpp
    clang/test/Misc/pragma-attribute-supported-attributes-list.test

Removed: 
    


################################################################################
diff  --git a/clang/include/clang/Basic/Attr.td b/clang/include/clang/Basic/Attr.td
index a35b2fcbc4fb5..f7ef3bf42ec2f 100644
--- a/clang/include/clang/Basic/Attr.td
+++ b/clang/include/clang/Basic/Attr.td
@@ -3915,7 +3915,7 @@ def Builtin : InheritableAttr {
 
 def EnforceTCB : InheritableAttr {
   let Spellings = [Clang<"enforce_tcb">];
-  let Subjects = SubjectList<[Function]>;
+  let Subjects = SubjectList<[Function, ObjCMethod]>;
   let Args = [StringArgument<"TCBName">];
   let Documentation = [EnforceTCBDocs];
   bit InheritEvenIfAlreadyPresent = 1;
@@ -3923,7 +3923,7 @@ def EnforceTCB : InheritableAttr {
 
 def EnforceTCBLeaf : InheritableAttr {
   let Spellings = [Clang<"enforce_tcb_leaf">];
-  let Subjects = SubjectList<[Function]>;
+  let Subjects = SubjectList<[Function, ObjCMethod]>;
   let Args = [StringArgument<"TCBName">];
   let Documentation = [EnforceTCBLeafDocs];
   bit InheritEvenIfAlreadyPresent = 1;

diff  --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h
index 53ac1d011d9e1..379e120e3a117 100644
--- a/clang/include/clang/Sema/Sema.h
+++ b/clang/include/clang/Sema/Sema.h
@@ -12988,7 +12988,8 @@ class Sema final {
   /// attempts to add itself into the container
   void CheckObjCCircularContainer(ObjCMessageExpr *Message);
 
-  void CheckTCBEnforcement(const CallExpr *TheCall, const FunctionDecl *Callee);
+  void CheckTCBEnforcement(const SourceLocation CallExprLoc,
+                           const NamedDecl *Callee);
 
   void AnalyzeDeleteExprMismatch(const CXXDeleteExpr *DE);
   void AnalyzeDeleteExprMismatch(FieldDecl *Field, SourceLocation DeleteLoc,

diff  --git a/clang/lib/Sema/SemaChecking.cpp b/clang/lib/Sema/SemaChecking.cpp
index e02104b4699e1..14e82e54eacb3 100644
--- a/clang/lib/Sema/SemaChecking.cpp
+++ b/clang/lib/Sema/SemaChecking.cpp
@@ -5497,7 +5497,9 @@ bool Sema::CheckFunctionCall(FunctionDecl *FDecl, CallExpr *TheCall,
   if (!FnInfo)
     return false;
 
-  CheckTCBEnforcement(TheCall, FDecl);
+  // Enforce TCB except for builtin calls, which are always allowed.
+  if (FDecl->getBuiltinID() == 0)
+    CheckTCBEnforcement(TheCall->getExprLoc(), FDecl);
 
   CheckAbsoluteValueFunction(TheCall, FDecl);
   CheckMaxUnsignedZero(TheCall, FDecl);
@@ -5537,6 +5539,8 @@ bool Sema::CheckObjCMethodCall(ObjCMethodDecl *Method, SourceLocation lbrac,
             /*IsMemberFunction=*/false, lbrac, Method->getSourceRange(),
             CallType);
 
+  CheckTCBEnforcement(lbrac, Method);
+
   return false;
 }
 
@@ -17359,13 +17363,11 @@ ExprResult Sema::SemaBuiltinMatrixColumnMajorStore(CallExpr *TheCall,
 /// CheckTCBEnforcement - Enforces that every function in a named TCB only
 /// directly calls other functions in the same TCB as marked by the enforce_tcb
 /// and enforce_tcb_leaf attributes.
-void Sema::CheckTCBEnforcement(const CallExpr *TheCall,
-                               const FunctionDecl *Callee) {
-  const FunctionDecl *Caller = getCurFunctionDecl();
+void Sema::CheckTCBEnforcement(const SourceLocation CallExprLoc,
+                               const NamedDecl *Callee) {
+  const NamedDecl *Caller = getCurFunctionOrMethodDecl();
 
-  // Calls to builtins are not enforced.
-  if (!Caller || !Caller->hasAttr<EnforceTCBAttr>() ||
-      Callee->getBuiltinID() != 0)
+  if (!Caller || !Caller->hasAttr<EnforceTCBAttr>())
     return;
 
   // Search through the enforce_tcb and enforce_tcb_leaf attributes to find
@@ -17383,9 +17385,8 @@ void Sema::CheckTCBEnforcement(const CallExpr *TheCall,
       [&](const auto *A) {
         StringRef CallerTCB = A->getTCBName();
         if (CalleeTCBs.count(CallerTCB) == 0) {
-          this->Diag(TheCall->getExprLoc(),
-                     diag::warn_tcb_enforcement_violation) << Callee
-                                                           << CallerTCB;
+          this->Diag(CallExprLoc, diag::warn_tcb_enforcement_violation)
+              << Callee << CallerTCB;
         }
       });
 }

diff  --git a/clang/test/Misc/pragma-attribute-supported-attributes-list.test b/clang/test/Misc/pragma-attribute-supported-attributes-list.test
index 944090509f55e..daae71f5167c4 100644
--- a/clang/test/Misc/pragma-attribute-supported-attributes-list.test
+++ b/clang/test/Misc/pragma-attribute-supported-attributes-list.test
@@ -61,8 +61,8 @@
 // CHECK-NEXT: DisableSanitizerInstrumentation (SubjectMatchRule_function, SubjectMatchRule_objc_method, SubjectMatchRule_variable_is_global)
 // CHECK-NEXT: DisableTailCalls (SubjectMatchRule_function, SubjectMatchRule_objc_method)
 // CHECK-NEXT: EnableIf (SubjectMatchRule_function)
-// CHECK-NEXT: EnforceTCB (SubjectMatchRule_function)
-// CHECK-NEXT: EnforceTCBLeaf (SubjectMatchRule_function)
+// CHECK-NEXT: EnforceTCB (SubjectMatchRule_function, SubjectMatchRule_objc_method)
+// CHECK-NEXT: EnforceTCBLeaf (SubjectMatchRule_function, SubjectMatchRule_objc_method)
 // CHECK-NEXT: EnumExtensibility (SubjectMatchRule_enum)
 // CHECK-NEXT: Error (SubjectMatchRule_function)
 // CHECK-NEXT: ExcludeFromExplicitInstantiation (SubjectMatchRule_variable, SubjectMatchRule_function, SubjectMatchRule_record)

diff  --git a/clang/test/Sema/attr-enforce-tcb-errors.m b/clang/test/Sema/attr-enforce-tcb-errors.m
new file mode 100644
index 0000000000000..f82d38c919d1d
--- /dev/null
+++ b/clang/test/Sema/attr-enforce-tcb-errors.m
@@ -0,0 +1,100 @@
+// RUN: %clang_cc1 -fsyntax-only -verify %s
+
+int foo();
+
+__attribute__((objc_root_class))
+ at interface AClass
+- (void)bothTCBAndTCBLeafOnSeparateRedeclarations __attribute__((enforce_tcb("x"))); // expected-note{{conflicting attribute is here}}
+
+- (void)bothTCBAndTCBLeafOnSeparateRedeclarationsOppositeOrder __attribute__((enforce_tcb_leaf("x"))); // expected-note{{conflicting attribute is here}}
+
+- (void)bothTCBAndTCBLeafButDifferentIdentifiersOnSeparateRedeclarations __attribute__((enforce_tcb("x")));
+
+- (void)bothTCBAndTCBLeafButDifferentIdentifiersOnSeparateRedeclarationsOppositeOrder __attribute__((enforce_tcb_leaf("x")));
+
+- (void)onInterfaceOnly __attribute__((enforce_tcb("test")));
+ at end
+
+ at interface AClass (NoImplementation)
+- (void)noArguments __attribute__((enforce_tcb)); // expected-error{{'enforce_tcb' attribute takes one argument}}
+
+- (void)tooManyArguments __attribute__((enforce_tcb("test", 12))); // expected-error{{'enforce_tcb' attribute takes one argument}}
+
+- (void)wrongArgumentType __attribute__((enforce_tcb(12))); // expected-error{{'enforce_tcb' attribute requires a string}}
+
+- (void)noArgumentsLeaf __attribute__((enforce_tcb_leaf)); // expected-error{{'enforce_tcb_leaf' attribute takes one argument}}
+
+- (void)tooManyArgumentsLeaf __attribute__((enforce_tcb_leaf("test", 12))); // expected-error{{'enforce_tcb_leaf' attribute takes one argument}}
+
+- (void)wrongArgumentTypeLeaf __attribute__((enforce_tcb_leaf(12))); // expected-error{{'enforce_tcb_leaf' attribute requires a string}}
+ at end
+
+ at implementation AClass
+- (void)onInterfaceOnly {
+  foo(); // expected-warning{{calling 'foo' is a violation of trusted computing base 'test'}}
+}
+
+- (void)bothTCBAndTCBLeaf
+    __attribute__((enforce_tcb("x")))
+    __attribute__((enforce_tcb_leaf("x"))) // expected-error{{attributes 'enforce_tcb_leaf("x")' and 'enforce_tcb("x")' are mutually exclusive}}
+{
+  foo(); // no-warning
+}
+
+- (void)bothTCBAndTCBLeafOnSeparateRedeclarations
+    __attribute__((enforce_tcb_leaf("x"))) // expected-error{{attributes 'enforce_tcb_leaf("x")' and 'enforce_tcb("x")' are mutually exclusive}}
+{
+  // Error recovery: no need to emit a warning when we didn't
+  // figure out our attributes to begin with.
+  foo(); // no-warning
+}
+
+- (void)bothTCBAndTCBLeafOppositeOrder
+    __attribute__((enforce_tcb_leaf("x")))
+    __attribute__((enforce_tcb("x"))) // expected-error{{attributes 'enforce_tcb("x")' and 'enforce_tcb_leaf("x")' are mutually exclusive}}
+{
+  foo(); // no-warning
+}
+
+- (void)bothTCBAndTCBLeafOnSeparateRedeclarationsOppositeOrder
+    __attribute__((enforce_tcb("x"))) // expected-error{{attributes 'enforce_tcb("x")' and 'enforce_tcb_leaf("x")' are mutually exclusive}}
+{
+  foo(); // no-warning
+}
+
+- (void)bothTCBAndTCBLeafButDifferentIdentifiers
+    __attribute__((enforce_tcb("x")))
+    __attribute__((enforce_tcb_leaf("y"))) // no-error
+{
+  foo(); // expected-warning{{calling 'foo' is a violation of trusted computing base 'x'}}
+}
+
+- (void)bothTCBAndTCBLeafButDifferentIdentifiersOppositeOrder
+    __attribute__((enforce_tcb_leaf("x")))
+    __attribute__((enforce_tcb("y"))) // no-error
+{
+  foo(); // expected-warning{{calling 'foo' is a violation of trusted computing base 'y'}}
+}
+
+- (void)bothTCBAndTCBLeafButDifferentIdentifiersOnSeparateRedeclarations
+    __attribute__((enforce_tcb_leaf("y"))) // no-error
+{
+  foo(); // expected-warning{{calling 'foo' is a violation of trusted computing base 'x'}}
+}
+
+- (void)bothTCBAndTCBLeafButDifferentIdentifiersOnSeparateRedeclarationsOppositeOrder
+    __attribute__((enforce_tcb("y"))) {
+  foo(); // expected-warning{{calling 'foo' is a violation of trusted computing base 'y'}}
+}
+
+- (void)errorRecoveryOverIndividualTCBs
+    __attribute__((enforce_tcb("y")))
+    __attribute__((enforce_tcb("x")))
+    __attribute__((enforce_tcb_leaf("x"))) // expected-error{{attributes 'enforce_tcb_leaf("x")' and 'enforce_tcb("x")' are mutually exclusive}}
+{
+  // FIXME: Ideally this should warn. The conflict between attributes
+  // for TCB "x" shouldn't affect the warning about TCB "y".
+  foo(); // no-warning
+}
+
+ at end

diff  --git a/clang/test/Sema/attr-enforce-tcb.m b/clang/test/Sema/attr-enforce-tcb.m
new file mode 100644
index 0000000000000..40b92c4293ec7
--- /dev/null
+++ b/clang/test/Sema/attr-enforce-tcb.m
@@ -0,0 +1,37 @@
+// RUN: %clang_cc1 -fsyntax-only -verify %s
+
+#define PLACE_IN_TCB(NAME) __attribute__((enforce_tcb(NAME)))
+#define PLACE_IN_TCB_LEAF(NAME) __attribute__((enforce_tcb_leaf(NAME)))
+
+__attribute__((objc_root_class))
+ at interface AClass
+ at property(readonly) id propertyNotInAnyTCB;
+ at end
+
+ at implementation AClass
+- (void)inTCBFoo PLACE_IN_TCB("foo") {
+  [self notInAnyTCB]; // expected-warning{{calling 'notInAnyTCB' is a violation of trusted computing base 'foo'}}
+}
+- (void)inTCBFooAsLeaf PLACE_IN_TCB_LEAF("foo") {
+  [self notInAnyTCB]; // no-warning
+}
+- (void)notInAnyTCB {
+}
++ (void)classMethodNotInAnyTCB {
+}
++ (void)classMethodInTCBFoo PLACE_IN_TCB("foo") {
+  [self inTCBFoo];       // no-warning
+  [self inTCBFooAsLeaf]; // no-warning
+  [self notInAnyTCB];    // expected-warning{{calling 'notInAnyTCB' is a violation of trusted computing base 'foo'}}
+}
+ at end
+
+PLACE_IN_TCB("foo")
+void call_objc_method(AClass *object) {
+  [object inTCBFoo];                // no-warning
+  [object inTCBFooAsLeaf];          // no-warning
+  [object notInAnyTCB];             // expected-warning{{calling 'notInAnyTCB' is a violation of trusted computing base 'foo'}}
+  [AClass classMethodNotInAnyTCB];  // expected-warning{{calling 'classMethodNotInAnyTCB' is a violation of trusted computing base 'foo'}}
+  [AClass classMethodInTCBFoo];     // no-warning
+  (void)object.propertyNotInAnyTCB; // expected-warning{{calling 'propertyNotInAnyTCB' is a violation of trusted computing base 'foo'}}
+}


        


More information about the cfe-commits mailing list