Skip to content

Commit d4f810f

Browse files
authored
Merge pull request #205 from SHA2017-badge/safe-mode
Safe mode to allow recovery from malware
2 parents 1348972 + 49e95f1 commit d4f810f

File tree

11 files changed

+92
-40
lines changed

11 files changed

+92
-40
lines changed

esp32/main.c

Lines changed: 52 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@
3535
#include "esp_system.h"
3636
#include "esp_task.h"
3737
#include "soc/cpu.h"
38+
#include "rom/rtc.h"
3839

3940
#include "sha2017_ota.h"
4041
#include "esprtcmem.h"
@@ -56,6 +57,7 @@
5657
#include "badge_base.h"
5758
#include "badge_first_run.h"
5859
#include <badge_input.h>
60+
#include <badge_button.h>
5961
#include <badge.h>
6062

6163
// MicroPython runs as a task under FreeRTOS
@@ -64,11 +66,53 @@
6466
#define MP_TASK_STACK_LEN (MP_TASK_STACK_SIZE / sizeof(StackType_t))
6567
#define MP_TASK_HEAP_SIZE (88 * 1024)
6668

69+
//define BUTTON_SAFE_MODE ((1 << BADGE_BUTTON_A) || (1 << BADGE_BUTTON_B))
70+
#define BUTTON_SAFE_MODE ((1 << BADGE_BUTTON_START))
71+
6772
STATIC StaticTask_t mp_task_tcb;
6873
STATIC StackType_t mp_task_stack[MP_TASK_STACK_LEN] __attribute__((aligned (8)));
6974
STATIC uint8_t mp_task_heap[MP_TASK_HEAP_SIZE];
7075

7176
extern uint32_t reset_cause;
77+
extern bool in_safe_mode;
78+
79+
static const char *import_blacklist[] = {
80+
"/lib/json",
81+
"/lib/os",
82+
"/lib/socket",
83+
"/lib/struct",
84+
"/lib/time",
85+
};
86+
87+
mp_import_stat_t
88+
mp_import_stat(const char *path) {
89+
if (in_safe_mode) {
90+
// be more strict in which modules we would like to load
91+
if (strncmp(path, "/lib/", 5) != 0) {
92+
return MP_IMPORT_STAT_NO_EXIST;
93+
}
94+
95+
/* check blacklist */
96+
int i;
97+
for (i=0; i<sizeof(import_blacklist)/sizeof(const char *); i++) {
98+
if (strcmp(path, import_blacklist[i]) == 0) {
99+
return MP_IMPORT_STAT_NO_EXIST;
100+
}
101+
}
102+
103+
const char *x = index(&path[5], '/');
104+
if (x == NULL) {
105+
// only allow directories
106+
mp_import_stat_t res = mp_vfs_import_stat(path);
107+
if (res != MP_IMPORT_STAT_DIR) {
108+
return MP_IMPORT_STAT_NO_EXIST;
109+
}
110+
return res;
111+
}
112+
}
113+
114+
return mp_vfs_import_stat(path);
115+
}
72116

