来自 M59 内存与资源安全审计(这 3 条 P1 很可能就是 2026-11-11 18:44 设备用户态崩塌的 成因:当时 sshd 连 fork 都做不到、ICMP 仍应答)。执行顺序按审计要求 P1-3 → P2-1 → P1-1 → P1-2。 P1-1 launcherd net.c:popen_read_tmo —— 对持续输出的子进程永不超时 + 堆无限增长 - 新增 meow_launcherd/popen_tmo.h:读循环的 deadline 移到**循环顶部**,输出加 256KB 硬 上限(超限返回 OVERFLOW,调用方 kill 子进程并按失败返回 NULL,绝不静默截断),缓冲交给 调用方或由本函数持有(无 static)。 - net.c 收尸改为 popen_tmo_reap_bounded(300ms + SIGKILL + 300ms):旧实现 SIGKILL 之后是 无条件 waitpid(…,0),子进程卡 D 态照样钉死 UI 线程。调用面(malloc 返回值 + free)不变, 14 个调用点零改动。 P1-2 audiod popen_read_tmo 的 static char buf[4096] 被 4 个线程共用 - 改成调用方传缓冲(`char *popen_read_tmo(tmo, cmd, out, cap)`),函数内无共享状态、不加锁 —— M55 刚把音量写路径做成无锁,音频线程上不能拿锁。7 个调用点各用自己的栈缓冲。 - 顺带修掉旧循环的 `remain` 不递减问题:旧写法每次 poll 都能重等满 tmo,最坏总时长 ≈ 4095 次 × 1500ms;现在总时长就是一个 tmo。 P1-3 netmgrd bt_scan_on/off 走无超时 system()(单线程主循环 + 55 个残留 bluetoothctl 的形态) - scan off:直接 run_cmd_ex(BT_SCAN_OFF_TMO_MS=600),超时如实回 MEOW_ERR_NODEV 并计入既有 bt_circuit_note。 - scan on:fork 一个 setsid 的 scan worker(在飞上限 1),worker 内部用 run_cmd_ex 跑同一条 pipeline(超时 + 输出上限);父进程只记账,bt_scan_reap() 在主循环每拍收割,过 deadline 杀**整个进程组**(pipeline 的 bluetoothctl 是孙进程,只杀 sh 会留孤儿)。 - 超时计入既有熔断(连 3 次 → 30s 内不再 fork);熔断中 scan on 不再起进程。 - 不在主循环里同步跑整条 pipeline:它要 ~5s(sleep 1 + dwell 4),同步跑等于每 7s 把 DNS 代理停 5s,是另一种挂死。 P2-1 扫描节流失效 7000 秒(mono_now() 返回秒,却与 7000 毫秒比较) - 节流改用 64 位毫秒时钟(bt_scan_now_ms / 函数指针钩子供宿主单测注入可控时钟),抽成纯 函数 bt_scan_throttle(now_ms);实际节流从 ~1.94 小时恢复到 7s。 测试(每条都有反向控制) - 新增 meow_launcherd/test_popen_tmo.c(已接入 build_launcher.sh test): 持续输出且永不退出的生产者 → 新循环 300ms 到点返回,旧循环 1500ms 内不返回; `yes`+64KB 上限 → 立刻 OVERFLOW;同一份 300KB 有界输入 → 旧循环照单全收 307200 字节、 新循环在上限处报 OVERFLOW;两线程交错读 → 旧 static 缓冲 A 读到 B 的内容,调用方缓冲各 读各的;收尸 313ms 有界且无残留子进程。 - meow_netmgrd/test_bt_ctl.c 增补:7s / 6.999s / 7.1s 边界(含走真实入口 bt_scan_on 的可控 时钟用例,秒/毫秒单位回归会在这里翻车);wedge 桩(scan 一律 exec sleep 60)下 scan off 611ms 有界返回且 ECHILD、scan on 的 worker 1200ms 窗口到期被整组收割、孙进程 全收(ECHILD)、超时进熔断并最终熔断拒绝 fork。 验证:netmgrd 宿主回归 79 PASS / 0 FAIL;test_bt_ctl ALL PASS;launcherd `build_launcher.sh test` ALL TESTS PASS(含新增用例);meow_netmgrd mipsel 交叉编译通过; audiod host 构建通过,test_audiod_host 的失败集合与改动前**逐条相同**(41 条,T8 SEGV 是 测试自身 strstr(q8,"rms=")+4 的既有缺陷,见 M59 审计 §5)。 仅源码:无二进制、未改 scripts/build/fw_content.conf。
93 lines
4.1 KiB
Bash
Executable File
93 lines
4.1 KiB
Bash
Executable File
#!/bin/bash
|
||
# build_launcher.sh — MeowOS launcher (A-1/A-2: launcher 用 SDK 渲染栈).
|
||
#
|
||
# 变更点(相对 M2.27 / A-0):
|
||
# - launcher 不再自建 back_buf/meow_present/refresh_governor —— 改用 SDK 渲染栈:
|
||
# fb 指向 SDK 的 back_buf(meow_ui_back_buf),呈现统一 meow_ui_flush()(SDK present,
|
||
# 内含 vsync + 帧率门控 + 原子 blit 脏区);刷新率档位经 meow_ui_set_refresh_rate()/
|
||
# set_refresh_always_max() 交给 SDK(归口 PERF_SCHEDULER 显示子域)。
|
||
# - 播放器 fb 双缓冲交互(fb_backup_player/fb_norm_buf0/fb_restore_player/FBIOPAN/yoffset)
|
||
# 保留不动(与 present 上屏不同层)。
|
||
# - launcher 与 SDK 共用同一 meow_font.o(已打进 meow_ui.a)——不再单独链 meow_font.a。
|
||
# - MEOWOS_VERSION 0.7.21 → 0.7.23(M2.28)。
|
||
#
|
||
# 用法(在 patch_v2/meow_launcherd 下或任意目录):
|
||
# bash build_launcher.sh # 交叉编译 meow_launcherd(mipsel 静态)
|
||
# bash build_launcher.sh test # 宿主 gcc 跑本目录 affected 单测(test_bt_page / test_netmgr_ipc)
|
||
#
|
||
# 工具链:优先环境变量 ZIGCC / MIPS_SYSROOT(M47 起),否则退回历史固定路径 $HOME/Project/R3ProII。
|
||
# export ZIGCC=$HOME/.tools/zig-mipsel-cc
|
||
set -e
|
||
cd "$(dirname "$0")"
|
||
|
||
CC="${ZIGCC:-$HOME/.tools/zig-mipsel-cc}"
|
||
[ -x "$CC" ] || CC="$HOME/Project/R3ProII/.tools/zig-mipsel-cc"
|
||
SYSROOT="${MIPS_SYSROOT:-$HOME/.tools/mipsel-linux-muslsf-cross/mipsel-linux-muslsf}"
|
||
[ -f "$SYSROOT/lib/libz.a" ] || SYSROOT="$HOME/Project/R3ProII/.tools/mipsel-linux-muslsf-cross/mipsel-linux-muslsf"
|
||
|
||
# ---------------- 宿主单测(M47 起提供入口;只跑本目录受影响的测试)----------------
|
||
run_tests() {
|
||
local HOSTCC="${HOSTCC:-gcc}"
|
||
local TMPD rc=0
|
||
TMPD="$(mktemp -d "${TMPDIR:-/tmp}/meow_launcher_test.XXXXXX")"
|
||
trap 'rm -rf "$TMPD"' EXIT
|
||
|
||
echo "== host test: test_bt_page =="
|
||
if "$HOSTCC" -I"../sdk" -I. -Wall -Wextra -fsanitize=undefined \
|
||
test_bt_page.c -o "$TMPD/test_bt_page"; then
|
||
"$TMPD/test_bt_page" || rc=1
|
||
else
|
||
rc=1
|
||
fi
|
||
|
||
echo "== host test: test_netmgr_ipc =="
|
||
if "$HOSTCC" -I"../sdk" -I. -Wall -Wextra -c netmgr_ipc.c -o "$TMPD/netmgr_ipc.test.o" \
|
||
&& "$HOSTCC" -I"../sdk" -I. -Wall -Wextra \
|
||
test_netmgr_ipc.c "$TMPD/netmgr_ipc.test.o" -lpthread -o "$TMPD/test_netmgr_ipc"; then
|
||
"$TMPD/test_netmgr_ipc" || rc=1
|
||
else
|
||
rc=1
|
||
fi
|
||
|
||
# M52:多字体日志跃迁签名(纯头文件逻辑,无设备/无 launcher 依赖)
|
||
echo "== host test: test_mf_logsig =="
|
||
if "$HOSTCC" -I. -Wall -Wextra test_mf_logsig.c -o "$TMPD/test_mf_logsig"; then
|
||
"$TMPD/test_mf_logsig" || rc=1
|
||
else
|
||
rc=1
|
||
fi
|
||
|
||
# M65:子进程 stdout 有界读取(popen_tmo.h;launcherd/net.c 与 audiod 共用)
|
||
# 含反向控制(旧循环在持续输出下永不返回 / 无输出上限 / static 缓冲串写)
|
||
echo "== host test: test_popen_tmo =="
|
||
if "$HOSTCC" -I. -Wall -Wextra test_popen_tmo.c -o "$TMPD/test_popen_tmo" -lpthread; then
|
||
"$TMPD/test_popen_tmo" || rc=1
|
||
else
|
||
rc=1
|
||
fi
|
||
|
||
if [ $rc -eq 0 ]; then echo "== ALL TESTS PASS =="; else echo "!! TESTS FAILED"; fi
|
||
return $rc
|
||
}
|
||
|
||
if [ "$1" = "test" ]; then
|
||
run_tests
|
||
exit $?
|
||
fi
|
||
|
||
[ -f "../sdk/meow_ui.a" ] || { echo "!! 缺 ../sdk/meow_ui.a,先跑 sdk/build_sdk.sh"; exit 1; }
|
||
"$CC" -I"../sdk" -Os -static -Wall -Wextra \
|
||
main_menu.c statusbar.c fb_compositor.c settings_page.c power_menu.c \
|
||
notif_center.c app_launcher.c pkg_install.c audio.c backlight.c net.c about.c \
|
||
subpage.c wifi_page.c bt_page.c netmgr_ipc.c now_playing.c bg_page.c \
|
||
font_theme.c keys.c util.c meow_dep.c key_router.c \
|
||
meow_touch.c meow_settings.c meow_notif.c meow_media.c meow_bgplay.c \
|
||
meow_bgmgr.c \
|
||
meow_ams_start.c lock_screen.c lock_screen_ui.c lock_settings.c \
|
||
"../sdk/meow_lyric.c" "../sdk/meow_lyric_view.c" "../sdk/meow_img_color.c" \
|
||
"../sdk/meow_ui.a" "$SYSROOT/lib/libz.a" -lpthread -o meow_launcherd
|
||
echo "== meow_launcherd =="
|
||
ls -la meow_launcherd
|
||
md5sum meow_launcherd
|
||
file meow_launcherd
|