Commit graph

29 commits

Author SHA1 Message Date
Andrew Boie
818a96d3af userspace: assign thread IDs at build time
Kernel object metadata had an extra data field added recently to
store bounds for stack objects. Use this data field to assign
IDs to thread objects at build time. This has numerous advantages:

* Threads can be granted permissions on kernel objects before the
  thread is initialized. Previously, it was necessary to call
  k_thread_create() with a K_FOREVER delay, assign permissions, then
  start the thread. Permissions are still completely cleared when
  a thread exits.

* No need for runtime logic to manage thread IDs

* Build error if CONFIG_MAX_THREAD_BYTES is set too low

Signed-off-by: Andrew Boie <andrew.p.boie@intel.com>
2017-11-03 11:29:23 -07:00
Leandro Pereira
da9b0ddf5b drivers: Rename random to entropy
This should clear up some of the confusion with random number
generators and drivers that obtain entropy from the hardware.  Also,
many hardware number generators have limited bandwidth, so it's natural
for their output to be only used for seeding a random number generator.

Signed-off-by: Leandro Pereira <leandro.pereira@intel.com>
2017-11-01 08:26:29 -04:00
Andrew Boie
e5b3918a9f userspace: remove some driver object types
Use-cases for these  subsystems appear to be limited to board/SOC
code, network stacks, or other drivers, no need to expose to
userspace at this time. If we change our minds it's easy enough
to add them back.

Signed-off-by: Andrew Boie <andrew.p.boie@intel.com>
2017-10-30 13:20:19 -07:00
Andrew Boie
bca15da650 userspace: treat thread stacks as kernel objects
We need to track permission on stack memory regions like we do
with other kernel objects. We want stacks to live in a memory
area that is outside the scope of memory domain permission
management. We need to be able track what stacks are in use,
and what stacks may be used by user threads trying to call
k_thread_create().

Some special handling is needed because thread stacks appear as
variously-sized arrays of struct _k_thread_stack_element which is
just a char. We need the entire array to be considered an object,
but also properly handle arrays of stacks.

Validation of stacks also requires that the bounds of the stack
are not exceeded. Various approaches were considered. Storing
the size in some header region of the stack itself would not allow
the stack to live in 'noinit'. Having a stack object be a data
structure that points to the stack buffer would confound our
current APIs for declaring stacks as arrays or struct members.
In the end, the struct _k_object was extended to store this size.

Signed-off-by: Andrew Boie <andrew.p.boie@intel.com>
2017-10-16 19:02:00 -07:00
Andrew Boie
a2b40ecfaf userspace handlers: finer control of init state
We also need macros to assert that an object must be in an
uninitialized state. This will be used for validating thread
and stack objects to k_thread_create(), which must not be already
in use.

Signed-off-by: Andrew Boie <andrew.p.boie@intel.com>
2017-10-16 19:02:00 -07:00
Andrew Boie
2574219d8b userspace: simplify thread_id checks
Signed-off-by: Andrew Boie <andrew.p.boie@intel.com>
2017-10-16 16:16:28 -07:00
Andrew Boie
41bab6e360 userspace: restrict k_object_access_all_grant()
This is too powerful for user mode, the other access APIs
require explicit permissions on the threads that are being
granted access.

The API is no longer exposed as a system call and hence will
only be usable by supervisor threads.

Signed-off-by: Andrew Boie <andrew.p.boie@intel.com>
2017-10-16 16:16:28 -07:00
Andrew Boie
04caa679c9 userspace: allow thread IDs to be re-used
It's currently too easy to run out of thread IDs as they
are never re-used on thread exit.

Now the kernel maintains a bitfield of in-use thread IDs,
updated on thread creation and termination. When a thread
exits, the permission bitfield for all kernel objects is
updated to revoke access for that retired thread ID, so that
a new thread re-using that ID will not gain access to objects
that it should not have.

Because of these runtime updates, setting the permission
bitmap for an object to all ones for a "public" object doesn't
work properly any more; a flag is now set for this instead.

Signed-off-by: Andrew Boie <andrew.p.boie@intel.com>
2017-10-16 16:16:28 -07:00
Andrew Boie
9bd5e76b47 userspace: don't adjust perms on object init
We got rid of letting uninitialized objects being a free-for-all
and permission to do stuff on an object is now done explicitly.

If a user thread is initializing an object, they will already have
permission on it.

