kernel: fix errno access for user mode

The errno "variable" is required to be thread-specific.
It gets defined to a macro which dereferences a pointer
returned by a kernel function.

In user mode, we cannot simply read/write the thread struct.
We do not have thread-local storage mechanism, so for now
use the lowest address of the thread stack to store this
value, since this is guaranteed to be read/writable by
a user thread.

The downside of this approach is potential stack corruption
if the stack pointer goes down this far but does not exceed
the location, since a fault won't be generated in this case.

Signed-off-by: Andrew Boie <andrew.p.boie@intel.com>
This commit is contained in:
Andrew Boie 2018-07-19 11:09:33 -07:00 committed by Andrew Boie
commit 7f4d006959
6 changed files with 69 additions and 5 deletions

View file

@ -13,6 +13,7 @@
*/
#include <kernel_structs.h>
#include <syscall_handler.h>
/*
* Define _k_neg_eagain for use in assembly files as errno.h is
@ -22,8 +23,20 @@
const int _k_neg_eagain = -EAGAIN;
#ifdef CONFIG_ERRNO
int *__errno(void)
#ifdef CONFIG_USERSPACE
int *_impl_z_errno(void)
{
/* Initialized to the lowest address in the stack so the thread can
* directly read/write it
*/
return _current->errno_location;
}
Z_SYSCALL_HANDLER0_SIMPLE(z_errno);
#else
int *_impl_z_errno(void)
{
return &_current->errno_var;
}
#endif
#endif /* CONFIG_USERSPACE */
#endif /* CONFIG_ERRNO */