Re: How to access kernel memory from user space
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
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
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
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
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
_ 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
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
_ 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
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
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