How to access kernel memory from user space
Gerry Weaver
gerryw at compvia.com
Thu Jan 15 11:22:46 PST 2009
_____
From: Alexej Sokolov [mailto:bsd.quest at googlemail.com]
To: Gerry Weaver [mailto:gerryw at compvia.com]
Cc: freebsd-hackers at 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 <gerryw at 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 at freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/freebsd-hackers
To unsubscribe, send any mail to "freebsd-hackers-unsubscribe at 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_t objoffset;
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.
Hi,
This looks like a very nice solution. I would like to see the user space code very much.
I really appreciate your help!
Thanks Again,
Gerry
More information about the freebsd-hackers
mailing list