Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

p54usb: rewriting rx/tx routines to make use of usb_anchor's facilities

Alan Stern found several flaws in p54usb's implementation and annotated:
"usb_kill_urb() and similar routines do not expect an URB's completion
routine to deallocate it.  This is almost obvious -- if the URB is deallocated
before the completion routine returns then there's no way for usb_kill_urb
to detect when the URB actually is complete."

This patch addresses all known limitations in the old implementation and fixes
khub's "use-after-freed" hang, when SLUB debug's poisoning option is enabled.

Signed-off-by: Christian Lamparter <chunkeey@web.de>
Cc: stable@kernel.org
Tested-by: Larry Finger <Larry.Finger@lwfinger.net>
Signed-off-by: John W. Linville <linville@tuxdriver.com>

authored by

Christian Lamparter and committed by
John W. Linville
dd397dc9 a07d3619

+102 -50
+101 -50
drivers/net/wireless/p54/p54usb.c
··· 86 86 struct ieee80211_hw *dev = info->dev; 87 87 struct p54u_priv *priv = dev->priv; 88 88 89 + skb_unlink(skb, &priv->rx_queue); 90 + 89 91 if (unlikely(urb->status)) { 90 - info->urb = NULL; 91 - usb_free_urb(urb); 92 + dev_kfree_skb_irq(skb); 92 93 return; 93 94 } 94 95 95 - skb_unlink(skb, &priv->rx_queue); 96 96 skb_put(skb, urb->actual_length); 97 97 98 98 if (priv->hw_type == P54U_NET2280) ··· 105 105 if (p54_rx(dev, skb)) { 106 106 skb = dev_alloc_skb(priv->common.rx_mtu + 32); 107 107 if (unlikely(!skb)) { 108 - usb_free_urb(urb); 109 108 /* TODO check rx queue length and refill *somewhere* */ 110 109 return; 111 110 } ··· 114 115 info->dev = dev; 115 116 urb->transfer_buffer = skb_tail_pointer(skb); 116 117 urb->context = skb; 117 - skb_queue_tail(&priv->rx_queue, skb); 118 118 } else { 119 119 if (priv->hw_type == P54U_NET2280) 120 120 skb_push(skb, priv->common.tx_hdr_len); ··· 128 130 WARN_ON(1); 129 131 urb->transfer_buffer = skb_tail_pointer(skb); 130 132 } 131 - 132 - skb_queue_tail(&priv->rx_queue, skb); 133 133 } 134 - 135 - usb_submit_urb(urb, GFP_ATOMIC); 134 + skb_queue_tail(&priv->rx_queue, skb); 135 + usb_anchor_urb(urb, &priv->submitted); 136 + if (usb_submit_urb(urb, GFP_ATOMIC)) { 137 + skb_unlink(skb, &priv->rx_queue); 138 + usb_unanchor_urb(urb); 139 + dev_kfree_skb_irq(skb); 140 + } 136 141 } 137 142 138 143 static void p54u_tx_reuse_skb_cb(struct urb *urb) ··· 145 144 usb_get_intfdata(usb_ifnum_to_if(urb->dev, 0)))->priv; 146 145 147 146 skb_pull(skb, priv->common.tx_hdr_len); 148 - usb_free_urb(urb); 149 - } 150 - 151 - static void p54u_tx_cb(struct urb *urb) 152 - { 153 - usb_free_urb(urb); 154 - } 155 - 156 - static void p54u_tx_free_cb(struct urb *urb) 157 - { 158 - kfree(urb->transfer_buffer); 159 - usb_free_urb(urb); 160 147 } 161 148 162 149 static void p54u_tx_free_skb_cb(struct urb *urb) ··· 154 165 usb_get_intfdata(usb_ifnum_to_if(urb->dev, 0)); 155 166 156 167 p54_free_skb(dev, skb); 157 - usb_free_urb(urb); 168 + } 169 + 170 + static void p54u_tx_dummy_cb(struct urb *urb) { } 171 + 172 + static void p54u_free_urbs(struct ieee80211_hw *dev) 173 + { 174 + struct p54u_priv *priv = dev->priv; 175 + usb_kill_anchored_urbs(&priv->submitted); 158 176 } 159 177 160 178 static int p54u_init_urbs(struct ieee80211_hw *dev) 161 179 { 162 180 struct p54u_priv *priv = dev->priv; 163 - struct urb *entry; 181 + struct urb *entry = NULL; 164 182 struct sk_buff *skb; 165 183 struct p54u_rx_info *info; 184 + int ret = 0; 166 185 167 186 while (skb_queue_len(&priv->rx_queue) < 32) { 168 187 skb = __dev_alloc_skb(priv->common.rx_mtu + 32, GFP_KERNEL); 169 - if (!skb) 170 - break; 188 + if (!skb) { 189 + ret = -ENOMEM; 190 + goto err; 191 + } 171 192 entry = usb_alloc_urb(0, GFP_KERNEL); 172 193 if (!entry) { 173 - kfree_skb(skb); 174 - break; 194 + ret = -ENOMEM; 195 + goto err; 175 196 } 197 + 176 198 usb_fill_bulk_urb(entry, priv->udev, 177 199 usb_rcvbulkpipe(priv->udev, P54U_PIPE_DATA), 178 200 skb_tail_pointer(skb), ··· 192 192 info->urb = entry; 193 193 info->dev = dev; 194 194 skb_queue_tail(&priv->rx_queue, skb); 195 - usb_submit_urb(entry, GFP_KERNEL); 195 + 196 + usb_anchor_urb(entry, &priv->submitted); 197 + ret = usb_submit_urb(entry, GFP_KERNEL); 198 + if (ret) { 199 + skb_unlink(skb, &priv->rx_queue); 200 + usb_unanchor_urb(entry); 201 + goto err; 202 + } 203 + usb_free_urb(entry); 204 + entry = NULL; 196 205 } 197 206 198 207 return 0; 199 - } 200 208 201 - static void p54u_free_urbs(struct ieee80211_hw *dev) 202 - { 203 - struct p54u_priv *priv = dev->priv; 204 - struct p54u_rx_info *info; 205 - struct sk_buff *skb; 206 - 207 - while ((skb = skb_dequeue(&priv->rx_queue))) { 208 - info = (struct p54u_rx_info *) skb->cb; 209 - if (!info->urb) 210 - continue; 211 - 212 - usb_kill_urb(info->urb); 213 - kfree_skb(skb); 214 - } 209 + err: 210 + usb_free_urb(entry); 211 + kfree_skb(skb); 212 + p54u_free_urbs(dev); 213 + return ret; 215 214 } 216 215 217 216 static void p54u_tx_3887(struct ieee80211_hw *dev, struct sk_buff *skb, ··· 218 219 { 219 220 struct p54u_priv *priv = dev->priv; 220 221 struct urb *addr_urb, *data_urb; 222 + int err = 0; 221 223 222 224 addr_urb = usb_alloc_urb(0, GFP_ATOMIC); 223 225 if (!addr_urb) ··· 233 233 usb_fill_bulk_urb(addr_urb, priv->udev, 234 234 usb_sndbulkpipe(priv->udev, P54U_PIPE_DATA), 235 235 &((struct p54_hdr *)skb->data)->req_id, 4, 236 - p54u_tx_cb, dev); 236 + p54u_tx_dummy_cb, dev); 237 237 usb_fill_bulk_urb(data_urb, priv->udev, 238 238 usb_sndbulkpipe(priv->udev, P54U_PIPE_DATA), 239 239 skb->data, skb->len, 240 240 free_on_tx ? p54u_tx_free_skb_cb : 241 241 p54u_tx_reuse_skb_cb, skb); 242 242 243 - usb_submit_urb(addr_urb, GFP_ATOMIC); 244 - usb_submit_urb(data_urb, GFP_ATOMIC); 243 + usb_anchor_urb(addr_urb, &priv->submitted); 244 + err = usb_submit_urb(addr_urb, GFP_ATOMIC); 245 + if (err) { 246 + usb_unanchor_urb(addr_urb); 247 + goto out; 248 + } 249 + 250 + usb_anchor_urb(addr_urb, &priv->submitted); 251 + err = usb_submit_urb(data_urb, GFP_ATOMIC); 252 + if (err) 253 + usb_unanchor_urb(data_urb); 254 + 255 + out: 256 + usb_free_urb(addr_urb); 257 + usb_free_urb(data_urb); 258 + 259 + if (err) 260 + p54_free_skb(dev, skb); 245 261 } 246 262 247 263 static __le32 p54u_lm87_chksum(const __le32 *data, size_t length) ··· 297 281 free_on_tx ? p54u_tx_free_skb_cb : 298 282 p54u_tx_reuse_skb_cb, skb); 299 283 300 - usb_submit_urb(data_urb, GFP_ATOMIC); 284 + usb_anchor_urb(data_urb, &priv->submitted); 285 + if (usb_submit_urb(data_urb, GFP_ATOMIC)) { 286 + usb_unanchor_urb(data_urb); 287 + skb_pull(skb, sizeof(*hdr)); 288 + p54_free_skb(dev, skb); 289 + } 290 + usb_free_urb(data_urb); 301 291 } 302 292 303 293 static void p54u_tx_net2280(struct ieee80211_hw *dev, struct sk_buff *skb, ··· 313 291 struct urb *int_urb, *data_urb; 314 292 struct net2280_tx_hdr *hdr; 315 293 struct net2280_reg_write *reg; 294 + int err = 0; 316 295 317 296 reg = kmalloc(sizeof(*reg), GFP_ATOMIC); 318 297 if (!reg) ··· 343 320 344 321 usb_fill_bulk_urb(int_urb, priv->udev, 345 322 usb_sndbulkpipe(priv->udev, P54U_PIPE_DEV), reg, sizeof(*reg), 346 - p54u_tx_free_cb, dev); 347 - usb_submit_urb(int_urb, GFP_ATOMIC); 323 + p54u_tx_dummy_cb, dev); 324 + 325 + /* 326 + * This flag triggers a code path in the USB subsystem that will 327 + * free what's inside the transfer_buffer after the callback routine 328 + * has completed. 329 + */ 330 + int_urb->transfer_flags |= URB_FREE_BUFFER; 348 331 349 332 usb_fill_bulk_urb(data_urb, priv->udev, 350 333 usb_sndbulkpipe(priv->udev, P54U_PIPE_DATA), 351 334 skb->data, skb->len, 352 335 free_on_tx ? p54u_tx_free_skb_cb : 353 336 p54u_tx_reuse_skb_cb, skb); 354 - usb_submit_urb(data_urb, GFP_ATOMIC); 337 + 338 + usb_anchor_urb(int_urb, &priv->submitted); 339 + err = usb_submit_urb(int_urb, GFP_ATOMIC); 340 + if (err) { 341 + usb_unanchor_urb(int_urb); 342 + goto out; 343 + } 344 + 345 + usb_anchor_urb(data_urb, &priv->submitted); 346 + err = usb_submit_urb(data_urb, GFP_ATOMIC); 347 + if (err) { 348 + usb_unanchor_urb(data_urb); 349 + goto out; 350 + } 351 + out: 352 + usb_free_urb(int_urb); 353 + usb_free_urb(data_urb); 354 + 355 + if (err) { 356 + skb_pull(skb, sizeof(*hdr)); 357 + p54_free_skb(dev, skb); 358 + } 355 359 } 356 360 357 361 static int p54u_write(struct p54u_priv *priv, ··· 935 885 goto err_free_dev; 936 886 937 887 skb_queue_head_init(&priv->rx_queue); 888 + init_usb_anchor(&priv->submitted); 938 889 939 890 p54u_open(dev); 940 891 err = p54_read_eeprom(dev);
+1
drivers/net/wireless/p54/p54usb.h
··· 133 133 134 134 spinlock_t lock; 135 135 struct sk_buff_head rx_queue; 136 + struct usb_anchor submitted; 136 137 }; 137 138 138 139 #endif /* P54USB_H */