kernel/net: fix use-after-free on refused TCP connections #622
Open
Leency
wants to merge 1 commits from
kernel-tcp-connrefused-uaf into main
pull from: kernel-tcp-connrefused-uaf
merge into: :main
:main
:hdaudio-irq-polling
:egor00f-patch-1
:opendial-update
:msgbox-update
:rdsave-rewrite
:krn_refactoring_curr_slot_idx_1
:fat-fix-stack-imbalance
:kernel-tcp-socket-buffer-128k
:fix_602
:kernel-tcp-socket-list-locking
:network/getsockname
:kernel-tcp-reassembly-queue
:kernel-tcp-connrefused-uaf
:rewrite_ide_drv
:libimg-png-8-bit
:apps/table-msvc-to-tcc
:netsurf-4
:vidmode-s3ide-clgd54xx-kms-etc
:updf-1.5
:pr-fs-unhardcode
:kbd-busoff
:webview-4
:workflow-fuse
:add-license-file-header-to-guide
:shell-improve-cpuid
:qrcodegen
:ci/update
:laser-tank-fix-win-height
:improvement/commit-and-branch-styles
:docs/libs
No Reviewers
Labels
Clear labels
Influence/Text/TYPO
AI
Eolite
FS
GSoC
Good First PR
HLL
HardwareTested
IRCC
Influence/Settings
Lang/C
Lang/FASM
Pay for the code
Subsystem/API
Subsystem/Audio
Subsystem/Graphics
Subsystem/IPC and events
Subsystem/Memory
Subsystem/Network
Subsystem/Services(daemon)
Subsystem/Taskmanager
Subsystem/VFS
Subsystem/Window
This issue or PR in the Google Source of Code program
The issue is suitable to beginners
Paid task
infinity service, audio drivers, midi, speacker, audio programs
vesa, vga, framebuffer, cursors, blitter, and video drivers
pipes, signals, events, shared memory
virt and phys memory allocators, malloc and other
userspace and kernel(for example: serial) services
process, threads, run apps, scheduler
drivers from filesystem, fs api, blkdev, programs that work with the file system
windows, skins, buttons, mouse and keyboard code for windows (not the base code)
Category
Applications
Category
Drivers
Category
General
Category
Kernel
Category
Libraries
Kind
Breaking
Breaking change that won't be backward compatible
Kind
Bug
Something is not working
Kind
Build
Kind
Documentation
Documentation changes
Kind
Enhancement
Improve existing functionality
Kind
Feature
New functionality
Kind
Security
This is security issue
Kind
Testing
Issue or pull request related to testing
PR
Ready to merge
Pull request is ready for merge
PR
Conflicts
PR conflicts with main
PR
Dependent
This PR is dependent on another PR
PR
Request changes
Changes requested in pull request
PR
Review required
Priority
Critical
1
The priority is critical
Priority
High
2
The priority is high
Priority
Medium
3
The priority is medium
Priority
Low
4
The priority is low
Reviewed
Confirmed
Issue has been confirmed
Reviewed
Duplicate
This issue or pull request already exists
Reviewed
Invalid
Invalid issue
Reviewed
Won't Fix
This issue won't be fixed
Status
Abandoned
Somebody has started to work on this but abandoned work
Status
Blocked
Something is blocking this issue or pull request
Status
Need More Info
Feedback is required to reproduce issue or to continue work
No labels
Milestone
No items
No Milestone
Projects
Clear projects
No projects
Notifications
Due Date
No due date set.
Dependencies
No dependencies set.
Reference: KolibriOS/kolibrios#622
Reference in New Issue
Block a user
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
Summary: when a RST+ACK arrived in SYN_SENT state, tcp_input released the
socket mutex after tcp_drop had already freed the socket, writing into
kernel heap that no longer belonged to it.
Details:
The "connection refused" path called tcp_drop and then jumped to .drop.
tcp_drop ends in tcp_close in both of its branches, and tcp_close calls
socket_free, which returns the 4 KiB socket structure to the kernel heap.
.drop then executed
on that freed block, corrupting whatever had been allocated there in the
meantime. Every refused connection -- a closed port, a service that is
down -- hit this, so the damage was easy to trigger from user space and
showed up later as unrelated page faults.
The fix follows the pattern the same file already uses in .unlock_and_close:
unlock the mutex while the socket is still alive, then call tcp_drop, then
leave through .drop_no_socket, which frees the packet buffer without
touching the socket. tcp_drop takes the socket in eax, so ebx is pushed and
popped into eax around the unlock.
Co-Authored-By: Claude Opus 5 noreply@anthropic.com
Summary: when a RST+ACK arrived in SYN_SENT state, tcp_input released the socket mutex after tcp_drop had already freed the socket, writing into kernel heap that no longer belonged to it. Подробно: The "connection refused" path called tcp_drop and then jumped to .drop. tcp_drop ends in tcp_close in both of its branches, and tcp_close calls socket_free, which returns the 4 KiB socket structure to the kernel heap. .drop then executed lea ecx, [ebx + SOCKET.mutex] call mutex_unlock on that freed block, corrupting whatever had been allocated there in the meantime. Every refused connection -- a closed port, a service that is down -- hit this, so the damage was easy to trigger from user space and showed up later as unrelated page faults. The fix follows the pattern the same file already uses in .unlock_and_close: unlock the mutex while the socket is still alive, then call tcp_drop, then leave through .drop_no_socket, which frees the packet buffer without touching the socket. tcp_drop takes the socket in eax, so ebx is pushed and popped into eax around the unlock. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>This PR is a nice example of #606 and #607 combined.
Let me think a bit how to tackle this problem as a whole.
The proposed solution might work in practice for most cases but is not structural in the bigger picture.
View command line instructions
Checkout
From your project repository, check out a new branch and test the changes.