Re: How to access kernel memory from user space

2012-02-23 Thread John Baldwin
On Wednesday, February 22, 2012 8:06:20 pm Ryan Stone wrote:
 On Wed, Feb 22, 2012 at 2:15 PM, Ian Lepore
 free...@damnhippie.dyndns.org wrote:
  I've never done this, but if I needed to, I think the first thing I'd
  try is to use an mmap(2) of /dev/kmem to map the memory you need into
  userspace (of course your userspace app will need to be running with
  root privs to do this).
 
  That leaves the interesting problem of locating what offset within the
  kernel virtual address space you need to map to get at your data.  Two
  things come to mind... have your kernel module export the address in a
  sysctl (that feels kind of hack-ish but it should be quick and easy to
  do), or use libkvm's kvm_nlist() function to locate the symbol within
  your module (I think that should be possible; again I've never actually
  done any of this).
 
 A far easier way to do this is to have the module create its own
 device in /dev that exports the memory by implementing the mmap
 interface in the cdev.

Yes.  Another option you can do if you want to let userland donate a buffer
to the kernel is to let userland create a buffer using shm_open() (probably
with SHM_ANON) and then use shm_map() in the kernel to map that into KVA.

-- 
John Baldwin
___
freebsd-hackers@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/freebsd-hackers
To unsubscribe, send any mail to freebsd-hackers-unsubscr...@freebsd.org


Re: How to access kernel memory from user space

2012-02-22 Thread Ian Lepore
On Wed, 2012-02-22 at 17:24 +, Svetlin Manavski wrote:
 Hi all,
 I have a very similar problem as described in this thread back in 2009:
 
 http://lists.freebsd.org/pipermail/freebsd-hackers/2009-January/027367.html
 
 I have a kernel module producing networking stats which I need to
 frequently read from the user space. A copy of the data structure would be
 too expensive so I need to access the kernel data directly from the user
 space.
 
 Unfortunately Alexej's code crashes in the following area:
 
 vm_map_lookup(kmem_map, addr, VM_PROT_ALL, myentry, myobject, mypindex,
 myprot, mywired); /* OUT */
 vm_map_lookup_done(kmem_map, myentry);
 I am using 64bit FreeBSD 8.2 on Intel Xeon hardware.
 Any idea how to make a stable implementation on my platform?
 
 Thank you,
 Svetlin
 ___
 freebsd-hackers@freebsd.org mailing list
 http://lists.freebsd.org/mailman/listinfo/freebsd-hackers
 To unsubscribe, send any mail to freebsd-hackers-unsubscr...@freebsd.org

I've never done this, but if I needed to, I think the first thing I'd
try is to use an mmap(2) of /dev/kmem to map the memory you need into
userspace (of course your userspace app will need to be running with
root privs to do this).  

That leaves the interesting problem of locating what offset within the
kernel virtual address space you need to map to get at your data.  Two
things come to mind... have your kernel module export the address in a
sysctl (that feels kind of hack-ish but it should be quick and easy to
do), or use libkvm's kvm_nlist() function to locate the symbol within
your module (I think that should be possible; again I've never actually
done any of this).

-- Ian


___
freebsd-hackers@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/freebsd-hackers
To unsubscribe, send any mail to freebsd-hackers-unsubscr...@freebsd.org


Re: How to access kernel memory from user space

2012-02-22 Thread Ryan Stone
On Wed, Feb 22, 2012 at 2:15 PM, Ian Lepore
free...@damnhippie.dyndns.org wrote:
 I've never done this, but if I needed to, I think the first thing I'd
 try is to use an mmap(2) of /dev/kmem to map the memory you need into
 userspace (of course your userspace app will need to be running with
 root privs to do this).

 That leaves the interesting problem of locating what offset within the
 kernel virtual address space you need to map to get at your data.  Two
 things come to mind... have your kernel module export the address in a
 sysctl (that feels kind of hack-ish but it should be quick and easy to
 do), or use libkvm's kvm_nlist() function to locate the symbol within
 your module (I think that should be possible; again I've never actually
 done any of this).

