aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorEric Biggers <ebiggers@google.com>2019-04-10 16:21:15 -0400
committerTheodore Ts'o <tytso@mit.edu>2019-04-17 12:43:29 -0400
commit2c58d548f5706d085c4b009f6abb945220460632 (patch)
treeb263f432d3ad778b6970ebbb842bd0a577e88cdc
parent4c4f7c19b3c721aed418bc97907b411608c5c6a0 (diff)
fscrypt: cache decrypted symlink target in ->i_link
Path lookups that traverse encrypted symlink(s) are very slow because each encrypted symlink needs to be decrypted each time it's followed. This also involves dropping out of rcu-walk mode. Make encrypted symlinks faster by caching the decrypted symlink target in ->i_link. The first call to fscrypt_get_symlink() sets it. Then, the existing VFS path lookup code uses the non-NULL ->i_link to take the fast path where ->get_link() isn't called, and lookups in rcu-walk mode remain in rcu-walk mode. Also set ->i_link immediately when a new encrypted symlink is created. To safely free the symlink target after an RCU grace period has elapsed, introduce a new function fscrypt_free_inode(), and make the relevant filesystems call it just before actually freeing the inode. Cc: Al Viro <viro@zeniv.linux.org.uk> Signed-off-by: Eric Biggers <ebiggers@google.com> Signed-off-by: Theodore Ts'o <tytso@mit.edu>
-rw-r--r--fs/crypto/hooks.c40
-rw-r--r--fs/crypto/keyinfo.c21
-rw-r--r--fs/ext4/super.c3
-rw-r--r--fs/f2fs/super.c3
-rw-r--r--fs/ubifs/super.c3
-rw-r--r--include/linux/fscrypt.h5
6 files changed, 68 insertions, 7 deletions
diff --git a/fs/crypto/hooks.c b/fs/crypto/hooks.c
index 042d5b44f4ed..2dc22549d724 100644
--- a/fs/crypto/hooks.c
+++ b/fs/crypto/hooks.c
@@ -189,11 +189,9 @@ int __fscrypt_encrypt_symlink(struct inode *inode, const char *target,
189 sd->len = cpu_to_le16(ciphertext_len); 189 sd->len = cpu_to_le16(ciphertext_len);
190 190
191 err = fname_encrypt(inode, &iname, sd->encrypted_path, ciphertext_len); 191 err = fname_encrypt(inode, &iname, sd->encrypted_path, ciphertext_len);
192 if (err) { 192 if (err)
193 if (!disk_link->name) 193 goto err_free_sd;
194 kfree(sd); 194
195 return err;
196 }
197 /* 195 /*
198 * Null-terminating the ciphertext doesn't make sense, but we still 196 * Null-terminating the ciphertext doesn't make sense, but we still
199 * count the null terminator in the length, so we might as well 197 * count the null terminator in the length, so we might as well
@@ -201,9 +199,20 @@ int __fscrypt_encrypt_symlink(struct inode *inode, const char *target,
201 */ 199 */
202 sd->encrypted_path[ciphertext_len] = '\0'; 200 sd->encrypted_path[ciphertext_len] = '\0';
203 201
202 /* Cache the plaintext symlink target for later use by get_link() */
203 err = -ENOMEM;
204 inode->i_link = kmemdup(target, len + 1, GFP_NOFS);
205 if (!inode->i_link)
206 goto err_free_sd;
207
204 if (!disk_link->name) 208 if (!disk_link->name)
205 disk_link->name = (unsigned char *)sd; 209 disk_link->name = (unsigned char *)sd;
206 return 0; 210 return 0;
211
212err_free_sd:
213 if (!disk_link->name)
214 kfree(sd);
215 return err;
207} 216}
208EXPORT_SYMBOL_GPL(__fscrypt_encrypt_symlink); 217EXPORT_SYMBOL_GPL(__fscrypt_encrypt_symlink);
209 218
@@ -212,7 +221,7 @@ EXPORT_SYMBOL_GPL(__fscrypt_encrypt_symlink);
212 * @inode: the symlink inode 221 * @inode: the symlink inode
213 * @caddr: the on-disk contents of the symlink 222 * @caddr: the on-disk contents of the symlink
214 * @max_size: size of @caddr buffer 223 * @max_size: size of @caddr buffer
215 * @done: if successful, will be set up to free the returned target 224 * @done: if successful, will be set up to free the returned target if needed
216 * 225 *
217 * If the symlink's encryption key is available, we decrypt its target. 226 * If the symlink's encryption key is available, we decrypt its target.
218 * Otherwise, we encode its target for presentation. 227 * Otherwise, we encode its target for presentation.
@@ -227,12 +236,18 @@ const char *fscrypt_get_symlink(struct inode *inode, const void *caddr,
227{ 236{
228 const struct fscrypt_symlink_data *sd; 237 const struct fscrypt_symlink_data *sd;
229 struct fscrypt_str cstr, pstr; 238 struct fscrypt_str cstr, pstr;
239 bool has_key;
230 int err; 240 int err;
231 241
232 /* This is for encrypted symlinks only */ 242 /* This is for encrypted symlinks only */
233 if (WARN_ON(!IS_ENCRYPTED(inode))) 243 if (WARN_ON(!IS_ENCRYPTED(inode)))
234 return ERR_PTR(-EINVAL); 244 return ERR_PTR(-EINVAL);
235 245
246 /* If the decrypted target is already cached, just return it. */
247 pstr.name = READ_ONCE(inode->i_link);
248 if (pstr.name)
249 return pstr.name;
250
236 /* 251 /*
237 * Try to set up the symlink's encryption key, but we can continue 252 * Try to set up the symlink's encryption key, but we can continue
238 * regardless of whether the key is available or not. 253 * regardless of whether the key is available or not.
@@ -240,6 +255,7 @@ const char *fscrypt_get_symlink(struct inode *inode, const void *caddr,
240 err = fscrypt_get_encryption_info(inode); 255 err = fscrypt_get_encryption_info(inode);
241 if (err) 256 if (err)
242 return ERR_PTR(err); 257 return ERR_PTR(err);
258 has_key = fscrypt_has_encryption_key(inode);
243 259
244 /* 260 /*
245 * For historical reasons, encrypted symlink targets are prefixed with 261 * For historical reasons, encrypted symlink targets are prefixed with
@@ -271,7 +287,17 @@ const char *fscrypt_get_symlink(struct inode *inode, const void *caddr,
271 goto err_kfree; 287 goto err_kfree;
272 288
273 pstr.name[pstr.len] = '\0'; 289 pstr.name[pstr.len] = '\0';
274 set_delayed_call(done, kfree_link, pstr.name); 290
291 /*
292 * Cache decrypted symlink targets in i_link for later use. Don't cache
293 * symlink targets encoded without the key, since those become outdated
294 * once the key is added. This pairs with the READ_ONCE() above and in
295 * the VFS path lookup code.
296 */
297 if (!has_key ||
298 cmpxchg_release(&inode->i_link, NULL, pstr.name) != NULL)
299 set_delayed_call(done, kfree_link, pstr.name);
300
275 return pstr.name; 301 return pstr.name;
276 302
277err_kfree: 303err_kfree:
diff --git a/fs/crypto/keyinfo.c b/fs/crypto/keyinfo.c
index bf291c10c682..82989098b2fc 100644
--- a/fs/crypto/keyinfo.c
+++ b/fs/crypto/keyinfo.c
@@ -584,9 +584,30 @@ out:
584} 584}
585EXPORT_SYMBOL(fscrypt_get_encryption_info); 585EXPORT_SYMBOL(fscrypt_get_encryption_info);
586 586
587/**
588 * fscrypt_put_encryption_info - free most of an inode's fscrypt data
589 *
590 * Free the inode's fscrypt_info. Filesystems must call this when the inode is
591 * being evicted. An RCU grace period need not have elapsed yet.
592 */
587void fscrypt_put_encryption_info(struct inode *inode) 593void fscrypt_put_encryption_info(struct inode *inode)
588{ 594{
589 put_crypt_info(inode->i_crypt_info); 595 put_crypt_info(inode->i_crypt_info);
590 inode->i_crypt_info = NULL; 596 inode->i_crypt_info = NULL;
591} 597}
592EXPORT_SYMBOL(fscrypt_put_encryption_info); 598EXPORT_SYMBOL(fscrypt_put_encryption_info);
599
600/**
601 * fscrypt_free_inode - free an inode's fscrypt data requiring RCU delay
602 *
603 * Free the inode's cached decrypted symlink target, if any. Filesystems must
604 * call this after an RCU grace period, just before they free the inode.
605 */
606void fscrypt_free_inode(struct inode *inode)
607{
608 if (IS_ENCRYPTED(inode) && S_ISLNK(inode->i_mode)) {
609 kfree(inode->i_link);
610 inode->i_link = NULL;
611 }
612}
613EXPORT_SYMBOL(fscrypt_free_inode);
diff --git a/fs/ext4/super.c b/fs/ext4/super.c
index 6ed4eb81e674..5b92054bf8ea 100644
--- a/fs/ext4/super.c
+++ b/fs/ext4/super.c
@@ -1110,6 +1110,9 @@ static int ext4_drop_inode(struct inode *inode)
1110static void ext4_i_callback(struct rcu_head *head) 1110static void ext4_i_callback(struct rcu_head *head)
1111{ 1111{
1112 struct inode *inode = container_of(head, struct inode, i_rcu); 1112 struct inode *inode = container_of(head, struct inode, i_rcu);
1113
1114 fscrypt_free_inode(inode);
1115
1113 kmem_cache_free(ext4_inode_cachep, EXT4_I(inode)); 1116 kmem_cache_free(ext4_inode_cachep, EXT4_I(inode));
1114} 1117}
1115 1118
diff --git a/fs/f2fs/super.c b/fs/f2fs/super.c
index f2aaa2cc6b3e..11b3a039a188 100644
--- a/fs/f2fs/super.c
+++ b/fs/f2fs/super.c
@@ -1003,6 +1003,9 @@ static void f2fs_dirty_inode(struct inode *inode, int flags)
1003static void f2fs_i_callback(struct rcu_head *head) 1003static void f2fs_i_callback(struct rcu_head *head)
1004{ 1004{
1005 struct inode *inode = container_of(head, struct inode, i_rcu); 1005 struct inode *inode = container_of(head, struct inode, i_rcu);
1006
1007 fscrypt_free_inode(inode);
1008
1006 kmem_cache_free(f2fs_inode_cachep, F2FS_I(inode)); 1009 kmem_cache_free(f2fs_inode_cachep, F2FS_I(inode));
1007} 1010}
1008 1011
diff --git a/fs/ubifs/super.c b/fs/ubifs/super.c
index 12628184772c..19fd21098745 100644
--- a/fs/ubifs/super.c
+++ b/fs/ubifs/super.c
@@ -276,7 +276,10 @@ static void ubifs_i_callback(struct rcu_head *head)
276{ 276{
277 struct inode *inode = container_of(head, struct inode, i_rcu); 277 struct inode *inode = container_of(head, struct inode, i_rcu);
278 struct ubifs_inode *ui = ubifs_inode(inode); 278 struct ubifs_inode *ui = ubifs_inode(inode);
279
279 kfree(ui->data); 280 kfree(ui->data);
281 fscrypt_free_inode(inode);
282
280 kmem_cache_free(ubifs_inode_slab, ui); 283 kmem_cache_free(ubifs_inode_slab, ui);
281} 284}
282 285
diff --git a/include/linux/fscrypt.h b/include/linux/fscrypt.h
index abe7081b6b22..28c74e0a7231 100644
--- a/include/linux/fscrypt.h
+++ b/include/linux/fscrypt.h
@@ -128,6 +128,7 @@ extern int fscrypt_inherit_context(struct inode *, struct inode *,
128/* keyinfo.c */ 128/* keyinfo.c */
129extern int fscrypt_get_encryption_info(struct inode *); 129extern int fscrypt_get_encryption_info(struct inode *);
130extern void fscrypt_put_encryption_info(struct inode *); 130extern void fscrypt_put_encryption_info(struct inode *);
131extern void fscrypt_free_inode(struct inode *);
131 132
132/* fname.c */ 133/* fname.c */
133extern int fscrypt_setup_filename(struct inode *, const struct qstr *, 134extern int fscrypt_setup_filename(struct inode *, const struct qstr *,
@@ -341,6 +342,10 @@ static inline void fscrypt_put_encryption_info(struct inode *inode)
341 return; 342 return;
342} 343}
343 344
345static inline void fscrypt_free_inode(struct inode *inode)
346{
347}
348
344 /* fname.c */ 349 /* fname.c */
345static inline int fscrypt_setup_filename(struct inode *dir, 350static inline int fscrypt_setup_filename(struct inode *dir,
346 const struct qstr *iname, 351 const struct qstr *iname,