21
21
#include " clang/StaticAnalyzer/Core/PathSensitive/CallDescription.h"
22
22
#include " clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h"
23
23
#include " clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
24
+ #include " clang/StaticAnalyzer/Core/PathSensitive/CheckerHelpers.h"
24
25
25
26
using namespace clang ;
26
27
using namespace ento ;
27
28
28
29
namespace {
29
- class MmapWriteExecChecker : public Checker <check::PreCall> {
30
+ class MmapWriteExecChecker
31
+ : public Checker<check::ASTDecl<TranslationUnitDecl>, check::PreCall> {
30
32
CallDescription MmapFn{CDM::CLibrary, {" mmap" }, 6 };
31
33
CallDescription MprotectFn{CDM::CLibrary, {" mprotect" }, 3 };
32
- static int ProtWrite;
33
- static int ProtExec;
34
- static int ProtRead;
35
34
const BugType BT{this , " W^X check fails, Write Exec prot flags set" ,
36
35
" Security" };
37
36
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
+
38
42
public:
43
+ void checkASTDecl (const TranslationUnitDecl *TU, AnalysisManager &Mgr,
44
+ BugReporter &BR) const ;
39
45
void checkPreCall (const CallEvent &Call, CheckerContext &C) const ;
40
- int ProtExecOv;
41
- int ProtReadOv;
42
46
};
43
47
}
44
48
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
+ }
48
63
49
64
void MmapWriteExecChecker::checkPreCall (const CallEvent &Call,
50
- CheckerContext &C) const {
65
+ CheckerContext &C) const {
51
66
if (matchesAny (Call, MmapFn, MprotectFn)) {
52
67
SVal ProtVal = Call.getArgSVal (2 );
53
68
auto ProtLoc = ProtVal.getAs <nonloc::ConcreteInt>();
54
69
if (!ProtLoc)
55
70
return ;
56
71
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 ;
65
72
66
- if ((Prot & ( ProtWrite | ProtExec)) == (ProtWrite | ProtExec)) {
73
+ if ((Prot & ProtWrite) && (Prot & ProtExec)) {
67
74
ExplodedNode *N = C.generateNonFatalErrorNode ();
68
75
if (!N)
69
76
return ;
@@ -80,17 +87,10 @@ void MmapWriteExecChecker::checkPreCall(const CallEvent &Call,
80
87
}
81
88
}
82
89
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>();
92
92
}
93
93
94
- bool ento::shouldRegisterMmapWriteExecChecker (const CheckerManager &mgr ) {
94
+ bool ento::shouldRegisterMmapWriteExecChecker (const CheckerManager &) {
95
95
return true ;
96
96
}
0 commit comments