drivers/usb/serial/keyspan.c | 2 ++ 1 file changed, 2 insertions(+)
usa49_glocont_callback() obtains the private data from all
ports of a serial device using usb_get_serial_port_data().
This can happen during keyspan_port_remove() which frees
the private data which can cause UAF.
Fix this by calling usb_set_serial_port_data(port, NULL)
inside keyspan_port_remove() right before kfree() of
private data. This in turn allows "if (!p_priv) continue;"
condition within usa49_glocont_callback() to execute
properly.
Reported-by: syzbot+e5e28c3e953b2eebb16e@syzkaller.appspotmail.com
Signed-off-by: Rafael Alejandro Diaz Cruz <rafad900@gmail.com>
---
drivers/usb/serial/keyspan.c | 2 ++
1 file changed, 2 insertions(+)
diff --git a/drivers/usb/serial/keyspan.c b/drivers/usb/serial/keyspan.c
index 4d3746c7a94e..0e08acb99970 100644
--- a/drivers/usb/serial/keyspan.c
+++ b/drivers/usb/serial/keyspan.c
@@ -2997,6 +2997,8 @@ static void keyspan_port_remove(struct usb_serial_port *port)
for (i = 0; i < ARRAY_SIZE(p_priv->in_buffer); ++i)
kfree(p_priv->in_buffer[i]);
+ usb_set_serial_port_data(port, NULL);
+
kfree(p_priv);
}
--
2.43.0
On Thu, Aug 20, 2026 at 12:06:21AM -0700, Rafael Alejandro Diaz Cruz wrote: > usa49_glocont_callback() obtains the private data from all > ports of a serial device using usb_get_serial_port_data(). > This can happen during keyspan_port_remove() which frees > the private data which can cause UAF. > > Fix this by calling usb_set_serial_port_data(port, NULL) > inside keyspan_port_remove() right before kfree() of > private data. This in turn allows "if (!p_priv) continue;" > condition within usa49_glocont_callback() to execute > properly. > > Reported-by: syzbot+e5e28c3e953b2eebb16e@syzkaller.appspotmail.com Please include a Link to the report as well (and a Fixes tag). > Signed-off-by: Rafael Alejandro Diaz Cruz <rafad900@gmail.com> > --- > drivers/usb/serial/keyspan.c | 2 ++ > 1 file changed, 2 insertions(+) > > diff --git a/drivers/usb/serial/keyspan.c b/drivers/usb/serial/keyspan.c > index 4d3746c7a94e..0e08acb99970 100644 > --- a/drivers/usb/serial/keyspan.c > +++ b/drivers/usb/serial/keyspan.c > @@ -2997,6 +2997,8 @@ static void keyspan_port_remove(struct usb_serial_port *port) > for (i = 0; i < ARRAY_SIZE(p_priv->in_buffer); ++i) > kfree(p_priv->in_buffer[i]); > > + usb_set_serial_port_data(port, NULL); > + This doesn't work as nothing prevents the completion handler from loading the pointer just before you set it to NULL here. > kfree(p_priv); > } The UAF syzbot reported is a symptom of a general problem with the disconnect handling. I've just sent a fix to address this here: https://lore.kernel.org/all/20260820145402.434447-2-johan@kernel.org/ Johan
© 2016 - 2026 Red Hat, Inc.