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()
Showing the changes to include/linux (2 of 18 files). Show all
Unified · Split
| @@ -211,7 +211,7 @@ struct dentry_operations { · 210 unmodified lines | ||
| 211 | 211 | |
| 212 | 212 | #define DCACHE_MAY_FREE 0x00800000 |
| 213 | 213 | #define DCACHE_FALLTHRU 0x01000000 /* Fall through to lower layer */ |
| 214 | −#define DCACHE_ENCRYPTED_WITH_KEY 0x02000000 /* dir is encrypted with a valid key */ | |
| 214 | +#define DCACHE_ENCRYPTED_NAME 0x02000000 /* Encrypted name (dir key was unavailable) */ | |
| 215 | 215 | #define DCACHE_OP_REAL 0x04000000 |
| 216 | 216 | |
| 217 | 217 | #define DCACHE_PAR_LOOKUP 0x10000000 /* being looked up (with parent locked shared) */ |
| @@ -33,6 +33,7 @@ struct fscrypt_name { · 32 unmodified lines | ||
| 33 | 33 | u32 hash; |
| 34 | 34 | u32 minor_hash; |
| 35 | 35 | struct fscrypt_str crypto_buf; |
| 36 | + bool is_ciphertext_name; | |
| 36 | 37 | }; |
| 37 | 38 | |
| 38 | 39 | #define FSTR_INIT(n, l) { .name = n, .len = l } |
| @@ -79,7 +80,8 @@ struct fscrypt_ctx { · 40 unmodified lines | ||
| 79 | 80 | |
| 80 | 81 | static inline bool fscrypt_has_encryption_key(const struct inode *inode) |
| 81 | 82 | { |
| 82 | − return (inode->i_crypt_info != NULL); | |
| 83 | + /* pairs with cmpxchg_release() in fscrypt_get_encryption_info() */ | |
| 84 | + return READ_ONCE(inode->i_crypt_info) != NULL; | |
| 83 | 85 | } |
| 84 | 86 | |
| 85 | 87 | static inline bool fscrypt_dummy_context_enabled(struct inode *inode) |
| @@ -88,9 +90,21 @@ static inline bool fscrypt_dummy_context_enabled(struct inode *inode) · 2 unmodified lines | ||
| 88 | 90 | inode->i_sb->s_cop->dummy_context(inode); |
| 89 | 91 | } |
| 90 | 92 | |
| 93 | +/* | |
| 94 | + * When d_splice_alias() moves a directory's encrypted alias to its decrypted | |
| 95 | + * alias as a result of the encryption key being added, DCACHE_ENCRYPTED_NAME | |
| 96 | + * must be cleared. Note that we don't have to support arbitrary moves of this | |
| 97 | + * flag because fscrypt doesn't allow encrypted aliases to be the source or | |
| 98 | + * target of a rename(). | |
| 99 | + */ | |
| 100 | +static inline void fscrypt_handle_d_move(struct dentry *dentry) | |
| 101 | +{ | |
| 102 | + dentry->d_flags &= ~DCACHE_ENCRYPTED_NAME; | |
| 103 | +} | |
| 104 | + | |
| 91 | 105 | /* crypto.c */ |
| 92 | 106 | extern void fscrypt_enqueue_decrypt_work(struct work_struct *); |
| 93 | −extern struct fscrypt_ctx *fscrypt_get_ctx(const struct inode *, gfp_t); | |
| 107 | +extern struct fscrypt_ctx *fscrypt_get_ctx(gfp_t); | |
| 94 | 108 | extern void fscrypt_release_ctx(struct fscrypt_ctx *); |
| 95 | 109 | extern struct page *fscrypt_encrypt_page(const struct inode *, struct page *, |
| 96 | 110 | unsigned int, unsigned int, |
| @@ -114,6 +128,7 @@ extern int fscrypt_inherit_context(struct inode *, struct inode *, · 17 unmodified lines | ||
| 114 | 128 | /* keyinfo.c */ |
| 115 | 129 | extern int fscrypt_get_encryption_info(struct inode *); |
| 116 | 130 | extern void fscrypt_put_encryption_info(struct inode *); |
| 131 | +extern void fscrypt_free_inode(struct inode *); | |
| 117 | 132 | |
| 118 | 133 | /* fname.c */ |
| 119 | 134 | extern int fscrypt_setup_filename(struct inode *, const struct qstr *, |
| @@ -214,13 +229,15 @@ extern int fscrypt_zeroout_range(const struct inode *, pgoff_t, sector_t, · 94 unmodified lines | ||
| 214 | 229 | |
| 215 | 230 | /* hooks.c */ |
| 216 | 231 | extern int fscrypt_file_open(struct inode *inode, struct file *filp); |
| 217 | −extern int __fscrypt_prepare_link(struct inode *inode, struct inode *dir); | |
| 232 | +extern int __fscrypt_prepare_link(struct inode *inode, struct inode *dir, | |
| 233 | + struct dentry *dentry); | |
| 218 | 234 | extern int __fscrypt_prepare_rename(struct inode *old_dir, |
| 219 | 235 | struct dentry *old_dentry, |
| 220 | 236 | struct inode *new_dir, |
| 221 | 237 | struct dentry *new_dentry, |
| 222 | 238 | unsigned int flags); |
| 223 | −extern int __fscrypt_prepare_lookup(struct inode *dir, struct dentry *dentry); | |
| 239 | +extern int __fscrypt_prepare_lookup(struct inode *dir, struct dentry *dentry, | |
| 240 | + struct fscrypt_name *fname); | |
| 224 | 241 | extern int __fscrypt_prepare_symlink(struct inode *dir, unsigned int len, |
| 225 | 242 | unsigned int max_len, |
| 226 | 243 | struct fscrypt_str *disk_link); |
| @@ -242,13 +259,16 @@ static inline bool fscrypt_dummy_context_enabled(struct inode *inode) · 15 unmodified lines | ||
| 242 | 259 | return false; |
| 243 | 260 | } |
| 244 | 261 | |
| 262 | +static inline void fscrypt_handle_d_move(struct dentry *dentry) | |
| 263 | +{ | |
| 264 | +} | |
| 265 | + | |
| 245 | 266 | /* crypto.c */ |
| 246 | 267 | static inline void fscrypt_enqueue_decrypt_work(struct work_struct *work) |
| 247 | 268 | { |
| 248 | 269 | } |
| 249 | 270 | |
| 250 | −static inline struct fscrypt_ctx *fscrypt_get_ctx(const struct inode *inode, | |
| 251 | − gfp_t gfp_flags) | |
| 271 | +static inline struct fscrypt_ctx *fscrypt_get_ctx(gfp_t gfp_flags) | |
| 252 | 272 | { |
| 253 | 273 | return ERR_PTR(-EOPNOTSUPP); |
| 254 | 274 | } |
| @@ -322,6 +342,10 @@ static inline void fscrypt_put_encryption_info(struct inode *inode) · 67 unmodified lines | ||
| 322 | 342 | return; |
| 323 | 343 | } |
| 324 | 344 | |
| 345 | +static inline void fscrypt_free_inode(struct inode *inode) | |
| 346 | +{ | |
| 347 | +} | |
| 348 | + | |
| 325 | 349 | /* fname.c */ |
| 326 | 350 | static inline int fscrypt_setup_filename(struct inode *dir, |
| 327 | 351 | const struct qstr *iname, |
| @@ -330,7 +354,7 @@ static inline int fscrypt_setup_filename(struct inode *dir, · 2 unmodified lines | ||
| 330 | 354 | if (IS_ENCRYPTED(dir)) |
| 331 | 355 | return -EOPNOTSUPP; |
| 332 | 356 | |
| 333 | − memset(fname, 0, sizeof(struct fscrypt_name)); | |
| 357 | + memset(fname, 0, sizeof(*fname)); | |
| 334 | 358 | fname->usr_fname = iname; |
| 335 | 359 | fname->disk_name.name = (unsigned char *)iname->name; |
| 336 | 360 | fname->disk_name.len = iname->len; |
| @@ -401,8 +425,8 @@ static inline int fscrypt_file_open(struct inode *inode, struct file *filp) · 64 unmodified lines | ||
| 401 | 425 | return 0; |
| 402 | 426 | } |
| 403 | 427 | |
| 404 | −static inline int __fscrypt_prepare_link(struct inode *inode, | |
| 405 | − struct inode *dir) | |
| 428 | +static inline int __fscrypt_prepare_link(struct inode *inode, struct inode *dir, | |
| 429 | + struct dentry *dentry) | |
| 406 | 430 | { |
| 407 | 431 | return -EOPNOTSUPP; |
| 408 | 432 | } |
| @@ -417,7 +441,8 @@ static inline int __fscrypt_prepare_rename(struct inode *old_dir, · 8 unmodified lines | ||
| 417 | 441 | } |
| 418 | 442 | |
| 419 | 443 | static inline int __fscrypt_prepare_lookup(struct inode *dir, |
| 420 | − struct dentry *dentry) | |
| 444 | + struct dentry *dentry, | |
| 445 | + struct fscrypt_name *fname) | |
| 421 | 446 | { |
| 422 | 447 | return -EOPNOTSUPP; |
| 423 | 448 | } |
| @@ -497,7 +522,7 @@ static inline int fscrypt_prepare_link(struct dentry *old_dentry, · 73 unmodified lines | ||
| 497 | 522 | struct dentry *dentry) |
| 498 | 523 | { |
| 499 | 524 | if (IS_ENCRYPTED(dir)) |
| 500 | − return __fscrypt_prepare_link(d_inode(old_dentry), dir); | |
| 525 | + return __fscrypt_prepare_link(d_inode(old_dentry), dir, dentry); | |
| 501 | 526 | return 0; |
| 502 | 527 | } |
| 503 | 528 | |
| @@ -538,27 +563,32 @@ static inline int fscrypt_prepare_rename(struct inode *old_dir, · 34 unmodified lines | ||
| 538 | 563 | * fscrypt_prepare_lookup - prepare to lookup a name in a possibly-encrypted directory |
| 539 | 564 | * @dir: directory being searched |
| 540 | 565 | * @dentry: filename being looked up |
| 541 | − * @flags: lookup flags | |
| 566 | + * @fname: (output) the name to use to search the on-disk directory | |
| 542 | 567 | * |
| 543 | − * Prepare for ->lookup() in a directory which may be encrypted. Lookups can be | |
| 544 | − * done with or without the directory's encryption key; without the key, | |
| 568 | + * Prepare for ->lookup() in a directory which may be encrypted by determining | |
| 569 | + * the name that will actually be used to search the directory on-disk. Lookups | |
| 570 | + * can be done with or without the directory's encryption key; without the key, | |
| 545 | 571 | * filenames are presented in encrypted form. Therefore, we'll try to set up |
| 546 | 572 | * the directory's encryption key, but even without it the lookup can continue. |
| 547 | 573 | * |
| 548 | − * To allow invalidating stale dentries if the directory's encryption key is | |
| 549 | − * added later, we also install a custom ->d_revalidate() method and use the | |
| 550 | − * DCACHE_ENCRYPTED_WITH_KEY flag to indicate whether a given dentry is a | |
| 551 | − * plaintext name (flag set) or a ciphertext name (flag cleared). | |
| 574 | + * This also installs a custom ->d_revalidate() method which will invalidate the | |
| 575 | + * dentry if it was created without the key and the key is later added. | |
| 552 | 576 | * |
| 553 | − * Return: 0 on success, -errno if a problem occurred while setting up the | |
| 554 | − * encryption key | |
| 577 | + * Return: 0 on success; -ENOENT if key is unavailable but the filename isn't a | |
| 578 | + * correctly formed encoded ciphertext name, so a negative dentry should be | |
| 579 | + * created; or another -errno code. | |
| 555 | 580 | */ |
| 556 | 581 | static inline int fscrypt_prepare_lookup(struct inode *dir, |
| 557 | 582 | struct dentry *dentry, |
| 558 | − unsigned int flags) | |
| 583 | + struct fscrypt_name *fname) | |
| 559 | 584 | { |
| 560 | 585 | if (IS_ENCRYPTED(dir)) |
| 561 | − return __fscrypt_prepare_lookup(dir, dentry); | |
| 586 | + return __fscrypt_prepare_lookup(dir, dentry, fname); | |
| 587 | + | |
| 588 | + memset(fname, 0, sizeof(*fname)); | |
| 589 | + fname->usr_fname = &dentry->d_name; | |
| 590 | + fname->disk_name.name = (unsigned char *)dentry->d_name.name; | |
| 591 | + fname->disk_name.len = dentry->d_name.len; | |
| 562 | 592 | return 0; |
| 563 | 593 | } |
| 564 | 594 | |