ATLAS Offline Software
PageAccessControl.cxx
Go to the documentation of this file.
1 /*
2  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
3 */
4 
5 #define DEBUG 1
6 #include <algorithm> /* sort etc */
7 #include <sys/mman.h> /* mprotect */
9 #include "CxxUtils/page_access.h"
11 #include <iostream>
14 
15 PageAccessControl::Entry::Entry(const void* a, size_t l, int p, void* pl):
16  addr(page_address(a)), lenProt(l), prot(p), leak(pl), restored(0) {}
17 
18 
19 void
21  if (!m_protectedIsSorted) {
22  std::sort(m_protected.begin(), m_protected.end());
24  }
25 }
26 bool
28  int rc(-1);
29  sort();
30  Entry ea(addr,0,0,0);
32  std::lower_bound(m_protected.begin(), m_protected.end(), ea);
33  if (entry != m_protected.end() &&
34  entry->addr == ea.addr) {
35  //found it. Restore page prot
36  const void* pageAddr = page_address(entry->addr);
37  void* pageAddr_nc ATLAS_THREAD_SAFE = const_cast<void*> (pageAddr);
38  rc=mprotect( pageAddr_nc, entry->lenProt, entry->prot);
39  if (rc==0) {
40 #ifdef DEBUG
41  printf("PageAccessControl::restorePageProt DEBUG: restored protection %i for page %p containing address %p \n",
42  entry->prot,
43  page_address(entry->addr),
44  entry->addr);
45  printf(" FIXME NOT Freeing memory at %p \n", entry->leak );
46 #endif
47  // free(entry->leak);
48  entry->leak=0;
49  ++(entry->restored);
50  }
51  } else printf("WARNING no entry in procmap for addr=%p, page protection not restored \n",addr);
52  return (rc == 0);
53 }
54 
55 bool
56 PageAccessControl::protectPage(const void* addr, size_t objSize, int prot) {
57  int rc(-1);
58  const procmaps::Entry *e=m_pmaps.getEntry(addr,true);
59  //this is the length of the range we are going to protect
60  if (0 != e) {
61  const void *pageAddr = page_address(addr);
62  size_t lenProt = (size_t)addr - (size_t)(pageAddr) + objSize;
63  size_t nextProt = (size_t)addr + objSize;
64  size_t nextUnprot = (size_t)(next_page_address((void*)(nextProt-1)));
65  int pageProt(PROT_NONE);
66  if (e->readable) pageProt |= PROT_READ;
67  if (e->writable) pageProt |= PROT_WRITE;
68  if (e->executable) pageProt |= PROT_EXEC;
69  if (pageProt != prot) {
70  //fill up the space from nextProt to nextUnprot to avoid allocations
71  //in the locked pages, and SEGVs...
72 // void *leak(0);
73 // if (0 == (prot & PROT_WRITE)) {
74 // size_t lenLeak(nextUnprot-nextProt-1);
75 // leak=malloc(lenLeak);
76 // if ((size_t)leak<nextUnprot && (size_t)leak + lenLeak>=nextUnprot) {
77 // //we do not want to allocate our buffer memory past the current
78 // //page, so trim it down
79 // free(leak);
80 // lenLeak=nextUnprot - (size_t)leak -1;
81 // leak=malloc(lenLeak);
82 // }
83 // if (leak < pageAddr ||
84 // (size_t)leak >= nextUnprot) {
85 // //leak has been allocated into previous/next page
86 // //better get rid of it as it will likely
87 // //be locked by another protectPage
88 // free(leak);
89 // leak=0;
90 // } else {
91 // #ifdef DEBUG
92 // printf("PageAccessControl::protectPage DEBUG: fill up space from %p to 0x%x to avoid allocations in locked pages\n",
93 // leak, (int)leak+lenLeak);
94 // #endif
95 // }
96 // }
97 
98  void* pageAddr_nc ATLAS_THREAD_SAFE = const_cast<void*> (pageAddr);
99  if (0 == (rc = mprotect( pageAddr_nc,
100  lenProt,
101  prot))) {
102  m_protected.push_back(Entry(pageAddr,lenProt, pageProt, 0));
103  m_protectedIsSorted=false; //FIXME we should use a mapvector
104 #ifdef DEBUG
105  printf("PageAccessControl::protectPage DEBUG: set protection %i for page range %p - 0x%lx containing address range=%p - 0x%lx\n",
106  prot,
107  pageAddr,
108  (long unsigned int)(nextUnprot - 1),
109  addr,
110  (long unsigned int)(nextProt -1) );
111 #endif
112  }
113  } else rc=0;
114  } else printf("PageAccessControl::protectPage WARNING: no entry in procmap for addr=%p, page protection not restored \n",addr);
115  return (rc == 0);
116 }
117 
118 bool PageAccessControl::accessed(const void* address) const {
119  bool acc(false);
120  //fixme: poor man implementation
121  Entry eaxx(address,0,0,0);
123  ea(endProtectedPtrs());
124  while (!acc && ia != ea) {
125  // std::cout << address << "page addr " << eaxx.addr << " ia " << ia->addr << " res " << ia->restored << std::endl;
126  acc = (eaxx.addr == ia->addr && 0 != ia->restored);
127  ++ia;
128  }
129  return acc;
130 }
xAOD::iterator
JetConstituentVector::iterator iterator
Definition: JetConstituentVector.cxx:68
PageAccessControl::m_protected
protected_t m_protected
Definition: PageAccessControl.h:109
athena::next_page_address
void * next_page_address(void *addr)
Definition: page_access.cxx:17
python.PerfMonSerializer.p
def p
Definition: PerfMonSerializer.py:743
PageAccessControl::m_protectedIsSorted
bool m_protectedIsSorted
Definition: PageAccessControl.h:110
PageAccessControl::const_iterator
protected_t::const_iterator const_iterator
Definition: PageAccessControl.h:92
PageAccessControl::restorePageProt
bool restorePageProt(const void *addr)
Definition: PageAccessControl.cxx:27
PageAccessControl::sort
void sort()
Definition: PageAccessControl.cxx:20
UploadAMITag.l
list l
Definition: UploadAMITag.larcaf.py:158
PageAccessControl::m_pmaps
procmaps m_pmaps
the content of /proc/self/maps
Definition: PageAccessControl.h:104
athena::page_address
const void * page_address(const void *addr)
Definition: page_access.cxx:11
PageAccessControl.h
AthenaPoolTestRead.acc
acc
Definition: AthenaPoolTestRead.py:16
PageAccessControl::beginProtectedPtrs
const_iterator beginProtectedPtrs() const
Definition: PageAccessControl.h:94
GetAllXsec.entry
list entry
Definition: GetAllXsec.py:132
RTTAlgmain.address
address
Definition: RTTAlgmain.py:55
page_access.h
DiTauMassTools::MaxHistStrategyV2::e
e
Definition: PhysicsAnalysis/TauID/DiTauMassTools/DiTauMassTools/HelperFunctions.h:26
a
TList * a
Definition: liststreamerinfos.cxx:10
procmaps::Entry
Definition: procmaps.h:20
procmaps::getEntry
const Entry * getEntry(const void *address, bool tryReloadMaps=true)
main entry point: get info for the page range containing address by default tries to reload /proc/sel...
Definition: procmaps.cxx:59
ATLAS_THREAD_SAFE
#define ATLAS_THREAD_SAFE
Definition: checker_macros.h:211
PageAccessControl::endProtectedPtrs
const_iterator endProtectedPtrs() const
Definition: PageAccessControl.h:95
checker_macros.h
Define macros for attributes used to control the static checker.
PageAccessControl::Entry::Entry
Entry(const void *a, size_t l, int p, void *pl)
Definition: PageAccessControl.cxx:15
PageAccessControl::accessed
bool accessed(const void *address) const
was the page containing address accessed?
Definition: PageAccessControl.cxx:118
PageAccessControl::protectPage
bool protectPage(T *addr, int prot)
protect the page containing addr, record the amount of memory we protected NOTE To avoid SEGV,...
Definition: PageAccessControl.h:49