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>
