LinuxQuestions.org
Visit Jeremy's Blog.
Home Forums Tutorials Articles Register
Go Back   LinuxQuestions.org > Forums > Non-*NIX Forums > Programming
User Name
Password
Programming This forum is for all programming questions.
The question does not have to be directly related to Linux and any language is fair game.

Notices


Reply
  Search this Thread
Old 09-25-2008, 05:32 PM   #1
cyent
Member
 
Registered: Aug 2001
Location: ChristChurch New Zealand
Distribution: Ubuntu
Posts: 398

Rep: Reputation: 87
Probing a virtual memory address.


Hokay, long long time ago, I worked on a Vax machine.

It had a nifty OS call that allowed you to probe a memory address and find out if you could read or write to it. (They were based on machine code instructions PROBER and PROBEW, power pc architecture has 'em too.)

Sure you can do...
int isWritable( int * p)
int tmp = *p;
int result = 0;
*p = tmp+1;
result = *p == (tmp+1);
*p = tmp;
return result;
}
but if there is nothing there you'll segfault, and if there is DMA hardware there... who knows what will happen.

Is there a linux routine I can invoke to work out if an address is writable?

Last edited by cyent; 09-25-2008 at 08:03 PM.
 
Old 09-26-2008, 01:36 AM   #2
jlliagre
Moderator
 
Registered: Feb 2004
Location: Outside Paris
Distribution: Solaris 11.4, Oracle Linux, Mint, Debian/WSL
Posts: 9,789

Rep: Reputation: 492Reputation: 492Reputation: 492Reputation: 492Reputation: 492
I would look at pmap source code. "pmap -x pid" is displaying the infomation needed.
 
Old 09-28-2008, 05:37 PM   #3
cyent
Member
 
Registered: Aug 2001
Location: ChristChurch New Zealand
Distribution: Ubuntu
Posts: 398

Original Poster
Rep: Reputation: 87
Quote:
Originally Posted by jlliagre View Post
I would look at pmap source code. "pmap -x pid" is displaying the infomation needed.
Actually pmap is remarkably crude about it, it is just printing /proc/PID/maps to the screen!

(To trivially see that, run "strace pmap -x PID")

Anything better out there?
 
Old 09-28-2008, 05:45 PM   #4
jlliagre
Moderator
 
Registered: Feb 2004
Location: Outside Paris
Distribution: Solaris 11.4, Oracle Linux, Mint, Debian/WSL
Posts: 9,789

Rep: Reputation: 492Reputation: 492Reputation: 492Reputation: 492Reputation: 492
I'm missing why you discard pmap and its Linux implementation. All the information you need is there, isn't it ?
 
Old 09-28-2008, 05:59 PM   #5
cyent
Member
 
Registered: Aug 2001
Location: ChristChurch New Zealand
Distribution: Ubuntu
Posts: 398

Original Poster
Rep: Reputation: 87
IsValidDataPointer,IsValidFunctionPointer

Quote:
Originally Posted by jlliagre View Post
I'm missing why you discard pmap and its Linux implementation. All the information you need is there, isn't it ?
Ok, let me take a step back.

I want to implement the following two asserts...

assert( IsValidDataPointer(pointer));

assert( IsValidFunctionPointer(pointer));

So what on ye olde 1980's Vax was a single machine code instruction, using the /proc/PID/maps solution will be open a file, scanf about 100 lines, close file. And scanf is an extraordinarily heavyweight function involving 10's of thousands of machine instructions.

Ok, can be done. Just seems way too heavyweight.
 
Old 09-28-2008, 08:43 PM   #6
jlliagre
Moderator
 
Registered: Feb 2004
Location: Outside Paris
Distribution: Solaris 11.4, Oracle Linux, Mint, Debian/WSL
Posts: 9,789

Rep: Reputation: 492Reputation: 492Reputation: 492Reputation: 492Reputation: 492
I agree it is heavyweight compared to a single machine code instruction but given the fact the x86 architecture is missing these instructions, it has to be done another way. The pmap solution is also probably inaccurate as the pseudo file content might be partially obsoleted by its own parsing. Beware too that a read-only memory address doesn't imply it is executable nor it necessarily points to a valid instruction.

Anyway, here is a quick and dirty portable implementation I just wrote to see if it was doable in C. Make sure compiler optimizations are disabled for the write probe to work.
Code:
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <unistd.h>
#include <setjmp.h>

jmp_buf env;

static void handler(int sig)
{
  signal(SIGSEGV,handler);
  longjmp(env, 1);
}

int prober(void *p)
{
  char *c=(char *)p;
  char z;
  if(setjmp(env)!=0) return(1);
  z=*c;
  return(0);
}

int probew(void *p)
{
  char *c=(char *)p;
  if(setjmp(env)!=0) return(1);
  *c^=0;
  return(0);
}

main(int argc, char **argv)
{
  char s[]="hi there";
  signal(SIGSEGV,handler);
  printf("%s\n", (prober((void *)s))?"Not readable":"Readable");
  printf("%s\n", (probew((void *)s))?"Not writable":"Writable");
  printf("%s\n", (prober((void *)main))?"Not readable":"Readable");
  printf("%s\n", (probew((void *)main))?"Not writable":"Writable");
}

Last edited by jlliagre; 09-28-2008 at 08:46 PM.
 
Old 09-28-2008, 10:05 PM   #7
cyent
Member
 
