On Wed, Nov 19, 2014 at 11:12:43AM -0500, random...@fastmail.us wrote: > On Wed, Nov 19, 2014, at 09:55, Dimitris Papastamos wrote: > > Regarding your question on cp -f then the answer is not quite. > > > > cp -f will try to unlink the destination if it fails to open it for > > whatever > > reason. > > And if the target is running and writing to a running binary is a > problem, opening it will fail with [ETXTBSY], meaning it will be > unlinked. You can argue about whether that is the purpose or something > else (permission errors within a directory you own) is the purpose, but > it will certainly solve that problem. >
Not always. One thing that reliably gets on people's nerves here is shared libraries. And those aren't protected with that ETXTBSY thing. The reason is that the MAP_DENYWRITE flag became the irrecoverable source of a DoS attack and had to be removed from the syscall. It can still be used in the kernel, which is why overwriting a running binary will fail, but it can't be used in userspace (or rather, is ignored), so opening a shared library that's in use for writing and truncating is possible. That means that cp -f on a used shared library will destroy all programs using it. Also, if you unlink the target file, that means that the file system gets into the state where the target file does not exist. If you then start the copy loop, the file system gets into the state where the file does exist, but has the wrong mode, wrong owner and probably wrong content. If anything happens to go wrong during that, the target file will be corrupted. If anything is looking for the target file in the meantime, they'll see it in the wrong state, which may cause surprise. After all, every single one of my programs failing at once would certainly surprise me! The correct solution is to copy the file to a temporary name in the same directory (or something else that guarentees it being on the same device as the target file), then change its mode and owner, and then move it into place. If anything goes wrong, just delete the temporary file. That way, you can even update /lib/libc.so with a shell script. But that only works for musl, of course. For most other libcs, you have to figure out in what order to update the different library files without breaking programs. That, or create a compiled program that does all the moving in one invocation, because a half-updated libc will probably mean that nothing can run until it's fixed. Ciao, Markus