Linux内核SCTP协议误差剖析与复现
宣布时间 2019-05-30Linux内核SCTP协议实现中保存一个清静误差CVE-2019-8956(CNVD-2019-06182、CNNVD-201902-823),,,,,可以导致拒绝效劳。。。该误差保存于net/sctp/socket.c中的sctp_sendmsg()函数,,,,,该函数在处置惩罚SENDALL标记操作历程时保存use-after-free误差。。。
SCTP协议简介
流控制传输协议(Stream Control Transmission Protocol,,,,,SCTP)是一种可靠的传输协议,,,,,它在两个端点之间提供稳固、有序的数据转达效劳(很是类似于 TCP),,,,,并且可以保唬唬唬护数据新闻界线(例如 UDP)。。。与TCP和 UDP差别,,,,,SCTP 是通过多宿主(Multi-homing)和多流(Multi-streaming)功效提供这些收益的,,,,,这两种功效均可提高可用性。。。
误差原理
误差补丁代码如下,,,,,补丁代码将list_for_each_entry换成了list_for_each_entry_safe。。。
宏界说list_for_each_entry_safe中添加了一个n,,,,,该n用来存放pos指向的节点的下一个节点位置。。。使用该宏可以对链表举行删除操作。。。
行2038,,,,,从msg中剖析出sinfo;;;;行2043,,,,,获取到sflags。。。
行2055,,,,,判断sflags是否为SCTP_SENDALL。。。若是保存,,,,,进入list_for_each_entry循环中,,,,,依次遍历ep->asocs链表。。。这里的asocs就是存放多个association毗连的链表。。。SCTP_SENDALL标记代表向asocs链表中的所有association毗连发送数据包。。。以是asocs链表中至少要保存一个association节点。。。进入sctp_sendmsg_check_sflags函数后,,,,,该函数实现如下:
首先,,,,,检查asoc是否处于CLOSED状态,,,,,检查asoc是否处于监听状态,,,,,检查asoc是否shutdown。。。
接下来,,,,,检查sflags是否为SCTP_ABORT,,,,,凭证rfc文档可知ABORT的用法以及ABORT指令的数据包名堂。。。SCTP_ABORT标记代表中止一个association毗连,,,,,这个也是导致误差的要害。。。
行1863,,,,,sctp_make_abort_user结构ABORT指令的chunk;;;;行1868,,,,,挪用sctp_primitive_ABORT发送中止一个association的chunk。。。
通过调试可知挪用sctp_sf_do_9_1_prm_abort函数举行ABORT操作,,,,,该函数将会举行如下操作:
添加一条删除asoc的commands,,,,,然后返回SCTP_DISPOSITION_ABORT。。。正常返回,,,,,继续剖析,,,,,返回到sctp_do_sm函数中。。。
行1188正常返回后,,,,,行1191挪用sctp_side_effects函数凭证状态机对应的状态举行操作。。。
行1246,,,,,将asoc置空,,,,,ABORT标记代表中止一个association操作竣事。。。从sctp_sendmsg_check_sflags函数返回到sctp_sendmsg函数中,,,,,宏list_for_each_entry循环中遍历获取第一个asoc节点时,,,,,进入sctp_sendmsg_check_sflags函数将第一个asoc置空,,,,,然后再举行遍历后面节点时,,,,,就爆发了零地点引用导致误差爆发。。。
误差复现
将sflags设置成SENDALL | ABORT,,,,,包管进入list_for_each_entry循环和sctp_sendmsg_check_sflags()函数即可。。。在4.20内核下验证如下。。。由于该误差是NULL-PTR deref,,,,,即是零地点解引用,,,,,无法进一步使用。。。
修复建议
该误差影响Linux Kernel 4.19.x和4.20.x,,,,,建议更新到version 4.20.8 或4.19.21。。。补丁链接如下:https://git.kernel.org/linus/ba59fb0273076637f0add4311faa990a5eec27c0


京公网安备11010802024551号