Open spoore1 opened 2 years ago
Attaching the umockdev files for both examples above.
==1841== Address 0x1ffeffee74 is on thread 1's stack
==1841== in frame #4, created by fido_hid_open (hid_linux.c:241)
Well, yes and no. It is either a libfido bug or a false positive. i.e. the issue is that we are sending the hdr
structure over to the parent process for emulation, and this reads uninitialized memory.
If that memory doesn't need to be initialized (for the kernel), then this can be safely ignored. Thing is here, that umockdev always does a read, even if a write would be sufficient. As such, false positives like this are likely to happen.
EDIT: Said differently, I see the following possibilities:
= {0,}
to initialize the stack structure.One could improve it in umockdev, but not easily. i.e. it would require adding API to only do partial memory reads/writes making the emulation layer more complicated. I don't expect that this happens often enough to make it worthwhile, i.e. it is easier to just deal with the false positive in the test.
OK, talked a bit too early. So, the above is true for fido2-token
and the valgrind error has nothing to do with the stack smash error in the python code (i.e. false positive). The problem is the following code combined with umockdev's emulation:
# Read report descriptor
buf = array("B", [0] * 4)
fcntl.ioctl(f, HIDIOCGRDESCSIZE, buf, True)
size = struct.unpack("<I", buf)[0]
buf += array("B", [0] * size)
fcntl.ioctl(f, HIDIOCGRDESC, buf, True)
i.e. it first reads the size into the header of the structure. Then it allocates enough memory and fetches it. The kernel will only write min(size in struct, 4kiB)
of the memory. umockdev however writes the whole 4kiB + 4B
(even overwriting the size).
This can be fixed in umockdev by adding a custom implementation for the IOCTL that will only update the correct memory areas. It isn't overly hard, but it is a bit of a pain (unless one accepts reading/writing the full 4kiB + 4B
but not actually modifying the tail, which wouldn't be thread safe).
It isn't overly hard, but it is a bit of a pain
I should have added what this means:
handle_ioctl
to resolve only the amount of memory needed. This is a bit of a pain, as it means first resolving the first 4 bytes, then doing the same for the correct length.IoctlData.resolve
to update the length of the data object and reload the rest of the data (so the data object remains valid for the pointer).I_VARLEN_STRUCT_IN
, though the code is not compiled currently.Note that in 2. and 3. we duplicate the size detection logic in umockdev-ioctl.vala
and ioctl_tree.c
. Not elegant, but everything else would require more code refactorings.
I'm trying to record some basic interactions with a Yubikey for FIDO2 token testing. To do this, I'm using the basic "ykman" command and record it with umockdev. When I run the recording through, I get an error about stack smashing:
And after help from @ueno I see this from valgrand: