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

Fix additional bad descriptor read issues #1340

Open
wants to merge 3 commits into
base: master
Choose a base branch
from

Conversation

addisoncrump
Copy link
Contributor

Extends #1308.

This fixes a few additional potential memory issues associated with bad descriptor reads. I will annotate the commit below.

@@ -212,7 +216,19 @@ static int parse_interface(libusb_context *ctx,
usb_interface->altsetting = altsetting;

ifp = altsetting + usb_interface->num_altsetting;

usb_interface->num_altsetting++;
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Moving this above ensures that the altsetting is cleared in the case of an error.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

All comments should be /* */.

Comment on lines +229 to +232
uint8_t stashedNumEndpoints = ifp->bNumEndpoints;
ifp->bNumEndpoints = 0;
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Stashing this ensures that we clear only the endpoints that are actually instantiated.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Line 228 says: stash /in case/ we have to clear it. Then line 231 goes on to clear it. This is confusing.

bNumEndpoints will represent the number of initialised endpoints

Can't we call it e.g. numInitialisedEndpoints then, instead of "stashedNumEndpoints"?

if (!endpoint) {
r = LIBUSB_ERROR_NO_MEM;
goto err;
}

ifp->endpoint = endpoint;
for (i = 0; i < ifp->bNumEndpoints; i++) {
r = parse_endpoint(ctx, endpoint + i, buffer, size);
for (; ifp->bNumEndpoints < stashedNumEndpoints; ifp->bNumEndpoints++) {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Making this explicit with the loop ensures that the endpoints are cleared in the case of an error.

uint8_t stashedNumInterfaces = config->bNumInterfaces;
config->bNumInterfaces = 0;

for (; config->bNumInterfaces < stashedNumInterfaces; config->bNumInterfaces++) {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same as previous: ensures that the interfaces are cleared in the case of an error.

@@ -1218,7 +1229,7 @@ static int parse_iad_array(struct libusb_context *ctx,

// First pass: Iterate through desc list, count number of IADs
iad_array->length = 0;
while (consumed < size) {
while (consumed + 1 < size) {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Prevents off-by-one heap overflow in the case that the amount consumed less than size, but by less than the descriptor we're about to read.

@@ -1242,7 +1253,7 @@ static int parse_iad_array(struct libusb_context *ctx,
// Second pass: Iterate through desc list, fill IAD structures
consumed = 0;
i = 0;
while (consumed < size) {
while (consumed + 9 < size) {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Prevents nine byte eight heap overflow in the case that the amount consumed less than size, but by less than the descriptor we're about to read.

@mcuee mcuee added the core Related to common codes label Nov 18, 2023
@hjelmn
Copy link
Member

hjelmn commented Dec 8, 2023

Instead of github conversations those would better be added as comments in the code. No one is going to come back to this PR to figure out why the code is structured the way it is.

@addisoncrump
Copy link
Contributor Author

Fair point, it hadn't been commented in my previous PR so I just assumed it wasn't necessary here. Will update and add a comment to my previous PR section as well.

@tormodvolden
Copy link
Contributor

Well, in the previous PR https://github.com/libusb/libusb/pull/1308/files the changed code is quite self-explanatory. This is not always the case here IMO. If there are e.g. subtle ordering requirements it is good to spell that out, since someone else might come later and change the code without thinking about that.

Am I the only one who think we could find better names than stashed_xxx multiple times? I understand it is for saving or backing up a value, but maybe e.g. the reason for doing so could be reflected in the name? Anyway it is just a matter of taste, and sometimes i is the best loop counter name.

@addisoncrump
Copy link
Contributor Author

Okay, comments added. Apologies for the delay.

@addisoncrump
Copy link
Contributor Author

This macOS test seems to be flaky... It did not fail in the previous CI run, and all that was changed in the last commit was some formatting items.

@tormodvolden
Copy link
Contributor

Yes, nothing to worry about. It is some kind of race condition that kicks in sometimes, and maybe limited to virtual machines.

@seanm
Copy link
Contributor

seanm commented May 28, 2024

@tormodvolden Looks like some of this will overlap/conflict with #1460. I propose getting 1460 merged first, then rebase this one.

@tormodvolden
Copy link
Contributor

Yes, this one needs some fixing up now that parse_descriptor() is gone.

@seanm
Copy link
Contributor

seanm commented May 29, 2024

The buffer overruns this PR fixes are hopefully already fixed by #1460

@addisoncrump
Copy link
Contributor Author

Sadly the code I wrote to test these cases is now wildly out of date. I will need to update it sometime after next week.

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

5 participants