Skip to content

Commit 9440a49

Browse files
authored
[clang][analyzer] MmapWriteExecChecker improvements (#97078)
Read the 'mmap' flags from macro values and use a better test for the error situation. Checker messages are improved too.
1 parent ed4e75d commit 9440a49

File tree

4 files changed

+35
-48
lines changed

4 files changed

+35
-48
lines changed

clang/include/clang/StaticAnalyzer/Checkers/Checkers.td

Lines changed: 0 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1045,18 +1045,6 @@ def MallocOverflowSecurityChecker : Checker<"MallocOverflow">,
10451045

10461046
def MmapWriteExecChecker : Checker<"MmapWriteExec">,
10471047
HelpText<"Warn on mmap() calls that are both writable and executable">,
1048-
CheckerOptions<[
1049-
CmdLineOption<Integer,
1050-
"MmapProtExec",
1051-
"Specifies the value of PROT_EXEC",
1052-
"0x04",
1053-
Released>,
1054-
CmdLineOption<Integer,
1055-
"MmapProtRead",
1056-
"Specifies the value of PROT_READ",
1057-
"0x01",
1058-
Released>
1059-
]>,
10601048
Documentation<HasDocumentation>;
10611049

10621050
def ReturnPointerRangeChecker : Checker<"ReturnPtrRange">,

clang/lib/StaticAnalyzer/Checkers/MmapWriteExecChecker.cpp

Lines changed: 29 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -21,49 +21,56 @@
2121
#include "clang/StaticAnalyzer/Core/PathSensitive/CallDescription.h"
2222
#include "clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h"
2323
#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
24+
#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerHelpers.h"
2425

2526
using namespace clang;
2627
using namespace ento;
2728

2829
namespace {
29-
class MmapWriteExecChecker : public Checker<check::PreCall> {
30+
class MmapWriteExecChecker
31+
: public Checker<check::ASTDecl<TranslationUnitDecl>, check::PreCall> {
3032
CallDescription MmapFn{CDM::CLibrary, {"mmap"}, 6};
3133
CallDescription MprotectFn{CDM::CLibrary, {"mprotect"}, 3};
32-
static int ProtWrite;
33-
static int ProtExec;
34-
static int ProtRead;
3534
const BugType BT{this, "W^X check fails, Write Exec prot flags set",
3635
"Security"};
3736

37+
// Default values are used if definition of the flags is not found.
38+
mutable int ProtRead = 0x01;
39+
mutable int ProtWrite = 0x02;
40+
mutable int ProtExec = 0x04;
41+
3842
public:
43+
void checkASTDecl(const TranslationUnitDecl *TU, AnalysisManager &Mgr,
44+
BugReporter &BR) const;
3945
void checkPreCall(const CallEvent &Call, CheckerContext &C) const;
40-
int ProtExecOv;
41-
int ProtReadOv;
4246
};
4347
}
4448

45-
int MmapWriteExecChecker::ProtWrite = 0x02;
46-
int MmapWriteExecChecker::ProtExec = 0x04;
47-
int MmapWriteExecChecker::ProtRead = 0x01;
49+
void MmapWriteExecChecker::checkASTDecl(const TranslationUnitDecl *TU,
50+
AnalysisManager &Mgr,
51+
BugReporter &BR) const {
52+
Preprocessor &PP = Mgr.getPreprocessor();
53+
const std::optional<int> FoundProtRead = tryExpandAsInteger("PROT_READ", PP);
54+
const std::optional<int> FoundProtWrite =
55+
tryExpandAsInteger("PROT_WRITE", PP);
56+
const std::optional<int> FoundProtExec = tryExpandAsInteger("PROT_EXEC", PP);
57+
if (FoundProtRead && FoundProtWrite && FoundProtExec) {
58+
ProtRead = *FoundProtRead;
59+
ProtWrite = *FoundProtWrite;
60+
ProtExec = *FoundProtExec;
61+
}
62+
}
4863

4964
void MmapWriteExecChecker::checkPreCall(const CallEvent &Call,
50-
CheckerContext &C) const {
65+
CheckerContext &C) const {
5166
if (matchesAny(Call, MmapFn, MprotectFn)) {
5267
SVal ProtVal = Call.getArgSVal(2);
5368
auto ProtLoc = ProtVal.getAs<nonloc::ConcreteInt>();
5469
if (!ProtLoc)
5570
return;
5671
int64_t Prot = ProtLoc->getValue().getSExtValue();
57-
if (ProtExecOv != ProtExec)
58-
ProtExec = ProtExecOv;
59-
if (ProtReadOv != ProtRead)
60-
ProtRead = ProtReadOv;
61-
62-
// Wrong settings
63-
if (ProtRead == ProtExec)
64-
return;
6572

66-
if ((Prot & (ProtWrite | ProtExec)) == (ProtWrite | ProtExec)) {
73+
if ((Prot & ProtWrite) && (Prot & ProtExec)) {
6774
ExplodedNode *N = C.generateNonFatalErrorNode();
6875
if (!N)
6976
return;
@@ -80,17 +87,10 @@ void MmapWriteExecChecker::checkPreCall(const CallEvent &Call,
8087
}
8188
}
8289

83-
void ento::registerMmapWriteExecChecker(CheckerManager &mgr) {
84-
MmapWriteExecChecker *Mwec =
85-
mgr.registerChecker<MmapWriteExecChecker>();
86-
Mwec->ProtExecOv =
87-
mgr.getAnalyzerOptions()
88-
.getCheckerIntegerOption(Mwec, "MmapProtExec");
89-
Mwec->ProtReadOv =
90-
mgr.getAnalyzerOptions()
91-
.getCheckerIntegerOption(Mwec, "MmapProtRead");
90+
void ento::registerMmapWriteExecChecker(CheckerManager &Mgr) {
91+
Mgr.registerChecker<MmapWriteExecChecker>();
9292
}
9393

94-
bool ento::shouldRegisterMmapWriteExecChecker(const CheckerManager &mgr) {
94+
bool ento::shouldRegisterMmapWriteExecChecker(const CheckerManager &) {
9595
return true;
9696
}

clang/test/Analysis/analyzer-config.c

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,6 @@
99
// CHECK-NEXT: alpha.clone.CloneChecker:ReportNormalClones = true
1010
// CHECK-NEXT: alpha.cplusplus.STLAlgorithmModeling:AggressiveStdFindModeling = false
1111
// CHECK-NEXT: alpha.osx.cocoa.DirectIvarAssignment:AnnotatedFunctions = false
12-
// CHECK-NEXT: alpha.security.MmapWriteExec:MmapProtExec = 0x04
13-
// CHECK-NEXT: alpha.security.MmapWriteExec:MmapProtRead = 0x01
1412
// CHECK-NEXT: alpha.security.taint.TaintPropagation:Config = ""
1513
// CHECK-NEXT: apply-fixits = false
1614
// CHECK-NEXT: assume-controlled-environment = false

clang/test/Analysis/mmap-writeexec.c

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,14 @@
1-
// RUN: %clang_analyze_cc1 -triple i686-unknown-linux -analyzer-checker=alpha.security.MmapWriteExec -analyzer-config alpha.security.MmapWriteExec:MmapProtExec=1 -analyzer-config alpha.security.MmapWriteExec:MmapProtRead=4 -DUSE_ALTERNATIVE_PROT_EXEC_DEFINITION -verify %s
1+
// RUN: %clang_analyze_cc1 -triple i686-unknown-linux -analyzer-checker=alpha.security.MmapWriteExec -DUSE_ALTERNATIVE_PROT_EXEC_DEFINITION -verify %s
22
// RUN: %clang_analyze_cc1 -triple x86_64-unknown-apple-darwin10 -analyzer-checker=alpha.security.MmapWriteExec -verify %s
33

4-
#define PROT_WRITE 0x02
54
#ifndef USE_ALTERNATIVE_PROT_EXEC_DEFINITION
6-
#define PROT_EXEC 0x04
7-
#define PROT_READ 0x01
8-
#else
95
#define PROT_EXEC 0x01
6+
#define PROT_WRITE 0x02
107
#define PROT_READ 0x04
8+
#else
9+
#define PROT_EXEC 0x08
10+
#define PROT_WRITE 0x04
11+
#define PROT_READ 0x02
1112
#endif
1213
#define MAP_PRIVATE 0x0002
1314
#define MAP_ANON 0x1000

0 commit comments

Comments
 (0)