If a supervisor thread is initializing an object, that supervisor
thread may or may not want that object added to its set of object
permissions for purposes of permission inheritance or dropping to
user mode.

Resetting all permissions on initialization makes objects much
harder to share and re-use; for example other threads will lose
access if some thread re-inits a shared semaphore.

For all these reasons, just keep the permissions as they are when
an object is initialized.

We will need some policy for permission reset when objects are
requested and released from pools, but the pool implementation
should take care of that.

Signed-off-by: Andrew Boie <andrew.p.boie@intel.com>
2017-10-16 16:16:28 -07:00
Andrew Boie
4a9a4240c6 userspace: add _k_object_uninit()
API to assist with re-using objects, such as terminated threads or
kernel objects returned to a pool.

Signed-off-by: Andrew Boie <andrew.p.boie@intel.com>
2017-10-16 16:16:28 -07:00
Andrew Boie
a89bf01192 kernel: add k_object_access_revoke() system call
Does the opposite of k_object_access_grant(); the provided thread will
lose access to that kernel object.

If invoked from userspace the caller must hace sufficient access
to that object and permission on the thread being revoked access.

Fix documentation for k_object_access_grant() API to reflect that
permission on the thread parameter is needed as well.

Signed-off-by: Andrew Boie <andrew.p.boie@intel.com>
2017-10-13 15:08:40 -07:00
Andrew Boie
47f8fd1d4d kernel: add K_INHERIT_PERMS flag
By default, threads are created only having access to their own thread
object and nothing else. This new flag to k_thread_create() gives the
thread access to all objects that the parent had at the time it was
created, with the exception of the parent thread itself.

Signed-off-by: Andrew Boie <andrew.p.boie@intel.com>
2017-10-13 12:17:13 -07:00
Andrew Boie
7e3d3d782f kernel: userspace.c code cleanup
- Dumping error messages split from _k_object_validate(), to avoid spam
  in test cases that are expected to have failure result.

- _k_object_find() prototype moved to syscall_handler.h

- Clean up k_object_access() implementation to avoid double object
  lookup and use single validation function

- Added comments, minor whitespace changes

Signed-off-by: Andrew Boie <andrew.p.boie@intel.com>
2017-10-12 16:26:28 -05:00
Andrew Boie
3a0f6848e4 kernel: policy change for uninitailized objects
The old policy was that objects that are not marked as initialized may
be claimed by any thread, user or kernel.

This has some undesirable implications:
- Kernel objects that were initailized at build time via some
  _<object name>_INITIALIZER macro, not intended for userspace to ever
  use, could be 'stolen' if their memory addresses were figured out and
  _k_object_init() was never called on them.
- In general, a malicious thread could initialize all unclaimed objects
  it could find, resulting in denial of service for the threads that
  these objects were intended for.

Now, performing any operation in user mode on a kernel object,
initialized or not, required that the calling user thread have
permission on it. Such permission would have to be explicitly granted or
inherited from a supervisor thread, as with this change only supervisor
thread will be able to claim uninitialized objects in this way.

If an uninitialized kernel object has permissions granted to multiple
threads, whatever thread actually initializes the object will reset all
permission bits to zero and grant only the calling thread access to that
object.

In other words, granting access to an uninitialized object to several
threads means that "whichever of these threads (or any kernel thread)
who actually initializes this object will obtain exclusive access to
that object, which it then may grant to other threads as it sees fit."

Signed-off-by: Andrew Boie <andrew.p.boie@intel.com>
2017-10-10 09:26:29 -07:00
Andrew Boie
1d483bb4a3 kernel: provide more info on object perm checks
We now show the caller's thread ID and dump out the permissions array
for the object that failed the check.

Signed-off-by: Andrew Boie <andrew.p.boie@intel.com>
2017-10-09 08:42:45 -07:00
Andrew Boie
c74983e8b4 kernel: remove some kernel objects from tracking
These are removed as the APIs that use them are not suitable for
exporting to userspace.

- Kernel workqueues run in supervisor mode, so it would not be
appropriate to allow user threads to submit work to them. A future
enhancement may extend or introduce parallel API where the workqueue
threads may run in user mode (or leave as an exercise to the user).

- Kernel slabs store private bookkeeping data inside the
user-accessible slab buffers themselves. Alternate APIs are planned
here for managing slabs of kernel objects, implemented within the
runtime library and not the kernel.

