summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRasmus Villemoes <linux@rasmusvillemoes.dk>2014-12-05 23:41:33 +0100
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2015-01-10 00:51:08 +0100
commit72392ed0eb6fde96826cb9d66bd4f50a7ba61450 (patch)
tree488408d7485349d5df0b3f4cca74cda5e9be4518
parentLinux 3.19-rc2 (diff)
downloadlinux-72392ed0eb6fde96826cb9d66bd4f50a7ba61450.tar.xz
linux-72392ed0eb6fde96826cb9d66bd4f50a7ba61450.zip
kernfs: Fix kernfs_name_compare
Returning a difference from a comparison functions is usually wrong (see acbbe6fbb240 "kcmp: fix standard comparison bug" for the long story). Here there is the additional twist that if the void pointers ns and kn->ns happen to differ by a multiple of 2^32, kernfs_name_compare returns 0, falsely reporting a match to the caller. Technically 'hash - kn->hash' is ok since the hashes are restricted to 31 bits, but it's better to avoid that subtlety. Signed-off-by: Rasmus Villemoes <linux@rasmusvillemoes.dk> Acked-by: Tejun Heo <tj@kernel.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-rw-r--r--fs/kernfs/dir.c12
1 files changed, 8 insertions, 4 deletions
diff --git a/fs/kernfs/dir.c b/fs/kernfs/dir.c
index 37989f02a226..2d881b381d2b 100644
--- a/fs/kernfs/dir.c
+++ b/fs/kernfs/dir.c
@@ -201,10 +201,14 @@ static unsigned int kernfs_name_hash(const char *name, const void *ns)
static int kernfs_name_compare(unsigned int hash, const char *name,
const void *ns, const struct kernfs_node *kn)
{
- if (hash != kn->hash)
- return hash - kn->hash;
- if (ns != kn->ns)
- return ns - kn->ns;
+ if (hash < kn->hash)
+ return -1;
+ if (hash > kn->hash)
+ return 1;
+ if (ns < kn->ns)
+ return -1;
+ if (ns > kn->ns)
+ return 1;
return strcmp(name, kn->name);
}