数据类型不匹配_数据类型不匹配造成的安全漏洞
2002年,从事FreeBSD开源操作系统项目的程序员意识到,他们对 getpeername 函数的实现存在安全漏洞,代码的简化版本如下:在上面的代码里,第7行给出的是库函数 memcpy 的原型,这个函数是要将一段指定长度的为n的字节从内存的一个区域复制到另一个区域。第14行的函数 copy_from_kernel 是要将一些操作系统内核维护的数据复制到指定的用户可以访问的内存区域。对用户来说,
2002年,从事FreeBSD开源操作系统项目的程序员意识到,他们对 getpeername 函数的实现存在安全漏洞,代码的简化版本如下:
在上面的代码里,第7行给出的是库函数 memcpy 的原型,这个函数是要将一段指定长度的为n的字节从内存的一个区域复制到另一个区域。
第14行的函数 copy_from_kernel 是要将一些操作系统内核维护的数据复制到指定的用户可以访问的内存区域。对用户来说,大多数内核维护的数据结构应该是不可读的,因为这些数据结构可能包含其他用户或系统上运行的其他作业的敏感信息。
显示未kbuf的区域是用户可读的。参数 maxlen 给出的是分配给用户的缓冲区的长度,这个缓冲区是用参数 user_dest 表示的。第16行的计算确保复制的字节数据不会超出源或目标缓冲区可用的范围。
上面代码的问题在于:若在调用 copy_from_kernel 的代码中对 maxlen使用了负值,那么第16行的最小值计算就会把这个值赋给 len,然后 len 作为参数 n 被传递给 memcpy。需要注意的是参数 n 是被声明为size_t的数据类型,size_t 是无符号整型,若 len 为负值,那么 memcpy 会把它当做一个非常大的正整数,并且试图将这样多字节的数据从内核区域复制到用户的缓冲区。虽然复制这么多字节(至少2^31个)实际上不会完成,但程序会遇到进程中非法地址的错误,还是能读到它没有被授权的内核区域。
size_t是标准C库中定义的,在32位系统中为 unsigned int,在64位系统中为 long unsigned int。
这个问题是由于数据类型不匹配造成的:在一个地方长度参数是有符号数,另一个地方是无符号数。这样的不匹配会带来缺陷,甚至导致安全漏洞。
幸运的是,没有案例报告有人在FreeBSD上利用了这个漏洞,随后关于这个漏洞的补丁就发布了。
要修正这个缺陷,只要将 copy_from_kernel 的参数 maxlen 声明为size_t类型,同时将局部变量 len 和返回值也声明为size_t,即与 memcpy中参数 n 的类型保持一致。
openvela 操作系统专为 AIoT 领域量身定制,以轻量化、标准兼容、安全性和高度可扩展性为核心特点。openvela 以其卓越的技术优势,已成为众多物联网设备和 AI 硬件的技术首选,涵盖了智能手表、运动手环、智能音箱、耳机、智能家居设备以及机器人等多个领域。
更多推荐



所有评论(0)