1

Given an untrusted memory address, is there a way in Linux to test whether it points to valid, accessible memory?

For example, in mach you can use vm_read_overwrite() to attempt to copy data from the specified location. If the address is invalid or inaccessible, it will return an error code rather than crashing the process.

Karl
  • 14,434
  • 9
  • 44
  • 61
  • 1
    Check this out http://stackoverflow.com/questions/7134590/how-to-test-if-an-address-is-readable-in-linux-userspace-app – imreal Jan 24 '13 at 17:50

3 Answers3

2

write from that memory (into /dev/null, for example (EDIT: with /dev/null it might not work as expected, use a pipe)), and you'll receive EFAULT error if the address is unaccessible.

I have no idea how to test for writable memory without destroying its content if it is writable.

Anton Kovalenko
  • 20,999
  • 2
  • 37
  • 69
  • "I have no idea how to test for writable memory without destroying its content if it is writable" If you do it from userspace, you won't destroy its content but get a segfault! – Eddy_Em Jan 24 '13 at 18:11
1

This a typical case of TOCTOU - you check at some point that the memory is writeable, then later on you try to write to it, and somehow (e.g. because the application deallocated it), the memory is no longer accessible.

There is only one valid way to actually do this, and that is, trap the fault you get from writing to it when you actually need to use it.

Of course, you can use tricks to try to figure out if the memory "may be writeable", but there is no way you can actually ensure it is writeable.

You may want to explain slightly more what you are actually trying to do, and maybe we can have some better ideas if you are more specific.

Mats Petersson
  • 126,704
  • 14
  • 140
  • 227
  • I'm not actually trying to write to the memory location. I just want to check that the memory can be read from. The context would be a halted process (all threads paused). – Karl Jan 24 '13 at 23:45
  • So why do you want to know if it's writeable if you don't want to write to it. And readable still has the same problem - you may well discover that it's readable RIGHT now, but a few instructions later it isn't, because some modification to the page-table. Still, the only guaranteed way is to handle segfaults in your code. – Mats Petersson Jan 24 '13 at 23:47
  • I don't want to know if it's writable. I never did. Also, if I trap the fault, how would I stop it from faulting again when I return from the signal handler? Would I need to alter the PC or change the register to point to a valid location? – Karl Jan 25 '13 at 00:10
  • Sorry, I misunderstood what you wanted - because it sad "overwrite" in your original post, I mistook that to mean you wanted to be able to write to the address. But either way, yes, you need to do something else when you get a segfault. But since there is no other way to be sure it's readable at the time you want to read it [I presume you DO want to read the memory, or are you just wanting to know if it is readable for some arbitrary reason?] - the simplest method is to use a C++ exception or setjmp/longjmp to get out of returning from segfault. – Mats Petersson Jan 25 '13 at 00:16
  • OK that makes sense, but now if all threads in a process (except for the one inspecting memory) are halted, would memory still be vulnerable to becoming inaccessible? – Karl Jan 25 '13 at 00:18
  • Possibly, if it has already been marked for freeing, and the OS just now got round to freeing it, for example. – Mats Petersson Jan 25 '13 at 00:32
1

You can try msync:

int page_size = getpagesize();                                                            
void *aligned = (void *)((uintptr_t)p & ~(page_size - 1));                           
if (msync(aligned, page_size, MS_ASYNC) == -1 && errno == ENOMEM) {
    // Non-accessibe
}

But this function may be slow and should not be used in performance critical circumstance.

Jamis
  • 3
  • 3
chen3feng
  • 151
  • 1
  • 7