关于CVE-2009-0029的困惑:Linux内核不安全的64位系统调用参数传递

时间:2013-09-19 01:47:01

标签: linux linux-kernel system-calls

以下是CVE-2009-0029的概述:

  

Linux内核2.6.28及更早版本的s390,powerpc,sparc64和mips 64位平台上的ABI要求64位寄存器中的32位参数在从用户发送时正确地进行符号扩展 - 模式应用程序,但无法验证这一点,这允许本地用户通过精心设计的系统调用导致拒绝服务(崩溃)或可能获得权限。

这怎么会出现?为什么缺陷不会影响x86_64或Intel Itanium?

Linux内核通过替换下面__SYSCALL_DEFINEx的marco定义来解决这个缺陷

#define __SYSCALL_DEFINEx(x, name, ...)                 \
     asmlinkage long sys##name(__SC_DECL##x(__VA_ARGS__)) 

#define __SYSCALL_DEFINEx(x, name, ...)                 \
     asmlinkage long sys##name(__SC_DECL##x(__VA_ARGS__));      \
     static inline long SYSC##name(__SC_DECL##x(__VA_ARGS__));  \
     asmlinkage long SyS##name(__SC_LONG##x(__VA_ARGS__))       \
     {                              \
         __SC_TEST##x(__VA_ARGS__);             \
         return (long) SYSC##name(__SC_CAST##x(__VA_ARGS__));   \
     }                              \
     SYSCALL_ALIAS(sys##name, SyS##name);               \
     static inline long SYSC##name(__SC_DECL##x(__VA_ARGS__))

我真的不知道怎么解决这个问题?

1 个答案:

答案 0 :(得分:1)

在这些体系结构中,32位值由64位寄存器处理。 因此,如果函数具有32位int参数,则恶意调用者可以将值放入此寄存器中,该值大于int的值。

此外,因为编译器“知道”int不能具有不适合int变量的值,所以不容易检查该值是否超出范围,因为编译器可以优化该检查。

作为一种变通方法,SyS_xxx函数首先假定其所有参数都是64位long值,然后将它们显式转换为实际类型。

在x86_64和Itanium上,处理器在访问32位值时忽略寄存器的高位。