CVE-2022-50536CVE-2022-50536是Linux内核BPF sockmap子系统中存在的一个高危释放后使用(Use-After-Free)漏洞。该漏洞位于内核的tcp_bpf_send_verdict()函数中,具体问题出现在TCP BPF重定向逻辑处理过程中。当通过BPF程序将TCP套接字重定向到另一个套接字时,内核会使用eval变量来跟踪当前的处理状态。在正常流程中,当apply_bytes的数据发送完成后,eval变量会被赋值为__SK_REDIRECT,表示需要将套接字所有权转移。然而,当消息存在more_data(更多数据需要处理)时,内核会进入循环继续处理剩余数据,但eval变量没有被正确重置为__SK_NONE状态。这导致在每次循环迭代中,内核都会错误地认为需要调用sock_put()来释放套接字引用,从而对同一个套接字引用计数执行多次递减操作。当引用计数降至零后,套接字被释放,但代码仍然尝试访问该套接字,最终触发内核级的释放后使用漏洞。该漏洞可被本地低权限用户利用,通过特制的BPF程序触发系统崩溃或权限提升,CVSS评分为7.8,属于高危级别。
该漏洞的核心问题在于tcp_bpf_send_verdict()函数中eval变量状态管理的逻辑缺陷。具体技术原理如下:
1. **漏洞触发路径**:在BPF sockmap重定向场景中,当用户态调用sendto()系统调用时,数据流经sock_sendmsg → tcp_bpf_sendmsg → tcp_bpf_send_verdict → tcp_bpf_sendmsg_redir/tcp_bpf_push的调用链。
2. **根本原因**:tcp_bpf_send_verdict()函数中,在处理完一轮apply_bytes数据后,会将eval变量设置为__SK_REDIRECT,表示套接字已被重定向,需要通过sock_put()释放引用。问题在于,当msg->more_data为真时(即还有更多数据待发送),函数进入下一轮循环处理,但没有将eval重置为__SK_NONE,导致在后续循环中再次错误地执行sock_put()。
3. **利用方式**:攻击者需要具备本地低权限访问能力(PR:L),可通过加载特制的BPF程序到sockmap中,然后通过该BPF程序触发TCP重定向路径,构造包含more_data的消息,使内核对同一套接字执行多次sock_put()操作。当引用计数归零后,套接字内存被释放,但内核仍持有该指针并尝试进行TCP传输(如调用__tcp_transmit_skb),从而触发refcount_t饱和警告和use-after-free。
4. **漏洞表现**:内核日志中会出现"refcount_t: addition on 0; use-after-free"警告,以及"Attempt to release TCP socket in state 1"错误信息,最终可能导致系统崩溃(内核panic)或被利用进行权限提升。