Skip site navigation (1)Skip section navigation (2)
Date:      Thu, 15 Jan 2009 13:22:42 -0600
From:      "Gerry Weaver" <gerryw@compvia.com>
To:        "Alexej Sokolov" <bsd.quest@googlemail.com>
Cc:        freebsd-hackers@freebsd.org
Subject:   Re: How to access kernel memory from user space
Message-ID:  <20090115192242.4fce7e00@mail01.compvia.com>
In-Reply-To: 671bb5fc0901151031w2da249ebu273dfb9429f82ac7@mail.gmail.com

next in thread | raw e-mail | index | archive | help
=5F=5F=5F=5F=5F =20

From: Alexej Sokolov [mailto:bsd.quest@googlemail.com]
To: Gerry Weaver [mailto:gerryw@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 <gerryw@compvia.com>
  Hello All,
 =20
  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 statis=
tics. I also have a user space process that needs to collect these stati=
stics every second or so. A copy operation from kernel to user space wou=
ld be too expensive. Is there a mechanism that would allow me to gain di=
rect access to my kernel array from user space=3F 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 obvio=
us.
   =20
 =20
  Thanks in advance,
  Gerry
  =5F=5F=5F=5F=5F=5F=5F=5F=5F=5F=5F=5F=5F=5F=5F=5F=5F=5F=5F=5F=5F=5F=5F=
=5F=5F=5F=5F=5F=5F=5F=5F=5F=5F=5F=5F=5F=5F=5F=5F=5F=5F=5F=5F=5F=5F=5F=5F
  freebsd-hackers@freebsd.org mailing list
  http://lists.freebsd.org/mailman/listinfo/freebsd-hackers
  To unsubscribe, send any mail to "freebsd-hackers-unsubscribe@freebsd.=
org"
  Hi,=20
some times ago I solve this task. That's my solution in a system call (w=
hithout cdev).=20
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>
=20
#include <vm/vm.h>
#include <vm/pmap.h>
#include <vm/vm=5Fmap.h>
#include <vm/vm=5Fparam.h>
#include <vm/vm=5Fkern.h>
#include <vm/vm=5Fobject.h>
  =20
=20
/* Arguments for syscall */
struct args {
=20
        /* Pointer to allocated Buffer */
        unsigned int  *p;
};=20
=20
/* String to be located in maped buffer */
const char *str =3D "BSD IS SEXY";
  =20
/* Syscall func */
static int=20
syscf(struct thread *td, void *sa)
{
        int error;
        struct args *uap;  =20
        vm=5Foffset=5Ft addr;          /* Kernel space address */
        vm=5Foffset=5Ft user=5Faddr;  /* User space address  */
  =20
        struct proc *procp =3D (struct proc *)td->td=5Fproc;
=20
        struct vmspace *vms =3D procp->p=5Fvmspace;                =20
=20
        uap =3D (struct args *)sa; =20

        PROC=5FLOCK(procp);
        user=5Faddr =3D round=5Fpage((vm=5Foffset=5Ft)vms->vm=5Fdaddr +=
=20
                          lim=5Fmax(procp, RLIMIT=5FDATA));
        PROC=5FUNLOCK(procp);
=20
        MALLOC(addr, vm=5Foffset=5Ft, PAGE=5FSIZE, M=5FDEVBUF, M=5FWAITO=
K | M=5FZERO);
=20
        vm=5Fmap=5Fentry=5Ft  myentry;
        vm=5Fobject=5Ft     myobject;
          vm=5Fpindex=5Ft     mypindex;
        vm=5Fprot=5Ft       myprot;
        boolean=5Ft       mywired;
        vm=5Fooffset=5Ft    objoffset;

        vm=5Fmap=5Flookup(&kmem=5Fmap, addr, VM=5FPROT=5FALL,
                        &myentry, &myobject, &mypindex, &myprot, &mywire=
d); /* OUT */
          vm=5Fmap=5Flookup=5Fdone(kmem=5Fmap, myentry);
=20
        printf("---> Syscall: hint for allocating space =3D 0x%X\n", add=
r);
 =20
        if (myobject =3D=3D kmem=5Fobject){
                printf("---> Syscall: Yes, it is kmem=5Fobj! \n");
          }
=20
        /* Offset in vm=5Fobject */  =20
        objoffset =3D addr - myentry->start + myentry->offset;
=20
        printf("------> Syscall: Object offset =3D 0x%X \n", (unsigned i=
nt)objoffset);
  =20
        /*
         * Try to map kernel buffer to user space =20
         */
        vm=5Fobject=5Freference(myobject); /* NEEDED Increment vm=5Fobj =
references */
        error =3D vm=5Fmap=5Ffind(&vms->vm=5Fmap, myobject, objoffset, (=
vm=5Foffset=5Ft *)&user=5Faddr,=20
                          PAGE=5FSIZE, TRUE, VM=5FPROT=5FRW, VM=5FPROT=
=5FRW,=20
                        MAP=5FENTRY=5FNOFAULT);
=20
        if (error =3D=3D KERN=5FSUCCESS) {
        /* copy string using kernel address */
                size=5Ft len;
                  copystr(str, (void *)addr, 12, &len);=20
=20
                /*=20
                 * Tell to user process it's  user space address=20
                 */
                *uap->p =3D user=5Faddr;
  =20
                /*=20
                 * Try to read the string using user space address
                 */    =20
                printf("String: %s\n", (char *)*uap->p);=20
=20
                printf("---> Syscall: user=5Faddr for allocating space =
=3D 0x%X\n", user=5Faddr);
          }
=20
        return (0);
}
=20
/* Sysent entity for syscall */
static struct sysent sc=5Fsysent =3D {
        1,                                              /* Number of arg=
uments */
        syscf                                   /* Syscall function    *=
/
  };
=20
/* Offset in sysent[] */
static int offset =3D NO=5FSYSCALL;
=20
/* Loader */
static int
load (struct module *m, int cmd, void *something)
{
        int error =3D 0;
        switch(cmd){
                case MOD=5FLOAD:
                          printf("Module with sysc loaded. Offset =3D %d=
 \n", offset);
                        break;
=20
                case MOD=5FUNLOAD:
                        printf("Module with sysc unloaded. Offset =3D %d=
 \n", offset);
                          break;
=20
                default:
                        error =3D EOPNOTSUPP;
                        break;
        }
        return (error);
}
=20
/* Syscall macro*/
SYSCALL=5FMODULE(fiveg=5Fsysc, &offset, &sc=5Fsysent, load, NULL);
 =20
If needed, I can post user space program.=20
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





   =20



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?20090115192242.4fce7e00>