ATLAS Offline Software
Loading...
Searching...
No Matches
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 */
11#include <iostream>
14
15PageAccessControl::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
19void
26bool
28 int rc(-1);
29 sort();
30 Entry ea(addr,0,0,0);
31 protected_t::iterator entry=
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
55bool
56PageAccessControl::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
118bool 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}
static Double_t a
static Double_t rc
const void * page_address(const void *addr)
void * next_page_address(void *addr)
Define macros for attributes used to control the static checker.
#define ATLAS_THREAD_SAFE
procmaps m_pmaps
the content of /proc/self/maps
bool accessed(const void *address) const
was the page containing address accessed?
bool restorePageProt(const void *addr)
const_iterator beginProtectedPtrs() const
bool protectPage(T *addr, int prot)
protect the page containing addr, record the amount of memory we protected NOTE To avoid SEGV,...
protected_t::const_iterator const_iterator
const_iterator endProtectedPtrs() const
const void * page_address(const void *addr)
void * next_page_address(void *addr)
void sort(typename DataModel_detail::iterator< DVL > beg, typename DataModel_detail::iterator< DVL > end)
Specialization of sort for DataVector/List.
protection of a memory region (see mprotect(2))
void * leak
pointer to the heap fragment we leaked before protecting the page
size_t lenProt
length of the protected region, from page addr to end of protected obj
const void * addr
address of page for which protection was requested. Used as key
Entry(const void *a, size_t l, int p, void *pl)