Skip to content

Commit

Permalink
MPU Hal (#1492)
Browse files Browse the repository at this point in the history
* Furi HAL: memory protection unit
* Core: prohibit NULL dereferencing, even for reads.
* Applications: fix NULL dereference
* Core: stack protection by MPU
* MPU: stack region alignment
* Apps: fix null pointer dereferences
* Threads: fix non-null arg check
* Desktop settings: fix null pointer dereference
* Core: documented null-check hack
* Fix null dereference issues
* Apps: args check
* Core: naming fixes
* format code
* Core: remove NONNULL specifier
* FurHal: move MPU initialization to begining, fix enum naming

Co-authored-by: あく <alleteam@gmail.com>
  • Loading branch information
DrZlo13 and skotopes authored Aug 3, 2022
1 parent 4a6477a commit eed4296
Show file tree
Hide file tree
Showing 29 changed files with 238 additions and 62 deletions.
2 changes: 1 addition & 1 deletion applications/archive/scenes/archive_scene_rename.c
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ void archive_scene_rename_on_enter(void* context) {
false);

ValidatorIsFile* validator_is_file = validator_is_file_alloc_init(
string_get_cstr(archive->browser->path), archive->file_extension, NULL);
string_get_cstr(archive->browser->path), archive->file_extension, "");
text_input_set_validator(text_input, validator_is_file_callback, validator_is_file);

