diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2019-05-08 00:28:04 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2019-05-08 00:28:04 -0400 |
commit | a9fbcd6728837268784439ad0b02ede2c024c516 (patch) | |
tree | 2a58af9a6f7573617ab482aea0998389d8b956af /fs/crypto/hooks.c | |
parent | 5abe37954e9a315c35c9490f78d55f307c3c636b (diff) | |
parent | 2c58d548f5706d085c4b009f6abb945220460632 (diff) |
Merge tag 'fscrypt_for_linus' of git://git.kernel.org/pub/scm/fs/fscrypt/fscrypt
Pull fscrypt updates from Ted Ts'o:
"Clean up fscrypt's dcache revalidation support, and other
miscellaneous cleanups"
* tag 'fscrypt_for_linus' of git://git.kernel.org/pub/scm/fs/fscrypt/fscrypt:
fscrypt: cache decrypted symlink target in ->i_link
vfs: use READ_ONCE() to access ->i_link
fscrypt: fix race where ->lookup() marks plaintext dentry as ciphertext
fscrypt: only set dentry_operations on ciphertext dentries
fs, fscrypt: clear DCACHE_ENCRYPTED_NAME when unaliasing directory
fscrypt: fix race allowing rename() and link() of ciphertext dentries
fscrypt: clean up and improve dentry revalidation
fscrypt: use READ_ONCE() to access ->i_crypt_info
fscrypt: remove WARN_ON_ONCE() when decryption fails
fscrypt: drop inode argument from fscrypt_get_ctx()
Diffstat (limited to 'fs/crypto/hooks.c')
-rw-r--r-- | fs/crypto/hooks.c | 68 |
1 files changed, 52 insertions, 16 deletions
diff --git a/fs/crypto/hooks.c b/fs/crypto/hooks.c index 56debb1fcf5e..2dc22549d724 100644 --- a/fs/crypto/hooks.c +++ b/fs/crypto/hooks.c | |||
@@ -49,7 +49,8 @@ int fscrypt_file_open(struct inode *inode, struct file *filp) | |||
49 | } | 49 | } |
50 | EXPORT_SYMBOL_GPL(fscrypt_file_open); | 50 | EXPORT_SYMBOL_GPL(fscrypt_file_open); |
51 | 51 | ||
52 | int __fscrypt_prepare_link(struct inode *inode, struct inode *dir) | 52 | int __fscrypt_prepare_link(struct inode *inode, struct inode *dir, |
53 | struct dentry *dentry) | ||
53 | { | 54 | { |
54 | int err; | 55 | int err; |
55 | 56 | ||
@@ -57,6 +58,10 @@ int __fscrypt_prepare_link(struct inode *inode, struct inode *dir) | |||
57 | if (err) | 58 | if (err) |
58 | return err; | 59 | return err; |
59 | 60 | ||
61 | /* ... in case we looked up ciphertext name before key was added */ | ||
62 | if (dentry->d_flags & DCACHE_ENCRYPTED_NAME) | ||
63 | return -ENOKEY; | ||
64 | |||
60 | if (!fscrypt_has_permitted_context(dir, inode)) | 65 | if (!fscrypt_has_permitted_context(dir, inode)) |
61 | return -EXDEV; | 66 | return -EXDEV; |
62 | 67 | ||
@@ -78,6 +83,11 @@ int __fscrypt_prepare_rename(struct inode *old_dir, struct dentry *old_dentry, | |||
78 | if (err) | 83 | if (err) |
79 | return err; | 84 | return err; |
80 | 85 | ||
86 | /* ... in case we looked up ciphertext name(s) before key was added */ | ||
87 | if ((old_dentry->d_flags | new_dentry->d_flags) & | ||
88 | DCACHE_ENCRYPTED_NAME) | ||
89 | return -ENOKEY; | ||
90 | |||
81 | if (old_dir != new_dir) { | 91 | if (old_dir != new_dir) { |
82 | if (IS_ENCRYPTED(new_dir) && | 92 | if (IS_ENCRYPTED(new_dir) && |
83 | !fscrypt_has_permitted_context(new_dir, | 93 | !fscrypt_has_permitted_context(new_dir, |
@@ -94,21 +104,21 @@ int __fscrypt_prepare_rename(struct inode *old_dir, struct dentry *old_dentry, | |||
94 | } | 104 | } |
95 | EXPORT_SYMBOL_GPL(__fscrypt_prepare_rename); | 105 | EXPORT_SYMBOL_GPL(__fscrypt_prepare_rename); |
96 | 106 | ||
97 | int __fscrypt_prepare_lookup(struct inode *dir, struct dentry *dentry) | 107 | int __fscrypt_prepare_lookup(struct inode *dir, struct dentry *dentry, |
108 | struct fscrypt_name *fname) | ||
98 | { | 109 | { |
99 | int err = fscrypt_get_encryption_info(dir); | 110 | int err = fscrypt_setup_filename(dir, &dentry->d_name, 1, fname); |
100 | 111 | ||
101 | if (err) | 112 | if (err && err != -ENOENT) |
102 | return err; | 113 | return err; |
103 | 114 | ||
104 | if (fscrypt_has_encryption_key(dir)) { | 115 | if (fname->is_ciphertext_name) { |
105 | spin_lock(&dentry->d_lock); | 116 | spin_lock(&dentry->d_lock); |
106 | dentry->d_flags |= DCACHE_ENCRYPTED_WITH_KEY; | 117 | dentry->d_flags |= DCACHE_ENCRYPTED_NAME; |
107 | spin_unlock(&dentry->d_lock); | 118 | spin_unlock(&dentry->d_lock); |
119 | d_set_d_op(dentry, &fscrypt_d_ops); | ||
108 | } | 120 | } |
109 | 121 | return err; | |
110 | d_set_d_op(dentry, &fscrypt_d_ops); | ||
111 | return 0; | ||
112 | } | 122 | } |
113 | EXPORT_SYMBOL_GPL(__fscrypt_prepare_lookup); | 123 | EXPORT_SYMBOL_GPL(__fscrypt_prepare_lookup); |
114 | 124 | ||
@@ -179,11 +189,9 @@ int __fscrypt_encrypt_symlink(struct inode *inode, const char *target, | |||
179 | sd->len = cpu_to_le16(ciphertext_len); | 189 | sd->len = cpu_to_le16(ciphertext_len); |
180 | 190 | ||
181 | err = fname_encrypt(inode, &iname, sd->encrypted_path, ciphertext_len); | 191 | err = fname_encrypt(inode, &iname, sd->encrypted_path, ciphertext_len); |
182 | if (err) { | 192 | if (err) |
183 | if (!disk_link->name) | 193 | goto err_free_sd; |
184 | kfree(sd); | 194 | |
185 | return err; | ||
186 | } | ||
187 | /* | 195 | /* |
188 | * Null-terminating the ciphertext doesn't make sense, but we still | 196 | * Null-terminating the ciphertext doesn't make sense, but we still |
189 | * 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 |
@@ -191,9 +199,20 @@ int __fscrypt_encrypt_symlink(struct inode *inode, const char *target, | |||
191 | */ | 199 | */ |
192 | sd->encrypted_path[ciphertext_len] = '\0'; | 200 | sd->encrypted_path[ciphertext_len] = '\0'; |
193 | 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 | |||
194 | if (!disk_link->name) | 208 | if (!disk_link->name) |
195 | disk_link->name = (unsigned char *)sd; | 209 | disk_link->name = (unsigned char *)sd; |
196 | return 0; | 210 | return 0; |
211 | |||
212 | err_free_sd: | ||
213 | if (!disk_link->name) | ||
214 | kfree(sd); | ||
215 | return err; | ||
197 | } | 216 | } |
198 | EXPORT_SYMBOL_GPL(__fscrypt_encrypt_symlink); | 217 | EXPORT_SYMBOL_GPL(__fscrypt_encrypt_symlink); |
199 | 218 | ||
@@ -202,7 +221,7 @@ EXPORT_SYMBOL_GPL(__fscrypt_encrypt_symlink); | |||
202 | * @inode: the symlink inode | 221 | * @inode: the symlink inode |
203 | * @caddr: the on-disk contents of the symlink | 222 | * @caddr: the on-disk contents of the symlink |
204 | * @max_size: size of @caddr buffer | 223 | * @max_size: size of @caddr buffer |
205 | * @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 |
206 | * | 225 | * |
207 | * 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. |
208 | * Otherwise, we encode its target for presentation. | 227 | * Otherwise, we encode its target for presentation. |
@@ -217,12 +236,18 @@ const char *fscrypt_get_symlink(struct inode *inode, const void *caddr, | |||
217 | { | 236 | { |
218 | const struct fscrypt_symlink_data *sd; | 237 | const struct fscrypt_symlink_data *sd; |
219 | struct fscrypt_str cstr, pstr; | 238 | struct fscrypt_str cstr, pstr; |
239 | bool has_key; | ||
220 | int err; | 240 | int err; |
221 | 241 | ||
222 | /* This is for encrypted symlinks only */ | 242 | /* This is for encrypted symlinks only */ |
223 | if (WARN_ON(!IS_ENCRYPTED(inode))) | 243 | if (WARN_ON(!IS_ENCRYPTED(inode))) |
224 | return ERR_PTR(-EINVAL); | 244 | return ERR_PTR(-EINVAL); |
225 | 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 | |||
226 | /* | 251 | /* |
227 | * 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 |
228 | * regardless of whether the key is available or not. | 253 | * regardless of whether the key is available or not. |
@@ -230,6 +255,7 @@ const char *fscrypt_get_symlink(struct inode *inode, const void *caddr, | |||
230 | err = fscrypt_get_encryption_info(inode); | 255 | err = fscrypt_get_encryption_info(inode); |
231 | if (err) | 256 | if (err) |
232 | return ERR_PTR(err); | 257 | return ERR_PTR(err); |
258 | has_key = fscrypt_has_encryption_key(inode); | ||
233 | 259 | ||
234 | /* | 260 | /* |
235 | * For historical reasons, encrypted symlink targets are prefixed with | 261 | * For historical reasons, encrypted symlink targets are prefixed with |
@@ -261,7 +287,17 @@ const char *fscrypt_get_symlink(struct inode *inode, const void *caddr, | |||
261 | goto err_kfree; | 287 | goto err_kfree; |
262 | 288 | ||
263 | pstr.name[pstr.len] = '\0'; | 289 | pstr.name[pstr.len] = '\0'; |
264 | 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 | |||
265 | return pstr.name; | 301 | return pstr.name; |
266 | 302 | ||
267 | err_kfree: | 303 | err_kfree: |