devnexen created this revision. devnexen added reviewers: dcoughlin, dergachev.a. devnexen created this object with visibility "All Users". Herald added subscribers: cfe-commits, hintonda, mgorny.
This new checker tests if both PROT_WRITE and PROT_EXEC have been set. Repository: rC Clang https://reviews.llvm.org/D42645 Files: include/clang/StaticAnalyzer/Checkers/Checkers.td lib/StaticAnalyzer/Checkers/CMakeLists.txt lib/StaticAnalyzer/Checkers/MmapWriteExecChecker.cpp
Index: lib/StaticAnalyzer/Checkers/MmapWriteExecChecker.cpp =================================================================== --- lib/StaticAnalyzer/Checkers/MmapWriteExecChecker.cpp +++ lib/StaticAnalyzer/Checkers/MmapWriteExecChecker.cpp @@ -0,0 +1,76 @@ +// MmapWriteExecChecker.cpp - Check for the prot argument +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This checker detects a common memory allocation security flaw. +// Suppose 'unsigned int n' comes from an untrusted source. If the +// code looks like 'malloc (n * 4)', and an attacker can make 'n' be +// say MAX_UINT/4+2, then instead of allocating the correct 'n' 4-byte +// elements, this will actually allocate only two because of overflow. +// Then when the rest of the program attempts to store values past the +// second element, these values will actually overwrite other items in +// the heap, probably allowing the attacker to execute arbitrary code. +// +//===----------------------------------------------------------------------===// + +#include "ClangSACheckers.h" + +#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h" +#include "clang/StaticAnalyzer/Core/Checker.h" +#include "clang/StaticAnalyzer/Core/CheckerManager.h" +#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h" + +using namespace clang; +using namespace ento; +using llvm::APSInt; + +namespace { +class MmapWriteExecChecker : public Checker<check::PostStmt<CallExpr>> { +#ifdef __GLIBC__ + static const int ProtWrite = 0x02; + static const int ProtExec = 0x01; +#else + static const int ProtWrite = 0x02; + static const int ProtExec = 0x04; +#endif + mutable std::unique_ptr<BugType> BT; +public: + void checkPostStmt(const CallExpr *S, CheckerContext &C) const; +}; +} + +void MmapWriteExecChecker::checkPostStmt(const CallExpr *CE, + CheckerContext &C) const { + StringRef FName = C.getCalleeName(CE); + if (FName.empty()) + return; + + if (FName == "mmap") { + SVal ProtVal = C.getSVal(CE->getArg(2)); + Optional<nonloc::ConcreteInt> Prot = ProtVal.getAs<nonloc::ConcreteInt>(); + int64_t prot = Prot->getValue().getSExtValue(); + + if ((prot & (ProtWrite | ProtExec))) { + if (!BT) { + BT.reset(new BugType(this, "W^X check fail", "Write Exec prot flags set")); + ExplodedNode *N = C.generateErrorNode(); + if (!N) + return; + + auto Report = llvm::make_unique<BugReport>( + *BT, "Both PROT_WRITE and PROT_EXEC flags had been set", N); + Report->addRange(CE->getArg(2)->getSourceRange()); + C.emitReport(std::move(Report)); + } + } + } +} + +void ento::registerMmapWriteExecChecker(CheckerManager &mgr) { + mgr.registerChecker<MmapWriteExecChecker>(); +} Index: lib/StaticAnalyzer/Checkers/CMakeLists.txt =================================================================== --- lib/StaticAnalyzer/Checkers/CMakeLists.txt +++ lib/StaticAnalyzer/Checkers/CMakeLists.txt @@ -50,6 +50,7 @@ MallocOverflowSecurityChecker.cpp MallocSizeofChecker.cpp MisusedMovedObjectChecker.cpp + MmapWriteExecChecker.cpp MPI-Checker/MPIBugReporter.cpp MPI-Checker/MPIChecker.cpp MPI-Checker/MPIFunctionClassifier.cpp Index: include/clang/StaticAnalyzer/Checkers/Checkers.td =================================================================== --- include/clang/StaticAnalyzer/Checkers/Checkers.td +++ include/clang/StaticAnalyzer/Checkers/Checkers.td @@ -86,7 +86,7 @@ // The APIModeling package is for checkers that model APIs and don't perform // any diagnostics. These checkers are always turned on; this package is -// intended for API modeling that is not controlled by the the target triple. +// intended for API modeling that is not controlled by the target triple. def APIModeling : Package<"apiModeling">, Hidden; def GoogleAPIModeling : Package<"google">, InPackage<APIModeling>; @@ -414,6 +414,10 @@ HelpText<"Check for overflows in the arguments to malloc()">, DescFile<"MallocOverflowSecurityChecker.cpp">; +def MmapWriteExecChecker : Checker<"MmapWriteExecChecker">, + HelpText<"Check if mmap() call is not both writable and executable">, + DescFile<"MmapWriteExecChecker.cpp">; + } // end "alpha.security" //===----------------------------------------------------------------------===//
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits