From owner-freebsd-hackers Fri Jul 13 7:51: 6 2001 Delivered-To: freebsd-hackers@freebsd.org Received: from Awfulhak.org (gw.Awfulhak.org [217.204.245.18]) by hub.freebsd.org (Postfix) with ESMTP id 78DD937B403; Fri, 13 Jul 2001 07:51:00 -0700 (PDT) (envelope-from brian@Awfulhak.org) Received: from hak.lan.Awfulhak.org (root@hak.lan.Awfulhak.org [172.16.0.12]) by Awfulhak.org (8.11.4/8.11.4) with ESMTP id f6DEoes25324; Fri, 13 Jul 2001 15:50:41 +0100 (BST) (envelope-from brian@lan.Awfulhak.org) Received: from hak.lan.Awfulhak.org (brian@localhost [127.0.0.1]) by hak.lan.Awfulhak.org (8.11.4/8.11.4) with ESMTP id f6DEqTW59861; Fri, 13 Jul 2001 15:52:29 +0100 (BST) (envelope-from brian@hak.lan.Awfulhak.org) Message-Id: <200107131452.f6DEqTW59861@hak.lan.Awfulhak.org> X-Mailer: exmh version 2.3.1 01/18/2001 with nmh-1.0.4 To: Alfred Perlstein Cc: Greg Lehey , y-carden@uniandes.edu.co, FreeBSD Hackers , brian@Awfulhak.org Subject: Re: Some questions about kernel programming In-Reply-To: Message from Alfred Perlstein of "Thu, 12 Jul 2001 21:28:09 CDT." <20010712212809.F6664@sneakerz.org> MIME-Version: 1.0 Content-Type: text/plain; charset="us-ascii" Content-ID: <59854.995035948.1@hak.lan.Awfulhak.org> Date: Fri, 13 Jul 2001 15:52:29 +0100 From: Brian Somers Sender: owner-freebsd-hackers@FreeBSD.ORG Precedence: bulk List-ID: List-Archive: (Web Archive) List-Help: (List Instructions) List-Subscribe: List-Unsubscribe: X-Loop: FreeBSD.ORG > > write() doesn't exist in the kernel. The simple answer is "you're > > going to have to read what the send() syscall does and emulate it". > > First, though, you need to answer the question "why do I want to do > > this in the kernel?" > > it actually exists, however the problem is that copyin and friends > assume a seperate address space, I wonder if one could do some trick > to alias the seperate address space on top of the kernel, that should > allow copyin and friends to work on pointers into the kernel's address > space. Solaris does this by passing a tag into it's driver calls. The tag is given to ddi_copy{in,out}() which DTRT. When a kernel wants to open a file, it does a layered open (lyr_open() or some such) which results in an opaque handle with which you can do other lyr_* calls such as lyr_ioctl(). The driver has to declare itself as being capable of doing layered opens (via the d_flag bit of it's devsw), meaning that it uses ddi_copy{in,out} rather than copy{in,out}. > > > 3. How I can copy a pointer string ( character array ) from user space to > > > kernel space using copyin() without the following problem (I can't > > > pass the length the explicitly from user land): > > > > > > struct MySystemCall_args { > > > char * address; > > > }; > > > > > > int MySystemCall( p,uap) > > > struct proc *p; > > > register struct MySystemCall_args *uap; > > > { > > > char *the_address; > > > > > > printf(" ---> uap->address : %s\n", uap->address ); > > > printf(" ---> (strlen (uap->address) * sizeof(char)) : %d \n", > > > (strlen (uap->address) * sizeof(char)) ); > > > copyin(uap->address, the_address, (strlen (uap->address) * sizeof(char)) > > > ); > > > printf("the_address: %s \n", the_address ); > > > printf("strlen (the_address): %d \n", strlen (the_address) ); > > > > > > When this code run in mode kernel: > > > ---> uap->address : 127.0.0.1 > > > ---> (strlen (uap->address) * sizeof(char)) : 9 > > > the_address : 127.0.0.1\M-"\M-Y\M-GX\M-p+\M-@@\M-_\M-*\M-@ > > > strlen (the_address): 20 > > > > > > This crash the kernel later... > > > > You've forgotten the terminating \0. Add one to the length. > > You can't call kernel strlen on a userland address, you must do > something like this: > > /* > * return number of characters in a userland address string > * or -1 if an illegal access occurs. > */ > int > user_strlen(uaddr) > char *uaddr; > { > int ret; > > ret = -1; > do { > ch = fubyte(uaddr); > ret++; > } while (ch != 0 && ch != -1); > > return (ch == -1 ? -1 : ret); > } Have a look at the digi driver in -current where I did this. The caveat is that the kernel code looks ugly. From the driver's ioctl routine: case DIGIIO_IDENT: return (copyout(sc->name, *(char **)data, strlen(sc->name) + 1)); and from digiio.h: #define DIGIIO_IDENT _IOW('e', 'E', char *) and from userland (digictl.c): char namedata[256], *name = namedata; .... } else if (ioctl(fd, DIGIIO_IDENT, &name) != 0) { > -- > -Alfred Perlstein [alfred@freebsd.org] > Ok, who wrote this damn function called '??'? > And why do my programs keep crashing in it? -- Brian http://www.freebsd-services.com/ Don't _EVER_ lose your sense of humour ! To Unsubscribe: send mail to majordomo@FreeBSD.org with "unsubscribe freebsd-hackers" in the body of the message