_____  

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





    
_______________________________________________
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"

Reply via email to