aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
Diffstat (limited to 'fs/crypto/hooks.c')
-rw-r--r--fs/crypto/hooks.c54
1 files changed, 49 insertions, 5 deletions
diff --git a/fs/crypto/hooks.c b/fs/crypto/hooks.c
index a3582f2ca376..7173233c26ca 100644
--- a/fs/crypto/hooks.c
+++ b/fs/crypto/hooks.c
@@ -59,8 +59,8 @@ int __fscrypt_prepare_link(struct inode *inode, struct inode *dir,
59 if (err) 59 if (err)
60 return err; 60 return err;
61 61
62 /* ... in case we looked up ciphertext name before key was added */ 62 /* ... in case we looked up no-key name before key was added */
63 if (dentry->d_flags & DCACHE_ENCRYPTED_NAME) 63 if (fscrypt_is_nokey_name(dentry))
64 return -ENOKEY; 64 return -ENOKEY;
65 65
66 if (!fscrypt_has_permitted_context(dir, inode)) 66 if (!fscrypt_has_permitted_context(dir, inode))
@@ -84,9 +84,9 @@ int __fscrypt_prepare_rename(struct inode *old_dir, struct dentry *old_dentry,
84 if (err) 84 if (err)
85 return err; 85 return err;
86 86
87 /* ... in case we looked up ciphertext name(s) before key was added */ 87 /* ... in case we looked up no-key name(s) before key was added */
88 if ((old_dentry->d_flags | new_dentry->d_flags) & 88 if (fscrypt_is_nokey_name(old_dentry) ||
89 DCACHE_ENCRYPTED_NAME) 89 fscrypt_is_nokey_name(new_dentry))
90 return -ENOKEY; 90 return -ENOKEY;
91 91
92 if (old_dir != new_dir) { 92 if (old_dir != new_dir) {
@@ -348,3 +348,47 @@ err_kfree:
348 return ERR_PTR(err); 348 return ERR_PTR(err);
349} 349}
350EXPORT_SYMBOL_GPL(fscrypt_get_symlink); 350EXPORT_SYMBOL_GPL(fscrypt_get_symlink);
351
352/**
353 * fscrypt_symlink_getattr() - set the correct st_size for encrypted symlinks
354 * @path: the path for the encrypted symlink being queried
355 * @stat: the struct being filled with the symlink's attributes
356 *
357 * Override st_size of encrypted symlinks to be the length of the decrypted
358 * symlink target (or the no-key encoded symlink target, if the key is
359 * unavailable) rather than the length of the encrypted symlink target. This is
360 * necessary for st_size to match the symlink target that userspace actually
361 * sees. POSIX requires this, and some userspace programs depend on it.
362 *
363 * This requires reading the symlink target from disk if needed, setting up the
364 * inode's encryption key if possible, and then decrypting or encoding the
365 * symlink target. This makes lstat() more heavyweight than is normally the
366 * case. However, decrypted symlink targets will be cached in ->i_link, so
367 * usually the symlink won't have to be read and decrypted again later if/when
368 * it is actually followed, readlink() is called, or lstat() is called again.
369 *
370 * Return: 0 on success, -errno on failure
371 */
372int fscrypt_symlink_getattr(const struct path *path, struct kstat *stat)
373{
374 struct dentry *dentry = path->dentry;
375 struct inode *inode = d_inode(dentry);
376 const char *link;
377 DEFINE_DELAYED_CALL(done);
378
379 /*
380 * To get the symlink target that userspace will see (whether it's the
381 * decrypted target or the no-key encoded target), we can just get it in
382 * the same way the VFS does during path resolution and readlink().
383 */
384 link = READ_ONCE(inode->i_link);
385 if (!link) {
386 link = inode->i_op->get_link(dentry, inode, &done);
387 if (IS_ERR(link))
388 return PTR_ERR(link);
389 }
390 stat->size = strlen(link);
391 do_delayed_call(&done);
392 return 0;
393}
394EXPORT_SYMBOL_GPL(fscrypt_symlink_getattr);