Loading net/wireless/wext.c +74 −67 Original line number Diff line number Diff line Loading @@ -890,25 +890,22 @@ static int ioctl_standard_call(struct net_device * dev, * a iw_handler but process it in your ioctl handler (i.e. use the * old driver API). */ static int ioctl_private_call(struct net_device *dev, struct ifreq *ifr, unsigned int cmd, iw_handler handler) static int get_priv_descr_and_size(struct net_device *dev, unsigned int cmd, const struct iw_priv_args **descrp) { struct iwreq * iwr = (struct iwreq *) ifr; const struct iw_priv_args * descr = NULL; struct iw_request_info info; int extra_size = 0; int i; int ret = -EINVAL; const struct iw_priv_args *descr; int i, extra_size; /* Get the description of the IOCTL */ for (i = 0; i < dev->wireless_handlers->num_private_args; i++) descr = NULL; for (i = 0; i < dev->wireless_handlers->num_private_args; i++) { if (cmd == dev->wireless_handlers->private_args[i].cmd) { descr = &(dev->wireless_handlers->private_args[i]); descr = &dev->wireless_handlers->private_args[i]; break; } } /* Compute the size of the set/get arguments */ if (descr != NULL) { extra_size = 0; if (descr) { if (IW_IS_SET(cmd)) { int offset = 0; /* For sub-ioctls */ /* Check for sub-ioctl handler */ Loading @@ -933,72 +930,82 @@ static int ioctl_private_call(struct net_device *dev, struct ifreq *ifr, extra_size = 0; } } *descrp = descr; return extra_size; } /* Prepare the call */ info.cmd = cmd; info.flags = 0; /* Check if we have a pointer to user space data or not. */ if (extra_size == 0) { /* No extra arguments. Trivial to handle */ ret = handler(dev, &info, &(iwr->u), (char *) &(iwr->u)); } else { static int ioctl_private_iw_point(struct iw_point *iwp, unsigned int cmd, const struct iw_priv_args *descr, iw_handler handler, struct net_device *dev, struct iw_request_info *info, int extra_size) { char *extra; int err; /* Check what user space is giving us */ if (IW_IS_SET(cmd)) { /* Check NULL pointer */ if ((iwr->u.data.pointer == NULL) && (iwr->u.data.length != 0)) if (!iwp->pointer && iwp->length != 0) return -EFAULT; /* Does it fits within bounds ? */ if (iwr->u.data.length > (descr->set_args & IW_PRIV_SIZE_MASK)) if (iwp->length > (descr->set_args & IW_PRIV_SIZE_MASK)) return -E2BIG; } else if (iwr->u.data.pointer == NULL) } else if (!iwp->pointer) return -EFAULT; /* Always allocate for max space. Easier, and won't last * long... */ extra = kmalloc(extra_size, GFP_KERNEL); if (extra == NULL) if (!extra) return -ENOMEM; /* If it is a SET, get all the extra data in here */ if (IW_IS_SET(cmd) && (iwr->u.data.length != 0)) { err = copy_from_user(extra, iwr->u.data.pointer, extra_size); if (err) { kfree(extra); return -EFAULT; if (IW_IS_SET(cmd) && (iwp->length != 0)) { if (copy_from_user(extra, iwp->pointer, extra_size)) { err = -EFAULT; goto out; } } /* Call the handler */ ret = handler(dev, &info, &(iwr->u), extra); err = handler(dev, info, (union iwreq_data *) iwp, extra); /* If we have something to return to the user */ if (!ret && IW_IS_GET(cmd)) { if (!err && IW_IS_GET(cmd)) { /* Adjust for the actual length if it's variable, * avoid leaking kernel bits outside. */ if (!(descr->get_args & IW_PRIV_SIZE_FIXED)) { extra_size = adjust_priv_size(descr->get_args, &(iwr->u.data)); } * avoid leaking kernel bits outside. */ if (!(descr->get_args & IW_PRIV_SIZE_FIXED)) extra_size = adjust_priv_size(descr->get_args, iwp); err = copy_to_user(iwr->u.data.pointer, extra, extra_size); if (err) ret = -EFAULT; if (copy_to_user(iwp->pointer, extra, extra_size)) err = -EFAULT; } /* Cleanup - I told you it wasn't that long ;-) */ out: kfree(extra); return err; } static int ioctl_private_call(struct net_device *dev, struct ifreq *ifr, unsigned int cmd, iw_handler handler) { struct iwreq *iwr = (struct iwreq *) ifr; int extra_size = 0, ret = -EINVAL; const struct iw_priv_args *descr; struct iw_request_info info; extra_size = get_priv_descr_and_size(dev, cmd, &descr); /* Prepare the call */ info.cmd = cmd; info.flags = 0; /* Check if we have a pointer to user space data or not. */ if (extra_size == 0) { /* No extra arguments. Trivial to handle */ ret = handler(dev, &info, &(iwr->u), (char *) &(iwr->u)); } else { ret = ioctl_private_iw_point(&iwr->u.data, cmd, descr, handler, dev, &info, extra_size); } /* Call commit handler if needed and defined */ if (ret == -EIWCOMMIT) Loading Loading
net/wireless/wext.c +74 −67 Original line number Diff line number Diff line Loading @@ -890,25 +890,22 @@ static int ioctl_standard_call(struct net_device * dev, * a iw_handler but process it in your ioctl handler (i.e. use the * old driver API). */ static int ioctl_private_call(struct net_device *dev, struct ifreq *ifr, unsigned int cmd, iw_handler handler) static int get_priv_descr_and_size(struct net_device *dev, unsigned int cmd, const struct iw_priv_args **descrp) { struct iwreq * iwr = (struct iwreq *) ifr; const struct iw_priv_args * descr = NULL; struct iw_request_info info; int extra_size = 0; int i; int ret = -EINVAL; const struct iw_priv_args *descr; int i, extra_size; /* Get the description of the IOCTL */ for (i = 0; i < dev->wireless_handlers->num_private_args; i++) descr = NULL; for (i = 0; i < dev->wireless_handlers->num_private_args; i++) { if (cmd == dev->wireless_handlers->private_args[i].cmd) { descr = &(dev->wireless_handlers->private_args[i]); descr = &dev->wireless_handlers->private_args[i]; break; } } /* Compute the size of the set/get arguments */ if (descr != NULL) { extra_size = 0; if (descr) { if (IW_IS_SET(cmd)) { int offset = 0; /* For sub-ioctls */ /* Check for sub-ioctl handler */ Loading @@ -933,72 +930,82 @@ static int ioctl_private_call(struct net_device *dev, struct ifreq *ifr, extra_size = 0; } } *descrp = descr; return extra_size; } /* Prepare the call */ info.cmd = cmd; info.flags = 0; /* Check if we have a pointer to user space data or not. */ if (extra_size == 0) { /* No extra arguments. Trivial to handle */ ret = handler(dev, &info, &(iwr->u), (char *) &(iwr->u)); } else { static int ioctl_private_iw_point(struct iw_point *iwp, unsigned int cmd, const struct iw_priv_args *descr, iw_handler handler, struct net_device *dev, struct iw_request_info *info, int extra_size) { char *extra; int err; /* Check what user space is giving us */ if (IW_IS_SET(cmd)) { /* Check NULL pointer */ if ((iwr->u.data.pointer == NULL) && (iwr->u.data.length != 0)) if (!iwp->pointer && iwp->length != 0) return -EFAULT; /* Does it fits within bounds ? */ if (iwr->u.data.length > (descr->set_args & IW_PRIV_SIZE_MASK)) if (iwp->length > (descr->set_args & IW_PRIV_SIZE_MASK)) return -E2BIG; } else if (iwr->u.data.pointer == NULL) } else if (!iwp->pointer) return -EFAULT; /* Always allocate for max space. Easier, and won't last * long... */ extra = kmalloc(extra_size, GFP_KERNEL); if (extra == NULL) if (!extra) return -ENOMEM; /* If it is a SET, get all the extra data in here */ if (IW_IS_SET(cmd) && (iwr->u.data.length != 0)) { err = copy_from_user(extra, iwr->u.data.pointer, extra_size); if (err) { kfree(extra); return -EFAULT; if (IW_IS_SET(cmd) && (iwp->length != 0)) { if (copy_from_user(extra, iwp->pointer, extra_size)) { err = -EFAULT; goto out; } } /* Call the handler */ ret = handler(dev, &info, &(iwr->u), extra); err = handler(dev, info, (union iwreq_data *) iwp, extra); /* If we have something to return to the user */ if (!ret && IW_IS_GET(cmd)) { if (!err && IW_IS_GET(cmd)) { /* Adjust for the actual length if it's variable, * avoid leaking kernel bits outside. */ if (!(descr->get_args & IW_PRIV_SIZE_FIXED)) { extra_size = adjust_priv_size(descr->get_args, &(iwr->u.data)); } * avoid leaking kernel bits outside. */ if (!(descr->get_args & IW_PRIV_SIZE_FIXED)) extra_size = adjust_priv_size(descr->get_args, iwp); err = copy_to_user(iwr->u.data.pointer, extra, extra_size); if (err) ret = -EFAULT; if (copy_to_user(iwp->pointer, extra, extra_size)) err = -EFAULT; } /* Cleanup - I told you it wasn't that long ;-) */ out: kfree(extra); return err; } static int ioctl_private_call(struct net_device *dev, struct ifreq *ifr, unsigned int cmd, iw_handler handler) { struct iwreq *iwr = (struct iwreq *) ifr; int extra_size = 0, ret = -EINVAL; const struct iw_priv_args *descr; struct iw_request_info info; extra_size = get_priv_descr_and_size(dev, cmd, &descr); /* Prepare the call */ info.cmd = cmd; info.flags = 0; /* Check if we have a pointer to user space data or not. */ if (extra_size == 0) { /* No extra arguments. Trivial to handle */ ret = handler(dev, &info, &(iwr->u), (char *) &(iwr->u)); } else { ret = ioctl_private_iw_point(&iwr->u.data, cmd, descr, handler, dev, &info, extra_size); } /* Call commit handler if needed and defined */ if (ret == -EIWCOMMIT) Loading