media: usb: siano: Fix undefined behavior bug in struct smsusb_urb_t
Subsystems (3)
PATCH 1/1 media: usb: siano: Fix undefined behavior bug in struct smsusb_urb_t
struct urb is a flexible structure, which means that it contains a flexible-array member at the bottom. This could potentially lead to an overwrite of the object wq at run-time with the contents of urb.
Fix this by placing object urb at the end of struct smsusb_urb_t.
--- drivers/media/usb/siano/smsusb.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
drivers/media/usb/siano/smsusb.c +2 -2
@@ -40,10 +40,10 @@ struct smsusb_urb_t {struct smscore_buffer_t *cb;struct smsusb_device_t *dev; -struct urb urb; -/* For the bottom half */ struct work_struct wq; + +struct urb urb; };struct smsusb_device_t {
Signature · 1 line
2.34.1
Quoted 5 lines · Gustavo A. R. Silva
struct urbis a flexible structure, which means that it contains a flexible-array member at the bottom. This could potentially lead to an overwrite of the objectwqat run-time with the contents ofurb.Fix this by placing object
urbat the end ofstruct smsusb_urb_t.
Does this really change the situation? "struct smsusb_device_t" contains an array of "struct smsusb_urb_t", so it seems to be like you're just shifting the "VLA inside a non-final member of a struct" thing around so that there is one more layer of abstraction in between.
Comments on "struct urb" say:
* Isochronous URBs have a different data transfer model, in part because
* the quality of service is only "best effort". Callers provide specially
* allocated URBs, with number_of_packets worth of iso_frame_desc structures
* at the end.
and:
/* (in) ISO ONLY */
And it looks like smsusb only uses that URB as a bulk URB, so the flex array is unused and we can't have an overflow here?
If this is intended to make it possible to enable some kinda compiler warning, it might be worth talking to the USB folks to figure out the right approach here.
Quoted 28 lines
Fixes dd47fbd40e6e ("[media] smsusb: don't sleep while atomic")Signed-off-by Gustavo A. R. Silva <[email protected]>--- drivers/media/usb/siano/smsusb.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)drivers/media/usb/siano/smsusb.c +2
-3@@ -40,10 +40,10 @@ struct smsusb_urb_t {struct smscore_buffer_t *cb;struct smsusb_device_t *dev; -struct urb urb; -/* For the bottom half */ struct work_struct wq; + +struct urb urb; };struct smsusb_device_t { --2.34.1
Greg Kroah-Hartman
maintainerQuoted 47 lines · Jann Horn
Quoted 5 lines · Gustavo A. R. Silva
struct urbis a flexible structure, which means that it contains a flexible-array member at the bottom. This could potentially lead to an overwrite of the objectwqat run-time with the contents ofurb.Fix this by placing object
urbat the end ofstruct smsusb_urb_t.Does this really change the situation? "struct
smsusb_device_t" contains an array of "structsmsusb_urb_t", so it seems to be like you're just shifting the "VLA inside a non-final member of a struct" thing around so that there is one more layer of abstraction in between.Comments on "struct urb" say:
* Isochronous URBs have a different data transfer model, in part because
* the quality of service is only "best effort". Callers provide specially
* allocated URBs, withnumber_of_packetsworth ofiso_frame_descstructures
* at the end.and:
/* (in) ISO ONLY */
And it looks like smsusb only uses that URB as a bulk URB, so the flex array is unused and we can't have an overflow here?
If this is intended to make it possible to enable some kinda compiler warning, it might be worth talking to the USB folks to figure out the right approach here.
Quoted 15 lines
Fixes dd47fbd40e6e ("[media] smsusb: don't sleep while atomic")Signed-off-by Gustavo A. R. Silva <[email protected]>--- drivers/media/usb/siano/smsusb.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)drivers/media/usb/siano/smsusb.c +0
-0@@ -40,10 +40,10 @@ struct smsusb_urb_t {struct smscore_buffer_t *cb;struct smsusb_device_t *dev;
Quoted 7 lines
drivers/media/usb/siano/smsusb.c struct smsusb_urb_t { · line 47
Quoted 7 lines
drivers/media/usb/siano/smsusb.c +2
-2-struct urb urb; -/* For the bottom half */ struct work_struct wq; + +struct urb urb; };
Yeah, this is going to get messy. Ideally, just dynamically create the urb and change this to a "struct urb *urb;" instead.
thanks,
greg k-h
Quoted 11 lines · Greg Kroah-Hartman
Quoted 10 lines · Jann Horn
Quoted 5 lines · Gustavo A. R. Silva
struct urbis a flexible structure, which means that it contains a flexible-array member at the bottom. This could potentially lead to an overwrite of the objectwqat run-time with the contents ofurb.Fix this by placing object
urbat the end ofstruct smsusb_urb_t.Does this really change the situation? "struct
smsusb_device_t" contains an array of "structsmsusb_urb_t", so it seems to be like
Yeah. I noticed that too.
Probably what Greg suggests (dynamically create the urb) can fix this, too.
I haven't taken a deep dive into this particular case. So, let me go and figure something out.
Quoted 37 lines
Quoted 37 lines
you're just shifting the "VLA inside a non-final member of a struct" thing around so that there is one more layer of abstraction in between.
Comments on "struct urb" say:
* Isochronous URBs have a different data transfer model, in part because
* the quality of service is only "best effort". Callers provide specially
* allocated URBs, withnumber_of_packetsworth ofiso_frame_descstructures
* at the end.and:
/* (in) ISO ONLY */
And it looks like smsusb only uses that URB as a bulk URB, so the flex array is unused and we can't have an overflow here?
If this is intended to make it possible to enable some kinda compiler warning, it might be worth talking to the USB folks to figure out the right approach here.
Quoted 15 lines
Fixes dd47fbd40e6e ("[media] smsusb: don't sleep while atomic")Signed-off-by Gustavo A. R. Silva <[email protected]>--- drivers/media/usb/siano/smsusb.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)drivers/media/usb/siano/smsusb.c +0
-0@@ -40,10 +40,10 @@ struct smsusb_urb_t {struct smscore_buffer_t *cb;struct smsusb_device_t *dev;
Quoted 10 lines
Quoted 7 lines
drivers/media/usb/siano/smsusb.c struct smsusb_urb_t { · line 47
Quoted 7 lines
drivers/media/usb/siano/smsusb.c +2
-2-struct urb urb; -/* For the bottom half */ struct work_struct wq; + +struct urb urb; };Yeah, this is going to get messy. Ideally, just dynamically create the urb and change this to a "struct urb *urb;" instead.
Probably, yes.
Thanks
--
Gustavo
Quoted 9 lines · Gustavo A. R. Silva
struct urbis a flexible structure, which means that it contains a flexible-array member at the bottom. This could potentially lead to an overwrite of the objectwqat run-time with the contents ofurb.Fix this by placing object
urbat the end ofstruct smsusb_urb_t.Fixes dd47fbd40e6e ("[media] smsusb: don't sleep while atomic")Signed-off-by Gustavo A. R. Silva <[email protected]>
As Jann pointed out, it's unlikely there is a function bug here, but I still think it's right to make sure this is robust and clears the way for -Wflex-array-member-not-at-end.
Signature · 1 line
Kees Cook
Quoted 7 lines · Kees Cook
Quoted 6 lines · Gustavo A. R. Silva
struct urbis a flexible structure, which means that it contains a flexible-array member at the bottom. This could potentially lead to an overwrite of the objectwqat run-time with the contents ofurb.Fix this by placing object
urbat the end ofstruct smsusb_urb_t.
Quoted 7 lines
Quoted 3 lines
Fixes dd47fbd40e6e ("[media] smsusb: don't sleep while atomic")Signed-off-by Gustavo A. R. Silva <[email protected]>As Jann pointed out, it's unlikely there is a function bug here, but I still think it's right to make sure this is robust and clears the way for -Wflex-array-member-not-at-end.
But if this change makes the warning go away, that just means the warning is implemented badly, right?
Like, before we had:
struct urb {
...
struct usb_iso_packet_descriptor iso_frame_desc[];
};
struct smsusb_urb_t {
...
struct urb urb; // not last element
...
};
whereas afterwards we have:
struct urb {
...
struct usb_iso_packet_descriptor iso_frame_desc[];
};
struct smsusb_urb_t {
...
struct urb urb;
};
struct smsusb_device_t {
...
struct smsusb_urb_t surbs[MAX_URBS]; // array, and not last element
...
};
That's basically the same pattern! Except that the new version has one more layer of indirection and there's an array involved.
And you can't address that by moving struct members around because of the involvement of the array.