forked from OSchip/llvm-project
[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
This commit is contained in:
parent
ec6d1a0278
commit
6f79700830
|
@ -18057,8 +18057,25 @@ void Sema::ActOnFields(Scope *S, SourceLocation RecLoc, Decl *EnclosingDecl,
|
|||
// Handle attributes before checking the layout.
|
||||
ProcessDeclAttributeList(S, Record, Attrs);
|
||||
|
||||
// Maybe randomize the record's decls.
|
||||
if (!getLangOpts().CPlusPlus && Record->hasAttr<RandomizeLayoutAttr>() &&
|
||||
// Check to see if a FieldDecl is a pointer to a function.
|
||||
auto IsFunctionPointer = [&](const Decl *D) {
|
||||
const FieldDecl *FD = dyn_cast<FieldDecl>(D);
|
||||
if (!FD)
|
||||
return false;
|
||||
QualType FieldType = FD->getType().getDesugaredType(Context);
|
||||
if (isa<PointerType>(FieldType)) {
|
||||
QualType PointeeType = cast<PointerType>(FieldType)->getPointeeType();
|
||||
return PointeeType.getDesugaredType(Context)->isFunctionType();
|
||||
}
|
||||
return false;
|
||||
};
|
||||
|
||||
// Maybe randomize the record's decls. We automatically randomize a record
|
||||
// of function pointers, unless it has the "no_randomize_layout" attribute.
|
||||
if (!getLangOpts().CPlusPlus &&
|
||||
(Record->hasAttr<RandomizeLayoutAttr>() ||
|
||||
(!Record->hasAttr<NoRandomizeLayoutAttr>() &&
|
||||
llvm::all_of(Record->decls(), IsFunctionPointer))) &&
|
||||
!Record->isUnion() && !getLangOpts().RandstructSeed.empty() &&
|
||||
!Record->isRandomized()) {
|
||||
SmallVector<Decl *, 32> NewDeclOrdering;
|
||||
|
|
|
@ -583,5 +583,49 @@ TEST(RANDSTRUCT_TEST, AnonymousStructsAndUnionsReferenced) {
|
|||
EXPECT_EQ(OriginalDeclCount, declCount(RD));
|
||||
}
|
||||
|
||||
TEST(RANDSTRUCT_TEST, AutoRandomizeStructOfFunctionPointers) {
|
||||
const std::unique_ptr<ASTUnit> AST = makeAST(R"c(
|
||||
typedef void (*func_ptr)();
|
||||
|
||||
struct test {
|
||||
func_ptr a;
|
||||
func_ptr b;
|
||||
func_ptr c;
|
||||
func_ptr d;
|
||||
func_ptr e;
|
||||
func_ptr f;
|
||||
func_ptr g;
|
||||
};
|
||||
)c");
|
||||
|
||||
EXPECT_FALSE(AST->getDiagnostics().hasErrorOccurred());
|
||||
|
||||
const RecordDecl *RD = getRecordDeclFromAST(AST->getASTContext(), "test");
|
||||
|
||||
EXPECT_TRUE(RD->isRandomized());
|
||||
}
|
||||
|
||||
TEST(RANDSTRUCT_TEST, DisableAutoRandomizeStructOfFunctionPointers) {
|
||||
const std::unique_ptr<ASTUnit> AST = makeAST(R"c(
|
||||
typedef void (*func_ptr)();
|
||||
|
||||
struct test {
|
||||
func_ptr a;
|
||||
func_ptr b;
|
||||
func_ptr c;
|
||||
func_ptr d;
|
||||
func_ptr e;
|
||||
func_ptr f;
|
||||
func_ptr g;
|
||||
} __attribute__((no_randomize_layout));
|
||||
)c");
|
||||
|
||||
EXPECT_FALSE(AST->getDiagnostics().hasErrorOccurred());
|
||||
|
||||
const RecordDecl *RD = getRecordDeclFromAST(AST->getASTContext(), "test");
|
||||
|
||||
EXPECT_FALSE(RD->isRandomized());
|
||||
}
|
||||
|
||||
} // namespace ast_matchers
|
||||
} // namespace clang
|
||||
|
|
Loading…
Reference in New Issue