What changed, and why it matters
This commit removes support for an old, discontinued hardware device called the Maix Bit from the Krux Bitcoin wallet firmware. The commit message says the Maix Bit's camera resolution (CIF) was the only one that fed frames larger than QVGA into a 'shannon entropy' module, overflowing that module's scratch buffer by 49,152 bytes. In plain terms, this is a fix for a buffer overflow bug, but the fix is to delete the only hardware configuration that triggered it rather than enlarge the buffer. Because the device was already discontinued and reportedly has no users, the practical risk is low, but the underlying overflow condition is a real memory-safety issue.
Verify that no other code path can still configure a framesize larger than QVGA for the entropy module, and consider adding an explicit guard or buffer-size assertion in the shannon entropy module so the overflow cannot reappear if a new device or sensor is added later. Users on Maix Bit hardware should migrate to a supported device because this firmware no longer supports it.
Security signals we found
Buffer overflow / scratch buffer overflow claimed in commit message (49,152 bytes)
Removal of vulnerable hardware code path rather than hardening the entropy module
Discontinuation of affected device reduces real-world exposure
Memory-safety issue in cryptographic/randomness-related entropy collection path
Evidence from the diff
The patch deletes Maix Bit (‘bit’) board detection, the OV5642 sensor driver entries, and the CIF framesize code path in src/krux/camera.py. The commit message explicitly frames the change as fixing a buffer overflow: the CIF frame (352x288) is larger than QVGA (320x240) and caused the shannon entropy module’s scratch buffer to overflow by 49152 bytes. The patch is a removal rather than a bounds-check or buffer-size fix, so it eliminates the vulnerable code path for current/future builds. The overflow itself is not demonstrated in the diff; only the removal of the triggering configuration is shown. No CVE or vendor advisory is supplied.
Changed components
src/krux/camera.pysrc/krux/kboard.pyfirmware/font/bdftokff.pytests/conftest.pytests/shared_mocks.pytests/test_camera.pytests/test_power.pytests/pages/test_flash_tools.pytests/pages/test_page.pyInspect captured patch +11 / −127
diff --git a/firmware/font/bdftokff.py b/firmware/font/bdftokff.py
index 6f0887f..36a4824 100644
--- a/firmware/font/bdftokff.py
+++ b/firmware/font/bdftokff.py
@@ -50,7 +50,6 @@ REF_DEVICES = [SMALL_FONT_REF, MID_FONT_REF, BIG_FONT_REF]
SMALL_FONT_DEVICES_TO_COPY = ["cube"]
MID_FONT_DEVICES_TO_COPY = [
- "bit",
"yahboom",
"wonder_mv",
"tzt",
diff --git a/src/krux/camera.py b/src/krux/camera.py
index 9508807..89d27e9 100644
--- a/src/krux/camera.py
+++ b/src/krux/camera.py
@@ -26,8 +26,7 @@ import sensor
from .krux_settings import Settings
from .kboard import kboard
-OV2640_ID = 0x2642 # Lenses, vertical flip - Bit
-OV5642_ID = 0x5642 # Lenses, horizontal flip - Bit
+OV2640_ID = 0x2642 # Lenses, vertical flip - Embed Fire
OV7740_ID = 0x7742 # No lenses, no Flip - M5sitckV, Amigo
GC0328_ID = 0x9D # Dock
GC2145_ID = 0x45 # Yahboom, WonderK
@@ -53,11 +52,6 @@ LUM_TH = {
(OV2640_ID, ENTROPY_MODE): (0x68, 0x78),
(OV2640_ID, BINARY_GRID_MODE): (0x44, 0x48),
(OV2640_ID, ZOOMED_MODE): (0x35, 0x50),
- (OV5642_ID, QR_SCAN_MODE): (0x60, 0x70),
- (OV5642_ID, ANTI_GLARE_MODE): (0x20, 0x28),
- (OV5642_ID, ENTROPY_MODE): (0x68, 0x78),
- (OV5642_ID, BINARY_GRID_MODE): (0x44, 0x48),
- (OV5642_ID, ZOOMED_MODE): (0x35, 0x50),
(OV7740_ID, QR_SCAN_MODE): (0x60, 0x70),
(OV7740_ID, ANTI_GLARE_MODE): (0x20, 0x28),
(OV7740_ID, ENTROPY_MODE): (0x68, 0x78),
@@ -114,18 +108,12 @@ class Camera:
sensor.set_pixformat(sensor.GRAYSCALE)
else:
sensor.set_pixformat(sensor.RGB565)
- if self.cam_id == OV5642_ID:
- sensor.set_hmirror(1)
if self.cam_id == OV2640_ID:
if kboard.is_embed_fire:
sensor.set_hmirror(0)
else:
sensor.set_vflip(1)
- if kboard.is_bit:
- # CIF mode will use central pixels and discard darker periphery
- sensor.set_framesize(sensor.CIF)
- else:
- sensor.set_framesize(sensor.QVGA)
+ sensor.set_framesize(sensor.QVGA)
if mode != ENTROPY_MODE:
if self.cam_id == OV7740_ID:
self.config_ov_7740()
@@ -186,7 +174,6 @@ class Camera:
GC0328_ID: self._config_gc0328_lum,
OV2640_ID: self._config_ovxx40_lum,
OV7740_ID: self._config_ovxx40_lum, # Same as OV2640
- OV5642_ID: self._config_ovxx40_lum, # Same as OV2640
GC2145_ID: self._config_gc2145_lum,
}
@@ -359,11 +346,7 @@ class Camera:
def snapshot(self):
"""Helper to take a customized snapshot from sensor"""
- img = sensor.snapshot()
- if kboard.is_bit:
- img.lens_corr(strength=1.1)
- img.rotation_corr(z_rotation=180)
- return img
+ return sensor.snapshot()
def initialize_run(self, mode=QR_SCAN_MODE):
"""Initializes and runs sensor"""
diff --git a/src/krux/kboard.py b/src/krux/kboard.py
index bf77ad9..30936c2 100644
--- a/src/krux/kboard.py
+++ b/src/krux/kboard.py
@@ -28,7 +28,6 @@ class KBoard:
def __init__(self):
self.is_amigo = board.config["type"] == "amigo"
- self.is_bit = board.config["type"] == "bit"
self.is_cube = board.config["type"] == "cube"
self.is_embed_fire = board.config["type"] == "embed_fire"
self.is_yahboom = board.config["type"] == "yahboom"
diff --git a/tests/conftest.py b/tests/conftest.py
index 15c2f2a..98cad5b 100644
--- a/tests/conftest.py
+++ b/tests/conftest.py
@@ -8,7 +8,6 @@ from .shared_mocks import (
board_m5stickv,
board_wonder_mv,
board_yahboom,
- board_bit,
board_wonder_k,
board_embed_fire,
encode_to_string,
@@ -172,15 +171,6 @@ def wonder_mv(monkeypatch, mp_modules):
reset_krux_modules()
-@pytest.fixture
-def bit(monkeypatch, mp_modules):
- import sys
-
- monkeypatch.setitem(sys.modules, "board", board_bit())
- monkeypatch.setitem(sys.modules, "pmu", None)
- reset_krux_modules()
-
-
@pytest.fixture
def wonder_k(monkeypatch, mp_modules):
import sys
@@ -207,7 +197,6 @@ def embed_fire(monkeypatch, mp_modules):
"cube",
"yahboom",
"wonder_mv",
- "bit",
"wonder_k",
]
)
diff --git a/tests/pages/test_flash_tools.py b/tests/pages/test_flash_tools.py
index c5b2d27..ad9ef69 100644
--- a/tests/pages/test_flash_tools.py
+++ b/tests/pages/test_flash_tools.py
@@ -89,7 +89,6 @@ def test_tc_flash_hash(multiple_devices, mocker):
"cube": 208,
"yahboom": DOCK_FW_POS,
"wonder_mv": DOCK_FW_POS,
- "bit": DOCK_FW_POS,
"wonder_k": DOCK_FW_POS,
}
users_data_words_positions = {
@@ -99,7 +98,6 @@ def test_tc_flash_hash(multiple_devices, mocker):
"cube": 222,
"yahboom": DOCK_USER_POS,
"wonder_mv": DOCK_USER_POS,
- "bit": DOCK_USER_POS,
"wonder_k": DOCK_USER_POS,
}
fw_words_pos = fw_words_positions[board.config["type"]]
diff --git a/tests/pages/test_page.py b/tests/pages/test_page.py
index b731697..cb2585f 100644
--- a/tests/pages/test_page.py
+++ b/tests/pages/test_page.py
@@ -367,7 +367,6 @@ def test_fit_to_line_text(mocker, multiple_devices, mock_page_cls):
AMIGO = "amigo"
M5 = "m5stickv"
DOCK = "dock"
- BIT = "bit"
CUBE = "cube"
YAHBOOM = "yahboom"
WONDER_MV = "wonder_mv"
@@ -379,7 +378,6 @@ def test_fit_to_line_text(mocker, multiple_devices, mock_page_cls):
AMIGO: "0123456789ab…opqrstuvwxyz",
M5: "0123456…tuvwxyz",
DOCK: "0123456789abc…nopqrstuvwxyz",
- BIT: "0123456789abc…nopqrstuvwxyz",
CUBE: "0123456789abc…nopqrstuvwxyz",
YAHBOOM: "0123456789abc…nopqrstuvwxyz",
WONDER_MV: "0123456789abc…nopqrstuvwxyz",
@@ -390,7 +388,6 @@ def test_fit_to_line_text(mocker, multiple_devices, mock_page_cls):
AMIGO: "0123456789ab…nopqrstuvwxy",
M5: "0123456…stuvwxy",
DOCK: "0123456789abc…mnopqrstuvwxy",
- BIT: "0123456789abc…mnopqrstuvwxy",
CUBE: "0123456789abc…mnopqrstuvwxy",
YAHBOOM: "0123456789abc…mnopqrstuvwxy",
WONDER_MV: "0123456789abc…mnopqrstuvwxy",
@@ -401,7 +398,6 @@ def test_fit_to_line_text(mocker, multiple_devices, mock_page_cls):
AMIGO: "0123456789ab…mnopqrstuvwx",
M5: "0123456…rstuvwx",
DOCK: "0123456789abc…lmnopqrstuvwx",
- BIT: "0123456789abc…lmnopqrstuvwx",
CUBE: "0123456789abc…lmnopqrstuvwx",
YAHBOOM: "0123456789abc…lmnopqrstuvwx",
WONDER_MV: "0123456789abc…lmnopqrstuvwx",
@@ -412,7 +408,6 @@ def test_fit_to_line_text(mocker, multiple_devices, mock_page_cls):
AMIGO: "0123456789ab…lmnopqrstuvw",
M5: "0123456…qrstuvw",
DOCK: "0123456789abc…klmnopqrstuvw",
- BIT: "0123456789abc…klmnopqrstuvw",
CUBE: "0123456789abc…klmnopqrstuvw",
YAHBOOM: "0123456789abc…klmnopqrstuvw",
WONDER_MV: "0123456789abc…klmnopqrstuvw",
@@ -423,7 +418,6 @@ def test_fit_to_line_text(mocker, multiple_devices, mock_page_cls):
AMIGO: "0123456789ab…ghijklmnopqr",
M5: "0123456…lmnopqr",
DOCK: "0123456789abc…fghijklmnopqr",
- BIT: "0123456789abc…fghijklmnopqr",
CUBE: "0123456789abc…fghijklmnopqr",
YAHBOOM: "0123456789abc…fghijklmnopqr",
WONDER_MV: "0123456789abc…fghijklmnopqr",
@@ -434,7 +428,6 @@ def test_fit_to_line_text(mocker, multiple_devices, mock_page_cls):
AMIGO: "0123456789ab…fghijklmnopq",
M5: "0123456…klmnopq",
DOCK: "0123456789abcdefghijklmnopq",
- BIT: "0123456789abcdefghijklmnopq",
CUBE: "0123456789abcdefghijklmnopq",
YAHBOOM: "0123456789abcdefghijklmnopq",
WONDER_MV: "0123456789abcdefghijklmnopq",
@@ -445,7 +438,6 @@ def test_fit_to_line_text(mocker, multiple_devices, mock_page_cls):
AMIGO: "0123456789ab…efghijklmnop",
M5: "0123456…jklmnop",
DOCK: "0123456789abcdefghijklmnop",
- BIT: "0123456789abcdefghijklmnop",
CUBE: "0123456789abcdefghijklmnop",
YAHBOOM: "0123456789abcdefghijklmnop",
WONDER_MV: "0123456789abcdefghijklmnop",
@@ -456,7 +448,6 @@ def test_fit_to_line_text(mocker, multiple_devices, mock_page_cls):
AMIGO: "0123456789abcdefghijklmno",
M5: "0123456…ijklmno",
DOCK: "0123456789abcdefghijklmno",
- BIT: "0123456789abcdefghijklmno",
CUBE: "0123456789abcdefghijklmno",
YAHBOOM: "0123456789abcdefghijklmno",
WONDER_MV: "0123456789abcdefghijklmno",
@@ -467,7 +458,6 @@ def test_fit_to_line_text(mocker, multiple_devices, mock_page_cls):
AMIGO: "0123456789abcdefghijklmn",
M5: "0123456…hijklmn",
DOCK: "0123456789abcdefghijklmn",
- BIT: "0123456789abcdefghijklmn",
CUBE: "0123456789abcdefghijklmn",
YAHBOOM: "0123456789abcdefghijklmn",
WONDER_MV: "0123456789abcdefghijklmn",
@@ -478,7 +468,6 @@ def test_fit_to_line_text(mocker, multiple_devices, mock_page_cls):
AMIGO: "0123456789abcdefghijklm",
M5: "0123456…ghijklm",
DOCK: "0123456789abcdefghijklm",
- BIT: "0123456789abcdefghijklm",
CUBE: "0123456789abcdefghijklm",
YAHBOOM: "0123456789abcdefghijklm",
WONDER_MV: "0123456789abcdefghijklm",
@@ -489,7 +478,6 @@ def test_fit_to_line_text(mocker, multiple_devices, mock_page_cls):
AMIGO: "0123456789abcdefghij",
M5: "0123456…defghij",
DOCK: "0123456789abcdefghij",
- BIT: "0123456789abcdefghij",
CUBE: "0123456789abcdefghij",
YAHBOOM: "0123456789abcdefghij",
WONDER_MV: "0123456789abcdefghij",
@@ -500,7 +488,6 @@ def test_fit_to_line_text(mocker, multiple_devices, mock_page_cls):
AMIGO: "0123456789abcdefg",
M5: "0123456…abcdefg",
DOCK: "0123456789abcdefg",
- BIT: "0123456789abcdefg",
CUBE: "0123456789abcdefg",
YAHBOOM: "0123456789abcdefg",
WONDER_MV: "0123456789abcdefg",
@@ -511,7 +498,6 @@ def test_fit_to_line_text(mocker, multiple_devices, mock_page_cls):
AMIGO: "0123456789abcdef",
M5: "0123456789abcdef",
DOCK: "0123456789abcdef",
- BIT: "0123456789abcdef",
CUBE: "0123456789abcdef",
YAHBOOM: "0123456789abcdef",
WONDER_MV: "0123456789abcdef",
@@ -522,7 +508,6 @@ def test_fit_to_line_text(mocker, multiple_devices, mock_page_cls):
AMIGO: "0123456789abcde",
M5: "0123456789abcde",
DOCK: "0123456789abcde",
- BIT: "0123456789abcde",
CUBE: "0123456789abcde",
YAHBOOM: "0123456789abcde",
WONDER_MV: "0123456789abcde",
diff --git a/tests/shared_mocks.py b/tests/shared_mocks.py
index ee6a709..ebf88de 100644
--- a/tests/shared_mocks.py
+++ b/tests/shared_mocks.py
@@ -665,29 +665,6 @@ def board_wonder_mv():
)
-def board_bit():
- return mock.MagicMock(
- config={
- "type": "bit",
- "lcd": {"height": 240, "width": 320, "invert": 0, "lcd_type": 0},
- "sdcard": {"sclk": 27, "mosi": 28, "miso": 26, "cs": 29},
- "board_info": {
- "BOOT_KEY": 16,
- "LED_R": 13,
- "LED_G": 12,
- "LED_B": 14,
- "MIC0_WS": 19,
- "MIC0_DATA": 20,
- "MIC0_BCK": 18,
- },
- "krux": {
- "pins": {"BUTTON_A": 22, "BUTTON_B": 21, "BUTTON_C": 16},
- "display": {"touch": False, "font": [8, 16], "font_wide": [16, 16]},
- },
- }
- )
-
-
def board_wonder_k():
return mock.MagicMock(
config={
@@ -946,30 +923,6 @@ def mock_context(mocker):
),
)
- elif board.config["type"] == "bit":
- return mocker.MagicMock(
- input=mocker.MagicMock(
- touch=None,
- enter_event=mocker.MagicMock(return_value=False),
- page_event=mocker.MagicMock(return_value=False),
- page_prev_event=mocker.MagicMock(return_value=False),
- touch_event=mocker.MagicMock(return_value=False),
- ),
- display=mocker.MagicMock(
- font_width=8,
- font_height=16,
- total_lines=20, # 320 / 16
- width=mocker.MagicMock(return_value=DOCK_WIDTH),
- height=mocker.MagicMock(return_value=DOCK_HEIGHT),
- usable_width=mocker.MagicMock(return_value=DOCK_USABLE_WIDTH),
- usable_pixels_in_line=mocker.MagicMock(return_value=DOCK_USABLE_WIDTH),
- ascii_chars_per_line=mocker.MagicMock(return_value=DOCK_IN_LINE),
- to_lines=mocker.MagicMock(return_value=[""]),
- max_menu_lines=mocker.MagicMock(return_value=9),
- draw_hcentered_text=mocker.MagicMock(return_value=1),
- ),
- )
-
elif board.config["type"] == "wonder_k":
return mocker.MagicMock(
input=mocker.MagicMock(
diff --git a/tests/test_camera.py b/tests/test_camera.py
index 78854ee..183a73c 100644
--- a/tests/test_camera.py
+++ b/tests/test_camera.py
@@ -17,7 +17,6 @@ def test_initialize_sensors(mocker, multiple_devices):
from krux.camera import (
Camera,
OV7740_ID,
- OV5642_ID,
OV2640_ID,
GC0328_ID,
GC2145_ID,
@@ -26,7 +25,6 @@ def test_initialize_sensors(mocker, multiple_devices):
SENSORS_LIST = [
(OV7740_ID, "config_ov_7740"),
(OV2640_ID, "config_ov_2640"),
- (OV5642_ID, None),
(GC0328_ID, None),
(GC2145_ID, "config_gc_2145"),
]
@@ -50,7 +48,7 @@ def test_initialize_sensors(mocker, multiple_devices):
krux.camera.sensor.set_vflip.reset_mock()
- if board.config["type"] in ("cube", "wonder_k") or c.cam_id == OV5642_ID:
+ if board.config["type"] in ("cube", "wonder_k"):
krux.camera.sensor.set_hmirror.assert_called_with(1)
else:
krux.camera.sensor.set_hmirror.assert_not_called()
@@ -68,16 +66,10 @@ def test_initialize_sensors(mocker, multiple_devices):
krux.camera.sensor.set_pixformat.reset_mock()
krux.camera.sensor.set_framesize.assert_called()
- if board.config["type"] != "bit":
- assert (
- krux.camera.sensor.set_framesize.call_args.args[0]._extract_mock_name()
- == "mock.QVGA"
- )
- else:
- assert (
- krux.camera.sensor.set_framesize.call_args.args[0]._extract_mock_name()
- == "mock.CIF"
- )
+ assert (
+ krux.camera.sensor.set_framesize.call_args.args[0]._extract_mock_name()
+ == "mock.QVGA"
+ )
krux.camera.sensor.set_framesize.reset_mock()
@@ -139,7 +131,6 @@ def test_toggle_mode(mocker, m5stickv):
from krux.camera import (
Camera,
OV7740_ID,
- OV5642_ID,
OV2640_ID,
GC0328_ID,
GC2145_ID,
@@ -148,7 +139,7 @@ def test_toggle_mode(mocker, m5stickv):
ZOOMED_MODE,
)
- SENSORS_LIST = [OV7740_ID, OV5642_ID, OV2640_ID, GC0328_ID, GC2145_ID]
+ SENSORS_LIST = [OV7740_ID, OV2640_ID, GC0328_ID, GC2145_ID]
for sensor_id in SENSORS_LIST:
mocker.patch("krux.camera.sensor.get_id", lambda: sensor_id)
@@ -167,18 +158,9 @@ def test_toggle_mode(mocker, m5stickv):
def test_snapshot(mocker, multiple_devices):
import krux
- import board
from krux.camera import Camera
- if board.config["type"] == "bit":
- image = mocker.MagicMock(
- lens_corr=mocker.MagicMock(), rotation_corr=mocker.MagicMock()
- )
- mock_snapshot = mocker.MagicMock(return_value=image)
- else:
- mock_snapshot = mocker.MagicMock()
-
- mocker.patch("krux.camera.sensor.snapshot", side_effect=mock_snapshot)
+ mocker.patch("krux.camera.sensor.snapshot", side_effect=mocker.MagicMock())
c = Camera()
c.initialize_sensor()
@@ -186,10 +168,6 @@ def test_snapshot(mocker, multiple_devices):
krux.camera.sensor.snapshot.assert_called()
- if board.config["type"] == "bit":
- image.lens_corr.assert_called_with(strength=1.1)
- image.rotation_corr.assert_called_with(z_rotation=180)
-
def test_stop_sensor(mocker, multiple_devices):
import krux
diff --git a/tests/test_power.py b/tests/test_power.py
index 43422ce..627fbc1 100644
--- a/tests/test_power.py
+++ b/tests/test_power.py
@@ -15,7 +15,7 @@ def test_pmu(mocker, multiple_devices):
manager = PowerManager()
- if board.config["type"] in ("dock", "yahboom", "wonder_mv", "bit", "wonder_k"):
+ if board.config["type"] in ("dock", "yahboom", "wonder_mv", "wonder_k"):
assert manager.pmu is None
assert manager.has_battery() is False
else:
Why this scored 52/100
Community notes
Notes can correct, qualify, or add evidence to the AI analysis. Every note shown here has been validated by a human moderator.
The AI analysis stands alone for now. Submit a note if you can add evidence or important context.