Skip to content

Commit 6f79700

Browse files
committed
[randstruct] Automatically randomize a structure of function pointers
Strutures of function pointers are a good surface area for attacks. We should therefore randomize them unless explicitly told not to. Reviewed By: aaron.ballman, MaskRay Differential Revision: https://reviews.llvm.org/D123544
1 parent ec6d1a0 commit 6f79700

File tree

2 files changed

+63
-2
lines changed

2 files changed

+63
-2
lines changed

clang/lib/Sema/SemaDecl.cpp

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18057,8 +18057,25 @@ void Sema::ActOnFields(Scope *S, SourceLocation RecLoc, Decl *EnclosingDecl,
1805718057
// Handle attributes before checking the layout.
1805818058
ProcessDeclAttributeList(S, Record, Attrs);
1805918059

18060-
// Maybe randomize the record's decls.
18061-
if (!getLangOpts().CPlusPlus && Record->hasAttr<RandomizeLayoutAttr>() &&
18060+
// Check to see if a FieldDecl is a pointer to a function.
18061+
auto IsFunctionPointer = [&](const Decl *D) {
18062+
const FieldDecl *FD = dyn_cast<FieldDecl>(D);
18063+
if (!FD)
18064+
return false;
18065+
QualType FieldType = FD->getType().getDesugaredType(Context);
18066+
if (isa<PointerType>(FieldType)) {
18067+
QualType PointeeType = cast<PointerType>(FieldType)->getPointeeType();
18068+
return PointeeType.getDesugaredType(Context)->isFunctionType();
18069+
}
18070+
return false;
18071+
};
18072+
18073+
// Maybe randomize the record's decls. We automatically randomize a record
18074+
// of function pointers, unless it has the "no_randomize_layout" attribute.
18075+
if (!getLangOpts().CPlusPlus &&
18076+
(Record->hasAttr<RandomizeLayoutAttr>() ||
18077+
(!Record->hasAttr<NoRandomizeLayoutAttr>() &&
18078+
llvm::all_of(Record->decls(), IsFunctionPointer))) &&
1806218079
!Record->isUnion() && !getLangOpts().RandstructSeed.empty() &&
1806318080
!Record->isRandomized()) {
1806418081
SmallVector<Decl *, 32> NewDeclOrdering;

clang/unittests/AST/RandstructTest.cpp

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -583,5 +583,49 @@ TEST(RANDSTRUCT_TEST, AnonymousStructsAndUnionsReferenced) {
583583
EXPECT_EQ(OriginalDeclCount, declCount(RD));
584584
}
585585

586+
TEST(RANDSTRUCT_TEST, AutoRandomizeStructOfFunctionPointers) {
587+
const std::unique_ptr<ASTUnit> AST = makeAST(R"c(
588+
typedef void (*func_ptr)();
589+
590+
struct test {
591+
func_ptr a;
592+
func_ptr b;
593+
func_ptr c;
594+
func_ptr d;
595+
func_ptr e;
596+
func_ptr f;
597+
func_ptr g;
598+
};
599+
)c");
600+
601+
EXPECT_FALSE(AST->getDiagnostics().hasErrorOccurred());
602+
603+
const RecordDecl *RD = getRecordDeclFromAST(AST->getASTContext(), "test");
604+
605+
EXPECT_TRUE(RD->isRandomized());
606+
}
607+
608+
TEST(RANDSTRUCT_TEST, DisableAutoRandomizeStructOfFunctionPointers) {
609+
const std::unique_ptr<ASTUnit> AST = makeAST(R"c(
610+
typedef void (*func_ptr)();
611+
612+
struct test {
613+
func_ptr a;
614+
func_ptr b;
615+
func_ptr c;
616+
func_ptr d;
617+
func_ptr e;
618+
func_ptr f;
619+
func_ptr g;
620+
} __attribute__((no_randomize_layout));
621+
)c");
622+
623+
EXPECT_FALSE(AST->getDiagnostics().hasErrorOccurred());
624+
625+
const RecordDecl *RD = getRecordDeclFromAST(AST->getASTContext(), "test");
626+
627+
EXPECT_FALSE(RD->isRandomized());
628+
}
629+
586630
} // namespace ast_matchers
587631
} // namespace clang

0 commit comments

Comments
 (0)