Commit c200367b authored by Leandro Pereira's avatar Leandro Pereira Committed by Anas Nashif
Browse files

drivers: Perform a runtime check if a driver is capable of an operation



Driver APIs might not implement all operations, making it possible for
a user thread to get the kernel to execute a function at 0x00000000.

Perform runtime checks in all the driver handlers, checking if they're
capable of performing the requested operation.

Fixes #6907.

Signed-off-by: default avatarLeandro Pereira <leandro.pereira@intel.com>
parent e7ded11a
Loading
Loading
Loading
Loading
+15 −1
Original line number Diff line number Diff line
@@ -364,6 +364,19 @@ add_custom_command(OUTPUT include/generated/syscall_dispatch.c ${syscall_list_h}
  DEPENDS ${syscalls_json}
  )

set(DRV_VALIDATION ${PROJECT_BINARY_DIR}/include/generated/driver-validation.h)
add_custom_command(
  OUTPUT ${DRV_VALIDATION}
  COMMAND
  ${PYTHON_EXECUTABLE}
  ${ZEPHYR_BASE}/scripts/gen_kobject_list.py
  --validation-output ${DRV_VALIDATION}
  $<$<BOOL:${CMAKE_VERBOSE_MAKEFILE}>:--verbose>
  WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
  )
add_custom_target(driver_validation_h_target DEPENDS ${DRV_VALIDATION})


# Generate offsets.c.obj from offsets.c
# Generate offsets.h     from offsets.c.obj

@@ -376,6 +389,7 @@ target_link_libraries(offsets zephyr_interface)
add_dependencies(     offsets
  syscall_list_h_target
  syscall_macros_h_target
  driver_validation_h_target
  )

add_custom_command(
@@ -782,7 +796,7 @@ if(CONFIG_USERSPACE)
    ${PYTHON_EXECUTABLE}
    ${GEN_KOBJ_LIST}
    --kernel $<TARGET_FILE:zephyr_prebuilt>
    --output ${OBJ_LIST}
    --gperf-output ${OBJ_LIST}
    $<$<BOOL:${CMAKE_VERBOSE_MAKEFILE}>:--verbose>
    DEPENDS zephyr_prebuilt
    WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
+3 −0
Original line number Diff line number Diff line
@@ -292,6 +292,9 @@ Several macros exist to validate arguments:
  a message parameter, instead printing the expression tested if it
  fails. The latter should only be used for the most obvious of tests.

* :c:macro:`_SYSCALL_DRIVER_OP()` checks at runtime if a driver
  instance is capable of performing a particular operation.

If any check fails, a kernel oops will be triggered which will kill the
calling thread. This is done instead of returning some error condition to
keep the APIs the same when calling from supervisor mode.
+14 −3
Original line number Diff line number Diff line
@@ -7,8 +7,19 @@
#include <adc.h>
#include <syscall_handler.h>

_SYSCALL_HANDLER1_SIMPLE_VOID(adc_enable, K_OBJ_DRIVER_ADC, struct device *);
_SYSCALL_HANDLER1_SIMPLE_VOID(adc_disable, K_OBJ_DRIVER_ADC, struct device *);
_SYSCALL_HANDLER(adc_enable, dev)
{
	_SYSCALL_DRIVER_ADC(dev, enable);
	_impl_adc_enable((struct device *)dev);
	return 0;
}

_SYSCALL_HANDLER(adc_disable, dev)
{
	_SYSCALL_DRIVER_ADC(dev, disable);
	_impl_adc_disable((struct device *)dev);
	return 0;
}

_SYSCALL_HANDLER(adc_read, dev, seq_table_p)
{
@@ -16,7 +27,7 @@ _SYSCALL_HANDLER(adc_read, dev, seq_table_p)
	struct adc_seq_table *seq_table = (struct adc_seq_table *)seq_table_p;
	int i;

	_SYSCALL_OBJ(dev, K_OBJ_DRIVER_ADC);
	_SYSCALL_DRIVER_ADC(dev, read);
	_SYSCALL_MEMORY_READ(seq_table, sizeof(struct adc_seq_table));
	_SYSCALL_MEMORY_ARRAY_READ(seq_table->entries, seq_table->num_entries,
				   sizeof(struct adc_seq_entry));
+6 −3
Original line number Diff line number Diff line
@@ -9,9 +9,12 @@

_SYSCALL_HANDLER(aio_cmp_disable, dev, index)
{
	_SYSCALL_OBJ(dev, K_OBJ_DRIVER_AIO);
	_SYSCALL_DRIVER_AIO_CMP(dev, disable);
	return _impl_aio_cmp_disable((struct device *)dev, index);
}

_SYSCALL_HANDLER1_SIMPLE(aio_cmp_get_pending_int, K_OBJ_DRIVER_AIO,
			 struct device *);
_SYSCALL_HANDLER(aio_cmp_get_pending_int, dev)
{
	_SYSCALL_DRIVER_AIO_CMP(dev, get_pending_int);
	return _impl_aio_get_pending_int((struct device *)dev, index);
}
+9 −5
Original line number Diff line number Diff line
@@ -11,9 +11,13 @@
 * instance and return an integral value
 */
#define COUNTER_HANDLER(name) \
	_SYSCALL_HANDLER1_SIMPLE(name, K_OBJ_DRIVER_COUNTER, struct device *)
	_SYSCALL_HANDLER(counter_ ## name, dev) \
	{ \
		_SYSCALL_DRIVER_COUNTER(dev, name); \
		return _impl_counter_ ## name((struct device *)dev); \
	}

COUNTER_HANDLER(counter_get_pending_int);
COUNTER_HANDLER(counter_read);
COUNTER_HANDLER(counter_stop);
COUNTER_HANDLER(counter_start);
COUNTER_HANDLER(get_pending_int)
COUNTER_HANDLER(read)
COUNTER_HANDLER(stop)
COUNTER_HANDLER(start)
Loading