Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Bounded flexible arrays: tag their element count #1409

Open
wants to merge 1 commit into
base: master
Choose a base branch
from

Conversation

seanm
Copy link
Contributor

@seanm seanm commented Dec 28, 2023

I took a stab at preparing for gcc/clang adding support for bounds checking of flexible arrays, see:

https://people.kernel.org/kees/bounded-flexible-arrays-in-c

And I think I found a small buffer overread in the process...

@mcuee mcuee added core Related to common codes Examples Examples labels Dec 29, 2023
@mcuee
Copy link
Member

mcuee commented Dec 29, 2023

Strange that umockdev_test failed in the CI for Linux.

libusb/libusb.h Outdated Show resolved Hide resolved
@seanm seanm mentioned this pull request Jan 2, 2024
@tormodvolden
Copy link
Contributor

Can we isolate the bug fix for 1.0.27 and take the rest afterwards?

@seanm
Copy link
Contributor Author

seanm commented Jan 4, 2024

Can we isolate the bug fix...

First I need someone to review the WIP and tell me if I'm even correct or not. :)

  1. have I correctly understood the size of these arrays?
  2. is there indeed a buffer overrun as I suspect?

...and take the rest afterwards

Sure, I can split them.

@tormodvolden
Copy link
Contributor

OK, so what you are saying is that if the device erroneously returns a string descriptor with an odd bLength, we would be reading a byte too much from the descriptor buffer, and if bLength=255 also beyond the buffer?

We are already issuing a warning on odd bLength, maybe we should just round bLength down to nearest even number before decoding the 16-bit characters? Well, maybe that's what your si_max is doing? :) Do we need all the size_of's? Is it even relevant what the storage size is, if we index them properly?

si and di are definitely source respectively destination index. di was used when reading from the source buffer because the latter is an array of 16-bit characters, as noted in a comment since it is a bit counter-intuitive. I guess in your version we wouldn't need both si and di.

@seanm
Copy link
Contributor Author

seanm commented Jan 4, 2024

OK, so what you are saying is that if the device erroneously returns a string descriptor with an odd bLength, we would be reading a byte too much from the descriptor buffer, and if bLength=255 also beyond the buffer?

Yes. It came about trying to figure out the count of usbi_string_descriptor.wData. Also, you can substitute 'maliciously' for 'erroneously'. :) In case it wasn't clear, the asserts in my WIP are triggered.

We are already issuing a warning on odd bLength

Correct. But it's just a warning and doesn't change the buffer read size.

maybe we should just round bLength down to nearest even number before decoding the 16-bit characters? Well, maybe that's what your si_max is doing? :)

Exactly.

Do we need all the size_of's? Is it even relevant what the storage size is, if we index them properly?

You mean int si_max = (str.desc.bLength - sizeof(uint8_t) - sizeof(uint8_t)) / sizeof(uint16_t);? Well, we could write int si_max = (str.desc.bLength - 2) / 2; if you prefer, but I thought the former was more explanatory, as it corresponds to the fields of the sturcture:

struct usbi_string_descriptor {
	uint8_t  bLength;
	uint8_t  bDescriptorType;
	uint16_t wData[LIBUSB_FLEXIBLE_ARRAY] LIBUSB_COUNTED_BY((bLength - 2) / 2);
} LIBUSB_PACKED;

Since compilers don't support it yet, I'm not sure how complicated the expressions within the 'counted_by' attribute can be...

si and di are definitely source respectively destination index.

Thanks for confirming.

di was used when reading from the source buffer because the latter is an array of 16-bit characters, as noted in a comment since it is a bit counter-intuitive.

Yeah. The source and destination buffers need not be the same size though, so I think it's much safer that they be individually indexed.

@seanm
Copy link
Contributor Author

seanm commented Jan 8, 2024

So assuming my analysis is correct here... I'll split this PR into 2 now...

@seanm
Copy link
Contributor Author

seanm commented Jan 9, 2024

...and take the rest afterwards

Sure, I can split them.

Done: #1432

@seanm seanm changed the title WIP: Bounded flexible arrays & buffer overread? Bounded flexible arrays: tag their element count Jan 9, 2024
@mcuee mcuee removed the Examples Examples label Jan 9, 2024
@tormodvolden
Copy link
Contributor

I will pick the LIBUSB_FLEXIBLE_ARRAY rename commit.

tormodvolden pushed a commit to tormodvolden/libusb that referenced this pull request Jan 9, 2024
This reflects the C99 terminology, instead of the old hack of using a
zero sized array.

Also adds the LIBUSB prefix to avoid namespace colisions, as this is
present in a public header.

References libusb#1409
tormodvolden added a commit to tormodvolden/libusb that referenced this pull request Jan 9, 2024
Thanks to Sean McBride for analysis.

References libusb#1409
@seanm
Copy link
Contributor Author

seanm commented Jan 16, 2024

Looks like clang master just got counted_by merged, so we'll soon be able to actually try this...

llvm/llvm-project@164f85db876e

tormodvolden pushed a commit that referenced this pull request Jan 19, 2024
This reflects the C99 terminology, instead of the old hack of using a
zero sized array.

Also adds the LIBUSB prefix to avoid namespace colisions, as this is
present in a public header.

References #1409
@seanm seanm force-pushed the bounded-flexible-arrays branch 2 times, most recently from 3c19ac3 to 28394f4 Compare January 21, 2024 04:06
@seanm
Copy link
Contributor Author

seanm commented Jan 21, 2024

Looks like clang master just got counted_by merged, so we'll soon be able to actually try this...

So I've tried it with clang, and it works except it doesn't allow even simple expressions, so things like LIBUSB_COUNTED_BY(bLength - 3) alas don't work...

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
core Related to common codes
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

4 participants