Signed-off-by: Andrew Boie <andrew.p.boie@intel.com>
2017-10-07 10:45:15 -07:00
Andrew Boie
743e4686a0 kernel: add syscalls for k_object_access APIs
These modify kernel object metadata and are intended to be callable from
user threads, need a privilege elevation for these to work.

Signed-off-by: Andrew Boie <andrew.p.boie@intel.com>
2017-10-05 12:53:41 -04:00
Andrew Boie
3b5ae804ad kernel: add k_object_access_all_grant() API
This is a helper API for objects that are intended to be globally
accessible.

Signed-off-by: Andrew Boie <andrew.p.boie@intel.com>
2017-10-05 12:53:41 -04:00
Andrew Boie
217017c924 kernel: rename k_object_grant_access()
Zephyr naming convention is to have the verb last.

Signed-off-by: Andrew Boie <andrew.p.boie@intel.com>
2017-10-05 12:53:41 -04:00
Andrew Boie
5bd891d3b6 gen_kobject_list.py: device driver support
Device drivers need to be treated like other kernel objects, with
thread-level permissions and validation of struct device pointers passed
in from userspace when making API calls.

However it's not sufficient to identify an object as a driver, we need
to know what subsystem it belongs to (if any) so that userspace cannot,
for example, make Ethernet driver API calls using a UART driver object.

Upon encountering a variable representing a device struct, we look at
the value of its driver_api member. If that corresponds to an instance
of a driver API struct belonging to a known subsystem, the proper
K_OBJ_DRIVER_* enumeration type will be associated with this device in
the generated gperf table.

If there is no API struct or it doesn't correspond to a known subsystem,
the device is omitted from the table; it's presumably used internally
by the kernel or is a singleton with specific APIs for it that do not
take a struct device parameter.

The list of kobjects and subsystems in the script is simplified since
the enumeration type name is strongly derived from the name of the data
structure.

A device object is marked as initialized after its init function has
been run at boot.

Signed-off-by: Andrew Boie <andrew.p.boie@intel.com>
2017-09-29 13:25:58 -07:00
Andrew Boie
fa94ee7460 syscalls: greatly simplify system call declaration
To define a system call, it's now sufficient to simply tag the inline
prototype with "__syscall" or "__syscall_inline" and include a special
generated header at the end of the header file.

The system call dispatch table and enumeration of system call IDs is now
automatically generated.

Signed-off-by: Andrew Boie <andrew.p.boie@intel.com>
2017-09-29 13:02:20 -07:00
Andrew Boie
fc273c0b23 kernel: convert k_sem APIs to system calls
Signed-off-by: Andrew Boie <andrew.p.boie@intel.com>
2017-09-28 08:56:20 -07:00
Andrew Boie
13ca6fe284 syscalls: reorganize headers
- syscall.h now contains those APIs needed to support invoking calls
  from user code. Some stuff moved out of main kernel.h.
- syscall_handler.h now contains directives useful for implementing
  system call handler functions. This header is not pulled in by
  kernel.h and is intended to be used by C files implementing kernel
  system calls and driver subsystem APIs.
- syscall_list.h now contains the #defines for system call IDs. This
  list is expected to grow quite large so it is put in its own header.
  This is now an enumerated type instead of defines to make things
  easier as we introduce system calls over the new few months. In the
  fullness of time when we desire to have a fixed userspace/kernel ABI,
  this can always be converted to defines.

Some new code added:

- _SYSCALL_MEMORY() macro added to check memory regions passed up from
  userspace in handler functions
- _syscall_invoke{7...10}() inline functions declare for invoking system
  calls with more than 6 arguments. 10 was chosen as the limit as that
  corresponds to the largest arg list we currently have
  which is for k_thread_create()

Other changes

- auto-generated K_SYSCALL_DECLARE* macros documented
- _k_syscall_table in userspace.c is not a placeholder. There's no
  strong need to generate it and doing so would require the introduction
  of a third build phase.

Signed-off-by: Andrew Boie <andrew.p.boie@intel.com>
2017-09-28 08:56:20 -07:00
Andrew Boie
1956f09590 kernel: allow up to 6 arguments for system calls
A quick look at "man syscall" shows that in Linux, all architectures
support at least 6 argument system calls, with a few supporting 7. We
can at least do 6 in Zephyr.

x86 port modified to use EBP register to carry the 6th system call
argument.

