diff options
| author | David S. Miller <davem@davemloft.net> | 2017-02-07 10:07:03 -0500 |
|---|---|---|
| committer | David S. Miller <davem@davemloft.net> | 2017-02-07 10:07:03 -0500 |
| commit | 6a413e269b170d6d3bd32a71de4d5dcf987d6843 (patch) | |
| tree | c17a5d52ac023e720cf7d57d479e0ac1a0524df3 | |
| parent | 432d4f8ab03527958294ad5e539acaebfc4625e3 (diff) | |
| parent | 2d6a0e9de03ee658a9adc3bfb2f0ca55dff1e478 (diff) | |
Merge branch 'net-Fix-on-stack-USB-buffers'
Ben Hutchings says:
====================
net: Fix on-stack USB buffers
Allocating USB buffers on the stack is not portable, and no longer
works on x86_64 (with VMAP_STACK enabled as per default). This
series fixes all the instances I could find where USB networking
drivers do that.
====================
Signed-off-by: David S. Miller <davem@davemloft.net>
| -rw-r--r-- | drivers/net/usb/catc.c | 56 | ||||
| -rw-r--r-- | drivers/net/usb/pegasus.c | 29 | ||||
| -rw-r--r-- | drivers/net/usb/rtl8150.c | 34 |
3 files changed, 86 insertions, 33 deletions
diff --git a/drivers/net/usb/catc.c b/drivers/net/usb/catc.c index 3daa41bdd4ea..0acc9b640419 100644 --- a/drivers/net/usb/catc.c +++ b/drivers/net/usb/catc.c | |||
| @@ -776,7 +776,7 @@ static int catc_probe(struct usb_interface *intf, const struct usb_device_id *id | |||
| 776 | struct net_device *netdev; | 776 | struct net_device *netdev; |
| 777 | struct catc *catc; | 777 | struct catc *catc; |
| 778 | u8 broadcast[ETH_ALEN]; | 778 | u8 broadcast[ETH_ALEN]; |
| 779 | int i, pktsz; | 779 | int pktsz, ret; |
| 780 | 780 | ||
| 781 | if (usb_set_interface(usbdev, | 781 | if (usb_set_interface(usbdev, |
| 782 | intf->altsetting->desc.bInterfaceNumber, 1)) { | 782 | intf->altsetting->desc.bInterfaceNumber, 1)) { |
| @@ -811,12 +811,8 @@ static int catc_probe(struct usb_interface *intf, const struct usb_device_id *id | |||
| 811 | if ((!catc->ctrl_urb) || (!catc->tx_urb) || | 811 | if ((!catc->ctrl_urb) || (!catc->tx_urb) || |
| 812 | (!catc->rx_urb) || (!catc->irq_urb)) { | 812 | (!catc->rx_urb) || (!catc->irq_urb)) { |
| 813 | dev_err(&intf->dev, "No free urbs available.\n"); | 813 | dev_err(&intf->dev, "No free urbs available.\n"); |
| 814 | usb_free_urb(catc->ctrl_urb); | 814 | ret = -ENOMEM; |
| 815 | usb_free_urb(catc->tx_urb); | 815 | goto fail_free; |
| 816 | usb_free_urb(catc->rx_urb); | ||
| 817 | usb_free_urb(catc->irq_urb); | ||
| 818 | free_netdev(netdev); | ||
| 819 | return -ENOMEM; | ||
| 820 | } | 816 | } |
| 821 | 817 | ||
| 822 | /* The F5U011 has the same vendor/product as the netmate but a device version of 0x130 */ | 818 | /* The F5U011 has the same vendor/product as the netmate but a device version of 0x130 */ |
| @@ -844,15 +840,24 @@ static int catc_probe(struct usb_interface *intf, const struct usb_device_id *id | |||
| 844 | catc->irq_buf, 2, catc_irq_done, catc, 1); | 840 | catc->irq_buf, 2, catc_irq_done, catc, 1); |
| 845 | 841 | ||
| 846 | if (!catc->is_f5u011) { | 842 | if (!catc->is_f5u011) { |
| 843 | u32 *buf; | ||
| 844 | int i; | ||
| 845 | |||
| 847 | dev_dbg(dev, "Checking memory size\n"); | 846 | dev_dbg(dev, "Checking memory size\n"); |
| 848 | 847 | ||
| 849 | i = 0x12345678; | 848 | buf = kmalloc(4, GFP_KERNEL); |
| 850 | catc_write_mem(catc, 0x7a80, &i, 4); | 849 | if (!buf) { |
| 851 | i = 0x87654321; | 850 | ret = -ENOMEM; |
| 852 | catc_write_mem(catc, 0xfa80, &i, 4); | 851 | goto fail_free; |
| 853 | catc_read_mem(catc, 0x7a80, &i, 4); | 852 | } |
| 853 | |||
| 854 | *buf = 0x12345678; | ||
| 855 | catc_write_mem(catc, 0x7a80, buf, 4); | ||
| 856 | *buf = 0x87654321; | ||
| 857 | catc_write_mem(catc, 0xfa80, buf, 4); | ||
| 858 | catc_read_mem(catc, 0x7a80, buf, 4); | ||
| 854 | 859 | ||
| 855 | switch (i) { | 860 | switch (*buf) { |
| 856 | case 0x12345678: | 861 | case 0x12345678: |
| 857 | catc_set_reg(catc, TxBufCount, 8); | 862 | catc_set_reg(catc, TxBufCount, 8); |
| 858 | catc_set_reg(catc, RxBufCount, 32); | 863 | catc_set_reg(catc, RxBufCount, 32); |
| @@ -867,6 +872,8 @@ static int catc_probe(struct usb_interface *intf, const struct usb_device_id *id | |||
| 867 | dev_dbg(dev, "32k Memory\n"); | 872 | dev_dbg(dev, "32k Memory\n"); |
| 868 | break; | 873 | break; |
| 869 | } | 874 | } |
| 875 | |||
| 876 | kfree(buf); | ||
| 870 | 877 | ||
| 871 | dev_dbg(dev, "Getting MAC from SEEROM.\n"); | 878 | dev_dbg(dev, "Getting MAC from SEEROM.\n"); |
| 872 | 879 | ||
| @@ -913,16 +920,21 @@ static int catc_probe(struct usb_interface *intf, const struct usb_device_id *id | |||
| 913 | usb_set_intfdata(intf, catc); | 920 | usb_set_intfdata(intf, catc); |
| 914 | 921 | ||
| 915 | SET_NETDEV_DEV(netdev, &intf->dev); | 922 | SET_NETDEV_DEV(netdev, &intf->dev); |
| 916 | if (register_netdev(netdev) != 0) { | 923 | ret = register_netdev(netdev); |
| 917 | usb_set_intfdata(intf, NULL); | 924 | if (ret) |
| 918 | usb_free_urb(catc->ctrl_urb); | 925 | goto fail_clear_intfdata; |
| 919 | usb_free_urb(catc->tx_urb); | 926 | |
| 920 | usb_free_urb(catc->rx_urb); | ||
| 921 | usb_free_urb(catc->irq_urb); | ||
| 922 | free_netdev(netdev); | ||
| 923 | return -EIO; | ||
| 924 | } | ||
| 925 | return 0; | 927 | return 0; |
| 928 | |||
| 929 | fail_clear_intfdata: | ||
| 930 | usb_set_intfdata(intf, NULL); | ||
| 931 | fail_free: | ||
| 932 | usb_free_urb(catc->ctrl_urb); | ||
| 933 | usb_free_urb(catc->tx_urb); | ||
| 934 | usb_free_urb(catc->rx_urb); | ||
| 935 | usb_free_urb(catc->irq_urb); | ||
| 936 | free_netdev(netdev); | ||
| 937 | return ret; | ||
| 926 | } | 938 | } |
| 927 | 939 | ||
| 928 | static void catc_disconnect(struct usb_interface *intf) | 940 | static void catc_disconnect(struct usb_interface *intf) |
diff --git a/drivers/net/usb/pegasus.c b/drivers/net/usb/pegasus.c index 24e803fe9a53..36674484c6fb 100644 --- a/drivers/net/usb/pegasus.c +++ b/drivers/net/usb/pegasus.c | |||
| @@ -126,40 +126,61 @@ static void async_ctrl_callback(struct urb *urb) | |||
| 126 | 126 | ||
| 127 | static int get_registers(pegasus_t *pegasus, __u16 indx, __u16 size, void *data) | 127 | static int get_registers(pegasus_t *pegasus, __u16 indx, __u16 size, void *data) |
| 128 | { | 128 | { |
| 129 | u8 *buf; | ||
| 129 | int ret; | 130 | int ret; |
| 130 | 131 | ||
| 132 | buf = kmalloc(size, GFP_NOIO); | ||
| 133 | if (!buf) | ||
| 134 | return -ENOMEM; | ||
| 135 | |||
| 131 | ret = usb_control_msg(pegasus->usb, usb_rcvctrlpipe(pegasus->usb, 0), | 136 | ret = usb_control_msg(pegasus->usb, usb_rcvctrlpipe(pegasus->usb, 0), |
| 132 | PEGASUS_REQ_GET_REGS, PEGASUS_REQT_READ, 0, | 137 | PEGASUS_REQ_GET_REGS, PEGASUS_REQT_READ, 0, |
| 133 | indx, data, size, 1000); | 138 | indx, buf, size, 1000); |
| 134 | if (ret < 0) | 139 | if (ret < 0) |
| 135 | netif_dbg(pegasus, drv, pegasus->net, | 140 | netif_dbg(pegasus, drv, pegasus->net, |
| 136 | "%s returned %d\n", __func__, ret); | 141 | "%s returned %d\n", __func__, ret); |
| 142 | else if (ret <= size) | ||
| 143 | memcpy(data, buf, ret); | ||
| 144 | kfree(buf); | ||
| 137 | return ret; | 145 | return ret; |
| 138 | } | 146 | } |
| 139 | 147 | ||
| 140 | static int set_registers(pegasus_t *pegasus, __u16 indx, __u16 size, void *data) | 148 | static int set_registers(pegasus_t *pegasus, __u16 indx, __u16 size, |
| 149 | const void *data) | ||
| 141 | { | 150 | { |
| 151 | u8 *buf; | ||
| 142 | int ret; | 152 | int ret; |
| 143 | 153 | ||
| 154 | buf = kmemdup(data, size, GFP_NOIO); | ||
| 155 | if (!buf) | ||
| 156 | return -ENOMEM; | ||
| 157 | |||
| 144 | ret = usb_control_msg(pegasus->usb, usb_sndctrlpipe(pegasus->usb, 0), | 158 | ret = usb_control_msg(pegasus->usb, usb_sndctrlpipe(pegasus->usb, 0), |
| 145 | PEGASUS_REQ_SET_REGS, PEGASUS_REQT_WRITE, 0, | 159 | PEGASUS_REQ_SET_REGS, PEGASUS_REQT_WRITE, 0, |
| 146 | indx, data, size, 100); | 160 | indx, buf, size, 100); |
| 147 | if (ret < 0) | 161 | if (ret < 0) |
| 148 | netif_dbg(pegasus, drv, pegasus->net, | 162 | netif_dbg(pegasus, drv, pegasus->net, |
| 149 | "%s returned %d\n", __func__, ret); | 163 | "%s returned %d\n", __func__, ret); |
| 164 | kfree(buf); | ||
| 150 | return ret; | 165 | return ret; |
| 151 | } | 166 | } |
| 152 | 167 | ||
| 153 | static int set_register(pegasus_t *pegasus, __u16 indx, __u8 data) | 168 | static int set_register(pegasus_t *pegasus, __u16 indx, __u8 data) |
| 154 | { | 169 | { |
| 170 | u8 *buf; | ||
| 155 | int ret; | 171 | int ret; |
| 156 | 172 | ||
| 173 | buf = kmemdup(&data, 1, GFP_NOIO); | ||
| 174 | if (!buf) | ||
| 175 | return -ENOMEM; | ||
| 176 | |||
| 157 | ret = usb_control_msg(pegasus->usb, usb_sndctrlpipe(pegasus->usb, 0), | 177 | ret = usb_control_msg(pegasus->usb, usb_sndctrlpipe(pegasus->usb, 0), |
| 158 | PEGASUS_REQ_SET_REG, PEGASUS_REQT_WRITE, data, | 178 | PEGASUS_REQ_SET_REG, PEGASUS_REQT_WRITE, data, |
| 159 | indx, &data, 1, 1000); | 179 | indx, buf, 1, 1000); |
| 160 | if (ret < 0) | 180 | if (ret < 0) |
| 161 | netif_dbg(pegasus, drv, pegasus->net, | 181 | netif_dbg(pegasus, drv, pegasus->net, |
| 162 | "%s returned %d\n", __func__, ret); | 182 | "%s returned %d\n", __func__, ret); |
| 183 | kfree(buf); | ||
| 163 | return ret; | 184 | return ret; |
| 164 | } | 185 | } |
| 165 | 186 | ||
diff --git a/drivers/net/usb/rtl8150.c b/drivers/net/usb/rtl8150.c index 95b7bd0d7abc..c81c79110cef 100644 --- a/drivers/net/usb/rtl8150.c +++ b/drivers/net/usb/rtl8150.c | |||
| @@ -155,16 +155,36 @@ static const char driver_name [] = "rtl8150"; | |||
| 155 | */ | 155 | */ |
| 156 | static int get_registers(rtl8150_t * dev, u16 indx, u16 size, void *data) | 156 | static int get_registers(rtl8150_t * dev, u16 indx, u16 size, void *data) |
| 157 | { | 157 | { |
| 158 | return usb_control_msg(dev->udev, usb_rcvctrlpipe(dev->udev, 0), | 158 | void *buf; |
| 159 | RTL8150_REQ_GET_REGS, RTL8150_REQT_READ, | 159 | int ret; |
| 160 | indx, 0, data, size, 500); | 160 | |
| 161 | buf = kmalloc(size, GFP_NOIO); | ||
| 162 | if (!buf) | ||
| 163 | return -ENOMEM; | ||
| 164 | |||
| 165 | ret = usb_control_msg(dev->udev, usb_rcvctrlpipe(dev->udev, 0), | ||
| 166 | RTL8150_REQ_GET_REGS, RTL8150_REQT_READ, | ||
| 167 | indx, 0, buf, size, 500); | ||
| 168 | if (ret > 0 && ret <= size) | ||
| 169 | memcpy(data, buf, ret); | ||
| 170 | kfree(buf); | ||
| 171 | return ret; | ||
| 161 | } | 172 | } |
| 162 | 173 | ||
| 163 | static int set_registers(rtl8150_t * dev, u16 indx, u16 size, void *data) | 174 | static int set_registers(rtl8150_t * dev, u16 indx, u16 size, const void *data) |
| 164 | { | 175 | { |
| 165 | return usb_control_msg(dev->udev, usb_sndctrlpipe(dev->udev, 0), | 176 | void *buf; |
| 166 | RTL8150_REQ_SET_REGS, RTL8150_REQT_WRITE, | 177 | int ret; |
| 167 | indx, 0, data, size, 500); | 178 | |
| 179 | buf = kmemdup(data, size, GFP_NOIO); | ||
| 180 | if (!buf) | ||
| 181 | return -ENOMEM; | ||
| 182 | |||
| 183 | ret = usb_control_msg(dev->udev, usb_sndctrlpipe(dev->udev, 0), | ||
| 184 | RTL8150_REQ_SET_REGS, RTL8150_REQT_WRITE, | ||
| 185 | indx, 0, buf, size, 500); | ||
| 186 | kfree(buf); | ||
| 187 | return ret; | ||
| 168 | } | 188 | } |
| 169 | 189 | ||
| 170 | static void async_set_reg_cb(struct urb *urb) | 190 | static void async_set_reg_cb(struct urb *urb) |
