首先看什么是CVE-2009-0029漏洞:
The ABI in the Linux kernel 2.6.28 and earlier on s390, powerpc, sparc64, and mips 64-bit platforms requires that a 32-bit argument in a 64-bit register was properly sign extended when sent from a user-mode application, but cannot verify this, which allows local users to cause a denial of service (crash) or possibly gain privileges via a crafted system call.
上面这段话是对CVE-2009-0029的说明,大概意思是说:在Linux 2.6.28及以前版本的内核中,IBM/S390、PowerPC、Sparc64以及MIPS 架构64位平台的ABI要求在系统调用时,用户空间程序将系统调用中32位的参数存放在64位的寄存器中要做到正确的符号扩展,但是用户空间程序却不能保证做到这点,这样就会可以通过向有漏洞的系统调用传送特制参数便可以导致系统崩溃或获得权限提升。
可能有人不理解ABI是什么意思,在这里当个小插曲简单介绍一下:大家都知道API,是定义了应用程序调用库的接口。那么ABI,其实就是定义了二进制接口,全称叫
Application Binary Interface.定义的内容大概包括
1、数据类型的大小、布局和对齐
2、调用约定(控制着函数的参数如何传送以及如何接受返回值),例如,是所有的参数都通过栈传递,还是部分参数通过寄存器传递;哪个寄存器用于哪个函数参数;通过栈传递的第一个函数参数是最先push到栈上还是最后
举个例子看一下:
int sys_sample(int arg)
{
....
return sample[arg];
}
根据ABI的规定,32位的参数存放在64位的寄存器上要自己进行符号扩展,但是程序是人写的,可能是疏忽,也可能是有意,总之并不能完全保证这一点,那么传参的时候,就会出现只修改了低32位,并没有修改高32位的情况,那么如果高32位是ffffffff,这个数就变为了一个很大的负数,在内核中执行,sample[arg]就会取到一个非法地址。