Signed-off-by: Andrew Boie <andrew.p.boie@intel.com>
2017-09-20 09:18:59 -07:00
Andrew Boie
a23c245a9a userspace: flesh out internal syscall interface
* Instead of a common system call entry function, we instead create a
table mapping system call ids to handler skeleton functions which are
invoked directly by the architecture code which receives the system
call.

* system call handler prototype specified. All but the most trivial
system calls will implement one of these. They validate all the
arguments, including verifying kernel/device object pointers, ensuring
that the calling thread has appropriate access to any memory buffers
passed in, and performing other parameter checks that the base system
call implementation does not check, or only checks with __ASSERT().

It's only possible to install a system call implementation directly
inside this table if the implementation has a return value and requires
no validation of any of its arguments.

A sample handler implementation for k_mutex_unlock() might look like:

u32_t _syscall_k_mutex_unlock(u32_t mutex_arg, u32_t arg2, u32_t arg3,
                              u32_t arg4, u32_t arg5, void *ssf)
{
        struct k_mutex *mutex = (struct k_mutex *)mutex_arg;
        _SYSCALL_ARG1;

        _SYSCALL_IS_OBJ(mutex, K_OBJ_MUTEX, 0,  ssf);
        _SYSCALL_VERIFY(mutex->lock_count > 0, ssf);
        _SYSCALL_VERIFY(mutex->owner == _current, ssf);

        k_mutex_unlock(mutex);

        return 0;
}

* the x86 port modified to work with the system call table instead of
calling a common handler function. fixed an issue where registers being
changed could confuse the compiler has been fixed; all registers, even
ones used for parameters, must be preserved across the system call.

* a new arch API for producing a kernel oops when validating system call
arguments added. The debug information reported will be from the system
call site and not inside the handler function.

Signed-off-by: Andrew Boie <andrew.p.boie@intel.com>
2017-09-15 13:44:45 -07:00
Andrew Boie
2acfcd6b05 userspace: add thread-level permission tracking
Now creating a thread will assign it a unique, monotonically increasing
id which is used to reference the permission bitfield in the kernel
object metadata.

Stub functions in userspace.c now implemented.

_new_thread is now wrapped in a common function with pre- and post-
architecture thread initialization tasks.

Signed-off-by: Andrew Boie <andrew.p.boie@intel.com>
2017-09-12 12:46:36 -07:00
Andrew Boie
5cfa5dc8db kernel: add K_USER flag and _is_thread_user()
Indicates that the thread is configured to run in user mode.
Delete stub function in userspace.c

Signed-off-by: Andrew Boie <andrew.p.boie@intel.com>
2017-09-12 12:46:36 -07:00
Andrew Boie
f564986d2f kernel: add _k_syscall_entry stub
This is the kernel-side landing site for system calls. It's currently
just a stub.

Signed-off-by: Andrew Boie <andrew.p.boie@intel.com>
2017-09-12 12:46:36 -07:00
Andrew Boie
945af95f42 kernel: introduce object validation mechanism
All system calls made from userspace which involve pointers to kernel
objects (including device drivers) will need to have those pointers
validated; userspace should never be able to crash the kernel by passing
it garbage.

The actual validation with _k_object_validate() will be in the system
call receiver code, which doesn't exist yet.

- CONFIG_USERSPACE introduced. We are somewhat far away from having an
  end-to-end implementation, but at least need a Kconfig symbol to
  guard the incoming code with. Formal documentation doesn't exist yet
  either, but will appear later down the road once the implementation is
  mostly finalized.

- In the memory region for RAM, the data section has been moved last,
  past bss and noinit. This ensures that inserting generated tables
  with addresses of kernel objects does not change the addresses of
  those objects (which would make the table invalid)

- The DWARF debug information in the generated ELF binary is parsed to
  fetch the locations of all kernel objects and pass this to gperf to
  create a perfect hash table of their memory addresses.

- The generated gperf code doesn't know that we are exclusively working
  with memory addresses and uses memory inefficently. A post-processing
  script process_gperf.py adjusts the generated code before it is
  compiled to work with pointer values directly and not strings
  containing them.

- _k_object_init() calls inserted into the init functions for the set of
  kernel object types we are going to support so far

Issue: ZEP-2187
Signed-off-by: Andrew Boie <andrew.p.boie@intel.com>
2017-09-07 16:33:33 -07:00