I am trying to figure out how to directly read any location in physical memory on a Power9 processor using /dev/mem. The following is the code that I have used to that end.
FILE* fp;
int _fdmem;
int *map = NULL;
const char memDevice[] = "/dev/mem";
_fdmem = open( "/dev/mem", O_RDWR | O_SYNC );
if (_fdmem < 0){
printf("Failed to open the /dev/mem !\n");
return 0;
}
else{
printf("open /dev/mem successfully !\n");
}
map= (int *)(mmap(NULL,1,PROT_READ|PROT_WRITE,MAP_PRIVATE,_fdmem,0));
fp=fopen("./memm2out.txt","w");
for (int i=0; i<131073;i++)
{
fprintf(fp, "%x",*(map+i));
}
When I run the code I get the following output.
open /dev/mem successfully !
Segmentation fault
Using GDB, this is where the segfault occurs
Program received signal SIGSEGV, Segmentation fault.
0x0000000100000a2c in main () at memmapper2.c:34
34 fprintf(fp, "%x",*(map+i));
When I use 131072 as the value for i there is no segfault, which makes me believe there is some kind of boundary to reading after 64 kB. The file is run with root permissions. The processor I'm using is running Linux kernel version 4.18. What may be restricting my access?
Edit: When the second mmap parameter is set to any value greater than 65536, mmap fails to open and gives the error message ": OPERATION NOT PERMITTED". Now, it's my understanding that what's happening here is that mmap maps the file pointer for /dev/mem to a specific location in virtual memory from which you can invoke the functionality of /dev/mem to read physical memory. Am I mistaken in this understanding?
Related
I'm developing an iOS app and when I run it on my devices I got lots of the following warnings:
MyApp(2138,0x104338000) malloc: *** can't protect(0x3) region for postlude guard page at 0x104950000
They don't stop the execution but looks scary and probably are related to occasional crash of my app. I googled and only found two pages on the entire web and none of the helps. I wonder if anyone here knows how to fix this?
Edit: here is the product scheme I used:
The error you're seeing comes from Apple's malloc implementation and is due to vm_protect failing when trying modify memory protection of the guard pages that have been added to your memory allocations.
So it sounds like you've enabled debugmalloc's MallocGuardEdges flag (I didn't think debugmalloc was available on ios devices).
The 0x3 = VM_PROT_READ | VM_PROT_WRITE in the message is saying that vm_protect failed to make the page read-write which means that this is happening in response to a free.
The only documented return codes for vm_protect are KERN_PROTECTION_FAILURE and KERN_INVALID_ADDRESS so at this point I can only guess what happened. Making a page read-write seems like a modest request, for a valid page you wouldn't expect KERN_PROTECTION_FAILURE, which leaves KERN_INVALID_ADDRESS, meaning that perhaps your page at 0x104950000 is invalid.
Which would imply a memory stomping bug.
The issue is one-year old, but we ran into the same issue and found this thread. We where able to simplify and reproduce it in latest Xcode 7.3 on Mac with the following piece of C code:
int main(int argc, char *argv[])
{
const int s = 100, n = 5000;
int i;
void *p = malloc(s);
for (i = 2 ; i <= n ; i++)
p = realloc(p,i * s);
for (i = n - 1 ; i > 0 ; i--)
{
void *newp = realloc(p,i * s);
if (newp != p)
printf("realloc(p,%d * %d = %d) changes pointer from %p to %p\n",i,s,i * s,p,newp);
p = newp;
}
free(p);
return 0;
}
This will trigger the malloc_printf() breakpoint in the 2nd for loop (when the reallocations shrink memory) and print:
malloc: *** can't protect(0x3) region for postlude guard page at 0x48ed000
It appears (setting a breakpoint on malloc_printf()) that this happens exactly on the first time that realloc() changes the returned pointer, the total output of above program is:
realloc(p,1249 * 100 = 124900) changes pointer from 0x48b0000 to 0x5000000
realloc(p,2 * 100 = 200) changes pointer from 0x5000000 to 0x240cc60
Playing a bit with combinations of the block size s and number of iterations n it happens at least for 10/50000, 100/5000, 200/5000, ..., it seems when the allocated memory i * s shrinks to around 124000 bytes. Other combinations like 1/200000 don't trigger malloc_printf().
Given the simplicity of this code snippet, we believe that this is a bug in Apple's malloc debug implementation.... or the message is supposed to be some informative (internal) message rather than trying to signal a real memory issue.
(A version of) the source code for Apple's malloc implementation can be found here http://www.opensource.apple.com/source/Libc/Libc-391.4.2/gen/scalable_malloc.c?txt. We are considering to raise with Apple Developer Centre...
So in short the answer is that it might very well not be a memory stomping bug in your code, but instead an issue in de malloc debug code itself, in which case you need to just ignore the message.
Many userspace CSPRNG's have an issue where after fork(2), it's possible for the two different processes to return the same stream of random bytes.
From looking at dtruss, it's clear that SecRandomCopyBytes is, at a minimum, seeding from /dev/random, but is it doing so in a way that's safe for use after fork()?
With the following source code:
#include <Security/Security.h>
int main() {
uint8_t data[8];
SecRandomCopyBytes(kSecRandomDefault, 8, data);
SecRandomCopyBytes(kSecRandomDefault, 8, data);
printf("%llu\n", *(uint64_t *)data);
}
I get the following from dtruss (with irrelevant stuff removed):
open("/dev/random\0", 0x0, 0x7FFF900D76F5) = 3 0
read(0x3, "\b\2029a6\020+\254\356\256\017\3171\222\376T\300\212\017\213\002\034w\3608\203-\214\373\244\177K\177Y\371\033\243Y\020\030*M\3264\265\027\216r\220\002\361\006\262\326\234\336\357F\035\036o\306\216\227\0", 0x40) = 64 0
read(0x3, "\223??3\263\324\3604\314:+\362c\311\274\326\a_Ga\331\261\022\023\265C\na\211]\356)\0", 0x20) = 32 0
The implementation is actually CCRandomCopyBytes():
http://www.opensource.apple.com/source/Security/Security-55471/libsecurity_keychain/lib/SecRandom.c
int SecRandomCopyBytes(SecRandomRef rnd, size_t count, uint8_t *bytes) {
if (rnd != kSecRandomDefault)
return errSecParam;
return CCRandomCopyBytes(kCCRandomDefault, bytes, count);
}
So the actual code is here:
http://www.opensource.apple.com/source/CommonCrypto/CommonCrypto-60049/lib/CommonRandom.c
The comments in the include for CCRandomCopyBytes state that it is fork() safe:
It is inconvenient to call system random number generators
directly. In the simple case of calling /dev/random, the caller
has to open the device and close it in addition to managing it
while it's open. This module has as its immediate raison d'ĂȘtre
the inconvenience of doing this. It manages a file descriptor to
/dev/random including the exception processing of what happens
in a fork() and exec(). Call CCRandomCopyBytes() and all the
fiddly bits are managed for you. Just get on with whatever you
were really trying to do.
[...]
In my own quick test, the child gets killed when it invokes SecRandomCopyBytes()
In How do I recover from EXC_BAD_ACCESS?, I figured out how to recover from an EXC_BAD_ACCESS, but I had the badly accessed pointer stored in a global. Obviously, this won't scale. When I run the code in the iOS Simulator (i386), I can see faultvaddr register in the Exception State Registers section of the debugger when inside my catch_exception_raise function. However, its value isn't the same or close to pointer returned from vm_allocate. Is there a way to get this value dynamically?
Given the catch_exception_raise function below, how would I discover the address that caused the EXC_BAD_ACCESS?
kern_return_t
catch_exception_raise(mach_port_t exception_port,
mach_port_t thread,
mach_port_t task,
exception_type_t exception,
exception_data_t code_vector,
mach_msg_type_number_t code_count)
{
fprintf(stderr, "catch_exception_raise %d\n", exception);
return KERN_SUCCESS;
}
There is a great amount of detail on that in the OS X and iOS Internals book (http://www.newosxbook.com). Listing 11-21 (ibid) in the book actually shows sample code to do so. In a nutshell, you've two options:
A) look at the exception itself from the exception data - convert the state to an arm_thread_state, something like so:
struct arm_thread_state *atsh = &exc.old_state;
printf ("CPSR is %p, PC is %p, etc.\n", atsh->cpsr, atsh->pc);
Or
B) call thread_get_state to the thread port (since you have that right there as argument #2), and get pc (the instruction pointer) or any of the other registers
EDIT
I'm not sure how to make A) work, but the following works (found here) for B) on the 32-bit iOS Simulator. I'm not sure what the arm register equivalent is for __faultvaddr, so you'd have to figure that out before trying arm.
// types from thread_status.h
x86_exception_state32_t x86_exception_state32;
mach_msg_type_number_t sc = x86_EXCEPTION_STATE32_COUNT;
thread_get_state(thread,
x86_EXCEPTION_STATE32,
(thread_state_t)&x86_exception_state32,
&sc);
I am trying to find memory leaks in a very complicated legacy system that is written in C++/C on the Solaris operating system. the idea is to log every malloc and free and then postproccess the log.
i was able to write a stub malloc and free function that gets called correctly. the problem is that they dont do anyhing other than log. As a result the sytem crashes
My question is: is they a substitute malloc library that works on solaris that is can call from my stub malloc& free functions?
Why don't you just do an LD_PRELOAD of libumem and use UMEM_DEBUG? The manpage for umem_debug should give you more information.
Ideally, You should some memory profiling tool but in the absence of the same you can try to implement your own leak detector as you plan to.
You can just call malloc and free library versions through your wrapper.
Here is a scheme that you may try to implement:
Your wrapper function should implement a functionality wherein your wrapper for malloc stores the line number, file name, size requested & address being returned by malloc in a linked list.
How to get filename and line number?
Hint: Use __FILE__, __LINE__
The free wrapper should check the address being sent for freeing against the list and remove the entry from the linked list.
At the end of the program you should print contents of this linked list which gives you leaking memory size, file name and line number from where the buffer was allocated.
Update:
How do you map program malloc calls to own wrapper calls without infinite recurssion?
Through clever Use of Macros!
#define malloc(X) my_malloc( X, __FILE__, __LINE__, __FUNCTION__)
void* my_malloc(size_t size, const char *file, int line, const char *func)
{
void *p = malloc(size);
printf ("Allocated = %s, %i, %s, %p[%li]\n", file, line, func, p, size);
/*Link List functionality goes in here*/
return p;
}
In addition to libumem, I would recommend using Solaris Studio dbx which includes with RTC, a memory leak detector.
This is my first question here :).
I been trying for while now to map physical memory to virtual memory in vxWorks 6.8 with no success,
I'm trying to use "vmMap" function but somehow it keeps return with:
errno = 0x30065 S_taskLib_NAME_NOT_FOUND.
my code is:
int page_size=0;
PHYS_ADDR GPIO_BASE_VIRTUAL_ADDR = 0x40E00000;
VIRT_ADDR VIRTUAL_ADDR=0;
page_size =vmPageSizeGet();
if((VIRTUAL_ADDR = (VIRT_ADDR)memalign(page_size,page_size*2))==NULL)// allocate 2 pages
{
printf("error in memalign() errno = 0x%x\n",errnoGet());
}
if(vmMap(NULL,VIRTUAL_ADDR,GPIO_BASE_VIRTUAL_ADDR,(page_size*2))== ERROR )
{
printf("Error mapping memory errno = 0x%x%\n",errnoGet());
}
Any help will be very appreciate,
thanks,
Moshe.
I see you already solved this long ago, but thought I'd leave some bread crumbs for whoever else might stumble this way in the dim & distant future..
Unless you're doing RTPs there's a good chance your MMU isn't even translating addresses. I.e., if something appears at say, 0x7fc00400 in the physical address space, you could simply cast that value to a pointer and use it.
*((short *) 0x7fc00400) = foo; // write 16 bits!
And Yes, these days it is almost sacrilege to suggest (ab)using pointers this way, but I would point out that if you're doing vxworks kernel space code, you're practically on the bare metal anyway, so why not?