深入分析图形渲染库精度问题引发的安全漏洞(上篇)
字数 1257 2025-08-20 18:17:42

图形渲染库精度问题引发的安全漏洞深入分析

1. 精度问题漏洞概述

精度问题漏洞是一种罕见但危险的漏洞类型,主要影响图形渲染库,偶尔也会出现在其他软件中。这类漏洞的根本原因是精度误差导致应用程序的安全假设失效,转而使用有限精度算法。

1.1 与整数溢出的对比

  • 整数溢出:运算结果太大而无法以给定精度准确表示
  • 精度问题漏洞:运算结果或结果的一部分太小而无法以给定精度准确表示

1.2 典型示例

float a = 100000000;
float b = 1;
float c = a + b;  // 实际结果为100000000而非100000001

2. SwiftShader中的精度问题

2.1 背景介绍

SwiftShader是OpenGL ES和Direct3D 9图形API的CPU实现,Chrome浏览器将其作为备选渲染库。

2.2 漏洞代码分析

// 纹理复制循环中的问题代码
float w = sRect.width() / dRect.width();
float h = sRect.height() / dRect.height();
const float xStart = sRect.x0 + 0.5f * w;
float y = sRect.y0 + 0.5f * h;
float x = xStart;

for(int j = dRect.y0; j < dRect.y1; j++) {
    x = xStart;
    for(int i = dRect.x0; i < dRect.x1; i++) {
        dest->copyInternal(source, i, j, x, y, options.filter);
        x += w;  // 迭代加法导致误差累积
    }
    y += h;
}

2.3 问题本质

  • 迭代加法导致误差累积传播,像滚雪球一样越来越大
  • 乘法实现误差更小且稳定,与操作数大小成正比

2.4 具体数值示例

当源宽度与目标宽度比为5828:8132时:

  • 前2046次迭代结果相同
  • 从2047次开始出现误差
  • 最终导致越界索引(8131次迭代时差值足够大)

3. Skia中的精度问题

3.1 背景介绍

Skia是Chrome、Firefox和Android使用的图形库,用于绘制canvas元素和SVG图像。

3.2 剪辑检查机制

Skia采用三级剪辑检查策略:

  1. 完全在绘图区域外:不绘制,立即返回
  2. 部分在绘图区域内:绘制并进行逐像素剪辑检查
  3. 完全在绘图区域内:直接绘制,不进行逐像素检查

3.3 主要精度问题

3.3.1 浮点到整数转换误差

// 问题函数1
static inline int round_down_to_int(SkScalar x) {
    double xx = x;
    xx -= 0.5;
    return (int)ceil(xx);
}

// 问题函数2
inline SkFDot6 SkScalarRoundToFDot6(SkScalar x, int shift = 0) {
    // 使用magic number进行转换
    double magic = (1LL << (52 - (fractionalBits))) * 1.5;
    tmp.fDouble = SkScalarToDouble(x) + magic;
    return tmp.fBits[0];
}

对于-0.499:

  • round_down_to_int返回0(通过检查)
  • SkScalarRoundToFDot6返回-32(对应-0.5)

3.3.2 分数相乘误差

static inline SkFixed(SkFixed a, SkFixed b) {
    return (SkFixed)((int64_t)a * b >> 16);  // 右移导致负数相乘问题
}

示例:

  • 预期:0xFFFFFFFE × 0xFFFFFFFE = 0xFFFFFFFC00000004 → 0xFFFFFFFC
  • 实际:0xFFFFFFFF(更大的结果)

3.4 组合利用

结合两个问题可以:

  1. 使x坐标足够小(<-0.5)
  2. 通过舍入操作变为整数时,尝试在x=-1处绘制
  3. 导致越界写入漏洞

4. 防御建议

4.1 通用防御措施

  1. 避免迭代累积误差:使用乘法而非迭代加法
  2. 增加安全余量:在边界检查中使用更大的安全余量
  3. 统一精度处理:确保所有转换使用相同算法

