clang  8.0.0
MmapWriteExecChecker.cpp
Go to the documentation of this file.
1 // MmapWriteExecChecker.cpp - Check for the prot argument -----------------===//
2 //
3 // The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 //
10 // This checker tests the 3rd argument of mmap's calls to check if
11 // it is writable and executable in the same time. It's somehow
12 // an optional checker since for example in JIT libraries it is pretty common.
13 //
14 //===----------------------------------------------------------------------===//
15 
17 
23 
24 using namespace clang;
25 using namespace ento;
26 using llvm::APSInt;
27 
28 namespace {
29 class MmapWriteExecChecker : public Checker<check::PreCall> {
30  CallDescription MmapFn;
31  CallDescription MprotectFn;
32  static int ProtWrite;
33  static int ProtExec;
34  static int ProtRead;
35  mutable std::unique_ptr<BugType> BT;
36 public:
37  MmapWriteExecChecker() : MmapFn("mmap", 6), MprotectFn("mprotect", 3) {}
38  void checkPreCall(const CallEvent &Call, CheckerContext &C) const;
39  int ProtExecOv;
40  int ProtReadOv;
41 };
42 }
43 
44 int MmapWriteExecChecker::ProtWrite = 0x02;
45 int MmapWriteExecChecker::ProtExec = 0x04;
46 int MmapWriteExecChecker::ProtRead = 0x01;
47 
48 void MmapWriteExecChecker::checkPreCall(const CallEvent &Call,
49  CheckerContext &C) const {
50  if (Call.isCalled(MmapFn) || Call.isCalled(MprotectFn)) {
51  SVal ProtVal = Call.getArgSVal(2);
52  Optional<nonloc::ConcreteInt> ProtLoc = ProtVal.getAs<nonloc::ConcreteInt>();
53  int64_t Prot = ProtLoc->getValue().getSExtValue();
54  if (ProtExecOv != ProtExec)
55  ProtExec = ProtExecOv;
56  if (ProtReadOv != ProtRead)
57  ProtRead = ProtReadOv;
58 
59  // Wrong settings
60  if (ProtRead == ProtExec)
61  return;
62 
63  if ((Prot & (ProtWrite | ProtExec)) == (ProtWrite | ProtExec)) {
64  if (!BT)
65  BT.reset(new BugType(this, "W^X check fails, Write Exec prot flags set", "Security"));
66 
67  ExplodedNode *N = C.generateNonFatalErrorNode();
68  if (!N)
69  return;
70 
71  auto Report = llvm::make_unique<BugReport>(
72  *BT, "Both PROT_WRITE and PROT_EXEC flags are set. This can "
73  "lead to exploitable memory regions, which could be overwritten "
74  "with malicious code", N);
75  Report->addRange(Call.getArgSourceRange(2));
76  C.emitReport(std::move(Report));
77  }
78  }
79 }
80 
81 void ento::registerMmapWriteExecChecker(CheckerManager &mgr) {
82  MmapWriteExecChecker *Mwec =
83  mgr.registerChecker<MmapWriteExecChecker>();
84  Mwec->ProtExecOv =
85  mgr.getAnalyzerOptions()
86  .getCheckerIntegerOption("MmapProtExec", 0x04, Mwec);
87  Mwec->ProtReadOv =
88  mgr.getAnalyzerOptions()
89  .getCheckerIntegerOption("MmapProtRead", 0x01, Mwec);
90 }
Dataflow Directional Tag Classes.