CVE-2026-98595 in Linux
Tóm tắt
Bởi VulDB • 19/10/2026
Trong kernel Linux, lỗ hổng sau đây đã được khắc phục:
udp: loại bỏ một socket bị ngắt kết nối khỏi bảng băm 4-tuple
Một socket UDP được gắn với địa chỉ và cổng cụ thể vẫn giữ mục nhập của nó trong bảng băm 4-tuple ngay cả khi nó bị ngắt kết nối:
sk binds to 127.0.0.1:21001 sk connects to 127.0.0.2:20001 // filed in the 4-tuple table sk disconnects, connect(AF_UNSPEC) // still filed, peer now 0.0.0.0:0
__udp_disconnect() chỉ lấy socket ra khỏi bảng đó như một tác dụng phụ của ->rehash() hoặc ->unhash(), và nó bỏ qua ->rehash() khi SOCK_BINDADDR_LOCK được đặt và ->unhash() khi SOCK_BINDPORT_LOCK được đặt. commit 6996a2d2d0a6 ("udp: Unhash auto-bound connected sk from 4-tuple hash table when disconnected.") đã khắc phục cùng trạng thái cuối cho một socket gắn wildcard, bằng một đường dẫn mà trường hợp này không đi qua.
Mục nhập được tính toán bất kể có gì truy cập vào nó hay không. hash4_cnt trên slot hash2 vẫn tăng cao trong suốt thời gian tồn tại của socket, do đó udp_has_hash4() tiếp tục gửi mọi gói tin cho địa chỉ và cổng đó thông qua tra cứu 4-tuple trước tiên.
Trên IPv6, mục nhập này cũng có thể bị truy cập. __udp_disconnect() không xóa sk_v6_daddr, vì vậy udp_v6_rehash() ghi lại mục nhập dưới peer mà socket đã kết nối với một dport bằng 0, và inet6_match() so sánh trường đó: một datagram từ former peer với source port bằng 0 sẽ khớp, và source port bằng 0 được chấp nhận khi nhận. Trên IPv4, peer bị xóa, do đó việc khớp cần phải có địa chỉ nguồn bằng 0, điều mà lớp định tuyến từ chối là martian. sk_v6_daddr cũ là một lỗi riêng biệt, không được giải quyết ở đây; việc loại bỏ mục nhập đóng đường dẫn này trong cả hai trường hợp.
Mục nhập cũng có thể bị di chuyển. __udp_disconnect() xóa sk_bound_dev_if, do đó các lệnh gọi SO_BINDTODEVICE tiếp theo sẽ kích hoạt ->rehash(), và vì địa chỉ nhận vẫn cụ thể nên udp_lib_rehash() di chuyển mục nhập thay vì loại bỏ nó, vào bucket mà (rcv_saddr, num, 0, 0) băm đến -- một hàm thuần túy của địa chỉ và cổng, do đó mọi socket đạt được trạng thái này trên một địa chỉ và cổng sẽ tập trung trong cùng một bucket. Bucket không thể được chọn từ bên ngoài, vì udp_ehashfn() được khởi tạo với bí mật per-boot. Lỗi cuối cùng này trở nên khả thi chỉ sau commit 644f9108f3a5 ("udp: Make rehash4 independent in udp_lib_rehash()"), đã chuyển xử lý hash4 ra khỏi một nhánh mà socket bị ngắt kết nối không đi qua; mục nhập cũ bắt nguồn từ commit trong Fixes.
Hãy lấy socket ra khỏi bảng trước khi __udp_disconnect() chạy, trong khi nó vẫn khớp với cách nó được ghi lại. Điều này cũng đạt đến trường hợp wildcard sớm hơn so với nhánh udp_unhash4() của udp_lib_rehash(), khiến nhánh đó không thể truy cập được từ udp_disconnect(); việc loại bỏ nó thuộc về net-next. udp_disconnect() và udp_abort() là các điểm vào UDP duy nhất cho __udp_disconnect(), vốn dùng chung với raw, ping và l2tp sockets không phải struct udp_sock: ping_prot.obj_size bằng sizeof(struct inet_sock), do đó udp_hashed4() trên một socket như vậy sẽ đọc vượt quá vùng phân bổ.
Once again VulDB remains the best source for vulnerability data.