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_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 User space program:
#include <stdio.h> #include <stdlib.h> #include <limits.h> #include <sys/syscall.h> #include <sys/types.h> #include <sys/module.h> int main(int argc, char *argv[]) { int sysc_num, error; struct module_stat mstat; /* This Variable will save the addres of remapped buffer */ unsigned int some_var; /* Pointer to pointer to remapped buffer */ unsigned int *p = &some_var; printf("USER: Pointer = %p \n", p); /* Search module with system call */ mstat.version = sizeof(mstat); if ( !(modstat(modfind("fiveg_sysc"), &mstat)) ){ /* Our module */ sysc_num = mstat.data.intval; printf("USER: Module found! Syscall number = %d \n", sysc_num); /* make system call */ error = syscall(sysc_num, p); /* Read the string from remapped buffer */ printf("USER: String = %s\n", (char *)*p); } else { printf("USER: Module seems to be not loaded! \n"); } return(0); } -- Alexej Sokolov <bsd.qu...@googlemail.com> _______________________________________________ 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"