You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

233 lines
6.4 KiB

/*
* Copyright 2002-2019 Intel Corporation.
*
* This software is provided to you as Sample Source Code as defined in the accompanying
* End User License Agreement for the Intel(R) Software Development Products ("Agreement")
* section 1.L.
*
* This software and the related documents are provided as is, with no express or implied
* warranties, other than those that are expressly stated in the License.
*/
/*! @file
The tool checks that page permissions in application process are not changed
after Pin writes a probe
*/
/* ===================================================================== */
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <iostream>
#include <fstream>
#include <string>
#include <linux/limits.h>
#include "pin.H"
#include <list>
#include "tool_macros.h"
using std::string;
using std::hex;
using std::list;
using std::cerr;
using std::dec;
using std::endl;
using std::cout;
/* Memory range */
struct RANGE_ATTR
{
RANGE_ATTR(ADDRINT start, ADDRINT end, string attr)
:_start(start), _end(end), _attr(attr) {}
ADDRINT _start;
ADDRINT _end;
string _attr;
};
/* A list of memory ranges */
class RANGES
{
public:
/* Get memory attributes under the specified address */
BOOL GetAttributes(ADDRINT addr, string *attr);
VOID AddRange(ADDRINT start, ADDRINT end, string attr);
private:
list <RANGE_ATTR> _ranges;
};
VOID RANGES::AddRange(ADDRINT start, ADDRINT end, string attr)
{
_ranges.push_back(RANGE_ATTR(start, end, attr));
}
/* Find range and get its attriutes */
BOOL RANGES::GetAttributes(ADDRINT addr, string *attrStr)
{
list < RANGE_ATTR>::iterator it = _ranges.begin();
for (; it != _ranges.end(); it++)
{
if ((it->_start <= addr) && (it->_end > addr))
{
*attrStr = it->_attr;
return TRUE;
}
}
return FALSE;
}
#if defined(TARGET_LINUX)
#define MAX_NUM_OF_RANGES_PER_FILENAME 10
/* Read /proc/self/maps and fill fileMap with ranges */
VOID FillFileMap(const char *name, RANGES *fileMap)
{
FILE *fp = fopen("/proc/self/maps", "r");
char buff[1024];
char attributes[MAX_NUM_OF_RANGES_PER_FILENAME][10];
unsigned long mapl[MAX_NUM_OF_RANGES_PER_FILENAME], maph[MAX_NUM_OF_RANGES_PER_FILENAME];
int nRange = 0;
while(fgets(buff, 1024, fp) != NULL)
{
if (strstr(buff, name) != 0)
{
if(sscanf(buff, "%lx-%lx %s", &mapl[nRange], &maph[nRange],
attributes[nRange]) != 3)
continue;
nRange++;
}
}
fclose(fp);
for (int i=0; i< nRange; i++)
{
fileMap->AddRange(mapl[i], maph[i], attributes[i]);
}
}
#elif defined(TARGET_MAC)
#include <mach/mach_vm.h>
#include <mach/mach_init.h>
#include <mach/vm_prot.h>
VOID FillFileMap(const char *name, RANGES *fileMap)
{
mach_vm_address_t address = 0;
mach_vm_address_t last_address = 0;
mach_vm_size_t size = 0;
while (1)
{
kern_return_t ret = KERN_SUCCESS;
natural_t depth = 1;
vm_region_submap_info_data_64_t info;
mach_msg_type_number_t count = VM_REGION_SUBMAP_INFO_COUNT_64;
ret = mach_vm_region_recurse(mach_task_self(), &address, &size, &depth, (vm_region_recurse_info_t)&info, &count);
if (ret != KERN_SUCCESS || (ADDRINT)address < (ADDRINT)last_address)
{
break;
}
char buf[4];
sprintf(buf, "%c%c%c", (info.protection & VM_PROT_READ) ? 'r' : '-',
(info.protection & VM_PROT_WRITE) ? 'w' : '-',
(info.protection & VM_PROT_EXECUTE) ? 'x' : '-');
fileMap->AddRange((unsigned long)address, (unsigned long)(address+size), buf);
last_address = address;
address += size;
}
}
#endif
VOID ToolDoNothing()
{
cout << "Tool replacement - nothing to do" << endl;
}
VOID ToolOne(size_t nBytes)
{
cout << "Tool replacement - print 1" << endl;
}
BOOL PutProbeAndCheckAttributes(IMG img, const char *rtnName, AFUNPTR rtnReplacement)
{
string shortName = IMG_Name(img);
string::size_type pos = shortName.rfind('/');
if (pos != string::npos)
shortName = shortName.substr(pos + 1);
RANGES fileMapBeforeProbe;
FillFileMap(shortName.c_str(), &fileMapBeforeProbe);
RTN rtn = RTN_FindByName(img, rtnName);
if (RTN_Valid(rtn) && RTN_IsSafeForProbedReplacement(rtn))
{
cout << "Looking at file " << shortName << endl;
ADDRINT addr = RTN_Address(rtn);
string origAttr;
BOOL res = fileMapBeforeProbe.GetAttributes(addr, &origAttr);
if (!res)
{
cerr << "Failed to read original page attributes from /proc/self/maps" << endl;
cerr << "The bug is in the test" << endl;
exit(-1);
}
RTN_ReplaceProbed(rtn, rtnReplacement);
RANGES fileMapAfterProbe;
FillFileMap(shortName.c_str(), &fileMapAfterProbe);
string newAttr = "-cant-read-maps-file-";
res = fileMapAfterProbe.GetAttributes(addr, &newAttr);
if (!res)
{
cerr << "Failed to read new page attributes from /proc/self/maps" << endl;
cerr << "The bug is in the test" << endl;
exit(-1);
}
if (newAttr != origAttr)
{
cout << "Original map was changes around address " << hex << addr << endl;
cout << "Org attributes: " << origAttr << " New attributes " << newAttr << endl;
exit(-1);
}
else
{
cout << "Original map was preserved around address " << hex << addr << endl;
cout << "Attributes: " << newAttr << endl;
}
return TRUE;
}
return FALSE;
}
VOID ImageLoad(IMG img, VOID * arg)
{
UINT32 *numOfInstrumentedRtnsPtr = (UINT32 *)arg;
if (PutProbeAndCheckAttributes(img, C_MANGLE("do_nothing"), (AFUNPTR)ToolDoNothing))
{
(*numOfInstrumentedRtnsPtr) ++;
cout << dec << *numOfInstrumentedRtnsPtr << " routines were instrumented" << endl;
}
if (PutProbeAndCheckAttributes(img, C_MANGLE("one"), (AFUNPTR)ToolOne))
{
(*numOfInstrumentedRtnsPtr) ++;
cout << dec << *numOfInstrumentedRtnsPtr << " routines were instrumented" << endl;
}
}
int main(INT32 argc, CHAR **argv)
{
PIN_Init(argc, argv);
PIN_InitSymbols();
UINT32 numOfInstrumentedRtns = 0;
IMG_AddInstrumentFunction(ImageLoad, (VOID*)&numOfInstrumentedRtns);
// Never returns
PIN_StartProgramProbed();
return 0;
}