Skip to content

Commit eed4296

Browse files
DrZlo13skotopes
andauthored
MPU Hal (#1492)
* 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>
1 parent 4a6477a commit eed4296

File tree

29 files changed

+238
-62
lines changed

29 files changed

+238
-62
lines changed

applications/archive/scenes/archive_scene_rename.c

+1-1
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ void archive_scene_rename_on_enter(void* context) {
3737
false);
3838

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

4343
string_clear(filename);

applications/bad_usb/bad_usb_app.c

+1-2
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ BadUsbApp* bad_usb_app_alloc(char* arg) {
2828

2929
string_init(app->file_path);
3030

31-
if(arg != NULL) {
31+
if(arg && strlen(arg)) {
3232
string_set_str(app->file_path, arg);
3333
}
3434

@@ -79,7 +79,6 @@ void bad_usb_app_free(BadUsbApp* app) {
7979
furi_assert(app);
8080

8181
// Views
82-
view_dispatcher_remove_view(app->view_dispatcher, BadUsbAppViewFileSelect);
8382
view_dispatcher_remove_view(app->view_dispatcher, BadUsbAppViewWork);
8483
bad_usb_free(app->bad_usb_view);
8584

applications/bad_usb/bad_usb_app_i.h

-1
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,5 @@ struct BadUsbApp {
3838

3939
typedef enum {
4040
BadUsbAppViewError,
41-
BadUsbAppViewFileSelect,
4241
BadUsbAppViewWork,
4342
} BadUsbAppView;

applications/bt/bt_service/bt.c

+2-1
Original file line numberDiff line numberDiff line change
@@ -347,7 +347,8 @@ static void bt_close_connection(Bt* bt) {
347347
furi_event_flag_set(bt->api_event, BT_API_UNLOCK_EVENT);
348348
}
349349

350-
int32_t bt_srv() {
350+
int32_t bt_srv(void* p) {
351+
UNUSED(p);
351352
Bt* bt = bt_alloc();
352353

353354
if(furi_hal_rtc_get_boot_mode() != FuriHalRtcBootModeNormal) {

applications/desktop/animations/views/bubble_animation_view.c

+15-10
Original file line numberDiff line numberDiff line change
@@ -143,22 +143,24 @@ static void bubble_animation_activate(BubbleAnimationView* view, bool force) {
143143
furi_assert(view);
144144
bool activate = true;
145145
BubbleAnimationViewModel* model = view_get_model(view->view);
146-
if(!model->current) {
146+
if(model->current == NULL) {
147147
activate = false;
148148
} else if(model->freeze_frame) {
149149
activate = false;
150150
} else if(model->current->active_frames == 0) {
151151
activate = false;
152152
}
153153

154-
if(!force) {
155-
if((model->active_ended_at + model->current->active_cooldown * 1000) >
156-
xTaskGetTickCount()) {
157-
activate = false;
158-
} else if(model->active_shift) {
159-
activate = false;
160-
} else if(model->current_frame >= model->current->passive_frames) {
161-
activate = false;
154+
if(model->current != NULL) {
155+
if(!force) {
156+
if((model->active_ended_at + model->current->active_cooldown * 1000) >
157+
xTaskGetTickCount()) {
158+
activate = false;
159+
} else if(model->active_shift) {
160+
activate = false;
161+
} else if(model->current_frame >= model->current->passive_frames) {
162+
activate = false;
163+
}
162164
}
163165
}
164166
view_commit_model(view->view, false);
@@ -288,7 +290,10 @@ static void bubble_animation_enter(void* context) {
288290
bubble_animation_activate(view, false);
289291

290292
BubbleAnimationViewModel* model = view_get_model(view->view);
291-
uint8_t frame_rate = model->current->icon_animation.frame_rate;
293+
uint8_t frame_rate = 0;
294+
if(model->current != NULL) {
295+
frame_rate = model->current->icon_animation.frame_rate;
296+
}
292297
view_commit_model(view->view, false);
293298

294299
if(frame_rate) {

applications/desktop/desktop_settings/desktop_settings_app.c

+1-1
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,7 @@ void desktop_settings_app_free(DesktopSettingsApp* app) {
9090
extern int32_t desktop_settings_app(void* p) {
9191
DesktopSettingsApp* app = desktop_settings_app_alloc();
9292
LOAD_DESKTOP_SETTINGS(&app->settings);
93-
if(!strcmp(p, DESKTOP_SETTINGS_RUN_PIN_SETUP_ARG)) {
93+
if(p && (strcmp(p, DESKTOP_SETTINGS_RUN_PIN_SETUP_ARG) == 0)) {
9494
scene_manager_next_scene(app->scene_manager, DesktopSettingsAppScenePinSetupHowto);
9595
} else {
9696
scene_manager_next_scene(app->scene_manager, DesktopSettingsAppSceneStart);

applications/gui/modules/button_menu.c

+11-9
Original file line numberDiff line numberDiff line change
@@ -185,17 +185,19 @@ static void button_menu_process_ok(ButtonMenu* button_menu, InputType type) {
185185
return false;
186186
});
187187

188-
if(item->type == ButtonMenuItemTypeControl) {
189-
if(type == InputTypeShort) {
190-
if(item && item->callback) {
191-
item->callback(item->callback_context, item->index, type);
188+
if(item) {
189+
if(item->type == ButtonMenuItemTypeControl) {
190+
if(type == InputTypeShort) {
191+
if(item && item->callback) {
192+
item->callback(item->callback_context, item->index, type);
193+
}
192194
}
193195
}
194-
}
195-
if(item->type == ButtonMenuItemTypeCommon) {
196-
if((type == InputTypePress) || (type == InputTypeRelease)) {
197-
if(item && item->callback) {
198-
item->callback(item->callback_context, item->index, type);
196+
if(item->type == ButtonMenuItemTypeCommon) {
197+
if((type == InputTypePress) || (type == InputTypeRelease)) {
198+
if(item && item->callback) {
199+
item->callback(item->callback_context, item->index, type);
200+
}
199201
}
200202
}
201203
}

applications/gui/modules/text_input.c

+1-1
Original file line numberDiff line numberDiff line change
@@ -147,7 +147,7 @@ static void text_input_backspace_cb(TextInputModel* model) {
147147

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

applications/gui/modules/validators.h

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
#pragma once
22

3-
// #include <gui/view.h>
43
#include <m-string.h>
4+
#include <core/common_defines.h>
55

66
#ifdef __cplusplus
77
extern "C" {

applications/ibutton/ibutton.c

+1-1
Original file line numberDiff line numberDiff line change
@@ -353,7 +353,7 @@ int32_t ibutton_app(void* p) {
353353
bool key_loaded = false;
354354
bool rpc_mode = false;
355355

356-
if(p) {
356+
if(p && strlen(p)) {
357357
uint32_t rpc_ctx = 0;
358358
if(sscanf(p, "RPC %lX", &rpc_ctx) == 1) {
359359
FURI_LOG_D(TAG, "Running in RPC mode");

applications/infrared/infrared.c

+1-1
Original file line numberDiff line numberDiff line change
@@ -405,7 +405,7 @@ int32_t infrared_app(void* p) {
405405
bool is_remote_loaded = false;
406406
bool is_rpc_mode = false;
407407

408-
if(p) {
408+
if(p && strlen(p)) {
409409
uint32_t rpc_ctx = 0;
410410
if(sscanf(p, "RPC %lX", &rpc_ctx) == 1) {
411411
infrared->rpc_ctx = (void*)rpc_ctx;

applications/input/input.c

+2-1
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,8 @@ const char* input_get_type_name(InputType type) {
6464
return "Unknown";
6565
}
6666

67-
int32_t input_srv() {
67+
int32_t input_srv(void* p) {
68+
UNUSED(p);
6869
input = malloc(sizeof(Input));
6970
input->thread_id = furi_thread_get_current_id();
7071
input->event_pubsub = furi_pubsub_alloc();

applications/lfrfid/lfrfid_app.cpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,7 @@ void LfRfidApp::run(void* _args) {
7474

7575
make_app_folder();
7676

77-
if(strlen(args)) {
77+
if(args && strlen(args)) {
7878
uint32_t rpc_ctx_ptr = 0;
7979
if(sscanf(args, "RPC %lX", &rpc_ctx_ptr) == 1) {
8080
rpc_ctx = (RpcAppSystem*)rpc_ctx_ptr;

applications/music_player/music_player.c

+1-1
Original file line numberDiff line numberDiff line change
@@ -300,7 +300,7 @@ int32_t music_player_app(void* p) {
300300
string_init(file_path);
301301

302302
do {
303-
if(p) {
303+
if(p && strlen(p)) {
304304
string_cat_str(file_path, p);
305305
} else {
306306
string_set_str(file_path, MUSIC_PLAYER_APP_PATH_FOLDER);

applications/nfc/nfc.c

+1-1
Original file line numberDiff line numberDiff line change
@@ -238,7 +238,7 @@ int32_t nfc_app(void* p) {
238238
char* args = p;
239239

240240
// Check argument and run corresponding scene
241-
if((*args != '\0')) {
241+
if(args && strlen(args)) {
242242
nfc_device_set_loading_callback(nfc->dev, nfc_show_loading_popup, nfc);
243243
uint32_t rpc_ctx = 0;
244244
if(sscanf(p, "RPC %lX", &rpc_ctx) == 1) {

applications/power/power_service/power.c

+1-1
Original file line numberDiff line numberDiff line change
@@ -200,7 +200,7 @@ static void power_check_battery_level_change(Power* power) {
200200
}
201201

202202
int32_t power_srv(void* p) {
203-
(void)p;
203+
UNUSED(p);
204204
Power* power = power_alloc();
205205
power_update_info(power);
206206
furi_record_create(RECORD_POWER, power);

applications/power/power_settings_app/power_settings_app.c

+1-1
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,7 @@ void power_settings_app_free(PowerSettingsApp* app) {
7676

7777
int32_t power_settings_app(void* p) {
7878
uint32_t first_scene = PowerSettingsAppSceneStart;
79-
if(p && !strcmp(p, "off")) {
79+
if(p && strlen(p) && !strcmp(p, "off")) {
8080
first_scene = PowerSettingsAppScenePowerOff;
8181
}
8282
PowerSettingsApp* app = power_settings_app_alloc(first_scene);

applications/rpc/rpc_system.c

+4
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,8 @@ static void rpc_system_system_device_info_callback(
7878
furi_assert(value);
7979
RpcSystemContext* ctx = context;
8080

81+
furi_assert(key);
82+
furi_assert(value);
8183
char* str_key = strdup(key);
8284
char* str_value = strdup(value);
8385

@@ -232,6 +234,8 @@ static void rpc_system_system_power_info_callback(
232234
furi_assert(value);
233235
RpcSystemContext* ctx = context;
234236

237+
furi_assert(key);
238+
furi_assert(value);
235239
char* str_key = strdup(key);
236240
char* str_value = strdup(value);
237241

applications/subghz/scenes/subghz_scene_save_name.c

+2-2
Original file line numberDiff line numberDiff line change
@@ -59,8 +59,8 @@ void subghz_scene_save_name_on_enter(void* context) {
5959
MAX_TEXT_INPUT_LEN, // buffer size
6060
dev_name_empty);
6161

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

6666
string_clear(file_name);

applications/subghz/subghz.c

+1-1
Original file line numberDiff line numberDiff line change
@@ -320,7 +320,7 @@ int32_t subghz_app(void* p) {
320320
subghz_environment_load_keystore(
321321
subghz->txrx->environment, EXT_PATH("subghz/assets/keeloq_mfcodes_user"));
322322
// Check argument and run corresponding scene
323-
if(p) {
323+
if(p && strlen(p)) {
324324
uint32_t rpc_ctx = 0;
325325
if(sscanf(p, "RPC %lX", &rpc_ctx) == 1) {
326326
subghz->rpc_ctx = (void*)rpc_ctx;

applications/unit_tests/rpc/rpc_test.c

+7-6
Original file line numberDiff line numberDiff line change
@@ -420,10 +420,12 @@ static void
420420
mu_check(result_msg_file->size == expected_msg_file->size);
421421
mu_check(result_msg_file->type == expected_msg_file->type);
422422

423-
mu_check(!result_msg_file->data == !expected_msg_file->data);
424-
mu_check(result_msg_file->data->size == expected_msg_file->data->size);
425-
for(int i = 0; i < result_msg_file->data->size; ++i) {
426-
mu_check(result_msg_file->data->bytes[i] == expected_msg_file->data->bytes[i]);
423+
if(result_msg_file->data && result_msg_file->type != PB_Storage_File_FileType_DIR) {
424+
mu_check(!result_msg_file->data == !expected_msg_file->data); // Zlo: WTF???
425+
mu_check(result_msg_file->data->size == expected_msg_file->data->size);
426+
for(int i = 0; i < result_msg_file->data->size; ++i) {
427+
mu_check(result_msg_file->data->bytes[i] == expected_msg_file->data->bytes[i]);
428+
}
427429
}
428430
}
429431

@@ -1346,8 +1348,7 @@ static void test_rpc_storage_rename_run(
13461348
}
13471349

13481350
MU_TEST(test_storage_rename) {
1349-
test_rpc_storage_rename_run(
1350-
NULL, NULL, ++command_id, PB_CommandStatus_ERROR_STORAGE_INVALID_NAME);
1351+
test_rpc_storage_rename_run("", "", ++command_id, PB_CommandStatus_ERROR_STORAGE_INVALID_NAME);
13511352

13521353
furi_check(!test_is_exists(TEST_DIR "empty.txt"));
13531354
test_create_file(TEST_DIR "empty.txt", 0);

applications/updater/updater.c

+1-1
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ static void
3434

3535
Updater* updater_alloc(const char* arg) {
3636
Updater* updater = malloc(sizeof(Updater));
37-
if(arg) {
37+
if(arg && strlen(arg)) {
3838
string_init_set_str(updater->startup_arg, arg);
3939
string_replace_str(updater->startup_arg, ANY_PATH(""), EXT_PATH(""));
4040
} else {

firmware/targets/f7/Inc/FreeRTOSConfig.h

+5-1
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ extern uint32_t SystemCoreClock;
3232
#define configUSE_16_BIT_TICKS 0
3333
#define configUSE_MUTEXES 1
3434
#define configQUEUE_REGISTRY_SIZE 0
35-
#define configCHECK_FOR_STACK_OVERFLOW 2
35+
#define configCHECK_FOR_STACK_OVERFLOW 0
3636
#define configUSE_RECURSIVE_MUTEXES 1
3737
#define configUSE_COUNTING_SEMAPHORES 1
3838
#define configENABLE_BACKWARD_COMPATIBILITY 0
@@ -145,3 +145,7 @@ standard names. */
145145
#define USE_CUSTOM_SYSTICK_HANDLER_IMPLEMENTATION 1
146146
#define configOVERRIDE_DEFAULT_TICK_CONFIGURATION \
147147
1 /* required only for Keil but does not hurt otherwise */
148+
149+
#define traceTASK_SWITCHED_IN() \
150+
extern void furi_hal_mpu_set_stack_protection(uint32_t* stack); \
151+
furi_hal_mpu_set_stack_protection((uint32_t*)pxCurrentTCB->pxStack)

firmware/targets/f7/furi_hal/furi_hal.c

+2-11
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
#include <furi_hal.h>
2+
#include <furi_hal_mpu.h>
23

34
#include <stm32wbxx_ll_cortex.h>
45

@@ -35,6 +36,7 @@ void furi_hal_deinit_early() {
3536
}
3637

3738
void furi_hal_init() {
39+
furi_hal_mpu_init();
3840
furi_hal_clock_init();
3941
furi_hal_console_init();
4042
furi_hal_rtc_init();
@@ -80,17 +82,6 @@ void furi_hal_init() {
8082
// FatFS driver initialization
8183
MX_FATFS_Init();
8284
FURI_LOG_I(TAG, "FATFS OK");
83-
84-
// Partial null pointer dereference protection
85-
LL_MPU_Disable();
86-
LL_MPU_ConfigRegion(
87-
LL_MPU_REGION_NUMBER0,
88-
0x00,
89-
0x0,
90-
LL_MPU_REGION_SIZE_1MB | LL_MPU_REGION_PRIV_RO_URO | LL_MPU_ACCESS_BUFFERABLE |
91-
LL_MPU_ACCESS_CACHEABLE | LL_MPU_ACCESS_SHAREABLE | LL_MPU_TEX_LEVEL1 |
92-
LL_MPU_INSTRUCTION_ACCESS_ENABLE);
93-
LL_MPU_Enable(LL_MPU_CTRL_PRIVILEGED_DEFAULT);
9485
}
9586

9687
void furi_hal_switch(void* address) {

firmware/targets/f7/furi_hal/furi_hal_interrupt.c

+19
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
#include <stm32wbxx.h>
77
#include <stm32wbxx_ll_tim.h>
88
#include <stm32wbxx_ll_rcc.h>
9+
#include <stm32wbxx_ll_cortex.h>
910

1011
#define TAG "FuriHalInterrupt"
1112

@@ -95,6 +96,10 @@ void furi_hal_interrupt_init() {
9596
LL_SYSCFG_DisableIT_FPU_IDC();
9697
LL_SYSCFG_DisableIT_FPU_IXC();
9798

99+
LL_HANDLER_EnableFault(LL_HANDLER_FAULT_USG);
100+
LL_HANDLER_EnableFault(LL_HANDLER_FAULT_BUS);
101+
LL_HANDLER_EnableFault(LL_HANDLER_FAULT_MEM);
102+
98103
FURI_LOG_I(TAG, "Init OK");
99104
}
100105

@@ -241,6 +246,20 @@ void HardFault_Handler() {
241246
}
242247

243248
void MemManage_Handler() {
249+
if(FURI_BIT(SCB->CFSR, SCB_CFSR_MMARVALID_Pos)) {
250+
uint32_t memfault_address = SCB->MMFAR;
251+
if(memfault_address < (1024 * 1024)) {
252+
// from 0x00 to 1MB, see FuriHalMpuRegionNULL
253+
furi_crash("NULL pointer dereference");
254+
} else {
255+
// write or read of MPU region 1 (FuriHalMpuRegionStack)
256+
furi_crash("MPU fault, possibly stack overflow");
257+
}
258+
} else if(FURI_BIT(SCB->CFSR, SCB_CFSR_MSTKERR_Pos)) {
259+
// push to stack on MPU region 1 (FuriHalMpuRegionStack)
260+
furi_crash("MemManage fault, possibly stack overflow");
261+
}
262+
244263
furi_crash("MemManage");
245264
}
246265

0 commit comments

Comments
 (0)