string_clear(filename);
Expand Down
3 changes: 1 addition & 2 deletions applications/bad_usb/bad_usb_app.c
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ BadUsbApp* bad_usb_app_alloc(char* arg) {

string_init(app->file_path);

if(arg != NULL) {
if(arg && strlen(arg)) {
string_set_str(app->file_path, arg);
}

Expand Down Expand Up @@ -79,7 +79,6 @@ void bad_usb_app_free(BadUsbApp* app) {
furi_assert(app);

// Views
view_dispatcher_remove_view(app->view_dispatcher, BadUsbAppViewFileSelect);
view_dispatcher_remove_view(app->view_dispatcher, BadUsbAppViewWork);
bad_usb_free(app->bad_usb_view);

Expand Down
1 change: 0 additions & 1 deletion applications/bad_usb/bad_usb_app_i.h
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,5 @@ struct BadUsbApp {

typedef enum {
BadUsbAppViewError,
BadUsbAppViewFileSelect,
BadUsbAppViewWork,
} BadUsbAppView;
3 changes: 2 additions & 1 deletion applications/bt/bt_service/bt.c
Original file line number Diff line number Diff line change
Expand Up @@ -347,7 +347,8 @@ static void bt_close_connection(Bt* bt) {
furi_event_flag_set(bt->api_event, BT_API_UNLOCK_EVENT);
}

int32_t bt_srv() {
int32_t bt_srv(void* p) {
UNUSED(p);
Bt* bt = bt_alloc();

if(furi_hal_rtc_get_boot_mode() != FuriHalRtcBootModeNormal) {
Expand Down
25 changes: 15 additions & 10 deletions applications/desktop/animations/views/bubble_animation_view.c
Original file line number Diff line number Diff line change
Expand Up @@ -143,22 +143,24 @@ static void bubble_animation_activate(BubbleAnimationView* view, bool force) {
furi_assert(view);
bool activate = true;
BubbleAnimationViewModel* model = view_get_model(view->view);
if(!model->current) {
if(model->current == NULL) {
activate = false;
} else if(model->freeze_frame) {
activate = false;
} else if(model->current->active_frames == 0) {
activate = false;
}

if(!force) {
if((model->active_ended_at + model->current->active_cooldown * 1000) >
xTaskGetTickCount()) {
activate = false;
} else if(model->active_shift) {
activate = false;
} else if(model->current_frame >= model->current->passive_frames) {
activate = false;
if(model->current != NULL) {
if(!force) {
if((model->active_ended_at + model->current->active_cooldown * 1000) >
xTaskGetTickCount()) {
activate = false;
} else if(model->active_shift) {
activate = false;
} else if(model->current_frame >= model->current->passive_frames) {
activate = false;
}
}
}
view_commit_model(view->view, false);
Expand Down Expand Up @@ -288,7 +290,10 @@ static void bubble_animation_enter(void* context) {
bubble_animation_activate(view, false);

BubbleAnimationViewModel* model = view_get_model(view->view);
uint8_t frame_rate = model->current->icon_animation.frame_rate;
uint8_t frame_rate = 0;
if(model->current != NULL) {
frame_rate = model->current->icon_animation.frame_rate;
}
view_commit_model(view->view, false);

if(frame_rate) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@ void desktop_settings_app_free(DesktopSettingsApp* app) {
extern int32_t desktop_settings_app(void* p) {
DesktopSettingsApp* app = desktop_settings_app_alloc();
LOAD_DESKTOP_SETTINGS(&app->settings);
if(!strcmp(p, DESKTOP_SETTINGS_RUN_PIN_SETUP_ARG)) {
if(p && (strcmp(p, DESKTOP_SETTINGS_RUN_PIN_SETUP_ARG) == 0)) {
scene_manager_next_scene(app->scene_manager, DesktopSettingsAppScenePinSetupHowto);
} else {
scene_manager_next_scene(app->scene_manager, DesktopSettingsAppSceneStart);
Expand Down
20 changes: 11 additions & 9 deletions applications/gui/modules/button_menu.c
Original file line number Diff line number Diff line change
Expand Up @@ -185,17 +185,19 @@ static void button_menu_process_ok(ButtonMenu* button_menu, InputType type) {
return false;
});

if(item->type == ButtonMenuItemTypeControl) {
if(type == InputTypeShort) {
if(item && item->callback) {
item->callback(item->callback_context, item->index, type);
if(item) {
if(item->type == ButtonMenuItemTypeControl) {
if(type == InputTypeShort) {
if(item && item->callback) {
item->callback(item->callback_context, item->index, type);
}
}
}
}
if(item->type == ButtonMenuItemTypeCommon) {
if((type == InputTypePress) || (type == InputTypeRelease)) {
if(item && item->callback) {
item->callback(item->callback_context, item->index, type);
if(item->type == ButtonMenuItemTypeCommon) {
if((type == InputTypePress) || (type == InputTypeRelease)) {
if(item && item->callback) {
item->callback(item->callback_context, item->index, type);
}
}
}
}
Expand Down
2 changes: 1 addition & 1 deletion applications/gui/modules/text_input.c
Original file line number Diff line number Diff line change
Expand Up @@ -147,7 +147,7 @@ static void text_input_backspace_cb(TextInputModel* model) {

static void text_input_view_draw_callback(Canvas* canvas, void* _model) {
TextInputModel* model = _model;
uint8_t text_length = strlen(model->text_buffer);
uint8_t text_length = model->text_buffer ? strlen(model->text_buffer) : 0;
uint8_t needed_string_width = canvas_width(canvas) - 8;
uint8_t start_pos = 4;

Expand Down
2 changes: 1 addition & 1 deletion applications/gui/modules/validators.h
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
#pragma once

// #include <gui/view.h>
#include <m-string.h>
#include <core/common_defines.h>

#ifdef __cplusplus
extern "C" {
Expand Down
2 changes: 1 addition & 1 deletion applications/ibutton/ibutton.c
Original file line number Diff line number Diff line change
Expand Up @@ -353,7 +353,7 @@ int32_t ibutton_app(void* p) {
bool key_loaded = false;
bool rpc_mode = false;

if(p) {
if(p && strlen(p)) {
uint32_t rpc_ctx = 0;
if(sscanf(p, "RPC %lX", &rpc_ctx) == 1) {
FURI_LOG_D(TAG, "Running in RPC mode");
Expand Down
2 changes: 1 addition & 1 deletion applications/infrared/infrared.c
Original file line number Diff line number Diff line change
Expand Up @@ -405,7 +405,7 @@ int32_t infrared_app(void* p) {
bool is_remote_loaded = false;
bool is_rpc_mode = false;

if(p) {
if(p && strlen(p)) {
uint32_t rpc_ctx = 0;
if(sscanf(p, "RPC %lX", &rpc_ctx) == 1) {
infrared->rpc_ctx = (void*)rpc_ctx;
Expand Down
3 changes: 2 additions & 1 deletion applications/input/input.c
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,8 @@ const char* input_get_type_name(InputType type) {
return "Unknown";
}

int32_t input_srv() {
int32_t input_srv(void* p) {
UNUSED(p);
input = malloc(sizeof(Input));
input->thread_id = furi_thread_get_current_id();
input->event_pubsub = furi_pubsub_alloc();
Expand Down
2 changes: 1 addition & 1 deletion applications/lfrfid/lfrfid_app.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ void LfRfidApp::run(void* _args) {

make_app_folder();

if(strlen(args)) {
if(args && strlen(args)) {
uint32_t rpc_ctx_ptr = 0;
if(sscanf(args, "RPC %lX", &rpc_ctx_ptr) == 1) {
rpc_ctx = (RpcAppSystem*)rpc_ctx_ptr;
Expand Down
2 changes: 1 addition & 1 deletion applications/music_player/music_player.c
Original file line number Diff line number Diff line change
Expand Up @@ -300,7 +300,7 @@ int32_t music_player_app(void* p) {
string_init(file_path);

do {
if(p) {
if(p && strlen(p)) {
string_cat_str(file_path, p);
} else {
string_set_str(file_path, MUSIC_PLAYER_APP_PATH_FOLDER);
Expand Down
2 changes: 1 addition & 1 deletion applications/nfc/nfc.c
Original file line number Diff line number Diff line change
Expand Up @@ -238,7 +238,7 @@ int32_t nfc_app(void* p) {
char* args = p;

// Check argument and run corresponding scene
if((*args != '\0')) {
if(args && strlen(args)) {
nfc_device_set_loading_callback(nfc->dev, nfc_show_loading_popup, nfc);
uint32_t rpc_ctx = 0;
if(sscanf(p, "RPC %lX", &rpc_ctx) == 1) {
Expand Down
2 changes: 1 addition & 1 deletion applications/power/power_service/power.c
Original file line number Diff line number Diff line change
Expand Up @@ -200,7 +200,7 @@ static void power_check_battery_level_change(Power* power) {
}

int32_t power_srv(void* p) {
(void)p;
UNUSED(p);
Power* power = power_alloc();
power_update_info(power);
furi_record_create(RECORD_POWER, power);
Expand Down
2 changes: 1 addition & 1 deletion applications/power/power_settings_app/power_settings_app.c
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ void power_settings_app_free(PowerSettingsApp* app) {

int32_t power_settings_app(void* p) {
uint32_t first_scene = PowerSettingsAppSceneStart;
if(p && !strcmp(p, "off")) {
if(p && strlen(p) && !strcmp(p, "off")) {
first_scene = PowerSettingsAppScenePowerOff;
}
PowerSettingsApp* app = power_settings_app_alloc(first_scene);
Expand Down
4 changes: 4 additions & 0 deletions applications/rpc/rpc_system.c
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,8 @@ static void rpc_system_system_device_info_callback(
furi_assert(value);
RpcSystemContext* ctx = context;

furi_assert(key);
furi_assert(value);
char* str_key = strdup(key);
char* str_value = strdup(value);

Expand Down Expand Up @@ -232,6 +234,8 @@ static void rpc_system_system_power_info_callback(
furi_assert(value);
RpcSystemContext* ctx = context;

furi_assert(key);
furi_assert(value);
char* str_key = strdup(key);
char* str_value = strdup(value);

Expand Down
4 changes: 2 additions & 2 deletions applications/subghz/scenes/subghz_scene_save_name.c
Original file line number Diff line number Diff line change
Expand Up @@ -59,8 +59,8 @@ void subghz_scene_save_name_on_enter(void* context) {
MAX_TEXT_INPUT_LEN, // buffer size
dev_name_empty);

ValidatorIsFile* validator_is_file = validator_is_file_alloc_init(
string_get_cstr(subghz->file_path), SUBGHZ_APP_EXTENSION, NULL);
ValidatorIsFile* validator_is_file =
validator_is_file_alloc_init(string_get_cstr(subghz->file_path), SUBGHZ_APP_EXTENSION, "");
text_input_set_validator(text_input, validator_is_file_callback, validator_is_file);

string_clear(file_name);
Expand Down
2 changes: 1 addition & 1 deletion applications/subghz/subghz.c
Original file line number Diff line number Diff line change
Expand Up @@ -320,7 +320,7 @@ int32_t subghz_app(void* p) {
subghz_environment_load_keystore(
subghz->txrx->environment, EXT_PATH("subghz/assets/keeloq_mfcodes_user"));
// Check argument and run corresponding scene
if(p) {
if(p && strlen(p)) {
uint32_t rpc_ctx = 0;
if(sscanf(p, "RPC %lX", &rpc_ctx) == 1) {
subghz->rpc_ctx = (void*)rpc_ctx;
Expand Down
13 changes: 7 additions & 6 deletions applications/unit_tests/rpc/rpc_test.c
Original file line number Diff line number Diff line change
Expand Up @@ -420,10 +420,12 @@ static void
mu_check(result_msg_file->size == expected_msg_file->size);
mu_check(result_msg_file->type == expected_msg_file->type);

mu_check(!result_msg_file->data == !expected_msg_file->data);
mu_check(result_msg_file->data->size == expected_msg_file->data->size);
for(int i = 0; i < result_msg_file->data->size; ++i) {
mu_check(result_msg_file->data->bytes[i] == expected_msg_file->data->bytes[i]);
if(result_msg_file->data && result_msg_file->type != PB_Storage_File_FileType_DIR) {
mu_check(!result_msg_file->data == !expected_msg_file->data); // Zlo: WTF???
mu_check(result_msg_file->data->size == expected_msg_file->data->size);
for(int i = 0; i < result_msg_file->data->size; ++i) {
mu_check(result_msg_file->data->bytes[i] == expected_msg_file->data->bytes[i]);
}
}
}

Expand Down Expand Up @@ -1346,8 +1348,7 @@ static void test_rpc_storage_rename_run(
}

MU_TEST(test_storage_rename) {
test_rpc_storage_rename_run(
NULL, NULL, ++command_id, PB_CommandStatus_ERROR_STORAGE_INVALID_NAME);
test_rpc_storage_rename_run("", "", ++command_id, PB_CommandStatus_ERROR_STORAGE_INVALID_NAME);

furi_check(!test_is_exists(TEST_DIR "empty.txt"));
test_create_file(TEST_DIR "empty.txt", 0);
Expand Down
2 changes: 1 addition & 1 deletion applications/updater/updater.c
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ static void

Updater* updater_alloc(const char* arg) {
Updater* updater = malloc(sizeof(Updater));
if(arg) {
if(arg && strlen(arg)) {
string_init_set_str(updater->startup_arg, arg);
string_replace_str(updater->startup_arg, ANY_PATH(""), EXT_PATH(""));
} else {
Expand Down
6 changes: 5 additions & 1 deletion firmware/targets/f7/Inc/FreeRTOSConfig.h
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ extern uint32_t SystemCoreClock;
#define configUSE_16_BIT_TICKS 0
#define configUSE_MUTEXES 1
#define configQUEUE_REGISTRY_SIZE 0
#define configCHECK_FOR_STACK_OVERFLOW 2
#define configCHECK_FOR_STACK_OVERFLOW 0
#define configUSE_RECURSIVE_MUTEXES 1
#define configUSE_COUNTING_SEMAPHORES 1
#define configENABLE_BACKWARD_COMPATIBILITY 0
Expand Down Expand Up @@ -145,3 +145,7 @@ standard names. */
#define USE_CUSTOM_SYSTICK_HANDLER_IMPLEMENTATION 1
#define configOVERRIDE_DEFAULT_TICK_CONFIGURATION \
1 /* required only for Keil but does not hurt otherwise */

#define traceTASK_SWITCHED_IN() \
extern void furi_hal_mpu_set_stack_protection(uint32_t* stack); \
furi_hal_mpu_set_stack_protection((uint32_t*)pxCurrentTCB->pxStack)
13 changes: 2 additions & 11 deletions firmware/targets/f7/furi_hal/furi_hal.c
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
#include <furi_hal.h>
#include <furi_hal_mpu.h>

#include <stm32wbxx_ll_cortex.h>

Expand Down Expand Up @@ -35,6 +36,7 @@ void furi_hal_deinit_early() {
}

void furi_hal_init() {
furi_hal_mpu_init();
furi_hal_clock_init();
furi_hal_console_init();
furi_hal_rtc_init();
Expand Down Expand Up @@ -80,17 +82,6 @@ void furi_hal_init() {
// FatFS driver initialization
MX_FATFS_Init();
FURI_LOG_I(TAG, "FATFS OK");

// Partial null pointer dereference protection
LL_MPU_Disable();
LL_MPU_ConfigRegion(
LL_MPU_REGION_NUMBER0,
0x00,
0x0,
LL_MPU_REGION_SIZE_1MB | LL_MPU_REGION_PRIV_RO_URO | LL_MPU_ACCESS_BUFFERABLE |
LL_MPU_ACCESS_CACHEABLE | LL_MPU_ACCESS_SHAREABLE | LL_MPU_TEX_LEVEL1 |
LL_MPU_INSTRUCTION_ACCESS_ENABLE);
LL_MPU_Enable(LL_MPU_CTRL_PRIVILEGED_DEFAULT);
}

void furi_hal_switch(void* address) {
Expand Down
19 changes: 19 additions & 0 deletions firmware/targets/f7/furi_hal/furi_hal_interrupt.c
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
#include <stm32wbxx.h>
#include <stm32wbxx_ll_tim.h>
#include <stm32wbxx_ll_rcc.h>
#include <stm32wbxx_ll_cortex.h>

#define TAG "FuriHalInterrupt"

Expand Down Expand Up @@ -95,6 +96,10 @@ void furi_hal_interrupt_init() {
LL_SYSCFG_DisableIT_FPU_IDC();
LL_SYSCFG_DisableIT_FPU_IXC();

LL_HANDLER_EnableFault(LL_HANDLER_FAULT_USG);
LL_HANDLER_EnableFault(LL_HANDLER_FAULT_BUS);
LL_HANDLER_EnableFault(LL_HANDLER_FAULT_MEM);

FURI_LOG_I(TAG, "Init OK");
}

Expand Down Expand Up @@ -241,6 +246,20 @@ void HardFault_Handler() {
}

void MemManage_Handler() {
if(FURI_BIT(SCB->CFSR, SCB_CFSR_MMARVALID_Pos)) {
uint32_t memfault_address = SCB->MMFAR;
if(memfault_address < (1024 * 1024)) {
// from 0x00 to 1MB, see FuriHalMpuRegionNULL
furi_crash("NULL pointer dereference");
} else {
// write or read of MPU region 1 (FuriHalMpuRegionStack)
furi_crash("MPU fault, possibly stack overflow");
}
} else if(FURI_BIT(SCB->CFSR, SCB_CFSR_MSTKERR_Pos)) {
// push to stack on MPU region 1 (FuriHalMpuRegionStack)
furi_crash("MemManage fault, possibly stack overflow");
}

furi_crash("MemManage");
}

Expand Down
Loading

0 comments on commit eed4296

Please sign in to comment.