Skip site navigation (1)Skip section navigation (2)
Date:      Thu, 04 Sep 1997 11:39:44 +0930
From:      Mike Smith <mike@smith.net.au>
To:        Simon Shapiro <Shimon@i-Connect.Net>
Cc:        Mike Smith <mike@smith.net.au>, freebsd-hackers@freebsd.org
Subject:   Re: IOCTL Commands - Where is my mistake? 
Message-ID:  <199709040209.LAA00716@word.smith.net.au>
In-Reply-To: Your message of "Wed, 03 Sep 1997 18:35:25 MST." <XFMail.970903183525.Shimon@i-Connect.Net> 

next in thread | previous in thread | raw e-mail | index | archive | help
> Thax for the help Mike!
> 
> Hi Mike Smith;  On 03-Sep-97 you wrote: 
> > > I want to pass IOCTL commands to a driver.  This is what I do:
> > > 
> > >     #define DPT_IOCTL_INTERNAL_METRICS       _IOW('D', 1, dpt_perf_t)
> >  
> >  You want to pass a pointer to the struct, not the struct itself.
> 
> I do.  what gave you the idea I do not?

dpt_perf_t is common lingo for a structure definition.  If you mean 
that it is a pointer, then you should not be calling it that.

> > >     switch (cmd) {
> > >     case DPT_IOCTL_INTERNAL_METRICS:
> > >          result = copyout((char *)&dpt->performance, 
> > >                          (dpt_softc_t *)(*(caddr_t *)cmdarg),
> > >                          sizeof(dpt_perf_t));
> >  
> >  This is *hideously* bogus.  Try :
> >  
> >       caddr_t dest;
> >  
> >               /* get address in userspace */
> >       dest = fuword(*(caddr_t *)cmdarg);
> 
> This is *hideously* not portable :-)  You assume an integer and a char *
> are the same.  Should be dest = (caddr_t)fuword....

Given that I am also assuming that a userspace pointer fits in a 
"word", the extra cast didn't seem worth the effort.  If/when fuaddr() 
comes into the picture, I'll start using it.

> I did.  I am still getting the SAME result.  Maybe I should re-state that:
> 
> If I do:
> 
> #define DPT_IOCTL_INTERNAL_METRICS    _IOR('D', 1, dpt_perf_t)
> 
> Then copyout fails!

Have you bothered to print the address that you are trying to copy out 
to?

> BUT if I do:
> 
> #define DPT_IOCTL_INTERNAL_METRICS   (IOC_INOUT | 1)
> 
> Then it WORKS.

So what?  You're the benficiary of a fencepost error in that you 
shouldn't be getting anything copied in or out at all.  Look at the 
definition of the _IO* macros :

#define _IOC(inout,group,num,len) \
        (inout | ((len & IOCPARM_MASK) << 16) | ((group) << 8) | (num))
#define _IO(g,n)        _IOC(IOC_VOID,  (g), (n), 0)
#define _IOR(g,n,t)     _IOC(IOC_OUT,   (g), (n), sizeof(t))
#define _IOW(g,n,t)     _IOC(IOC_IN,    (g), (n), sizeof(t))
/* this should be _IORW, but stdio got there first */
#define _IOWR(g,n,t)    _IOC(IOC_INOUT, (g), (n), sizeof(t))

> The fact that the contents of cmd (NOT the identity of cmdarg!) changes
> the outcome of copyout, coupled with the fact that your version, although
> not nearly as *hideously* bogus as mine, does NOT work, coupled to the
> fact that ioctl does work, leads me to belive that I am making a stupid 
> mistake, but your solution is not indicating my error.

I have, indeed, indicated your error.  The object supplied as an 
argument to the ioctl is copied to/from kernel space dependant on the 
_IO macro flavour.  The *address* of this copied object is passed to 
your ioctl handler in (cmdarg).  You can either pass a user-space 
address in, and use this address as the argument to a copyout, or you 
can request that the entire structure be copied out and supply an 
entire structure.

mike





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