Merge tag 'fscrypt_for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tytso...
[sfrench/cifs-2.6.git] / fs / ext4 / namei.c
index 6577a3c458151342771842357552a225bc9e0d16..b81f7d46f344d482d4a7ab15a5cc1ad3654b3259 100644 (file)
@@ -1237,37 +1237,24 @@ static void dx_insert_block(struct dx_frame *frame, u32 hash, ext4_lblk_t block)
 }
 
 /*
- * NOTE! unlike strncmp, ext4_match returns 1 for success, 0 for failure.
+ * Test whether a directory entry matches the filename being searched for.
  *
- * `len <= EXT4_NAME_LEN' is guaranteed by caller.
- * `de != NULL' is guaranteed by caller.
+ * Return: %true if the directory entry matches, otherwise %false.
  */
-static inline int ext4_match(struct ext4_filename *fname,
-                            struct ext4_dir_entry_2 *de)
+static inline bool ext4_match(const struct ext4_filename *fname,
+                             const struct ext4_dir_entry_2 *de)
 {
-       const void *name = fname_name(fname);
-       u32 len = fname_len(fname);
+       struct fscrypt_name f;
 
        if (!de->inode)
-               return 0;
+               return false;
 
+       f.usr_fname = fname->usr_fname;
+       f.disk_name = fname->disk_name;
 #ifdef CONFIG_EXT4_FS_ENCRYPTION
-       if (unlikely(!name)) {
-               if (fname->usr_fname->name[0] == '_') {
-                       int ret;
-                       if (de->name_len < 16)
-                               return 0;
-                       ret = memcmp(de->name + de->name_len - 16,
-                                    fname->crypto_buf.name + 8, 16);
-                       return (ret == 0) ? 1 : 0;
-               }
-               name = fname->crypto_buf.name;
-               len = fname->crypto_buf.len;
-       }
+       f.crypto_buf = fname->crypto_buf;
 #endif
-       if (de->name_len != len)
-               return 0;
-       return (memcmp(de->name, name, len) == 0) ? 1 : 0;
+       return fscrypt_match_name(&f, de->name, de->name_len);
 }
 
 /*
@@ -1281,48 +1268,31 @@ int ext4_search_dir(struct buffer_head *bh, char *search_buf, int buf_size,
        struct ext4_dir_entry_2 * de;
        char * dlimit;
        int de_len;
-       int res;
 
        de = (struct ext4_dir_entry_2 *)search_buf;
        dlimit = search_buf + buf_size;
        while ((char *) de < dlimit) {
                /* this code is executed quadratically often */
                /* do minimal checking `by hand' */
-               if ((char *) de + de->name_len <= dlimit) {
-                       res = ext4_match(fname, de);
-                       if (res < 0) {
-                               res = -1;
-                               goto return_result;
-                       }
-                       if (res > 0) {
-                               /* found a match - just to be sure, do
-                                * a full check */
-                               if (ext4_check_dir_entry(dir, NULL, de, bh,
-                                               bh->b_data,
-                                                bh->b_size, offset)) {
-                                       res = -1;
-                                       goto return_result;
-                               }
-                               *res_dir = de;
-                               res = 1;
-                               goto return_result;
-                       }
-
+               if ((char *) de + de->name_len <= dlimit &&
+                   ext4_match(fname, de)) {
+                       /* found a match - just to be sure, do
+                        * a full check */
+                       if (ext4_check_dir_entry(dir, NULL, de, bh, bh->b_data,
+                                                bh->b_size, offset))
+                               return -1;
+                       *res_dir = de;
+                       return 1;
                }
                /* prevent looping on a bad block */
                de_len = ext4_rec_len_from_disk(de->rec_len,
                                                dir->i_sb->s_blocksize);
-               if (de_len <= 0) {
-                       res = -1;
-                       goto return_result;
-               }
+               if (de_len <= 0)
+                       return -1;
                offset += de_len;
                de = (struct ext4_dir_entry_2 *) ((char *) de + de_len);
        }
-
-       res = 0;
-return_result:
-       return res;
+       return 0;
 }
 
 static int is_dx_internal_node(struct inode *dir, ext4_lblk_t block,
@@ -1616,16 +1586,9 @@ static struct dentry *ext4_lookup(struct inode *dir, struct dentry *dentry, unsi
                if (!IS_ERR(inode) && ext4_encrypted_inode(dir) &&
                    (S_ISDIR(inode->i_mode) || S_ISLNK(inode->i_mode)) &&
                    !fscrypt_has_permitted_context(dir, inode)) {
-                       int nokey = ext4_encrypted_inode(inode) &&
-                               !fscrypt_has_encryption_key(inode);
-                       if (nokey) {
-                               iput(inode);
-                               return ERR_PTR(-ENOKEY);
-                       }
                        ext4_warning(inode->i_sb,
                                     "Inconsistent encryption contexts: %lu/%lu",
-                                    (unsigned long) dir->i_ino,
-                                    (unsigned long) inode->i_ino);
+                                    dir->i_ino, inode->i_ino);
                        iput(inode);
                        return ERR_PTR(-EPERM);
                }
@@ -1833,24 +1796,15 @@ int ext4_find_dest_de(struct inode *dir, struct inode *inode,
        int nlen, rlen;
        unsigned int offset = 0;
        char *top;
-       int res;
 
        de = (struct ext4_dir_entry_2 *)buf;
        top = buf + buf_size - reclen;
        while ((char *) de <= top) {
                if (ext4_check_dir_entry(dir, NULL, de, bh,
-                                        buf, buf_size, offset)) {
-                       res = -EFSCORRUPTED;
-                       goto return_result;
-               }
-               /* Provide crypto context and crypto buffer to ext4 match */
-               res = ext4_match(fname, de);
-               if (res < 0)
-                       goto return_result;
-               if (res > 0) {
-                       res = -EEXIST;
-                       goto return_result;
-               }
+                                        buf, buf_size, offset))
+                       return -EFSCORRUPTED;
+               if (ext4_match(fname, de))
+                       return -EEXIST;
                nlen = EXT4_DIR_REC_LEN(de->name_len);
                rlen = ext4_rec_len_from_disk(de->rec_len, buf_size);
                if ((de->inode ? rlen - nlen : rlen) >= reclen)
@@ -1858,15 +1812,11 @@ int ext4_find_dest_de(struct inode *dir, struct inode *inode,
                de = (struct ext4_dir_entry_2 *)((char *)de + rlen);
                offset += rlen;
        }
-
        if ((char *) de > top)
-               res = -ENOSPC;
-       else {
-               *dest_de = de;
-               res = 0;
-       }
-return_result:
-       return res;
+               return -ENOSPC;
+
+       *dest_de = de;
+       return 0;
 }
 
 void ext4_insert_dentry(struct inode *inode,