A far easier way to do this is to have the module create its own
device in /dev that exports the memory by implementing the mmap
interface in the cdev.
___
freebsd-hackers@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/freebsd-hackers
To unsubscribe, send any mail to freebsd-hackers-unsubscr...@freebsd.org


Re: How to access kernel memory from user space

2009-01-16 Thread Alexej Sokolov
On Thu, Jan 15, 2009 at 01:22:18PM -0600, Gerry Weaver wrote:
 _  
 
 From: Alexej Sokolov [mailto:bsd.qu...@googlemail.com]
 To: Gerry Weaver [mailto:ger...@compvia.com]
 Cc: freebsd-hackers@freebsd.org
 Sent: Thu, 15 Jan 2009 12:31:00 -0600
 Subject: Re: How to access kernel memory from user space
 
 
 
 
 2008/12/23 Gerry Weaver ger...@compvia.com
   Hello All,
   
   I am working on a driver that collects various network statistics via pfil. 
 I have a simple array of structures that I use to store the statistics. I 
 also have a user space process that needs to collect these statistics every 
 second or so. A copy operation from kernel to user space would be too 
 expensive. Is there a mechanism that would allow me to gain direct access to 
 my kernel array from user space? The user process would only need read 
 access. It seems like maybe this could be done with mmap, but since this is 
 not a character driver, there is no device file etc.. I'm a newbie, so I 
 apologize if this is something that should be obvious.
 
   
   Thanks in advance,
   Gerry
   ___
   freebsd-hackers@freebsd.org mailing list
   http://lists.freebsd.org/mailman/listinfo/freebsd-hackers
   To unsubscribe, send any mail to freebsd-hackers-unsubscr...@freebsd.org
   Hi, 
 some times ago I solve this task. That's my solution in a system call 
 (whithout cdev). 
 Thanx in advance for founded mistakes and possible bugs (-:
 
 
 #include sys/param.h
   #include sys/proc.h
 #include sys/conf.h
 #include sys/module.h
 #include sys/sysent.h
 #include sys/kernel.h
 #include sys/systm.h
 #include sys/sysproto.h
   #include sys/resourcevar.h
  
 #include vm/vm.h
 #include vm/pmap.h
 #include vm/vm_map.h
 #include vm/vm_param.h
 #include vm/vm_kern.h
 #include vm/vm_object.h

  
 /* Arguments for syscall */
 struct args {
  
 /* Pointer to allocated Buffer */
 unsigned int  *p;
 }; 
  
 /* String to be located in maped buffer */
 const char *str = BSD IS SEXY;

 /* Syscall func */
 static int 
 syscf(struct thread *td, void *sa)
 {
 int error;
 struct args *uap;   
 vm_offset_t addr;  /* Kernel space address */
 vm_offset_t user_addr;  /* User space address  */

 struct proc *procp = (struct proc *)td-td_proc;
  
 struct vmspace *vms = procp-p_vmspace; 
  
 uap = (struct args *)sa;  
 
 PROC_LOCK(procp);
 user_addr = round_page((vm_offset_t)vms-vm_daddr + 
   lim_max(procp, RLIMIT_DATA));
 PROC_UNLOCK(procp);
  
 MALLOC(addr, vm_offset_t, PAGE_SIZE, M_DEVBUF, M_WAITOK | M_ZERO);
  
 vm_map_entry_t  myentry;
 vm_object_t myobject;
   vm_pindex_t mypindex;
 vm_prot_t   myprot;
 boolean_t   mywired;
 vm_ooffset_tobjoffset;
 
 vm_map_lookup(kmem_map, addr, VM_PROT_ALL,
 myentry, myobject, mypindex, myprot, mywired); 
 /* OUT */
   vm_map_lookup_done(kmem_map, myentry);
  
 printf(--- Syscall: hint for allocating space = 0x%X\n, addr);
   
 if (myobject == kmem_object){
 printf(--- Syscall: Yes, it is kmem_obj! \n);
   }
  
 /* Offset in vm_object */   
 objoffset = addr - myentry-start + myentry-offset;
  
 printf(-- Syscall: Object offset = 0x%X \n, (unsigned 
 int)objoffset);

 /*
  * Try to map kernel buffer to user space  
  */
 vm_object_reference(myobject); /* NEEDED Increment vm_obj references 
 */
 error = vm_map_find(vms-vm_map, myobject, objoffset, (vm_offset_t 
 *)user_addr, 
   PAGE_SIZE, TRUE, VM_PROT_RW, VM_PROT_RW, 
 MAP_ENTRY_NOFAULT);
  
 if (error == KERN_SUCCESS) {
 /* copy string using kernel address */
 size_t len;
   copystr(str, (void *)addr, 12, len); 
  
 /* 
  * Tell to user process it's  user space address 
  */
 *uap-p = user_addr;

 /* 
  * Try to read the string using user space address
  */ 
 printf(String: %s\n, (char *)*uap-p); 
  
 printf(--- Syscall: user_addr for allocating space = 
 0x%X\n, user_addr);
   }
  
 return (0);
 }
  
 /* Sysent entity for syscall */
 static struct sysent sc_sysent = {
 1,  /* Number of 
 arguments */
 syscf   /* Syscall function*/
   };
  
 /* Offset in sysent[] */
 static int offset = NO_SYSCALL;
  
 /* Loader */
 static int
 load (struct module *m, int cmd, void *something)
 {
 int error = 0;
 switch(cmd){
 case MOD_LOAD:
   printf(Module

Re: How to access kernel memory from user space

2009-01-15 Thread Alexej Sokolov
2008/12/23 Gerry Weaver ger...@compvia.com

 Hello All,

 I am working on a driver that collects various network statistics via pfil.
 I have a simple array of structures that I use to store the statistics. I
 also have a user space process that needs to collect these statistics every
 second or so. A copy operation from kernel to user space would be too
 expensive. Is there a mechanism that would allow me to gain direct access to
 my kernel array from user space? The user process would only need read
 access. It seems like maybe this could be done with mmap, but since this is
 not a character driver, there is no device file etc.. I'm a newbie, so I
 apologize if this is something that should be obvious.


 Thanks in advance,
 Gerry
 ___
 freebsd-hackers@freebsd.org mailing list
 http://lists.freebsd.org/mailman/listinfo/freebsd-hackers
 To unsubscribe, send any mail to freebsd-hackers-unsubscr...@freebsd.org

Hi,
some times ago I solve this task. That's my solution in a system call
(whithout cdev).
Thanx in advance for founded mistakes and possible bugs (-:


#include sys/param.h
#include sys/proc.h
#include sys/conf.h
#include sys/module.h
#include sys/sysent.h
#include sys/kernel.h
#include sys/systm.h
#include sys/sysproto.h
#include sys/resourcevar.h

#include vm/vm.h
#include vm/pmap.h
#include vm/vm_map.h
#include vm/vm_param.h
#include vm/vm_kern.h
#include vm/vm_object.h


/* Arguments for syscall */
struct args {

/* Pointer to allocated Buffer */
unsigned int  *p;
};

/* String to be located in maped buffer */
const char *str = BSD IS SEXY;

/* Syscall func */
static int
syscf(struct thread *td, void *sa)
{
int error;
struct args *uap;
vm_offset_t addr;  /* Kernel space address */
vm_offset_t user_addr;  /* User space address  */

struct proc *procp = (struct proc *)td-td_proc;

struct vmspace *vms = procp-p_vmspace;

uap = (struct args *)sa;

PROC_LOCK(procp);
user_addr = round_page((vm_offset_t)vms-vm_daddr +
lim_max(procp, RLIMIT_DATA));
PROC_UNLOCK(procp);

MALLOC(addr, vm_offset_t, PAGE_SIZE, M_DEVBUF, M_WAITOK | M_ZERO);

vm_map_entry_t  myentry;
vm_object_t myobject;
vm_pindex_t mypindex;
vm_prot_t   myprot;
boolean_t   mywired;
vm_ooffset_tobjoffset;

vm_map_lookup(kmem_map, addr, VM_PROT_ALL,
myentry, myobject, mypindex, myprot, mywired);
/* OUT */
vm_map_lookup_done(kmem_map, myentry);

printf(--- Syscall: hint for allocating space = 0x%X\n, addr);

if (myobject == kmem_object){
printf(--- Syscall: Yes, it is kmem_obj! \n);
}

/* Offset in vm_object */
objoffset = addr - myentry-start + myentry-offset;

printf(-- Syscall: Object offset = 0x%X \n, (unsigned
int)objoffset);

/*
 * Try to map kernel buffer to user space
 */
vm_object_reference(myobject); /* NEEDED Increment vm_obj references
*/
error = vm_map_find(vms-vm_map, myobject, objoffset, (vm_offset_t
*)user_addr,
PAGE_SIZE, TRUE, VM_PROT_RW, VM_PROT_RW,
MAP_ENTRY_NOFAULT);

if (error == KERN_SUCCESS) {
/* copy string using kernel address */
size_t len;
copystr(str, (void *)addr, 12, len);

/*
 * Tell to user process it's  user space address
 */
*uap-p = user_addr;

/*
 * Try to read the string using user space address
 */
printf(String: %s\n, (char *)*uap-p);

printf(--- Syscall: user_addr for allocating space =
0x%X\n, user_addr);
}

return (0);
}

/* Sysent entity for syscall */
static struct sysent sc_sysent = {
1,  /* Number of
arguments */
syscf   /* Syscall function*/
};

/* Offset in sysent[] */
static int offset = NO_SYSCALL;

/* Loader */
static int
load (struct module *m, int cmd, void *something)
{
int error = 0;
switch(cmd){
case MOD_LOAD:
printf(Module with sysc loaded. Offset = %d \n,
offset);
break;

case MOD_UNLOAD:
printf(Module with sysc unloaded. Offset = %d \n,
offset);
break;

default:
error = EOPNOTSUPP;
break;
}
return (error);
}

/* Syscall macro*/
SYSCALL_MODULE(fiveg_sysc, offset, sc_sysent, load, NULL);

If needed, I can post user space program.
___
freebsd-hackers@freebsd.org mailing list

Re: How to access kernel memory from user space

2009-01-15 Thread Gerry Weaver
_  

From: Alexej Sokolov [mailto:bsd.qu...@googlemail.com]
To: Gerry Weaver [mailto:ger...@compvia.com]
Cc: freebsd-hackers@freebsd.org
Sent: Thu, 15 Jan 2009 12:31:00 -0600
Subject: Re: How to access kernel memory from user space




2008/12/23 Gerry Weaver ger...@compvia.com
  Hello All,
  
  I am working on a driver that collects various network statistics via pfil. I 
have a simple array of structures that I use to store the statistics. I also 
have a user space process that needs to collect these statistics every second 
or so. A copy operation from kernel to user space would be too expensive. Is 
there a mechanism that would allow me to gain direct access to my kernel array 
from user space? The user process would only need read access. It seems like 
maybe this could be done with mmap, but since this is not a character driver, 
there is no device file etc.. I'm a newbie, so I apologize if this is something 
that should be obvious.

  
  Thanks in advance,
  Gerry
  ___
  freebsd-hackers@freebsd.org mailing list
  http://lists.freebsd.org/mailman/listinfo/freebsd-hackers
  To unsubscribe, send any mail to freebsd-hackers-unsubscr...@freebsd.org
  Hi, 
some times ago I solve this task. That's my solution in a system call (whithout 
cdev). 
Thanx in advance for founded mistakes and possible bugs (-:


#include sys/param.h
  #include sys/proc.h
#include sys/conf.h
#include sys/module.h
#include sys/sysent.h
#include sys/kernel.h
#include sys/systm.h
#include sys/sysproto.h
  #include sys/resourcevar.h
 
#include vm/vm.h
#include vm/pmap.h
#include vm/vm_map.h
#include vm/vm_param.h
#include vm/vm_kern.h
#include vm/vm_object.h
   
 
/* Arguments for syscall */
struct args {
 
/* Pointer to allocated Buffer */
unsigned int  *p;
}; 
 
/* String to be located in maped buffer */
const char *str = BSD IS SEXY;
   
/* Syscall func */
static int 
syscf(struct thread *td, void *sa)
{
int error;
struct args *uap;   
vm_offset_t addr;  /* Kernel space address */
vm_offset_t user_addr;  /* User space address  */
   
struct proc *procp = (struct proc *)td-td_proc;
 
struct vmspace *vms = procp-p_vmspace; 
 
uap = (struct args *)sa;  

PROC_LOCK(procp);
user_addr = round_page((vm_offset_t)vms-vm_daddr + 
  lim_max(procp, RLIMIT_DATA));
PROC_UNLOCK(procp);
 
MALLOC(addr, vm_offset_t, PAGE_SIZE, M_DEVBUF, M_WAITOK | M_ZERO);
 
vm_map_entry_t  myentry;
vm_object_t myobject;
  vm_pindex_t mypindex;
vm_prot_t   myprot;
boolean_t   mywired;
vm_ooffset_tobjoffset;

vm_map_lookup(kmem_map, addr, VM_PROT_ALL,
myentry, myobject, mypindex, myprot, mywired); /* 
OUT */
  vm_map_lookup_done(kmem_map, myentry);
 
printf(--- Syscall: hint for allocating space = 0x%X\n, addr);
  
if (myobject == kmem_object){
printf(--- Syscall: Yes, it is kmem_obj! \n);
  }
 
/* Offset in vm_object */   
objoffset = addr - myentry-start + myentry-offset;
 
printf(-- Syscall: Object offset = 0x%X \n, (unsigned 
int)objoffset);
   
/*
 * Try to map kernel buffer to user space  
 */
vm_object_reference(myobject); /* NEEDED Increment vm_obj references */
error = vm_map_find(vms-vm_map, myobject, objoffset, (vm_offset_t 
*)user_addr, 
  PAGE_SIZE, TRUE, VM_PROT_RW, VM_PROT_RW, 
MAP_ENTRY_NOFAULT);
 
if (error == KERN_SUCCESS) {
/* copy string using kernel address */
size_t len;
  copystr(str, (void *)addr, 12, len); 
 
/* 
 * Tell to user process it's  user space address 
 */
*uap-p = user_addr;
   
/* 
 * Try to read the string using user space address
 */ 
printf(String: %s\n, (char *)*uap-p); 
 
printf(--- Syscall: user_addr for allocating space = 0x%X\n, 
user_addr);
  }
 
return (0);
}
 
/* Sysent entity for syscall */
static struct sysent sc_sysent = {
1,  /* Number of arguments 
*/
syscf   /* Syscall function*/
  };
 
/* Offset in sysent[] */
static int offset = NO_SYSCALL;
 
/* Loader */
static int
load (struct module *m, int cmd, void *something)
{
int error = 0;
switch(cmd){
case MOD_LOAD:
  printf(Module with sysc loaded. Offset = %d \n, 
offset);
break;
 
case MOD_UNLOAD:
printf(Module with sysc unloaded. Offset = %d \n, 
offset

Re: How to access kernel memory from user space

2008-12-24 Thread Peter Jeremy
On 2008-Dec-22 18:05:34 -0600, Gerry Weaver ger...@compvia.com wrote:
I am working on a driver that collects various network statistics via
pfil. I have a simple array of structures that I use to store the
statistics. I also have a user space process that needs to collect
these statistics every second or so.

The easiest (and hackiest) approach would be to kldsym(2) to locate
the symbol in KVM and then mmap(2) the relevant part of /dev/kmem.
The biggest downside is that the userland process needs to be group
kmem.

The other approach would be for your kernel driver to grow a character
device node and directly support mmap.

-- 
Peter Jeremy
Please excuse any delays as the result of my ISP's inability to implement
an MTA that is either RFC2821-compliant or matches their claimed behaviour.


pgpRmxXhQAlnw.pgp
Description: PGP signature


Re: How to access kernel memory from user space

2008-12-24 Thread Gerry Weaver
_  

From: Peter Jeremy [mailto:peterjer...@optushome.com.au]
To: Gerry Weaver [mailto:ger...@compvia.com]
Cc: freebsd-hackers@freebsd.org
Sent: Wed, 24 Dec 2008 02:44:45 -0600
Subject: Re: How to access kernel memory from user space

On 2008-Dec-22 18:05:34 -0600, Gerry Weaver ger...@compvia.com wrote:
  I am working on a driver that collects various network statistics via
  pfil. I have a simple array of structures that I use to store the
  statistics. I also have a user space process that needs to collect
  these statistics every second or so.
  
  The easiest (and hackiest) approach would be to kldsym(2) to locate
  the symbol in KVM and then mmap(2) the relevant part of /dev/kmem.
  The biggest downside is that the userland process needs to be group
  kmem.
  
  The other approach would be for your kernel driver to grow a character
  device node and directly support mmap.
  
  -- 
  Peter Jeremy
  Please excuse any delays as the result of my ISP's inability to implement
  an MTA that is either RFC2821-compliant or matches their claimed 
behaviour.Hello All,

Happy Holidays Everyone!!

Thanks for the advice Peter. In this case, the driver I'm working on will run 
on a dedicated
embedded platform, so process group membership shouldn't be an issue. My main 
concern is performance. Any additional overhead will effect the stats, so I 
want to try
to keep it minimal. Is there any significant trade off in performance between 
the two
approaches? The typical data array size is around 20k. Also, Is there anything 
in the source
or ports tree that I could use as an example for the device node case? I've 
been looking around,
but haven't found anything yet. I'll continue digging though ;-)

Thanks Again,
Gerry


  
___
freebsd-hackers@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/freebsd-hackers
To unsubscribe, send any mail to freebsd-hackers-unsubscr...@freebsd.org


Re: How to access kernel memory from user space

2008-12-23 Thread Roman Divacky
On Mon, Dec 22, 2008 at 06:05:34PM -0600, Gerry Weaver wrote:
 Hello All,
 
 I am working on a driver that collects various network statistics via pfil. I 
 have a simple array of structures that I use to store the statistics. I also 
 have a user space process that needs to collect these statistics every second 
 or so. A copy operation from kernel to user space would be too expensive. Is 
 there a mechanism that would allow me to gain direct access to my kernel 
 array from user space? The user process would only need read access. It seems 
 like maybe this could be done with mmap, but since this is not a character 
 driver, there is no device file etc.. I'm a newbie, so I apologize if this is 
 something that should be obvious.

would it be feasible to allocate a buffer in userspace and map it into the 
kernelspace?
if so, I believe sf_buf (man 9 sf_buf) should work


   roman
___
freebsd-hackers@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/freebsd-hackers
To unsubscribe, send any mail to freebsd-hackers-unsubscr...@freebsd.org


Re: How to access kernel memory from user space

2008-12-22 Thread Jacky Oh
hi Gerry..


you may be interested in the following functions:

int copyin(const void *uaddr, void *kaddr, size_t len);
int copyout(const void *kaddr, void *uaddr, size_t len);
int copyinstr(const void *uaddr, void *kaddr, size_t len, size_t *done);
int bcopy(const void *src, const void *dst, len);

this functions are using for syscalls related work, among other
things..lucky!!

Jacky Ohwers

2008/12/23 Gerry Weaver ger...@compvia.com

 Hello All,

 I am working on a driver that collects various network statistics via pfil.
 I have a simple array of structures that I use to store the statistics. I
 also have a user space process that needs to collect these statistics every
 second or so. A copy operation from kernel to user space would be too
 expensive. Is there a mechanism that would allow me to gain direct access to
 my kernel array from user space? The user process would only need read
 access. It seems like maybe this could be done with mmap, but since this is
 not a character driver, there is no device file etc.. I'm a newbie, so I
 apologize if this is something that should be obvious.


 Thanks in advance,
 Gerry
 ___
 freebsd-hackers@freebsd.org mailing list
 http://lists.freebsd.org/mailman/listinfo/freebsd-hackers
 To unsubscribe, send any mail to freebsd-hackers-unsubscr...@freebsd.org

___
freebsd-hackers@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/freebsd-hackers
To unsubscribe, send any mail to freebsd-hackers-unsubscr...@freebsd.org