int get_user_ifreq(struct ifreq *ifr, void __user **ifrdata, void __user *arg);
 int put_user_ifreq(struct ifreq *ifr, void __user *arg);
 int dev_ioctl(struct net *net, unsigned int cmd, struct ifreq *ifr,
-               bool *need_copyout);
+               void __user *data, bool *need_copyout);
 int dev_ifconf(struct net *net, struct ifconf __user *ifc);
-int dev_ethtool(struct net *net, struct ifreq *);
+int dev_ethtool(struct net *net, struct ifreq *ifr, void __user *userdata);
 unsigned int dev_get_flags(const struct net_device *);
 int __dev_change_flags(struct net_device *dev, unsigned int flags,
                       struct netlink_ext_ack *extack);
 
        return err;
 }
 
-static int dev_siocdevprivate(struct net_device *dev,
-                             struct ifreq *ifr, unsigned int cmd)
+static int dev_siocdevprivate(struct net_device *dev, struct ifreq *ifr,
+                             void __user *data, unsigned int cmd)
 {
        const struct net_device_ops *ops = dev->netdev_ops;
-       void __user *data = ifr->ifr_data;
 
        if (ops->ndo_siocdevprivate) {
                if (netif_device_present(dev))
        }
 
        /* fall back to do_ioctl for drivers not yet converted */
+       ifr->ifr_data = data;
        return dev_do_ioctl(dev, ifr, cmd);
 }
 
 /*
  *     Perform the SIOCxIFxxx calls, inside rtnl_lock()
  */
