SubmittedCWE-476 — NULL Pointer Dereference
TelephonyStateRegistryService::UpdateNetworkState 在 EXT_WRAPPER 分支未检查 network...
View Upstream Issuegitcode.com/openharmony/telephony_state_registry/issues/254CWE:CWE-476 — NULL Pointer Dereference
Repository:telephony_state_registry
Date:2026-05-07
Reporter:Zirui
漏洞概述
TelephonyStateRegistryService::UpdateNetworkState 函数在 line 391 对 networkState 做了 nullptr 检查(用于 deep copy),但在 line 403-419 的 observer 通知循环中,当 TELEPHONY_EXT_WRAPPER.onNetworkStateUpdated_ 非空时,直接调用 networkState->Marshalling(data)(line 410),未检查 networkState 是否为 nullptr。
漏洞详情
问题代码
文件: services/src/telephony_state_registry_service.cpp:378-423
int32_t TelephonyStateRegistryService::UpdateNetworkState(int32_t slotId, const sptr<NetworkState> &networkState)
{
// ... permission checks ...
std::unique_lock<std::shared_mutex> uniLock(lock_);
searchNetworkState_[slotId] = networkState;
if (networkState != nullptr) { // ← line 391: 此处有 null check
sptr<NetworkState> searchNetworkState = sptr<NetworkState>::MakeSptr();
if (searchNetworkState != nullptr) {
MessageParcel networkData;
networkState->Marshalling(networkData);
searchNetworkState->ReadFromParcel(networkData);
searchNetworkState_[slotId] = searchNetworkState;
}
}
uniLock.unlock();
std::shared_lock<std::shared_mutex> lock(lock_);
for (size_t i = 0; i < stateRecords_.size(); i++) {
TelephonyStateRegistryRecord r = stateRecords_[i];
if (r.IsExistStateListener(...) && (r.slotId_ == slotId) &&
r.telephonyObserver_ != nullptr) {
if (TELEPHONY_EXT_WRAPPER.onNetworkStateUpdated_ != nullptr) {
sptr<NetworkState> networkStateExt = new NetworkState();
MessageParcel data;
networkState->Marshalling(data); // ← line 410: 无 null check,崩溃
networkStateExt->ReadFromParcel(data);
TELEPHONY_EXT_WRAPPER.onNetworkStateUpdated_(slotId, r, networkStateExt, networkState);
r.telephonyObserver_->OnNetworkStateUpdated(slotId, networkStateExt);
} else {
r.telephonyObserver_->OnNetworkStateUpdated(slotId, networkState); // ← 传 nullptr 给 observer
}
}
}
// ...
}
对比:同函数正确实现
Line 391 已经证明 networkState 可以为 nullptr(否则不需要检查),但 line 410 的代码路径未做同样的保护。
触发条件
UpdateNetworkState被调用时networkState参数为 nullptr- 系统加载了 TELEPHONY_EXT_WRAPPER 扩展(
onNetworkStateUpdated_非空) - 存在已注册的 OBSERVER_MASK_NETWORK_STATE 监听器
- Line 410 解引用 nullptr → SIGSEGV
攻击面分析
UpdateNetworkState通过 IPC 从TelephonyStateRegistryStub::OnUpdateNetworkState调用- Stub 层(line 334-348)对
Unmarshalling返回值有 nullptr 检查,正常 IPC 路径不会传入 nullptr - 但函数签名接受
const sptr<NetworkState>&,内部其他调用路径可能传入 nullptr - Line 391 的 null check 证明开发者预期此参数可能为 nullptr
- 当 EXT_WRAPPER 扩展加载时,服务进程崩溃(DoS)
影响
- telephony_state_registry 服务进程崩溃
- 所有依赖电话状态注册服务的应用功能中断
- 服务重启期间电话状态通知丢失
修复建议
for (size_t i = 0; i < stateRecords_.size(); i++) {
TelephonyStateRegistryRecord r = stateRecords_[i];
if (r.IsExistStateListener(TelephonyObserverBroker::OBSERVER_MASK_NETWORK_STATE) && (r.slotId_ == slotId) &&
r.telephonyObserver_ != nullptr) {
if (TELEPHONY_EXT_WRAPPER.onNetworkStateUpdated_ != nullptr) {
+ if (networkState == nullptr) {
+ TELEPHONY_LOGE("networkState is nullptr, skip ext wrapper");
+ continue;
+ }
sptr<NetworkState> networkStateExt = new NetworkState();
MessageParcel data;
networkState->Marshalling(data);
涉及文件
services/src/telephony_state_registry_service.cpp(line 410) — 缺失 null check