kernel/net: fix wild write in tcp_set_persist
Check kernel codestyle / Check kernel codestyle (pull_request) Successful in 18s
Test PR / Build (es_ES) (pull_request) Successful in 2m27s
Test PR / Build (ru_RU) (pull_request) Successful in 2m31s
Test PR / Build (en_US) (pull_request) Successful in 2m34s
Build system / Build (en_US) (push) Successful in 2m10s
Build system / Build (es_ES) (push) Successful in 2m14s
Build system / Build (ru_RU) (push) Successful in 2m20s
Build system / Publish Images (push) Successful in 1m45s
Check kernel codestyle / Check kernel codestyle (pull_request) Successful in 18s
Test PR / Build (es_ES) (pull_request) Successful in 2m27s
Test PR / Build (ru_RU) (pull_request) Successful in 2m31s
Test PR / Build (en_US) (pull_request) Successful in 2m34s
Build system / Build (en_US) (push) Successful in 2m10s
Build system / Build (es_ES) (push) Successful in 2m14s
Build system / Build (ru_RU) (push) Successful in 2m20s
Build system / Publish Images (push) Successful in 1m45s
tcp_set_persist takes the socket pointer in eax and uses ebx as a
scratch register to compute the RTO:
mov ebx, [eax + TCP_SOCKET.t_srtt]
shr ebx, 2
add ebx, [eax + TCP_SOCKET.t_rttvar]
shr ebx, 1
mov cl, [eax + TCP_SOCKET.t_rxtshift]
shl ebx, cl
By the time the persist timer is armed ebx therefore holds the timeout
value, not the socket. The flag store nevertheless went through ebx, so
it wrote to the linear address <RTO> + TCP_SOCKET.timer_flags -- an
unmapped low address -- instead of setting timer_flag_persist on the
socket.
Any TCP connection whose peer advertises a zero window takes this path
from tcp_output.enter_persist and faults the kernel:
K : Page fault
K : EBX : 0000000A
K : EIP : 80037DF3 (tcp_set_persist, the flag store)
K : Process - forced terminate PID: 00000005
Observed with NetSurf on a HTTP/2 connection to www.redhat.com, where
twelve multiplexed streams closed the receive window. Store the flag
through eax, which tcpt_rangeset leaves untouched.
Assisted-by: Claude Opus 5 <noreply@anthropic.com>
This commit was merged in pull request #625.
This commit is contained in:
@@ -488,7 +488,7 @@ tcp_set_persist:
|
||||
; Start/restart persistence timer.
|
||||
|
||||
tcpt_rangeset [eax + TCP_SOCKET.timer_persist], ebx, TCP_time_pers_min, TCP_time_pers_max
|
||||
or [ebx + TCP_SOCKET.timer_flags], timer_flag_persist
|
||||
or [eax + TCP_SOCKET.timer_flags], timer_flag_persist
|
||||
pop ebx
|
||||
|
||||
cmp [eax + TCP_SOCKET.t_rxtshift], TCP_max_rxtshift
|
||||
|
||||
Reference in New Issue
Block a user