ANDROID: sdcardfs: Switch to internal case insensitive compare
authorDaniel Rosenberg <drosen@google.com>
Thu, 9 Mar 2017 01:20:02 +0000 (17:20 -0800)
committerDaniel Rosenberg <drosen@google.com>
Tue, 30 Jan 2018 03:40:05 +0000 (19:40 -0800)
There were still a few places where we called into a case
insensitive lookup that was not defined by sdcardfs.
Moving them all to the same place will allow us to switch
the implementation in the future.

Additionally, the check in fixup_perms_recursive did not
take into account the length of both strings, causing
extraneous matches when the name we were looking for was
a prefix of the child name.

Signed-off-by: Daniel Rosenberg <drosen@google.com>
Change-Id: I45ce768cd782cb4ea1ae183772781387c590ecc2

fs/sdcardfs/dentry.c
fs/sdcardfs/derived_perm.c
fs/sdcardfs/packagelist.c
fs/sdcardfs/sdcardfs.h

index d1eff456cc8adabf39526dde760f830469340a95..2797d2fc42275bae0699e5abdbf0f9eaa2e17285 100644 (file)
@@ -82,11 +82,7 @@ static int sdcardfs_d_revalidate(struct dentry *dentry, unsigned int flags)
                spin_lock_nested(&dentry->d_lock, DENTRY_D_LOCK_NESTED);
        }
 
-       if (dentry->d_name.len != lower_dentry->d_name.len) {
-               __d_drop(dentry);
-               err = 0;
-       } else if (strncasecmp(dentry->d_name.name, lower_dentry->d_name.name,
-                               dentry->d_name.len) != 0) {
+       if (!qstr_case_eq(&dentry->d_name, &lower_dentry->d_name)) {
                __d_drop(dentry);
                err = 0;
        }
@@ -165,7 +161,7 @@ static int sdcardfs_cmp_ci(const struct dentry *dentry,
        }
        */
        if (name->len == len) {
-               if (strncasecmp(name->name, str, len) == 0)
+               if (str_n_case_eq(name->name, str, len))
                        return 0;
        }
        return 1;
index 0f227b95c9e389e007fb5b392c34645c19af3b4a..69ffbf25364516728b8d175e9e3237f547898364 100644 (file)
@@ -285,7 +285,7 @@ static void __fixup_perms_recursive(struct dentry *dentry, struct limit_search *
        if (needs_fixup(info->perm)) {
                list_for_each_entry(child, &dentry->d_subdirs, d_child) {
                        spin_lock_nested(&child->d_lock, depth + 1);
-                       if (!(limit->flags & BY_NAME) || !strncasecmp(child->d_name.name, limit->name, limit->length)) {
+                       if (!(limit->flags & BY_NAME) || qstr_case_eq(&child->d_name, &limit->name)) {
                                if (d_inode(child)) {
                                        get_derived_permission(dentry, child);
                                        fixup_tmp_permissions(d_inode(child));
index 5f81284a4f44ee450f7556d004ba470d703d1c17..d933bffacc7afb7f42642a4aaeeadd0c3126e305 100644 (file)
@@ -254,8 +254,7 @@ static void fixup_all_perms_name(const struct qstr *key)
        struct sdcardfs_sb_info *sbinfo;
        struct limit_search limit = {
                .flags = BY_NAME,
-               .name = key->name,
-               .length = key->len,
+               .name = QSTR_INIT(key->name, key->len),
        };
        list_for_each_entry(sbinfo, &sdcardfs_super_list, list) {
                if (sbinfo_has_sdcard_magic(sbinfo))
@@ -268,8 +267,7 @@ static void fixup_all_perms_name_userid(const struct qstr *key, userid_t userid)
        struct sdcardfs_sb_info *sbinfo;
        struct limit_search limit = {
                .flags = BY_NAME | BY_USERID,
-               .name = key->name,
-               .length = key->len,
+               .name = QSTR_INIT(key->name, key->len),
                .userid = userid,
        };
        list_for_each_entry(sbinfo, &sdcardfs_super_list, list) {
index 7740124049cd96f6bcabdb08ddee6f6337a360a1..a42125ef39f52652bfc4f40c4bc73e62a7962d14 100644 (file)
@@ -476,8 +476,7 @@ extern void packagelist_exit(void);
 #define BY_USERID      (1 << 1)
 struct limit_search {
        unsigned int flags;
-       const char *name;
-       size_t length;
+       struct qstr name;
        userid_t userid;
 };
 
@@ -618,6 +617,11 @@ static inline bool str_case_eq(const char *s1, const char *s2)
        return !strcasecmp(s1, s2);
 }
 
+static inline bool str_n_case_eq(const char *s1, const char *s2, size_t len)
+{
+       return !strncasecmp(s1, s2, len);
+}
+
 static inline bool qstr_case_eq(const struct qstr *q1, const struct qstr *q2)
 {
        return q1->len == q2->len && str_case_eq(q1->name, q2->name);