riscv-software-src / riscv-pk

RISC-V Proxy Kernel
Other
581 stars 307 forks source link

Double conversion of struct stat #221

Closed zeldin closed 3 years ago

zeldin commented 3 years ago

When responding to the syscall SYS_stat (or related variants), pk calls the function copy_stat() to convert the struct frontend_stat provided by spike into a regular struct stat. However, after returning from the syscall, newlib calls the function _conv_stat(), which also converts to a regular struct stat, this time from a struct kernel_stat (which looks identical to the struct frontend_stat). So the stat struct gets converted twice, with a garbage result.

I don't know whether it's the pk or newlib which should stop converting, I guess pk should use the same output format as the linux kernel does? (Edit: The riscv native linux kernel, I mean.)

aswaterman commented 3 years ago

Newlib programs that used struct stat previously worked, so this sounds like a newlib regression. I believe pk already matches the linux kernel in this regard, given that glibc programs once ran upon it (before they started needing more syscalls than we currently provide).

zeldin commented 3 years ago

Hm, it could be that glibc and newlib have different definitions of struct stat; the format of the data output by pk will depend on that definition, and thus also on which set of include files you compile pk against. Which seems wrong in itself, since the output of the pk should not be dependent on which libc the application is using.

The newlib code doesn't seem to have been changed since Dec 26, 2017...

aswaterman commented 3 years ago

Well, pk is supposed to adhere to the Linux ABI, so if glibc programs run correctly, then pk is probably correct.

zeldin commented 3 years ago

I tested just now. It does not work with a glibc program either.

I think it's like this:

So based on this I believe the correct thing to do is to replace the call to copy_stat in pk with a call to memcpy. I have verified that this works with both glibc and newlib programs. And the behaviour of memcpy is not dependant on which set of include files you compile pk with.

I'll create a pull request with this change.

aswaterman commented 3 years ago

But that means that if you compile pk with newlib headers, it doesn't comply to the Linux ABI.

I think the right solution is to not depend on the headers and to conform to the Linux ABI.

zeldin commented 3 years ago

Yup. If you compile the current pk sources with newlib, it does not comply with the Linux ABI. If we change it to use memcpy instead of copy_stat, then it complies to the Linux ABI and does not depend on headers.

aswaterman commented 3 years ago

OK, cool.

zeldin commented 3 years ago

(Ostensibly, the frontend_stat struct could be different from the kernel format, and warrant a different copy_stat variant, but I don't think there is any benefit in doing that. The current frontend_stat looks specifically crafted to match the kernel one.)