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

llext: fix handling of unimplemented syscalls #79309

Conversation

pillo79
Copy link
Collaborator

@pillo79 pillo79 commented Oct 2, 2024

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.

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);

Copy link
Collaborator

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?

Copy link
Collaborator Author

@pillo79 pillo79 Oct 2, 2024

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:

  1. the stored address is not NULL, so LLEXT happily links the code
  2. at runtime, actual calls to an unimplemented z_impl_foo() jump at the location of a void *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).

@fabiobaltieri fabiobaltieri assigned teburd and unassigned nashif Oct 8, 2024
@fabiobaltieri
Copy link
Member

You folks may want to bring include/zephyr/linker/llext-sections.ld under the area explicitly

@carlescufi carlescufi merged commit 11c350e into zephyrproject-rtos:main Oct 8, 2024
41 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants