CVE-2023-53686CVE-2023-53686是Linux内核net/handshake子系统中存在的一个空指针解引用漏洞,位于netlink接口函数handshake_nl_done_doit()中。该漏洞源于在套接字查找失败的情况下仍然调用了trace_handshake_cmd_done_err()追踪函数,并且在释放文件描述符之后才对sock->sk进行解引用操作,导致访问已释放或无效的内存区域。当攻击者通过netlink套接字发送特制的DONE消息时,内核会进入handshake_nl_done_doit()函数处理流程。若套接字查找过程未能成功获取到有效的socket对象,程序会继续执行后续代码并尝试访问sock->sk字段,从而触发空指针解引用错误。KASAN(Kernel Address Sanitizer)检测到该问题,报告在虚拟地址dfff800000000003处发生内核分页请求错误,范围为[0x0000000000000018-0x000000000000001f],属于level 1 translation fault。该漏洞可被本地低权限用户触发,导致系统崩溃(内核Oops),造成拒绝服务攻击。该漏洞在Linux 6.5-rc7版本中被发现和修复,影响多个Linux内核稳定版本。
该漏洞的技术原理涉及Linux内核net/handshake模块的netlink消息处理流程。具体而言,handshake_nl_done_doit()函数是genetlink(通用netlink)框架中用于处理握手完成通知的回调函数。漏洞的触发需要满足以下条件:
1. 攻击者通过netlink套接字(AF_NETLINK)向handshake netlink族发送DONE类型的命令消息;
2. 内核调用handshake_nl_done_doit()函数进行处理;
3. 函数内部通过netlink_getsockbyportid()等接口尝试查找与netlink端口ID关联的socket对象;
4. 若查找失败(例如socket已被关闭或端口ID无效),sock指针为NULL;
5. 然而函数仍然继续执行trace_handshake_cmd_done_err()追踪调用,该函数内部尝试访问sock->sk成员;
6. 由于sock为NULL,访问sock->sk时偏移量0x18处发生空指针解引用;
7. 此外,即使sock非NULL,在调用trace_handshake_cmd_done_err()之前已释放了file结构体,导致sock->sk指向已释放的内存,产生use-after-free问题。
修复方案包括:1)在套接字查找失败时直接返回错误,不调用trace函数;2)在释放file之前先完成trace调用;3)同时还原了之前提交的7afc6d0a107f补丁中关于未初始化局部变量的修改。