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
2526using namespace clang ;
2627using namespace ento ;
2728
2829namespace {
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+
3842public:
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
4964void 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}
0 commit comments