本页面介绍了在 android-mainline
上发现的、可能对合作伙伴具有重大意义的重要问题和错误修复。
2024 年 11 月 15 日
Clang 已更新至
android-mainline
和android16-6.12
的 19.0.1 版本- 摘要:新版 Clang 引入了数组的边界清理器,其中数组的大小存储在一个单独的变量中,该变量使用
__counted_by
属性链接到数组。如果未正确更新数组大小,此功能可能会导致内核崩溃。错误消息如下所示:
UBSAN: array-index-out-of-bounds in common/net/wireless/nl80211.c index 0 is out of range for type 'struct ieee80211_channel *[] __counted_by(n_channels)' (aka 'struct ieee80211_channel *[]')
详情:边界清理器对于通过检测越界访问来保护内核的完整性至关重要。并且在启用
CONFIG_UBSAN_TRAP
后,边界清理器会在发现任何问题时触发内核崩溃。- 旧版边界清理器仅检查固定大小的数组,无法检查动态分配的数组。新版本使用
__counted_by
属性在运行时确定数组边界,并检测更多越界访问的情况。但是,在某些情况下,在设置大小变量之前访问数组,从而触发边界清理器并导致内核崩溃。要解决此问题,请在分配底层内存后立即设置数组的大小,如 aosp/3343204 中所示。
- 旧版边界清理器仅检查固定大小的数组,无法检查动态分配的数组。新版本使用
关于
CONFIG_UBSAN_SIGNED_WRAP
:尽管有-fwrapv
编译器标志,但新版 Clang 仍会清理有符号整数溢出和下溢。-fwrapv
标志旨在将有符号整数视为具有已定义溢出行为的二进制补码无符号整数。- 虽然清理 Linux 内核中的有符号整数溢出有助于识别错误,但在某些情况下,溢出是故意的,例如,对于
atomic_long_t
。因此,CONFIG_UBSAN_SIGNED_WRAP
已被禁用,以允许 UBSAN 仅作为边界清理器发挥作用。
- 虽然清理 Linux 内核中的有符号整数溢出有助于识别错误,但在某些情况下,溢出是故意的,例如,对于
关于
CONFIG_UBSAN_TRAP
:UBSAN 配置为在检测到问题时触发内核崩溃,以保护内核的完整性。但是,我们从 10 月 23 日到 11 月 12 日禁用了此行为。我们这样做是为了在修复已知的__counted_by
问题时解除编译器更新的阻止。
- 摘要:新版 Clang 引入了数组的边界清理器,其中数组的大小存储在一个单独的变量中,该变量使用
2024 年 11 月 1 日
- Linux 6.12-rc4 登陆
- 摘要:
CONFIG_OF_DYNAMIC
可能会导致有缺陷的驱动程序出现严重的回归。 - 详情:在将 Linux
6.12-rc1
合并到android-mainline
中时,我们注意到树外驱动程序无法加载的问题。暴露驱动程序错误的更改被确定为提交274aff8711b2 ("clk: Add KUnit tests for clks registered with struct clk_parent_data")
,我们暂时在 aosp/3287735 中还原了它。该更改选择了CONFIG_OF_OVERLAY
,它选择了CONFIG_OF_DYNAMIC
。使用!OF_DYNAMIC
,of_node_get()
和of_node_put()
上的引用计数被有效地禁用,因为它们被实现为noops
。再次启用OF_DYNAMIC
会再次暴露驱动程序在错误地实现struct device_node
的引用计数方面的问题。这会导致各种类型的错误,如内存损坏、释放后使用和内存泄漏。 - 必须检查所有使用 OF 解析相关 API 的情况。以下列表是不完整的,但包含我们一直在观察的情况
- 释放后使用 (UAF)
- 重用相同的
device_node
参数:这些函数在给定的节点上调用of_node_put()
,可能需要在调用它们之前添加of_node_get()
(例如,当使用相同的节点作为参数重复调用时)of_find_compatible_node()
of_find_node_by_name()
of_find_node_by_path()
of_find_node_by_type()
of_get_next_cpu_node()
of_get_next_parent()
of_get_next_child()
of_get_next_available_child()
of_get_next_reserved_child()
of_find_node_with_property()
of_find_matching_node_and_match()
- 在从某些循环中任何类型的退出后使用
device_node
for_each_available_child_of_node_scoped()
for_each_available_child_of_node()
for_each_child_of_node_scoped()
for_each_child_of_node()
- 保留来自
device_node
的char *
属性的直接指针,例如,使用const char *foo = struct device_node::name
of_property_read_string()
of_property_read_string_array()
of_property_read_string_index()
of_get_property()
- 重用相同的
- 内存泄漏
- 获取
device_node
并忘记取消引用它 (of_node_put()
)。从这些返回的节点需要在某个时候释放of_find_compatible_node()
of_find_node_by_name()
of_find_node_by_path()
of_find_node_by_type()
of_find_node_by_phandle()
of_parse_phandle()
of_find_node_opts_by_path()
of_get_next_cpu_node()
of_get_compatible_child()
of_get_child_by_name()
of_get_parent()
of_get_next_parent()
of_get_next_child()
of_get_next_available_child()
of_get_next_reserved_child()
of_find_node_with_property()
of_find_matching_node_and_match()
- 获取
- 从循环迭代中保留
device_node
。如果您要从以下循环中返回或跳出,则需要在某个时候删除剩余的引用for_each_available_child_of_node()
for_each_child_of_node()
for_each_node_by_type()
for_each_compatible_node()
of_for_each_phandle()
- 释放后使用 (UAF)
- 在 Linux
6.12-rc4
登陆时,之前提到的更改已恢复(请参阅 aosp/3315251),再次启用CONFIG_OF_DYNAMIC
并可能暴露有缺陷的驱动程序。
- 摘要: