Skip site navigation (1)Skip section navigation (2)
Date:      Fri, 13 Jul 2001 15:52:29 +0100
From:      Brian Somers <brian@Awfulhak.org>
To:        Alfred Perlstein <bright@sneakerz.org>
Cc:        Greg Lehey <grog@FreeBSD.ORG>, y-carden@uniandes.edu.co, FreeBSD Hackers <hackers@FreeBSD.ORG>, brian@Awfulhak.org
Subject:   Re: Some questions about kernel programming 
Message-ID:  <200107131452.f6DEqTW59861@hak.lan.Awfulhak.org>
In-Reply-To: Message from Alfred Perlstein <bright@sneakerz.org>  of "Thu, 12 Jul 2001 21:28:09 CDT." <20010712212809.F6664@sneakerz.org> 

next in thread | previous in thread | raw e-mail | index | archive | help
> > 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 <brian@freebsd-services.com>                <brian@Awfulhak.org>
      http://www.freebsd-services.com/        <brian@[uk.]FreeBSD.org>
Don't _EVER_ lose your sense of humour !      <brian@[uk.]OpenBSD.org>



To Unsubscribe: send mail to majordomo@FreeBSD.org
with "unsubscribe freebsd-hackers" in the body of the message




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