ftpd: truncate the file on STOR instead of overwriting in place #706
Dismiss Review
Are you sure you want to dismiss this review?
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
No Assignees
Notifications
Due Date
No due date set.
Dependencies
No dependencies set.
Reference: KolibriOS/kolibrios#706
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.
cmdSTOR opens the destination with O_CREATE + O_WRITE, and libio only
truncates on write when the position is already at EOF (libio.asm:314),
which never happens here. Replacing a longer file with a shorter one
therefore kept the old tail: 4096-byte A overwritten by 1024-byte B
produced a 4096-byte file holding B followed by A[1024:4096], and
overwriting with zero bytes left the file completely untouched.
Call file.truncate (SF 70.4, size = Position = 0) right after a
successful open so that STOR replaces the file, as RFC 959 requires.
The descriptor survives the call in ebx because sendFTP clobbers the
registers. A failed truncate closes the descriptor and answers 550
through a new .truncate_error path.
The libio import list gains file_truncate, exported since 2009.
STOR: усекать файл при перезаписи, чтобы не оставался старый хвост
Проблема
cmdSTOR открывает целевой файл с O_CREATE + O_WRITE, а libio усекает файл при записи только если позиция уже находится в EOF (libio.asm:314). В этом сценарии условие никогда не выполняется. Поэтому при замене длинного файла коротким сохранялся старый хвост: 4096-байтный A, перезаписанный 1024-байтным B, давал 4096-байтный файл, содержащий B, а затем A[1024:4096]. Перезапись нулевым количеством байт вообще не изменяла файл.
Решение
Сразу после успешного открытия вызывается file.truncate (SF 70.4, size = Position = 0), чтобы STOR заменял файл, как требует RFC 959. Дескриптор сохраняется в ebx после вызова, так как sendFTP затирает регистры. Если truncate завершается ошибкой, дескриптор закрывается, а ответ 550 отправляется через новый обработчик .truncate_error.
Дополнительно
В список импортов libio добавлен file_truncate (экспортируется с 2009 года).
Что проверил. Сам фикс правильный:
file.openставит позицию в 0, иfile.truncateусекает файл именно до позиции. Обычная запись усекает только тогда, когда позиция в конце файла, поэтому без этого вызова старый хвост оставался.Что было не так. При ошибке truncate новый путь
.truncate_errorзакрывал файл, но не закрывал data-соединение и не сбрасывал режим. Поэтому следующий STOR/RETR подхватывал старый сокет.Что исправил (
programs/network/ftpd/commands.inc):Так же убирает за собой
abort_transfer. Текст ответа сменил на «Cannot truncate file», чтобы он называл настоящую причину.@Leency этот PR не решает проблемы с незакрытыми data-сокетами?
#707
e5b3aa5c88tof658a6d3ec