diff options
| author | Ben Hutchings <ben@decadent.org.uk> | 2017-02-04 11:56:03 -0500 |
|---|---|---|
| committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2017-02-18 09:11:42 -0500 |
| commit | 878b015bcc726560b13be2d906caf6923428f05d (patch) | |
| tree | e355d20b8e23168e8d9ff926327d4400191b2580 /drivers/net/usb | |
| parent | b90cb484c068b3fd30aee322506d38bcc2f43838 (diff) | |
pegasus: Use heap buffers for all register access
[ Upstream commit 5593523f968bc86d42a035c6df47d5e0979b5ace ]
Allocating USB buffers on the stack is not portable, and no longer
works on x86_64 (with VMAP_STACK enabled as per default).
Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2")
References: https://bugs.debian.org/852556
Reported-by: Lisandro Damián Nicanor Pérez Meyer <lisandro@debian.org>
Tested-by: Lisandro Damián Nicanor Pérez Meyer <lisandro@debian.org>
Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
Signed-off-by: David S. Miller <davem@davemloft.net>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'drivers/net/usb')
| -rw-r--r-- | drivers/net/usb/pegasus.c | 29 |
1 files changed, 25 insertions, 4 deletions
diff --git a/drivers/net/usb/pegasus.c b/drivers/net/usb/pegasus.c index 1434e5dd5f9c..ee40ac23507a 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 | ||
