vfs: Don't exchange "short" filenames unconditionally.

Only exchange source and destination filenames
if flags contain RENAME_EXCHANGE.
In case if executable file was running and replaced by
other file /proc/PID/exe should still show correct file name,
not the old name of the file by which it was replaced.

The scenario when this bug manifests itself was like this:
* ALT Linux uses rpm and start-stop-daemon;
* during a package upgrade rpm creates a temporary file
for an executable to rename it upon successful unpacking;
* start-stop-daemon is run subsequently and it obtains
the (nonexistant) temporary filename via /proc/PID/exe
thus failing to identify the running process.

Note that "long" filenames (> DNAiME_INLINE_LEN) are still
exchanged without RENAME_EXCHANGE and this behaviour exists
long enough (should be fixed too apparently).
So this patch is just an interim workaround that restores
behavior for "short" names as it was before changes
introduced by commit da1ce0670c14 ("vfs: add cross-rename").

See https://lkml.org/lkml/2014/9/7/6 for details.

AV: the comments about being more careful with ->d_name.hash
than with ->d_name.name are from back in 2.3.40s; they
became obsolete by 2.3.60s, when we started to unhash the
target instead of swapping hash chain positions followed
by d_delete() as we used to do when dcache was first
introduced.

Acked-by: Miklos Szeredi <mszeredi@suse.cz>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Alexander Viro <viro@zeniv.linux.org.uk>
Cc: linux-fsdevel@vger.kernel.org
Cc: stable@vger.kernel.org
Fixes: da1ce0670c14 "vfs: add cross-rename"
Signed-off-by: Mikhail Efremov <sem@altlinux.org>
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>

authored by Mikhail Efremov and committed by Al Viro d2fa4a84 a28ddb87

Changed files
+18 -9
fs
+18 -9
fs/dcache.c
··· 2372 2372 } 2373 2373 EXPORT_SYMBOL(dentry_update_name_case); 2374 2374 2375 - static void switch_names(struct dentry *dentry, struct dentry *target) 2375 + static void switch_names(struct dentry *dentry, struct dentry *target, 2376 + bool exchange) 2376 2377 { 2377 2378 if (dname_external(target)) { 2378 2379 if (dname_external(dentry)) { ··· 2407 2406 */ 2408 2407 unsigned int i; 2409 2408 BUILD_BUG_ON(!IS_ALIGNED(DNAME_INLINE_LEN, sizeof(long))); 2409 + if (!exchange) { 2410 + memcpy(dentry->d_iname, target->d_name.name, 2411 + target->d_name.len + 1); 2412 + dentry->d_name.hash_len = target->d_name.hash_len; 2413 + return; 2414 + } 2410 2415 for (i = 0; i < DNAME_INLINE_LEN / sizeof(long); i++) { 2411 2416 swap(((long *) &dentry->d_iname)[i], 2412 2417 ((long *) &target->d_iname)[i]); ··· 2463 2456 * When switching names, the actual string doesn't strictly have to 2464 2457 * be preserved in the target - because we're dropping the target 2465 2458 * anyway. As such, we can just do a simple memcpy() to copy over 2466 - * the new name before we switch. 2467 - * 2468 - * Note that we have to be a lot more careful about getting the hash 2469 - * switched - we have to switch the hash value properly even if it 2470 - * then no longer matches the actual (corrupted) string of the target. 2471 - * The hash value has to match the hash queue that the dentry is on.. 2459 + * the new name before we switch, unless we are going to rehash 2460 + * it. Note that if we *do* unhash the target, we are not allowed 2461 + * to rehash it without giving it a new name/hash key - whether 2462 + * we swap or overwrite the names here, resulting name won't match 2463 + * the reality in filesystem; it's only there for d_path() purposes. 2464 + * Note that all of this is happening under rename_lock, so the 2465 + * any hash lookup seeing it in the middle of manipulations will 2466 + * be discarded anyway. So we do not care what happens to the hash 2467 + * key in that case. 2472 2468 */ 2473 2469 /* 2474 2470 * __d_move - move a dentry ··· 2517 2507 d_hash(dentry->d_parent, dentry->d_name.hash)); 2518 2508 } 2519 2509 2520 - 2521 2510 /* Switch the names.. */ 2522 - switch_names(dentry, target); 2511 + switch_names(dentry, target, exchange); 2523 2512 2524 2513 /* ... and switch them in the tree */ 2525 2514 if (IS_ROOT(dentry)) {