73117
void mp_task(void *pvParameter) {
74118
volatile uint32_t sp = (uint32_t)get_sp();
@@ -96,7 +140,7 @@ void mp_task(void *pvParameter) {
96140
// run boot-up scripts
97141
pyexec_frozen_module("_boot.py");
98142
if (pyexec_mode_kind != PYEXEC_MODE_RAW_REPL) {
99-
pyexec_file("boot.py");
143+
pyexec_frozen_module("boot.py");
100144
}
101145
// if (pyexec_mode_kind == PYEXEC_MODE_FRIENDLY_REPL) {
102146
// pyexec_file("main.py");
@@ -176,6 +220,13 @@ void app_main(void) {
176220
}
177221

178222
} else {
223+
uint32_t reset_cause = rtc_get_reset_reason(0);
224+
if (reset_cause != DEEPSLEEP_RESET) {
225+
badge_init();
226+
if ((badge_input_button_state & BUTTON_SAFE_MODE) == BUTTON_SAFE_MODE) {
227+
in_safe_mode = true;
228+
}
229+
}
179230
xTaskCreateStaticPinnedToCore(mp_task, "mp_task", MP_TASK_STACK_LEN, NULL, MP_TASK_PRIORITY,
180231
&mp_task_stack[0], &mp_task_tcb, 0);
181232
}

esp32/modbadge.c

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -242,6 +242,11 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_0(badge_mpr121_get_touch_info_obj, badge_mpr121_g
242242
#endif // I2C_MPR121_ADDR
243243

244244

245+
bool RTC_DATA_ATTR in_safe_mode = false;
246+
STATIC mp_obj_t badge_safe_mode() {
247+
return mp_obj_new_bool(in_safe_mode);
248+
}
249+
STATIC MP_DEFINE_CONST_FUN_OBJ_0(badge_safe_mode_obj, badge_safe_mode);
245250
// E-Ink (badge_eink.h)
246251

247252
STATIC mp_obj_t badge_eink_init_() {
@@ -682,6 +687,8 @@ STATIC const mp_rom_map_elem_t badge_module_globals_table[] = {
682687
{MP_OBJ_NEW_QSTR(MP_QSTR_unmount_sdcard), (mp_obj_t)&badge_unmount_sdcard_obj},
683688
{MP_OBJ_NEW_QSTR(MP_QSTR_mount_bpp), (mp_obj_t)&badge_mount_bpp_obj},
684689

690+
{MP_OBJ_NEW_QSTR(MP_QSTR_safe_mode), (mp_obj_t)&badge_safe_mode_obj},
691+
685692
};
686693

687694
STATIC MP_DEFINE_CONST_DICT(badge_module_globals, badge_module_globals_table);

esp32/modules/_boot.py

Lines changed: 2 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,6 @@
11
import badge, gc, uos
22

3-
try:
4-
badge.mount_root()
5-
uos.mount(uos.VfsNative(None), '/')
6-
with open("/boot.py", "r") as f:
7-
f.close()
8-
9-
except OSError:
10-
import inisetup
11-
vfs = inisetup.setup()
3+
badge.mount_root()
4+
uos.mount(uos.VfsNative(None), '/')
125

136
gc.collect()
Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,13 @@
1-
import uos
2-
3-
def boot():
4-
print("Updating 'boot.py'...")
5-
with open("/boot.py", "w") as f:
6-
f.write("""\
71
# This file is executed on every boot (including wake-boot from deepsleep)
82
import badge, machine, esp, ugfx, sys
93
badge.init()
104
ugfx.init()
115
esp.rtcmem_write(0,0)
126
esp.rtcmem_write(1,0)
13-
splash = badge.nvs_get_str('boot','splash','splash')
7+
if badge.safe_mode():
8+
splash = 'splash'
9+
else:
10+
splash = badge.nvs_get_str('boot','splash','splash')
1411
if machine.reset_cause() != machine.DEEPSLEEP_RESET:
1512
print('[BOOT] Cold boot')
1613
else:
@@ -39,4 +36,3 @@ def boot():
3936
time.sleep(5)
4037
import appglue
4138
appglue.home()
42-
""")

esp32/modules/inisetup.py

Lines changed: 0 additions & 8 deletions
This file was deleted.

esp32/modules/launcher.py

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -166,9 +166,16 @@ def start():
166166
ugfx.clear(ugfx.WHITE)
167167
ugfx.flush()
168168

169-
ugfx.string_box(148,0,148,26, "STILL", "Roboto_BlackItalic24", ugfx.BLACK, ugfx.justifyCenter)
169+
if badge.safe_mode():
170+
still = "SAFE"
171+
anyway = "Mode"
172+
else:
173+
still = "STILL"
174+
anyway = "Anyway"
175+
176+
ugfx.string_box(148,0,148,26, still, "Roboto_BlackItalic24", ugfx.BLACK, ugfx.justifyCenter)
170177
ugfx.string_box(148,23,148,23, "Hacking", "PermanentMarker22", ugfx.BLACK, ugfx.justifyCenter)
171-
ugfx.string_box(148,48,148,26, "Anyway", "Roboto_BlackItalic24", ugfx.BLACK, ugfx.justifyCenter)
178+
ugfx.string_box(148,48,148,26, anyway, "Roboto_BlackItalic24", ugfx.BLACK, ugfx.justifyCenter)
172179

173180
#the line under the text
174181
str_len = ugfx.get_string_width("Hacking","PermanentMarker22")

esp32/modules/post_ota.py

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,6 @@
11
import badge, easydraw
22

33
def u0to1():
4-
import create
5-
create.boot()
64
easydraw.msg("Applied patch 1")
75

86
def u1to2():

esp32/modules/splash.py

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -35,10 +35,18 @@ def draw(mode, goingToSleep=False):
3535
info2 = 'Press select to start OTA update'
3636
else:
3737
info2 = ''
38-
l = ugfx.get_string_width(info1,"Roboto_Regular12")
39-
ugfx.string(296-l, 0, info1, "Roboto_Regular12",ugfx.BLACK)
40-
l = ugfx.get_string_width(info2,"Roboto_Regular12")
41-
ugfx.string(296-l, 12, info2, "Roboto_Regular12",ugfx.BLACK)
38+
39+
def disp_string_right(y, s):
40+
l = ugfx.get_string_width(s,"Roboto_Regular12")
41+
ugfx.string(296-l, y, s, "Roboto_Regular12",ugfx.BLACK)
42+
43+
disp_string_right(0, info1)
44+
disp_string_right(12, info2)
45+
46+
if badge.safe_mode():
47+
disp_string_right(92, "Safe Mode - services disabled")
48+
disp_string_right(104, "Sleep disabled - will drain battery quickly")
49+
disp_string_right(116, "Press Reset button to exit")
4250

4351
easydraw.nickname()
4452

@@ -156,7 +164,8 @@ def onSleep(idleTime):
156164
if not easywifi.failure():
157165
spoc.show(False) # Check sponsors
158166

159-
services.setup(draw) # Start services
167+
if not badge.safe_mode():
168+
services.setup(draw) # Start services
160169

161170
draw(False)
162171
services.force_draw()

esp32/modules/tasks/powermanagement.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ def pm_task():
1818
idleTime = virtualtimers.idle_time()
1919
print("[Power management] Next task wants to run in "+str(idleTime)+" ms.")
2020

21-
if idleTime>30000:
21+
if idleTime>30000 and not badge.safe_mode():
2222
global onSleepCallback
2323
if not onSleepCallback==None:
2424
print("[Power management] Running onSleepCallback...")

esp32/modules/version.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,2 @@
1-
build = 8
2-
name = "Maffe Maniak"
1+
build = 9
2+
name = "Sinistere Site"

0 commit comments

Comments
 (0)