-static int dev_ifsioc(struct net *net, struct ifreq *ifr, unsigned int cmd)
+static int dev_ifsioc(struct net *net, struct ifreq *ifr, void __user *data,
+                     unsigned int cmd)
 {
        int err;
        struct net_device *dev = __dev_get_by_name(net, ifr->ifr_name);
        default:
                if (cmd >= SIOCDEVPRIVATE &&
                    cmd <= SIOCDEVPRIVATE + 15)
-                       return dev_siocdevprivate(dev, ifr, cmd);
+                       return dev_siocdevprivate(dev, ifr, data, cmd);
 
                if (cmd == SIOCBONDENSLAVE ||
                    cmd == SIOCBONDRELEASE ||
  *     positive or a negative errno code on error.
  */
 
-int dev_ioctl(struct net *net, unsigned int cmd, struct ifreq *ifr, bool *need_copyout)
+int dev_ioctl(struct net *net, unsigned int cmd, struct ifreq *ifr,
+             void __user *data, bool *need_copyout)
 {
        int ret;
        char *colon;
        case SIOCETHTOOL:
                dev_load(net, ifr->ifr_name);
                rtnl_lock();
-               ret = dev_ethtool(net, ifr);
+               ret = dev_ethtool(net, ifr, data);
                rtnl_unlock();
                if (colon)
                        *colon = ':';
                if (!ns_capable(net->user_ns, CAP_NET_ADMIN))
                        return -EPERM;
                rtnl_lock();
-               ret = dev_ifsioc(net, ifr, cmd);
+               ret = dev_ifsioc(net, ifr, data, cmd);
                rtnl_unlock();
                if (colon)
                        *colon = ':';
        case SIOCBONDINFOQUERY:
                dev_load(net, ifr->ifr_name);
                rtnl_lock();
-               ret = dev_ifsioc(net, ifr, cmd);
+               ret = dev_ifsioc(net, ifr, data, cmd);
                rtnl_unlock();
                if (need_copyout)
                        *need_copyout = false;
                     cmd <= SIOCDEVPRIVATE + 15)) {
                        dev_load(net, ifr->ifr_name);
                        rtnl_lock();
-                       ret = dev_ifsioc(net, ifr, cmd);
+                       ret = dev_ifsioc(net, ifr, data, cmd);
                        rtnl_unlock();
                        return ret;
                }
 
 
 /* The main entry point in this file.  Called from net/core/dev_ioctl.c */
 
-int dev_ethtool(struct net *net, struct ifreq *ifr)
+int dev_ethtool(struct net *net, struct ifreq *ifr, void __user *useraddr)
 {
        struct net_device *dev = __dev_get_by_name(net, ifr->ifr_name);
-       void __user *useraddr = ifr->ifr_data;
        u32 ethcmd, sub_cmd;
        int rc;
        netdev_features_t old_features;
 
        bool need_copyout;
        int err;
        void __user *argp = (void __user *)arg;
+       void __user *data;
 
        err = sock->ops->ioctl(sock, cmd, arg);
 
        if (err != -ENOIOCTLCMD)
                return err;
 
-       if (copy_from_user(&ifr, argp, sizeof(struct ifreq)))
+       if (get_user_ifreq(&ifr, &data, argp))
                return -EFAULT;
-       err = dev_ioctl(net, cmd, &ifr, &need_copyout);
+       err = dev_ioctl(net, cmd, &ifr, data, &need_copyout);
        if (!err && need_copyout)
-               if (copy_to_user(argp, &ifr, sizeof(struct ifreq)))
+               if (put_user_ifreq(&ifr, argp))
                        return -EFAULT;
 
        return err;
        net = sock_net(sk);
        if (unlikely(cmd >= SIOCDEVPRIVATE && cmd <= (SIOCDEVPRIVATE + 15))) {
                struct ifreq ifr;
+               void __user *data;
                bool need_copyout;
-               if (copy_from_user(&ifr, argp, sizeof(struct ifreq)))
+               if (get_user_ifreq(&ifr, &data, argp))
                        return -EFAULT;
-               err = dev_ioctl(net, cmd, &ifr, &need_copyout);
+               err = dev_ioctl(net, cmd, &ifr, data, &need_copyout);
                if (!err && need_copyout)
-                       if (copy_to_user(argp, &ifr, sizeof(struct ifreq)))
+                       if (put_user_ifreq(&ifr, argp))
                                return -EFAULT;
        } else
 #ifdef CONFIG_WEXT_CORE
        saved = ifr.ifr_settings.ifs_ifsu.raw_hdlc;
        ifr.ifr_settings.ifs_ifsu.raw_hdlc = compat_ptr(uptr32);
 
-       err = dev_ioctl(net, SIOCWANDEV, &ifr, NULL);
+       err = dev_ioctl(net, SIOCWANDEV, &ifr, NULL, NULL);
        if (!err) {
                ifr.ifr_settings.ifs_ifsu.raw_hdlc = saved;
                if (put_user_ifreq(&ifr, uifr32))
                                 struct compat_ifreq __user *u_ifreq32)
 {
        struct ifreq ifreq;
-       u32 data32;
+       void __user *data;
 
-       if (copy_from_user(ifreq.ifr_name, u_ifreq32->ifr_name, IFNAMSIZ))
+       if (get_user_ifreq(&ifreq, &data, u_ifreq32))
                return -EFAULT;
-       if (get_user(data32, &u_ifreq32->ifr_data))
-               return -EFAULT;
-       ifreq.ifr_data = compat_ptr(data32);
+       ifreq.ifr_data = data;
 
-       return dev_ioctl(net, cmd, &ifreq, NULL);
-}
-
-static int compat_ifreq_ioctl(struct net *net, struct socket *sock,
-                             unsigned int cmd,
-                             unsigned long arg,
-                             struct compat_ifreq __user *uifr32)
-{
-       struct ifreq ifr;
-       bool need_copyout;
-       int err;
-
-       err = sock->ops->ioctl(sock, cmd, arg);
-
-       /* If this ioctl is unknown try to hand it down
-        * to the NIC driver.
-        */
-       if (err != -ENOIOCTLCMD)
-               return err;
-
-       if (get_user_ifreq(&ifr, NULL, uifr32))
-               return -EFAULT;
-       err = dev_ioctl(net, cmd, &ifr, &need_copyout);
-       if (!err && need_copyout)
-               if (put_user_ifreq(&ifr, uifr32))
-                       return -EFAULT;
-
-       return err;
+       return dev_ioctl(net, cmd, &ifreq, data, NULL);
 }
 
 /* Since old style bridge ioctl's endup using SIOCDEVPRIVATE
        case SIOCBONDRELEASE:
        case SIOCBONDSETHWADDR:
        case SIOCBONDCHANGEACTIVE:
-               return compat_ifreq_ioctl(net, sock, cmd, arg, argp);
-
        case SIOCSARP:
        case SIOCGARP:
        case SIOCDARP: