Search Linux Wireless

Re: [PATCH] wext: Fix 32 bit iwpriv compatibility issue with 64 bit Kernel

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

 



Hi,

If a wireless driver uses "iw_handler_def.private_args" to populate
iwpriv command for private ioctls
but  handlers for private ioctls(iw_handler) of iw_handler_def.private
is set to NULL like "atmel" and "airo" wireless drivers.
For those case, the IOCTLs from SIOCIWFIRSTPRIV to SIOCIWLASTPRIV will
follow the path ndo_do_ioctl().
Accordingly when the filled up "iw_point" structure comes from 32 bit
iwpriv to 64 bit Kernel, Kernel will not convert the pointer and sends
it to driver. So, the driver may get the invalid data.

We have used another iwr (i.e; iwrp) to pass things to driver. Changes
are as follows. Please have look into this.

     diff --git a/net/wireless/wext-core.c b/net/wireless/wext-core.c
index 6250b1c..50583fb 100644
--- a/net/wireless/wext-core.c
+++ b/net/wireless/wext-core.c
@@ -958,8 +958,28 @@ static int wireless_process_ioctl(struct net
*net, struct ifreq *ifr,
            return private(dev, iwr, cmd, info, handler);
    }
    /* Old driver API : call driver ioctl handler */
-   if (dev->netdev_ops->ndo_do_ioctl)
-       return dev->netdev_ops->ndo_do_ioctl(dev, ifr, cmd);
+   if (dev->netdev_ops->ndo_do_ioctl) {
+       if (info->flags & IW_REQUEST_FLAG_COMPAT) {
+           int ret = 0;
+           struct iwreq iwrp;
+           struct compat_iw_point *iwp_compat =
+               (struct compat_iw_point *) &iwr->u.data;
+
+           strncpy(iwrp.ifr_ifrn.ifrn_name, iwr->ifr_ifrn.ifrn_name, IFNAMSIZ);
+           iwrp.u.data.pointer = compat_ptr(iwp_compat->pointer);
+           iwrp.u.data.length = iwp_compat->length;
+           iwrp.u.data.flags = iwp_compat->flags;
+
+           ret = dev->netdev_ops->ndo_do_ioctl(dev, (struct ifreq *)
&iwrp, cmd);
+
+           iwp_compat->pointer = ptr_to_compat(iwrp.u.data.pointer);
+           iwp_compat->length = iwrp.u.data.length;
+           iwp_compat->flags = iwrp.u.data.flags;
+           return ret;
+       } else {
+           return dev->netdev_ops->ndo_do_ioctl(dev, ifr, cmd);
+       }
+   }
    return -EOPNOTSUPP;
 }

Is it Ok?

Thanks,
Prasun

On Tue, May 31, 2016 at 3:55 PM, Johannes Berg
<johannes@xxxxxxxxxxxxxxxx> wrote:
> Hi,
>
> I must say, this is a bit of a surprise - where is iwpriv actually
> still relevant? What driver could this possibly matter for?
>
> Anyway ...
>
>> +     if (dev->netdev_ops->ndo_do_ioctl) {
>> +             if ((info->flags & IW_REQUEST_FLAG_COMPAT) &&
>> +                             (cmd >= SIOCIWFIRSTPRIV && cmd <=
>> SIOCIWLASTPRIV)) {
>
> This has coding style issues, obviously.
>
> Also, handling the non-compat case would allow you to return and reduce
> indentation by one in the large code block that handles the compat.
>
>> +                     int ret = 0;
>> +                     struct compat_iw_point *iwp_compat = (struct compat_iw_point *) &iwr->u.data;
>> +                     struct iw_point *iwp = &iwr->u.data;
>> +                     __u16 length = iwp_compat->length, flags = iwp_compat->flags;
>> +
>> +                     iwp->pointer = compat_ptr(iwp_compat->pointer);
>> +                     iwp->length = length;
>> +                     iwp->flags = flags;
>> +
>> +                     ret = dev->netdev_ops->ndo_do_ioctl(dev, ifr, cmd);
>> +
>> +                     length = iwp->length;
>> +                     flags = iwp->flags;
>> +                     iwp_compat->pointer = ptr_to_compat(iwp->pointer);
>> +                     iwp_compat->length = length;
>> +                     iwp_compat->flags = flags;
>
> Why don't you just put another ifr/iwr on the stack, and use that to
> pass things to the driver? This modify-in-place of 'iwp', which
> requires loading all the variables first, seems very awkward to me.
>
>
> johannes



-- 
Thanks,
Prasun
--
To unsubscribe from this list: send the line "unsubscribe linux-wireless" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html



[Index of Archives]     [Linux Host AP]     [ATH6KL]     [Linux Wireless Personal Area Network]     [Linux Bluetooth]     [Linux Netdev]     [Kernel Newbies]     [Linux Kernel]     [IDE]     [Git]     [Netfilter]     [Bugtraq]     [Yosemite Hiking]     [MIPS Linux]     [ARM Linux]     [Linux RAID]

  Powered by Linux