-
Notifications
You must be signed in to change notification settings - Fork 6.7k
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
llext: fix handling of unimplemented syscalls #79309
llext: fix handling of unimplemented syscalls #79309
Conversation
When building an LLEXT-enabled kernel, 62b19ef added weak aliases of all syscall implementation functions to a pointer to NULL, with the assumption that LLEXT would check the required symbols at link time and fail if any of them were found. This check, however, is ineffective in the current implementation: the actual address that is exported is the rather normal-looking location of the variable containing the NULL pointer. This defeats the NULL symbol validity checks in llext_link.c and causes the extension to crash at runtime by jumping to a location containing a few zeroes in read-only data memory. This commit makes sure the alias target is actually placed at address 0 using the llext-sections.ld linker fragment, so that undefined syscall implementations are exported as NULLs and as such properly flagged at link time. The test for this functionality is also updated to reflect the change. Signed-off-by: Luca Burelli <[email protected]>
* The syscalls test above verifies that custom syscalls defined by extensions | ||
* are properly exported. Since `ext_syscalls.h` declares ext_syscall_fail, we | ||
* know it is picked up by the syscall build machinery, but the implementation | ||
* for it is missing. Make sure the exported symbol for it is NULL. | ||
*/ | ||
ZTEST(llext, test_ext_syscall_fail) | ||
{ | ||
const void * const esf_fn = LLEXT_FIND_BUILTIN_SYM(z_impl_ext_syscall_fail); | ||
|
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.
asserting est_fn is not null should still be done here no?
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.
No, llext_find_sym
returns pointers to actual functions/data, so it makes sense for esf_fn
to be NULL.
As it is currently done in main
, and only in the case of unimplemented syscalls, the pointer returned by llext_find_sym
points to a pointer to NULL (which is what was being tested here). But I assume this was a mistake, since:
- the stored address is not NULL, so LLEXT happily links the code
- at runtime, actual calls to an unimplemented
z_impl_foo()
jump at the location of avoid *z_impl_foo = NULL
, and the CPU fetches 4 or 8 zeroes as instructions. 💣
With this PR, the stored address is NULL, find_sym
returns that NULL (not "no symbol", but "that symbol is defined and its value is NULL"), and the link process fails (as it should, there is no implementation for that symbol after all).
You folks may want to bring |
When building an LLEXT-enabled kernel, 62b19ef added weak aliases of all
z_impl_
* functions to a pointer to NULL, with the assumption that LLEXT would check the required symbols at link time and fail if any of them were found.This check, however, is ineffective in the current implementation: the actual address that is exported is the rather normal-looking location of the variable containing the NULL pointer. This defeats the NULL symbol validity checks in
llext_link.c
and causes the extension to crash at runtime by jumping to a location containing a few zeroes in read-only data memory.This PR makes sure the alias target is actually placed at address 0 using the
llext-sections.ld
linker fragment, so that undefined syscall implementations are exported as NULLs and as such properly flagged at link time.The test for this functionality is also updated to reflect the change.