Need Help on compat_ioctl implementation

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Hello all,
I am facing some difficulty to implement compat_ioctl entry point in
my driver code, please help me out to sort out the things.
The ioctl is READ WRITE type,
It takes one header structure as argument the structure is as follows,
typedef struct
   {
       unsigned int Header;
       void  *          Data;
       unsigned int  Size;
   } IOCTL_HEADER;

corresponding compat strucutre is
typedef struct ioctl_header32
{
compat_uint_t  Header ;
compat_uptr_t Data ;
compat_uint_t Size ;
}IOCTL_HEADER32 ;

the IOCTL is expected to fill following structure and return.
typedef struct
{
   unsigned int msgsize;
   char           msg[512];
} MSG ;

compat_ioctl entry point is as follows.

long func_ioctl32(

           struct file *filp,

           unsigned int cmd,

           unsigned long arg)
{
   long ret = 0 ;
   IOCTL_HEADER hdr64 ;
   IOCTL_HEADER32 __user *hdr32 ;
   unsigned long tmp ;
   u64 data ;
   unsigned long size ;

   hdr32 = (IOCTL_HEADER32 __user *)compat_ptr(arg) ;
   __get_user(tmp, &(hdr32->Header)) ;
   __get_user(data, &(hdr32->Data)) ;
   __get_user(size, &(hdr32->Size)) ;

   if(!access_ok(
                 VERIEY_READ|VERIFY_WRITE,
                 compat_ptr(data),
                 sizeof(unsigned long)))
   {
       printk("No access to this address\n") ;
       return -EFAULT ;
   }

   hdr64.Header = tmp ;
   hdr64.Data    = data ;
   hdr64.Size   = size ;
   handle_ioctls(filp, cmd, (void *)&hdr64) ; /*This func is specific
to compat ioctl.*/

  return ret;
}

In handle_ioctl I am doing following steps.
{
ioctl_hdr = (IOCTL_HEADER *)cmd_buff ;

   switch(cmd)
   {
       case IOCTL_MSG_GET :
            {
                MSG32 *msg32 ; /* Compat msg struct is defined.*/
                 MSG msg ;
                unsigned int i ;

                msg32 = (MSG32 __user *)ioctl_hdr->Data ;
                msg.msgsize = 128 ;
                strcpy(msg.msg, MSG_STR) ; /*MSG_STR is a macro string*/
                put_user(msg.msgsize, &(msg32->msgsize)) ; /* This
works fine.*/
                put_user(msg.msg[0], (char *) compat_ptr(msg32->msg))
; /* This is giving SEG FAULT */
            }
    }
}

Question :
What is the correct way to perform string copy? Or is this method
correct? if not what is the correct way?
Any links or pointers are most welcome

Thanks in advance
Devesh
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to [email protected]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

[Index of Archives]     [Kernel Newbies]     [Netfilter]     [Bugtraq]     [Photo]     [Stuff]     [Gimp]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Video 4 Linux]     [Linux for the blind]     [Linux Resources]
  Powered by Linux