Skip to content

Commit 9dab880

Browse files
minskMedvedavem330
authored andcommitted
nfc: pn533: Wait for out_urb's completion in pn533_usb_send_frame()
Fix a use-after-free that occurs in hcd when in_urb sent from pn533_usb_send_frame() is completed earlier than out_urb. Its callback frees the skb data in pn533_send_async_complete() that is used as a transfer buffer of out_urb. Wait before sending in_urb until the callback of out_urb is called. To modify the callback of out_urb alone, separate the complete function of out_urb and ack_urb. Found by a modified version of syzkaller. BUG: KASAN: use-after-free in dummy_timer Call Trace: memcpy (mm/kasan/shadow.c:65) dummy_perform_transfer (drivers/usb/gadget/udc/dummy_hcd.c:1352) transfer (drivers/usb/gadget/udc/dummy_hcd.c:1453) dummy_timer (drivers/usb/gadget/udc/dummy_hcd.c:1972) arch_static_branch (arch/x86/include/asm/jump_label.h:27) static_key_false (include/linux/jump_label.h:207) timer_expire_exit (include/trace/events/timer.h:127) call_timer_fn (kernel/time/timer.c:1475) expire_timers (kernel/time/timer.c:1519) __run_timers (kernel/time/timer.c:1790) run_timer_softirq (kernel/time/timer.c:1803) Fixes: c46ee38 ("NFC: pn533: add NXP pn533 nfc device driver") Signed-off-by: Minsuk Kang <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent 2ab6478 commit 9dab880

File tree

1 file changed

+41
-3
lines changed

1 file changed

+41
-3
lines changed

drivers/nfc/pn533/usb.c

Lines changed: 41 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -153,10 +153,17 @@ static int pn533_usb_send_ack(struct pn533 *dev, gfp_t flags)
153153
return usb_submit_urb(phy->ack_urb, flags);
154154
}
155155

156+
struct pn533_out_arg {
157+
struct pn533_usb_phy *phy;
158+
struct completion done;
159+
};
160+
156161
static int pn533_usb_send_frame(struct pn533 *dev,
157162
struct sk_buff *out)
158163
{
159164
struct pn533_usb_phy *phy = dev->phy;
165+
struct pn533_out_arg arg;
166+
void *cntx;
160167
int rc;
161168

162169
if (phy->priv == NULL)
@@ -168,10 +175,17 @@ static int pn533_usb_send_frame(struct pn533 *dev,
168175
print_hex_dump_debug("PN533 TX: ", DUMP_PREFIX_NONE, 16, 1,
169176
out->data, out->len, false);
170177

178+
init_completion(&arg.done);
179+
cntx = phy->out_urb->context;
180+
phy->out_urb->context = &arg;
181+
171182
rc = usb_submit_urb(phy->out_urb, GFP_KERNEL);
172183
if (rc)
173184
return rc;
174185

186+
wait_for_completion(&arg.done);
187+
phy->out_urb->context = cntx;
188+
175189
if (dev->protocol_type == PN533_PROTO_REQ_RESP) {
176190
/* request for response for sent packet directly */
177191
rc = pn533_submit_urb_for_response(phy, GFP_KERNEL);
@@ -408,7 +422,31 @@ static int pn533_acr122_poweron_rdr(struct pn533_usb_phy *phy)
408422
return arg.rc;
409423
}
410424

411-
static void pn533_send_complete(struct urb *urb)
425+
static void pn533_out_complete(struct urb *urb)
426+
{
427+
struct pn533_out_arg *arg = urb->context;
428+
struct pn533_usb_phy *phy = arg->phy;
429+
430+
switch (urb->status) {
431+
case 0:
432+
break; /* success */
433+
case -ECONNRESET:
434+
case -ENOENT:
435+
dev_dbg(&phy->udev->dev,
436+
"The urb has been stopped (status %d)\n",
437+
urb->status);
438+
break;
439+
case -ESHUTDOWN:
440+
default:
441+
nfc_err(&phy->udev->dev,
442+
"Urb failure (status %d)\n",
443+
urb->status);
444+
}
445+
446+
complete(&arg->done);
447+
}
448+
449+
static void pn533_ack_complete(struct urb *urb)
412450
{
413451
struct pn533_usb_phy *phy = urb->context;
414452

@@ -496,10 +534,10 @@ static int pn533_usb_probe(struct usb_interface *interface,
496534

497535
usb_fill_bulk_urb(phy->out_urb, phy->udev,
498536
usb_sndbulkpipe(phy->udev, out_endpoint),
499-
NULL, 0, pn533_send_complete, phy);
537+
NULL, 0, pn533_out_complete, phy);
500538
usb_fill_bulk_urb(phy->ack_urb, phy->udev,
501539
usb_sndbulkpipe(phy->udev, out_endpoint),
502-
NULL, 0, pn533_send_complete, phy);
540+
NULL, 0, pn533_ack_complete, phy);
503541

504542
switch (id->driver_info) {
505543
case PN533_DEVICE_STD:

0 commit comments

Comments
 (0)