Registered: Aug 2001
Location: ChristChurch New Zealand
Distribution: Ubuntu
Posts: 398

Original Poster
Rep: Reputation: 87
Quote:
Originally Posted by jlliagre View Post
Anyway, here is a quick and dirty portable implementation I just wrote to see if it was doable in C. Make sure compiler optimizations are disabled for the write probe to work.
Nah. Don't need to disable optimization, just need volatile....
Code:
int probew(void *p)
{
  volatile unsigned char *c=(volatile char *)p;
  unsigned char temp;
  if(setjmp(env)!=0) return(1);
  // Preserve *c, may segfault if can't read
  temp = *c;
  *c = 0;
  if (*c == 0) // That write seems to have worked, 
    if(temp !=0) // Maybe it was 0 anyway
    {
      *c = temp; // Put it back. 
      return 0;  // Say it is writable.
    }

  // Well try write a 0xff instead
  *c=0xff;
  if (*c != 0xff) // Whoops, that didn't work
    return 1; // Say not writable.

  *c = temp; // Put it back
  return(0); // Say writable.
}

main(int argc, char **argv)
{
  char s[]="hi there";
  signal(SIGSEGV,handler);
  printf("%s\n", (prober((void *)s))?"Not readable":"Readable");
  printf("%s\n", (probew((void *)s))?"Not writable":"Writable");
  printf("%s\n", (prober((void *)main))?"Not readable":"Readable");
  printf("%s\n", (probew((void *)main))?"Not writable":"Writable");
}
[/QUOTE]
 
Old 09-29-2008, 01:35 AM   #8
jlliagre
Moderator
 
Registered: Feb 2004
Location: Outside Paris
Distribution: Solaris 11.4, Oracle Linux, Mint, Debian/WSL
Posts: 9,789

Rep: Reputation: 492Reputation: 492Reputation: 492Reputation: 492Reputation: 492
Your probew implementation is doing unnecessary tests if your goal is to implement the VAX original instructions and might be destructive too if you are unlucky.
 
Old 09-29-2008, 03:56 PM   #9
cyent
Member
 
Registered: Aug 2001
Location: ChristChurch New Zealand
Distribution: Ubuntu
Posts: 398

Original Poster
Rep: Reputation: 87
I guess I'm trying to be too portable...

Quote:
Originally Posted by jlliagre View Post
Your probew implementation is doing unnecessary tests if your goal is to implement the VAX original instructions and might be destructive too if you are unlucky.
The program I want to use this on also runs on an embedded device without MMU, and your test would pass erroneously on areas with no ram. Hmm. But it would screw up DMA devices.

As to the unlucky, I doubt if your test is atomic either. Your test probably also compiles to load to register, do something in register, store to memory.

The sad thing is the routine I want is available in the kernel... It is called "access_ok". It just doesn't seem to be exported into userland.
 
Old 10-02-2008, 08:05 AM   #10
jlliagre
Moderator
 
Registered: Feb 2004
Location: Outside Paris
Distribution: Solaris 11.4, Oracle Linux, Mint, Debian/WSL
Posts: 9,789

Rep: Reputation: 492Reputation: 492Reputation: 492Reputation: 492Reputation: 492
Every program that writes something to a random address might screw up itself of worst, especially if it writes something different than what was there before.

On your embedded device, access_ok might be implemented by using a similar approach than the initial solution I suggested, according to its documentation.

Note that, depending on architecture, this function probably just checks that the pointer is in the user space range - after calling this function, memory access functions may still return -EFAULT.

I'm afraid what you are after has no perfect solution.
 
Old 10-02-2008, 04:37 PM   #11
cyent
Member
 
Registered: Aug 2001
Location: ChristChurch New Zealand
Distribution: Ubuntu
Posts: 398

Original Poster
Rep: Reputation: 87
Quote:
Originally Posted by jlliagre View Post
I'm afraid what you are after has no perfect solution.
Hah! There is one.... VERR and VERW are the x86 machine ops equivalent to the Vax PROBER PROBEW

Now I just need to work out to package it as a snippet of inline assembler, I'm done!
 
  


Reply



Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is Off
HTML code is Off



Similar Threads
Thread Thread Starter Forum Replies Last Post
Difference between resident memory,shared memory and virtual memory in system monitor mathimca05 Linux - Newbie 1 11-11-2007 04:05 AM
how to find physical address of kernel virtual address kushneeraj Programming 0 10-20-2006 07:29 PM
API for mapping Physical Address to Virtual Address Lakshman_smt Linux - Software 2 10-15-2006 09:08 PM
Memory Mapping (same physical address = virtual address) skd.tech Linux - Kernel 7 07-24-2006 11:13 PM
RH 8.0 Mapping Virtual Memory to get access to VMIC Reflective Memory PCI card. Merlin53 Linux - Hardware 0 05-05-2003 12:50 PM

LinuxQuestions.org > Forums > Non-*NIX Forums > Programming

All times are GMT -5. The time now is 11:39 PM.

Main Menu
Advertisement
My LQ
Write for LQ
LinuxQuestions.org is looking for people interested in writing Editorials, Articles, Reviews, and more. If you'd like to contribute content, let us know.
Main Menu
Syndicate
RSS1  Latest Threads
RSS1  LQ News
Twitter: @linuxquestions
Open Source Consulting | Domain Registration