4.2 SwiftShader特定建议

  • 重构纹理复制循环,使用乘法计算坐标
  • 对关键计算进行最大误差分析
  • 限制纹理大小以减小误差影响范围

4.3 Skia特定建议

  • 在所有路径上启用逐像素剪辑检查
  • 统一浮点到整数转换算法
  • 修复SkFixedMul中的负数处理问题

5. 总结

图形渲染库中的精度问题可能导致严重的安全漏洞,特别是越界读写问题。这些问题通常源于:

  1. 迭代计算导致的误差累积
  2. 不同精度转换算法的不一致性
  3. 边界检查中的安全余量不足

开发者需要特别注意图形计算中的精度处理,特别是在安全敏感的上下文中。通过采用更精确的算法、统一转换方法和适当的边界检查,可以显著降低这类漏洞的风险。

图形渲染库精度问题引发的安全漏洞深入分析 1. 精度问题漏洞概述 精度问题漏洞是一种罕见但危险的漏洞类型,主要影响图形渲染库,偶尔也会出现在其他软件中。这类漏洞的根本原因是精度误差导致应用程序的安全假设失效,转而使用有限精度算法。 1.1 与整数溢出的对比 整数溢出 :运算结果太大而无法以给定精度准确表示 精度问题漏洞 :运算结果或结果的一部分太小而无法以给定精度准确表示 1.2 典型示例 2. SwiftShader中的精度问题 2.1 背景介绍 SwiftShader是OpenGL ES和Direct3D 9图形API的CPU实现,Chrome浏览器将其作为备选渲染库。 2.2 漏洞代码分析 2.3 问题本质 迭代加法 导致误差累积传播,像滚雪球一样越来越大 乘法实现 误差更小且稳定,与操作数大小成正比 2.4 具体数值示例 当源宽度与目标宽度比为5828:8132时: 前2046次迭代结果相同 从2047次开始出现误差 最终导致越界索引(8131次迭代时差值足够大) 3. Skia中的精度问题 3.1 背景介绍 Skia是Chrome、Firefox和Android使用的图形库,用于绘制canvas元素和SVG图像。 3.2 剪辑检查机制 Skia采用三级剪辑检查策略: 完全在绘图区域外 :不绘制,立即返回 部分在绘图区域内 :绘制并进行逐像素剪辑检查 完全在绘图区域内 :直接绘制,不进行逐像素检查 3.3 主要精度问题 3.3.1 浮点到整数转换误差 对于-0.499: round_down_to_int 返回0(通过检查) SkScalarRoundToFDot6 返回-32(对应-0.5) 3.3.2 分数相乘误差 示例: 预期:0xFFFFFFFE × 0xFFFFFFFE = 0xFFFFFFFC00000004 → 0xFFFFFFFC 实际:0xFFFFFFFF(更大的结果) 3.4 组合利用 结合两个问题可以: 使x坐标足够小( <-0.5) 通过舍入操作变为整数时,尝试在x=-1处绘制 导致越界写入漏洞 4. 防御建议 4.1 通用防御措施 避免迭代累积误差 :使用乘法而非迭代加法 增加安全余量 :在边界检查中使用更大的安全余量 统一精度处理 :确保所有转换使用相同算法 4.2 SwiftShader特定建议 重构纹理复制循环,使用乘法计算坐标 对关键计算进行最大误差分析 限制纹理大小以减小误差影响范围 4.3 Skia特定建议 在所有路径上启用逐像素剪辑检查 统一浮点到整数转换算法 修复SkFixedMul中的负数处理问题 5. 总结 图形渲染库中的精度问题可能导致严重的安全漏洞,特别是越界读写问题。这些问题通常源于: 迭代计算导致的误差累积 不同精度转换算法的不一致性 边界检查中的安全余量不足 开发者需要特别注意图形计算中的精度处理,特别是在安全敏感的上下文中。通过采用更精确的算法、统一转换方法和适当的边界检查,可以显著降低这类漏洞的风险。