Re: Kernel Panic while trying to access the datastructure parameter in ioctl call.
Re: Kernel Panic while trying to access the datastructure parameter in ioctl call.
- Subject: Re: Kernel Panic while trying to access the datastructure parameter in ioctl call.
- From: Terry Lambert <email@hidden>
- Date: Wed, 18 Jul 2007 12:36:25 -0700
On Jul 18, 2007, at 11:40 AM, JanakiRam wrote:
The problem is the kernel panic is comming up when i try to
access the data in kernel function.
int ioctl_functionpointer(dev_t dev, u_long cmd, caddr_t arg,int
fflag, struct proc *p)
{
IOCTL_Struct_t*ctl = (PF_Ctl_t*)arg;
char data[2048];
if (!ctl) {
return -1;
}
if ((ctl->dptr) ) {
int res = copyin((void *)ctl->dptr, (void *)data,
ctl->bytes);
if (res != 0)
printf ("error in copyin");
}
return 0;
}
If i comment the line copyin function call , then its
working fine.
Then the problem is one of you declaring the ioctl argument
incorrectly, or alignment/packing, or your pointer is bogus, or your
length is bogus, or that your copyin() call is happening in a process
context different from the process context in which the original ioctl
structure was supplied.
-
The way ioctl works is by allocating memory at the BSD layer, and
copying in the argument structure (if any; you must specify either
_IOW or _IOWR for the copyin to take place) into that allocated region
in kernel space, and then passing the address of that around.
It knows the length of this structure by virtue of the declaration of
the ioctl; there is a bit field breakdown of the ioctl's numberic
namespace that is used for this, which is declared in <sys/ioccom.h>,
which everyone who declares an ioctl themselves must use.
When the call completes, if the call was successful (no error), AND
_IOR or _IOWR was specified, then the contents of that structure are
copied back out to user space, and the ioctl returns.
Pointers interior to the ioctl structure are your responsibility.
So what could have gone wrong?
(1) If you declared the ioctl argument incorrectly, then the copied in
data could be short or incomplete. The fact that the:
if ((ctl->dptr) ) {
didn't panic on its own only means that the allocated memory area was
either (a) large enough, or (b) that it was allocated adjacent to an
already allocated region, so the pointer dereference didn't end up
failing. You could still have failed to include 'W' in the _IO
declaration, which means the data never made it in from user space,
and the only thing in the buffer is stack garbage.
(2) If you structure alignment or packing is different in kernel space
than in user space (which it could be, because you didn't explicitly
use a #pragma or __attribute__ to pack your structure), then the
structure you are dereferencing may not have it's fields aligned with
the structure that user space filled out. So the field you think you
are getting may be overlaid with some other field(s) in the structure,
and you are getting garbage.
(3) If you fill out a bogus pointer in the structure in user space,
then the area you are attempting to copy in may in fact be garbage or
not in the user address space; this should not result in a panic,
however, and what should happen is EFAULT (or in the case of
copyinstr, perhaps ENAMETOOLONG, if there is no NULL termination.
(4) The most likely cause is that your length is bogus; I notice that
your buffer "data" (which should not be a stack buffer, it should be
allocated!) is 2K in size, but you don't do anything to ensure that
your count "bytes" is > 0 and less than 2K, so you could easily be
overflowing the buffer. Another possibility is that, since 2K is a
heck of a lot of data in kernel terms (1/8th of your entire available
stack!!!), you could be trashing the kernel stack, resulting in the
panic (this is less likely than simply having a bogus length and
smashing your own stack, but it's a possibility).
(5) Finally, if you are using a worker thread to do the work instead
of doing it in the context of the process making the call (you should
know whether or not you are using one - in fact, you should have told
us this when you asked the question...), then it's trying to copy in
from kernel_process, which is the wrong process to copy in from.
Basically, all copies in or out MUST occur in the context of the
process requesting the copy.
I've tried to use the copyinstr instead of copyin , then also
its showing panic screen.
Please help me to solve this.
Per the above, the most likely fix is to:
(1) use allocated memory instead of a 2K stack buffer
(2) check you length argument to ensure that it is > 0 and < 2k
-- Terry
_______________________________________________
Do not post admin requests to the list. They will be ignored.
Darwin-dev mailing list (email@hidden)
Help/Unsubscribe/Update your Subscription:
This email sent to email@hidden