-
Notifications
You must be signed in to change notification settings - Fork 13.4k
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 proposal for hardfault with batt_smbus module #15789
Conversation
…n batt_smbus module by writing beyond buffer end due to device returning longer byte_count than requested/expected)
Co-authored-by: Daniel Agar <daniel@agar.ca>
@flochir Thanks for notice. I have also added commit to fix compilation issue on some boards (airmind_mindpx-v2_default for example). |
I'm not seeing the difference? What could be different is the linking dependencies, which often aren't 100% correct because you typically get common dependencies (like mathlib) included by something else. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
But why did you leave cpy_len in?
Can you explain? what is cpy_len? @jimdgit |
The code was changed, so it is not longer an issue. |
If you're referring to math::min those are all static constexpr, so it ends up being the same thing, but with a bit of type safety and easier to read. https://github.com/PX4/Firmware/blob/0dc8bb9c864dc49bbbe255ea0177480b46522d7d/src/lib/mathlib/math/Limits.hpp#L54-L57 |
I see ok great! |
Co-authored-by: Beat Küng <beat-kueng@gmx.net>
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks
@BazookaJoe1900 So there really is no way to request a specific amount of bytes from the client. The slave will send the amount of bytes associated to that command. I2C::transfer() will limit its amount of read bytes to recv_len, but the byte_count originates directly from the device and will still be the full length of data available. To respect that on a lower level the SMBus driver may need to overwrite I2C::transfer(). Btw. there may be another issue to check. What happens if recv_len passed to I2C::transfer() is longer than the amount of data the SMBUS slave wants to transmit? Timeouts? Maybe there's some error or optimization potential here. |
I 100% agree. We should not be messing with that.
That needs to be handled elsewhere and so far there is no evidence to that effect. We don't want to break other things. |
It's directly subject to the SMBus protocol, so I don't see where else it could be handled. I'll see if I can run some tests against my setup. |
@flochir thanks for the notes. |
It happens for me when I read DeviceName (SBS Cmd 0x21) from a smart battery with a TI chipset.
And this is what I get: The call returns the correct value for device name. |
It's a custom BMS for Li-Ion we developed (also not based on BQ40Z50) so it doesn't return the default device string. I get the expected feedback from the device and it's working fine. Just hit that bug while working on it and wanted to get it discussed/cleared. |
A copy should always be length checked, but really on the surface it sounds like you only expected 8 bytes when you should have expected 13. No? |
In my case I only need the first 8 bytes. Of course that's how I hit this issue. It could happen with other batteries/chipsets anytime, though, even with a larger buffer. |
Side note: I did a quick test and requested a larger amount of data than returned through byte_count. Everything's stll working, so at least there don't seem to be any serious immediate problems. |
* Added buffer length check to SMBus::block_read (triggered hardfault in batt_smbus module by writing beyond buffer end due to device returning longer byte_count than requested/expected) Co-authored-by: Florian Olbrich <florian.olbrich@scarabot.de> Co-authored-by: Daniel Agar <daniel@agar.ca> Co-authored-by: BazookaJoe1900 <BazookaJoe1900@gmail.com> Co-authored-by: Beat Küng <beat-kueng@gmx.net>
Added buffer length check to SMBus::block_read (triggered hardfault in batt_smbus module by writing beyond buffer end due to device returning longer byte_count than requested/expected)
I ran into a hardfault when reading Smart Battery data with SMBus::block_read.
The fault is triggered in line 126 of
/Firmware/src/lib/drivers/smbus/SMBus.cpp
when memcpy writes beyond the end of the buffer “data” provided by the caller.
In my case the smbus device returned a byte count larger than the requested length (13 instead of 8 bytes).
I fixed this by adding a check for the length limit before the memcpy call, see
I experienced hardfaults working on a SMBUS battery driver based on batt_smbus. They werde triggered by the device returning a bigger byte_count value than was requested (13 bytes in byte_count versus a buffer length of 8 in my case), which lead to memcpy(data, &rx_data[4], byte_count); writing beyond the limit of the provided buffer.
As a fix I added a buffer length check to SMBus::block_read to force the maximum received data length to the length of the buffer provided by the caller.
I experienced that issue with a 3DR Solo battery among others.