diff --git a/debian/changelog b/debian/changelog index 246e1b0e9..d959e6096 100644 --- a/debian/changelog +++ b/debian/changelog @@ -225,6 +225,8 @@ linux (3.16.5-1) UNRELEASED; urgency=low * radeon: Don't check for installed firmware if driver is built-in (Closes: #763305) * Bump ABI to 3 + * vfs: fold swapping ->d_name.hash into switch_names() + * vfs: Don't exchange "short" filenames unconditionally. (Closes: #763700) [ Aurelien Jarno ] * [arm64] Change RTC_DRV_PL031 and RTC_DRV_XGENE from modules to built-ins diff --git a/debian/patches/bugfix/all/fold-swapping-d_name.hash-into-switch_names.patch b/debian/patches/bugfix/all/fold-swapping-d_name.hash-into-switch_names.patch new file mode 100644 index 000000000..b1d7a79ce --- /dev/null +++ b/debian/patches/bugfix/all/fold-swapping-d_name.hash-into-switch_names.patch @@ -0,0 +1,41 @@ +From: Linus Torvalds +Date: Wed, 24 Sep 2014 12:27:39 -0700 +Subject: fold swapping ->d_name.hash into switch_names() +Origin: https://git.kernel.org/linus/a28ddb87cdddb0db57466ba7f59f831002f4340c + +and do it along with ->d_name.len there + +Signed-off-by: Linus Torvalds +Signed-off-by: Al Viro +[bwh: Backported to 3.16: change __d_materialise_dentry() as well] +--- + fs/dcache.c | 3 +-- + 1 file changed, 1 insertion(+), 2 deletions(-) + +--- a/fs/dcache.c ++++ b/fs/dcache.c +@@ -2441,7 +2441,7 @@ static void switch_names(struct dentry * + } + } + } +- swap(dentry->d_name.len, target->d_name.len); ++ swap(dentry->d_name.hash_len, target->d_name.hash_len); + } + + static void dentry_lock_for_move(struct dentry *dentry, struct dentry *target) +@@ -2540,7 +2540,6 @@ static void __d_move(struct dentry *dent + + /* Switch the names.. */ + switch_names(dentry, target); +- swap(dentry->d_name.hash, target->d_name.hash); + + /* ... and switch the parents */ + if (IS_ROOT(dentry)) { +@@ -2679,7 +2678,6 @@ static void __d_materialise_dentry(struc + dparent = dentry->d_parent; + + switch_names(dentry, anon); +- swap(dentry->d_name.hash, anon->d_name.hash); + + dentry->d_parent = dentry; + list_del_init(&dentry->d_u.d_child); diff --git a/debian/patches/bugfix/all/vfs-Don-t-exchange-short-filenames-unconditionally.patch b/debian/patches/bugfix/all/vfs-Don-t-exchange-short-filenames-unconditionally.patch new file mode 100644 index 000000000..124d1a7ba --- /dev/null +++ b/debian/patches/bugfix/all/vfs-Don-t-exchange-short-filenames-unconditionally.patch @@ -0,0 +1,115 @@ +From: Mikhail Efremov +Date: Wed, 24 Sep 2014 22:14:33 +0400 +Subject: vfs: Don't exchange "short" filenames unconditionally. +Origin: https://git.kernel.org/linus/d2fa4a8476b911782f7e5167db18770222ac40c3 + +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 +Cc: Linus Torvalds +Cc: Alexander Viro +Cc: linux-fsdevel@vger.kernel.org +Cc: stable@vger.kernel.org +Fixes: da1ce0670c14 "vfs: add cross-rename" +Signed-off-by: Mikhail Efremov +Signed-off-by: Al Viro +[bwh: Backported to 3.16: + - Adjust context + - Change __d_materialise_dentry() as well] +--- + fs/dcache.c | 27 ++++++++++++++++++--------- + 1 file changed, 18 insertions(+), 9 deletions(-) + +--- a/fs/dcache.c ++++ b/fs/dcache.c +@@ -2401,7 +2401,8 @@ void dentry_update_name_case(struct dent + } + EXPORT_SYMBOL(dentry_update_name_case); + +-static void switch_names(struct dentry *dentry, struct dentry *target) ++static void switch_names(struct dentry *dentry, struct dentry *target, ++ bool exchange) + { + if (dname_external(target)) { + if (dname_external(dentry)) { +@@ -2435,6 +2436,12 @@ static void switch_names(struct dentry * + */ + unsigned int i; + BUILD_BUG_ON(!IS_ALIGNED(DNAME_INLINE_LEN, sizeof(long))); ++ if (!exchange) { ++ memcpy(dentry->d_iname, target->d_name.name, ++ target->d_name.len + 1); ++ dentry->d_name.hash_len = target->d_name.hash_len; ++ return; ++ } + for (i = 0; i < DNAME_INLINE_LEN / sizeof(long); i++) { + swap(((long *) &dentry->d_iname)[i], + ((long *) &target->d_iname)[i]); +@@ -2484,12 +2491,15 @@ static void dentry_unlock_parents_for_mo + * When switching names, the actual string doesn't strictly have to + * be preserved in the target - because we're dropping the target + * anyway. As such, we can just do a simple memcpy() to copy over +- * the new name before we switch. +- * +- * Note that we have to be a lot more careful about getting the hash +- * switched - we have to switch the hash value properly even if it +- * then no longer matches the actual (corrupted) string of the target. +- * The hash value has to match the hash queue that the dentry is on.. ++ * the new name before we switch, unless we are going to rehash ++ * it. Note that if we *do* unhash the target, we are not allowed ++ * to rehash it without giving it a new name/hash key - whether ++ * we swap or overwrite the names here, resulting name won't match ++ * the reality in filesystem; it's only there for d_path() purposes. ++ * Note that all of this is happening under rename_lock, so the ++ * any hash lookup seeing it in the middle of manipulations will ++ * be discarded anyway. So we do not care what happens to the hash ++ * key in that case. + */ + /* + * __d_move - move a dentry +@@ -2539,7 +2549,7 @@ static void __d_move(struct dentry *dent + list_del(&target->d_u.d_child); + + /* Switch the names.. */ +- switch_names(dentry, target); ++ switch_names(dentry, target, exchange); + + /* ... and switch the parents */ + if (IS_ROOT(dentry)) { +@@ -2677,7 +2687,7 @@ static void __d_materialise_dentry(struc + + dparent = dentry->d_parent; + +- switch_names(dentry, anon); ++ switch_names(dentry, anon, false); + + dentry->d_parent = dentry; + list_del_init(&dentry->d_u.d_child); diff --git a/debian/patches/series b/debian/patches/series index 713b7e1fc..dafa8f03c 100644 --- a/debian/patches/series +++ b/debian/patches/series @@ -135,3 +135,5 @@ debian/revert-staging-sm7xxfb-remove-driver.patch features/all/sfc-Adding-PCI-ID-for-Solarflare-7000-series-40G-net.patch features/all/sfc-Add-40G-link-capability-decoding.patch bugfix/s390/s390-3215-fix-tty-output-containing-tabs.patch +bugfix/all/fold-swapping-d_name.hash-into-switch_names.patch +bugfix/all/vfs-Don-t-exchange-short-filenames-unconditionally.patch