Subject: Re: bug#27986: 26.0.50; 'rename-file' can rename files without confirmation

From: Paul Eggert <[email-masked]>
Date: Mon, 14 Aug 2017 16:31:38 -0700

Eli Zaretskii wrote:
> Could you please take a step back and elaborate on the
> races and the security problems related to this, and why the change in
> the semantics you propose is the solution?

Currently (rename-file A B) requires at least two system calls to work: one to 
test whether B is a directory, and the other to actually do the rename. This 
leads to race conditions if other actors change the file system between the two 
calls.

For example, suppose a victim is about to execute (rename-file "/tmp/foo" 
"/tmp/bar" t), and suppose an attacker wants to destroy the victim's file 
/home/victim/secret/foo. The attacker can do (make-symbolic-link 
"/home/victim/secret" "/tmp/bar"), and this will cause the victim to lose all 
the data in /home/victim/secret/bar even though the attacker is supposed to lack 
access to anything under /home/victim/secret. I doubt whether this is the only 
such scenario; it's just the first one that popped into my mind.

As icing on the cake, the current behavior of (rename-file A B) disagrees with 
its documentation when B is an existing directory.

There is no good solution to this problem. All solutions are bad, in that either 
they are not 100% backward compatible with existing behavior, or they continue 
to encourage insecure Elisp code. The proposed patch attempts to choose the 
least bad way forward, by making the default behavior more secure, at a 
relatively minor cost in compatibility. Most uses of rename-file etc. won't care 
about the change, and the ones that do care are likely to have security problems 
anyway.

The proposed solution improves security, because a common pattern in Lisp code 
when creating a file BAR "atomically" is to create and write a temporary file 
FOO and then execute (rename-file FOO BAR). Currently, this approach can be 
attacked in the way described when BAR's parent directory is /tmp or any similar 
directory. With the proposed patch, this approach cannot be hijacked in this 
way, because BAR will be a file name and not a directory name. That is, the call 
to rename-file will specify whether the destination-directory semantics are 
desired, rather than relying on the state of the filesystem to specify it. This 
is more secure because the state of the filesystem is partially under control of 
attackers.