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>