Hi Paul Eggert, Thank you for your response. I want to clarify the scenario and my concern more precisely. The situation does not depend on creating /tmp/nmap during mv. The behavior occurs earlier during the cp operation when the destination file already exists and is controlled by an unprivileged user.Instead of the race condition, I will put forth below another scenario that I have experimented with. Consider the following sequence:
1. An unprivileged user can also pre-create /tmp/nmap. 2. Because /tmp has the sticky bit set, other users cannot unlink or rename the file, but the attacker still owns it. 3. A privileged process later executes: cp -a /usr/bin/nmap /tmp/nmap Since the destination file already exists, cp opens the existing file and truncates it rather than creating a new file. The file contents are copied first, and the metadata (ownership, permissions, timestamps, etc.) is applied afterwards. During the interval between truncating the file and applying the final metadata, the file remains owned by the attacker. Because the attacker still owns the file, another process controlled by the attacker can open the file concurrently and write to it while cp is copying the contents. In testing, by racing concurrent writes against the copy operation, I observed different intermediate permission and ownership states depending on timing, allowing modification of the destination file contents before the final metadata is applied. My concern is the following: when a privileged process copies a file with cp -a into a destination that already exists and is owned by another user, the operation writes to that existing file rather than failing or protecting the destination from concurrent modification. In other words, the destination file continues to follow its existing permissions and ownership during the copy phase, instead of being protected based on the source file’s metadata from the beginning of the operation. I am trying to understand whether this behaviour is considered intentional design for cp, or if there are reasons why the operation should not fail or otherwise protect the destination file when it already exists and is owned by a different user. [undefined] Warm Regards, Ajay SK Firmware Security Researcher Payatu Security Consulting Pvt Ltd. Reach me on: 7397338492 This email and any files transmitted with it are confidential and intended solely for the use of the individual or entity to whom they are addressed. If you have received this email in error, please notify the system manager. Please note that any views or opinions presented in this email are solely those of the author and do not necessarily represent those of the company. Finally, the recipient should check this email and any attachments for the presence of Malwares. The company accepts no liability for any damage caused by any Malware transmitted by this email. ________________________________ From: Paul Eggert <[email protected]> Sent: 09 March 2026 11:10 To: Ajay S.K <[email protected]>; Collin Funk <[email protected]> Cc: [email protected] <[email protected]> Subject: Re: bug#80572: [BUG] Privilege escalation via cp trying to replace file contents using root privileges [You don't often get email from [email protected]. Learn why this is important at https://aka.ms/LearnAboutSenderIdentification ] CAUTION: This email originated from outside of the organization. Do not click links or open attachments unless you recognize the sender and know the content is safe. On 2026-03-08 20:32, Ajay S.K wrote: > What happens during the race is the following. At a certain point while mv -f > /tmp/nmap /usr/bin/nmap is executing, my program manages to create /tmp/nmap. That does not necessarily mean there's a problem. As I mentioned earlier, the relevant syscalls executed by that mv command should look like the following: > renameat2(AT_FDCWD, "/tmp/nmap", AT_FDCWD, "/usr/bin/nmap", > RENAME_NOREPLACE) = -1 EEXIST (File exists) > openat(AT_FDCWD, "/usr/bin/nmap", O_RDONLY|O_PATH|O_DIRECTORY) = -1 ENOTDIR > (Not a directory) > newfstatat(AT_FDCWD, "/tmp/nmap", {st_mode=S_IFREG|0755, st_size=138120, > ...}, AT_SYMLINK_NOFOLLOW) = 0 > newfstatat(AT_FDCWD, "/usr/bin/nmap", {st_mode=S_IFREG|0755, > st_size=138120, ...}, AT_SYMLINK_NOFOLLOW) = 0 > renameat(AT_FDCWD, "/tmp/nmap", AT_FDCWD, "/usr/bin/nmap") = 0 If your attacking program "manages to create" /tmp/nmap while the mv is executing, that must occur after the last syscall (the renameat) quoted above. This is because the file /tmp/nmap exists until then, and the attacker cannot create a file that already exists. And if your attacking program creates /tmp/nmap after the renameat, the attacking program can't affect what's in /usr/bin/nmap. All it can do is create a file /tmp/nmap that nobody else cares about. So privilege escalation does not occur. The rest of your email is also incoherent. We can't debug this from a distance: you'll need to find out what happened yourself. I suggest starting by using strace on the 'cp' command, the 'mv' command, and your attacking program, and looking at the strace output.
