]>
Commit | Line | Data |
---|---|---|
efcc7ae2 EB |
1 | /* |
2 | * fs/crypto/hooks.c | |
3 | * | |
4 | * Encryption hooks for higher-level filesystem operations. | |
5 | */ | |
6 | ||
7 | #include <linux/ratelimit.h> | |
8 | #include "fscrypt_private.h" | |
9 | ||
10 | /** | |
11 | * fscrypt_file_open - prepare to open a possibly-encrypted regular file | |
12 | * @inode: the inode being opened | |
13 | * @filp: the struct file being set up | |
14 | * | |
15 | * Currently, an encrypted regular file can only be opened if its encryption key | |
16 | * is available; access to the raw encrypted contents is not supported. | |
17 | * Therefore, we first set up the inode's encryption key (if not already done) | |
18 | * and return an error if it's unavailable. | |
19 | * | |
20 | * We also verify that if the parent directory (from the path via which the file | |
21 | * is being opened) is encrypted, then the inode being opened uses the same | |
22 | * encryption policy. This is needed as part of the enforcement that all files | |
23 | * in an encrypted directory tree use the same encryption policy, as a | |
24 | * protection against certain types of offline attacks. Note that this check is | |
25 | * needed even when opening an *unencrypted* file, since it's forbidden to have | |
26 | * an unencrypted file in an encrypted directory. | |
27 | * | |
28 | * Return: 0 on success, -ENOKEY if the key is missing, or another -errno code | |
29 | */ | |
30 | int fscrypt_file_open(struct inode *inode, struct file *filp) | |
31 | { | |
32 | int err; | |
33 | struct dentry *dir; | |
34 | ||
35 | err = fscrypt_require_key(inode); | |
36 | if (err) | |
37 | return err; | |
38 | ||
39 | dir = dget_parent(file_dentry(filp)); | |
40 | if (IS_ENCRYPTED(d_inode(dir)) && | |
41 | !fscrypt_has_permitted_context(d_inode(dir), inode)) { | |
42 | pr_warn_ratelimited("fscrypt: inconsistent encryption contexts: %lu/%lu", | |
43 | d_inode(dir)->i_ino, inode->i_ino); | |
44 | err = -EPERM; | |
45 | } | |
46 | dput(dir); | |
47 | return err; | |
48 | } | |
49 | EXPORT_SYMBOL_GPL(fscrypt_file_open); | |
0ea87a96 EB |
50 | |
51 | int __fscrypt_prepare_link(struct inode *inode, struct inode *dir) | |
52 | { | |
53 | int err; | |
54 | ||
55 | err = fscrypt_require_key(dir); | |
56 | if (err) | |
57 | return err; | |
58 | ||
59 | if (!fscrypt_has_permitted_context(dir, inode)) | |
60 | return -EPERM; | |
61 | ||
62 | return 0; | |
63 | } | |
64 | EXPORT_SYMBOL_GPL(__fscrypt_prepare_link); | |
94b26f36 EB |
65 | |
66 | int __fscrypt_prepare_rename(struct inode *old_dir, struct dentry *old_dentry, | |
67 | struct inode *new_dir, struct dentry *new_dentry, | |
68 | unsigned int flags) | |
69 | { | |
70 | int err; | |
71 | ||
72 | err = fscrypt_require_key(old_dir); | |
73 | if (err) | |
74 | return err; | |
75 | ||
76 | err = fscrypt_require_key(new_dir); | |
77 | if (err) | |
78 | return err; | |
79 | ||
80 | if (old_dir != new_dir) { | |
81 | if (IS_ENCRYPTED(new_dir) && | |
82 | !fscrypt_has_permitted_context(new_dir, | |
83 | d_inode(old_dentry))) | |
84 | return -EPERM; | |
85 | ||
86 | if ((flags & RENAME_EXCHANGE) && | |
87 | IS_ENCRYPTED(old_dir) && | |
88 | !fscrypt_has_permitted_context(old_dir, | |
89 | d_inode(new_dentry))) | |
90 | return -EPERM; | |
91 | } | |
92 | return 0; | |
93 | } | |
94 | EXPORT_SYMBOL_GPL(__fscrypt_prepare_rename); | |
32c3cf02 EB |
95 | |
96 | int __fscrypt_prepare_lookup(struct inode *dir, struct dentry *dentry) | |
97 | { | |
98 | int err = fscrypt_get_encryption_info(dir); | |
99 | ||
100 | if (err) | |
101 | return err; | |
102 | ||
103 | if (fscrypt_has_encryption_key(dir)) { | |
104 | spin_lock(&dentry->d_lock); | |
105 | dentry->d_flags |= DCACHE_ENCRYPTED_WITH_KEY; | |
106 | spin_unlock(&dentry->d_lock); | |
107 | } | |
108 | ||
109 | d_set_d_op(dentry, &fscrypt_d_ops); | |
110 | return 0; | |
111 | } | |
112 | EXPORT_SYMBOL_GPL(__fscrypt_prepare_lookup); |