aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorEric Biggers <ebiggers@google.com>2019-03-20 14:39:13 -0400
committerTheodore Ts'o <tytso@mit.edu>2019-04-17 10:07:51 -0400
commitb01531db6cec2aa330dbc91bfbfaaef4a0d387a4 (patch)
tree215e407f512e5b48d4f3269c3ab717f3080fcf51
parentd456a33f041af4b54f3ce495a86d00c246165032 (diff)
fscrypt: fix race where ->lookup() marks plaintext dentry as ciphertext
->lookup() in an encrypted directory begins as follows: 1. fscrypt_prepare_lookup(): a. Try to load the directory's encryption key. b. If the key is unavailable, mark the dentry as a ciphertext name via d_flags. 2. fscrypt_setup_filename(): a. Try to load the directory's encryption key. b. If the key is available, encrypt the name (treated as a plaintext name) to get the on-disk name. Otherwise decode the name (treated as a ciphertext name) to get the on-disk name. But if the key is concurrently added, it may be found at (2a) but not at (1a). In this case, the dentry will be wrongly marked as a ciphertext name even though it was actually treated as plaintext. This will cause the dentry to be wrongly invalidated on the next lookup, potentially causing problems. For example, if the racy ->lookup() was part of sys_mount(), then the new mount will be detached when anything tries to access it. This is despite the mountpoint having a plaintext path, which should remain valid now that the key was added. Of course, this is only possible if there's a userspace race. Still, the additional kernel-side race is confusing and unexpected. Close the kernel-side race by changing fscrypt_prepare_lookup() to also set the on-disk filename (step 2b), consistent with the d_flags update. Fixes: 28b4c263961c ("ext4 crypto: revalidate dentry after adding or removing the key") Signed-off-by: Eric Biggers <ebiggers@google.com> Signed-off-by: Theodore Ts'o <tytso@mit.edu>
-rw-r--r--fs/crypto/fname.c1
-rw-r--r--fs/crypto/hooks.c11
-rw-r--r--fs/ext4/ext4.h62
-rw-r--r--fs/ext4/namei.c76
-rw-r--r--fs/f2fs/namei.c17
-rw-r--r--fs/ubifs/dir.c8
-rw-r--r--include/linux/fscrypt.h30
7 files changed, 139 insertions, 66 deletions
diff --git a/fs/crypto/fname.c b/fs/crypto/fname.c
index 050384c79f40..eccea3d8f923 100644
--- a/fs/crypto/fname.c
+++ b/fs/crypto/fname.c
@@ -356,6 +356,7 @@ int fscrypt_setup_filename(struct inode *dir, const struct qstr *iname,
356 } 356 }
357 if (!lookup) 357 if (!lookup)
358 return -ENOKEY; 358 return -ENOKEY;
359 fname->is_ciphertext_name = true;
359 360
360 /* 361 /*
361 * We don't have the key and we are doing a lookup; decode the 362 * We don't have the key and we are doing a lookup; decode the
diff --git a/fs/crypto/hooks.c b/fs/crypto/hooks.c
index 9d8910e86ee5..042d5b44f4ed 100644
--- a/fs/crypto/hooks.c
+++ b/fs/crypto/hooks.c
@@ -104,20 +104,21 @@ int __fscrypt_prepare_rename(struct inode *old_dir, struct dentry *old_dentry,
104} 104}
105EXPORT_SYMBOL_GPL(__fscrypt_prepare_rename); 105EXPORT_SYMBOL_GPL(__fscrypt_prepare_rename);
106 106
107int __fscrypt_prepare_lookup(struct inode *dir, struct dentry *dentry) 107int __fscrypt_prepare_lookup(struct inode *dir, struct dentry *dentry,
108 struct fscrypt_name *fname)
108{ 109{
109 int err = fscrypt_get_encryption_info(dir); 110 int err = fscrypt_setup_filename(dir, &dentry->d_name, 1, fname);
110 111
111 if (err) 112 if (err && err != -ENOENT)
112 return err; 113 return err;
113 114
114 if (!fscrypt_has_encryption_key(dir)) { 115 if (fname->is_ciphertext_name) {
115 spin_lock(&dentry->d_lock); 116 spin_lock(&dentry->d_lock);
116 dentry->d_flags |= DCACHE_ENCRYPTED_NAME; 117 dentry->d_flags |= DCACHE_ENCRYPTED_NAME;
117 spin_unlock(&dentry->d_lock); 118 spin_unlock(&dentry->d_lock);
118 d_set_d_op(dentry, &fscrypt_d_ops); 119 d_set_d_op(dentry, &fscrypt_d_ops);
119 } 120 }
120 return 0; 121 return err;
121} 122}
122EXPORT_SYMBOL_GPL(__fscrypt_prepare_lookup); 123EXPORT_SYMBOL_GPL(__fscrypt_prepare_lookup);
123 124
diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h
index 82ffdacdc7fa..e64a4ee96d30 100644
--- a/fs/ext4/ext4.h
+++ b/fs/ext4/ext4.h
@@ -2287,23 +2287,47 @@ extern unsigned ext4_free_clusters_after_init(struct super_block *sb,
2287ext4_fsblk_t ext4_inode_to_goal_block(struct inode *); 2287ext4_fsblk_t ext4_inode_to_goal_block(struct inode *);
2288 2288
2289#ifdef CONFIG_FS_ENCRYPTION 2289#ifdef CONFIG_FS_ENCRYPTION
2290static inline void ext4_fname_from_fscrypt_name(struct ext4_filename *dst,
2291 const struct fscrypt_name *src)
2292{
2293 memset(dst, 0, sizeof(*dst));
2294
2295 dst->usr_fname = src->usr_fname;
2296 dst->disk_name = src->disk_name;
2297 dst->hinfo.hash = src->hash;
2298 dst->hinfo.minor_hash = src->minor_hash;
2299 dst->crypto_buf = src->crypto_buf;
2300}
2301
2290static inline int ext4_fname_setup_filename(struct inode *dir, 2302static inline int ext4_fname_setup_filename(struct inode *dir,
2291 const struct qstr *iname, 2303 const struct qstr *iname,
2292 int lookup, struct ext4_filename *fname) 2304 int lookup,
2305 struct ext4_filename *fname)
2293{ 2306{
2294 struct fscrypt_name name; 2307 struct fscrypt_name name;
2295 int err; 2308 int err;
2296 2309
2297 memset(fname, 0, sizeof(struct ext4_filename));
2298
2299 err = fscrypt_setup_filename(dir, iname, lookup, &name); 2310 err = fscrypt_setup_filename(dir, iname, lookup, &name);
2311 if (err)
2312 return err;
2300 2313
2301 fname->usr_fname = name.usr_fname; 2314 ext4_fname_from_fscrypt_name(fname, &name);
2302 fname->disk_name = name.disk_name; 2315 return 0;
2303 fname->hinfo.hash = name.hash; 2316}
2304 fname->hinfo.minor_hash = name.minor_hash; 2317
2305 fname->crypto_buf = name.crypto_buf; 2318static inline int ext4_fname_prepare_lookup(struct inode *dir,
2306 return err; 2319 struct dentry *dentry,
2320 struct ext4_filename *fname)
2321{
2322 struct fscrypt_name name;
2323 int err;
2324
2325 err = fscrypt_prepare_lookup(dir, dentry, &name);
2326 if (err)
2327 return err;
2328
2329 ext4_fname_from_fscrypt_name(fname, &name);
2330 return 0;
2307} 2331}
2308 2332
2309static inline void ext4_fname_free_filename(struct ext4_filename *fname) 2333static inline void ext4_fname_free_filename(struct ext4_filename *fname)
@@ -2317,19 +2341,27 @@ static inline void ext4_fname_free_filename(struct ext4_filename *fname)
2317 fname->usr_fname = NULL; 2341 fname->usr_fname = NULL;
2318 fname->disk_name.name = NULL; 2342 fname->disk_name.name = NULL;
2319} 2343}
2320#else 2344#else /* !CONFIG_FS_ENCRYPTION */
2321static inline int ext4_fname_setup_filename(struct inode *dir, 2345static inline int ext4_fname_setup_filename(struct inode *dir,
2322 const struct qstr *iname, 2346 const struct qstr *iname,
2323 int lookup, struct ext4_filename *fname) 2347 int lookup,
2348 struct ext4_filename *fname)
2324{ 2349{
2325 fname->usr_fname = iname; 2350 fname->usr_fname = iname;
2326 fname->disk_name.name = (unsigned char *) iname->name; 2351 fname->disk_name.name = (unsigned char *) iname->name;
2327 fname->disk_name.len = iname->len; 2352 fname->disk_name.len = iname->len;
2328 return 0; 2353 return 0;
2329} 2354}
2330static inline void ext4_fname_free_filename(struct ext4_filename *fname) { }
2331 2355
2332#endif 2356static inline int ext4_fname_prepare_lookup(struct inode *dir,
2357 struct dentry *dentry,
2358 struct ext4_filename *fname)
2359{
2360 return ext4_fname_setup_filename(dir, &dentry->d_name, 1, fname);
2361}
2362
2363static inline void ext4_fname_free_filename(struct ext4_filename *fname) { }
2364#endif /* !CONFIG_FS_ENCRYPTION */
2333 2365
2334/* dir.c */ 2366/* dir.c */
2335extern int __ext4_check_dir_entry(const char *, unsigned int, struct inode *, 2367extern int __ext4_check_dir_entry(const char *, unsigned int, struct inode *,
diff --git a/fs/ext4/namei.c b/fs/ext4/namei.c
index 980166a8122a..3ba6f30db8d9 100644
--- a/fs/ext4/namei.c
+++ b/fs/ext4/namei.c
@@ -1327,7 +1327,7 @@ static int is_dx_internal_node(struct inode *dir, ext4_lblk_t block,
1327} 1327}
1328 1328
1329/* 1329/*
1330 * ext4_find_entry() 1330 * __ext4_find_entry()
1331 * 1331 *
1332 * finds an entry in the specified directory with the wanted name. It 1332 * finds an entry in the specified directory with the wanted name. It
1333 * returns the cache buffer in which the entry was found, and the entry 1333 * returns the cache buffer in which the entry was found, and the entry
@@ -1337,39 +1337,32 @@ static int is_dx_internal_node(struct inode *dir, ext4_lblk_t block,
1337 * The returned buffer_head has ->b_count elevated. The caller is expected 1337 * The returned buffer_head has ->b_count elevated. The caller is expected
1338 * to brelse() it when appropriate. 1338 * to brelse() it when appropriate.
1339 */ 1339 */
1340static struct buffer_head * ext4_find_entry (struct inode *dir, 1340static struct buffer_head *__ext4_find_entry(struct inode *dir,
1341 const struct qstr *d_name, 1341 struct ext4_filename *fname,
1342 struct ext4_dir_entry_2 **res_dir, 1342 struct ext4_dir_entry_2 **res_dir,
1343 int *inlined) 1343 int *inlined)
1344{ 1344{
1345 struct super_block *sb; 1345 struct super_block *sb;
1346 struct buffer_head *bh_use[NAMEI_RA_SIZE]; 1346 struct buffer_head *bh_use[NAMEI_RA_SIZE];
1347 struct buffer_head *bh, *ret = NULL; 1347 struct buffer_head *bh, *ret = NULL;
1348 ext4_lblk_t start, block; 1348 ext4_lblk_t start, block;
1349 const u8 *name = d_name->name; 1349 const u8 *name = fname->usr_fname->name;
1350 size_t ra_max = 0; /* Number of bh's in the readahead 1350 size_t ra_max = 0; /* Number of bh's in the readahead
1351 buffer, bh_use[] */ 1351 buffer, bh_use[] */
1352 size_t ra_ptr = 0; /* Current index into readahead 1352 size_t ra_ptr = 0; /* Current index into readahead
1353 buffer */ 1353 buffer */
1354 ext4_lblk_t nblocks; 1354 ext4_lblk_t nblocks;
1355 int i, namelen, retval; 1355 int i, namelen, retval;
1356 struct ext4_filename fname;
1357 1356
1358 *res_dir = NULL; 1357 *res_dir = NULL;
1359 sb = dir->i_sb; 1358 sb = dir->i_sb;
1360 namelen = d_name->len; 1359 namelen = fname->usr_fname->len;
1361 if (namelen > EXT4_NAME_LEN) 1360 if (namelen > EXT4_NAME_LEN)
1362 return NULL; 1361 return NULL;
1363 1362
1364 retval = ext4_fname_setup_filename(dir, d_name, 1, &fname);
1365 if (retval == -ENOENT)
1366 return NULL;
1367 if (retval)
1368 return ERR_PTR(retval);
1369
1370 if (ext4_has_inline_data(dir)) { 1363 if (ext4_has_inline_data(dir)) {
1371 int has_inline_data = 1; 1364 int has_inline_data = 1;
1372 ret = ext4_find_inline_entry(dir, &fname, res_dir, 1365 ret = ext4_find_inline_entry(dir, fname, res_dir,
1373 &has_inline_data); 1366 &has_inline_data);
1374 if (has_inline_data) { 1367 if (has_inline_data) {
1375 if (inlined) 1368 if (inlined)
@@ -1389,7 +1382,7 @@ static struct buffer_head * ext4_find_entry (struct inode *dir,
1389 goto restart; 1382 goto restart;
1390 } 1383 }
1391 if (is_dx(dir)) { 1384 if (is_dx(dir)) {
1392 ret = ext4_dx_find_entry(dir, &fname, res_dir); 1385 ret = ext4_dx_find_entry(dir, fname, res_dir);
1393 /* 1386 /*
1394 * On success, or if the error was file not found, 1387 * On success, or if the error was file not found,
1395 * return. Otherwise, fall back to doing a search the 1388 * return. Otherwise, fall back to doing a search the
@@ -1453,7 +1446,7 @@ restart:
1453 goto cleanup_and_exit; 1446 goto cleanup_and_exit;
1454 } 1447 }
1455 set_buffer_verified(bh); 1448 set_buffer_verified(bh);
1456 i = search_dirblock(bh, dir, &fname, 1449 i = search_dirblock(bh, dir, fname,
1457 block << EXT4_BLOCK_SIZE_BITS(sb), res_dir); 1450 block << EXT4_BLOCK_SIZE_BITS(sb), res_dir);
1458 if (i == 1) { 1451 if (i == 1) {
1459 EXT4_I(dir)->i_dir_start_lookup = block; 1452 EXT4_I(dir)->i_dir_start_lookup = block;
@@ -1484,10 +1477,50 @@ cleanup_and_exit:
1484 /* Clean up the read-ahead blocks */ 1477 /* Clean up the read-ahead blocks */
1485 for (; ra_ptr < ra_max; ra_ptr++) 1478 for (; ra_ptr < ra_max; ra_ptr++)
1486 brelse(bh_use[ra_ptr]); 1479 brelse(bh_use[ra_ptr]);
1487 ext4_fname_free_filename(&fname);
1488 return ret; 1480 return ret;
1489} 1481}
1490 1482
1483static struct buffer_head *ext4_find_entry(struct inode *dir,
1484 const struct qstr *d_name,
1485 struct ext4_dir_entry_2 **res_dir,
1486 int *inlined)
1487{
1488 int err;
1489 struct ext4_filename fname;
1490 struct buffer_head *bh;
1491
1492 err = ext4_fname_setup_filename(dir, d_name, 1, &fname);
1493 if (err == -ENOENT)
1494 return NULL;
1495 if (err)
1496 return ERR_PTR(err);
1497
1498 bh = __ext4_find_entry(dir, &fname, res_dir, inlined);
1499
1500 ext4_fname_free_filename(&fname);
1501 return bh;
1502}
1503
1504static struct buffer_head *ext4_lookup_entry(struct inode *dir,
1505 struct dentry *dentry,
1506 struct ext4_dir_entry_2 **res_dir)
1507{
1508 int err;
1509 struct ext4_filename fname;
1510 struct buffer_head *bh;
1511
1512 err = ext4_fname_prepare_lookup(dir, dentry, &fname);
1513 if (err == -ENOENT)
1514 return NULL;
1515 if (err)
1516 return ERR_PTR(err);
1517
1518 bh = __ext4_find_entry(dir, &fname, res_dir, NULL);
1519
1520 ext4_fname_free_filename(&fname);
1521 return bh;
1522}
1523
1491static struct buffer_head * ext4_dx_find_entry(struct inode *dir, 1524static struct buffer_head * ext4_dx_find_entry(struct inode *dir,
1492 struct ext4_filename *fname, 1525 struct ext4_filename *fname,
1493 struct ext4_dir_entry_2 **res_dir) 1526 struct ext4_dir_entry_2 **res_dir)
@@ -1546,16 +1579,11 @@ static struct dentry *ext4_lookup(struct inode *dir, struct dentry *dentry, unsi
1546 struct inode *inode; 1579 struct inode *inode;
1547 struct ext4_dir_entry_2 *de; 1580 struct ext4_dir_entry_2 *de;
1548 struct buffer_head *bh; 1581 struct buffer_head *bh;
1549 int err;
1550
1551 err = fscrypt_prepare_lookup(dir, dentry, flags);
1552 if (err)
1553 return ERR_PTR(err);
1554 1582
1555 if (dentry->d_name.len > EXT4_NAME_LEN) 1583 if (dentry->d_name.len > EXT4_NAME_LEN)
1556 return ERR_PTR(-ENAMETOOLONG); 1584 return ERR_PTR(-ENAMETOOLONG);
1557 1585
1558 bh = ext4_find_entry(dir, &dentry->d_name, &de, NULL); 1586 bh = ext4_lookup_entry(dir, dentry, &de);
1559 if (IS_ERR(bh)) 1587 if (IS_ERR(bh))
1560 return ERR_CAST(bh); 1588 return ERR_CAST(bh);
1561 inode = NULL; 1589 inode = NULL;
diff --git a/fs/f2fs/namei.c b/fs/f2fs/namei.c
index f5e34e467003..c3e8a901d47a 100644
--- a/fs/f2fs/namei.c
+++ b/fs/f2fs/namei.c
@@ -436,19 +436,23 @@ static struct dentry *f2fs_lookup(struct inode *dir, struct dentry *dentry,
436 nid_t ino = -1; 436 nid_t ino = -1;
437 int err = 0; 437 int err = 0;
438 unsigned int root_ino = F2FS_ROOT_INO(F2FS_I_SB(dir)); 438 unsigned int root_ino = F2FS_ROOT_INO(F2FS_I_SB(dir));
439 struct fscrypt_name fname;
439 440
440 trace_f2fs_lookup_start(dir, dentry, flags); 441 trace_f2fs_lookup_start(dir, dentry, flags);
441 442
442 err = fscrypt_prepare_lookup(dir, dentry, flags);
443 if (err)
444 goto out;
445
446 if (dentry->d_name.len > F2FS_NAME_LEN) { 443 if (dentry->d_name.len > F2FS_NAME_LEN) {
447 err = -ENAMETOOLONG; 444 err = -ENAMETOOLONG;
448 goto out; 445 goto out;
449 } 446 }
450 447
451 de = f2fs_find_entry(dir, &dentry->d_name, &page); 448 err = fscrypt_prepare_lookup(dir, dentry, &fname);
449 if (err == -ENOENT)
450 goto out_splice;
451 if (err)
452 goto out;
453 de = __f2fs_find_entry(dir, &fname, &page);
454 fscrypt_free_filename(&fname);
455
452 if (!de) { 456 if (!de) {
453 if (IS_ERR(page)) { 457 if (IS_ERR(page)) {
454 err = PTR_ERR(page); 458 err = PTR_ERR(page);
@@ -488,8 +492,7 @@ static struct dentry *f2fs_lookup(struct inode *dir, struct dentry *dentry,
488 } 492 }
489out_splice: 493out_splice:
490 new = d_splice_alias(inode, dentry); 494 new = d_splice_alias(inode, dentry);
491 if (IS_ERR(new)) 495 err = PTR_ERR_OR_ZERO(new);
492 err = PTR_ERR(new);
493 trace_f2fs_lookup_end(dir, dentry, ino, err); 496 trace_f2fs_lookup_end(dir, dentry, ino, err);
494 return new; 497 return new;
495out_iput: 498out_iput:
diff --git a/fs/ubifs/dir.c b/fs/ubifs/dir.c
index 5767b373a8ff..b73de6d04fa3 100644
--- a/fs/ubifs/dir.c
+++ b/fs/ubifs/dir.c
@@ -220,11 +220,9 @@ static struct dentry *ubifs_lookup(struct inode *dir, struct dentry *dentry,
220 220
221 dbg_gen("'%pd' in dir ino %lu", dentry, dir->i_ino); 221 dbg_gen("'%pd' in dir ino %lu", dentry, dir->i_ino);
222 222
223 err = fscrypt_prepare_lookup(dir, dentry, flags); 223 err = fscrypt_prepare_lookup(dir, dentry, &nm);
224 if (err) 224 if (err == -ENOENT)
225 return ERR_PTR(err); 225 return d_splice_alias(NULL, dentry);
226
227 err = fscrypt_setup_filename(dir, &dentry->d_name, 1, &nm);
228 if (err) 226 if (err)
229 return ERR_PTR(err); 227 return ERR_PTR(err);
230 228
diff --git a/include/linux/fscrypt.h b/include/linux/fscrypt.h
index 76c518f1e4c7..abe7081b6b22 100644
--- a/include/linux/fscrypt.h
+++ b/include/linux/fscrypt.h
@@ -33,6 +33,7 @@ struct fscrypt_name {
33 u32 hash; 33 u32 hash;
34 u32 minor_hash; 34 u32 minor_hash;
35 struct fscrypt_str crypto_buf; 35 struct fscrypt_str crypto_buf;
36 bool is_ciphertext_name;
36}; 37};
37 38
38#define FSTR_INIT(n, l) { .name = n, .len = l } 39#define FSTR_INIT(n, l) { .name = n, .len = l }
@@ -234,7 +235,8 @@ extern int __fscrypt_prepare_rename(struct inode *old_dir,
234 struct inode *new_dir, 235 struct inode *new_dir,
235 struct dentry *new_dentry, 236 struct dentry *new_dentry,
236 unsigned int flags); 237 unsigned int flags);
237extern int __fscrypt_prepare_lookup(struct inode *dir, struct dentry *dentry); 238extern int __fscrypt_prepare_lookup(struct inode *dir, struct dentry *dentry,
239 struct fscrypt_name *fname);
238extern int __fscrypt_prepare_symlink(struct inode *dir, unsigned int len, 240extern int __fscrypt_prepare_symlink(struct inode *dir, unsigned int len,
239 unsigned int max_len, 241 unsigned int max_len,
240 struct fscrypt_str *disk_link); 242 struct fscrypt_str *disk_link);
@@ -347,7 +349,7 @@ static inline int fscrypt_setup_filename(struct inode *dir,
347 if (IS_ENCRYPTED(dir)) 349 if (IS_ENCRYPTED(dir))
348 return -EOPNOTSUPP; 350 return -EOPNOTSUPP;
349 351
350 memset(fname, 0, sizeof(struct fscrypt_name)); 352 memset(fname, 0, sizeof(*fname));
351 fname->usr_fname = iname; 353 fname->usr_fname = iname;
352 fname->disk_name.name = (unsigned char *)iname->name; 354 fname->disk_name.name = (unsigned char *)iname->name;
353 fname->disk_name.len = iname->len; 355 fname->disk_name.len = iname->len;
@@ -434,7 +436,8 @@ static inline int __fscrypt_prepare_rename(struct inode *old_dir,
434} 436}
435 437
436static inline int __fscrypt_prepare_lookup(struct inode *dir, 438static inline int __fscrypt_prepare_lookup(struct inode *dir,
437 struct dentry *dentry) 439 struct dentry *dentry,
440 struct fscrypt_name *fname)
438{ 441{
439 return -EOPNOTSUPP; 442 return -EOPNOTSUPP;
440} 443}
@@ -555,25 +558,32 @@ static inline int fscrypt_prepare_rename(struct inode *old_dir,
555 * fscrypt_prepare_lookup - prepare to lookup a name in a possibly-encrypted directory 558 * fscrypt_prepare_lookup - prepare to lookup a name in a possibly-encrypted directory
556 * @dir: directory being searched 559 * @dir: directory being searched
557 * @dentry: filename being looked up 560 * @dentry: filename being looked up
558 * @flags: lookup flags 561 * @fname: (output) the name to use to search the on-disk directory
559 * 562 *
560 * Prepare for ->lookup() in a directory which may be encrypted. Lookups can be 563 * Prepare for ->lookup() in a directory which may be encrypted by determining
561 * done with or without the directory's encryption key; without the key, 564 * the name that will actually be used to search the directory on-disk. Lookups
565 * can be done with or without the directory's encryption key; without the key,
562 * filenames are presented in encrypted form. Therefore, we'll try to set up 566 * filenames are presented in encrypted form. Therefore, we'll try to set up
563 * the directory's encryption key, but even without it the lookup can continue. 567 * the directory's encryption key, but even without it the lookup can continue.
564 * 568 *
565 * This also installs a custom ->d_revalidate() method which will invalidate the 569 * This also installs a custom ->d_revalidate() method which will invalidate the
566 * dentry if it was created without the key and the key is later added. 570 * dentry if it was created without the key and the key is later added.
567 * 571 *
568 * Return: 0 on success, -errno if a problem occurred while setting up the 572 * Return: 0 on success; -ENOENT if key is unavailable but the filename isn't a
569 * encryption key 573 * correctly formed encoded ciphertext name, so a negative dentry should be
574 * created; or another -errno code.
570 */ 575 */
571static inline int fscrypt_prepare_lookup(struct inode *dir, 576static inline int fscrypt_prepare_lookup(struct inode *dir,
572 struct dentry *dentry, 577 struct dentry *dentry,
573 unsigned int flags) 578 struct fscrypt_name *fname)
574{ 579{
575 if (IS_ENCRYPTED(dir)) 580 if (IS_ENCRYPTED(dir))
576 return __fscrypt_prepare_lookup(dir, dentry); 581 return __fscrypt_prepare_lookup(dir, dentry, fname);
582
583 memset(fname, 0, sizeof(*fname));
584 fname->usr_fname = &dentry->d_name;
585 fname->disk_name.name = (unsigned char *)dentry->d_name.name;
586 fname->disk_name.len = dentry->d_name.len;
577 return 0; 587 return 0;
578} 588}
579 589