xref: /openbmc/linux/fs/ext4/crypto.c (revision 3030b59c)
1 // SPDX-License-Identifier: GPL-2.0
2 
3 #include <linux/quotaops.h>
4 
5 #include "ext4.h"
6 #include "xattr.h"
7 #include "ext4_jbd2.h"
8 
9 static void ext4_fname_from_fscrypt_name(struct ext4_filename *dst,
10 					 const struct fscrypt_name *src)
11 {
12 	memset(dst, 0, sizeof(*dst));
13 
14 	dst->usr_fname = src->usr_fname;
15 	dst->disk_name = src->disk_name;
16 	dst->hinfo.hash = src->hash;
17 	dst->hinfo.minor_hash = src->minor_hash;
18 	dst->crypto_buf = src->crypto_buf;
19 }
20 
21 int ext4_fname_setup_filename(struct inode *dir, const struct qstr *iname,
22 			      int lookup, struct ext4_filename *fname)
23 {
24 	struct fscrypt_name name;
25 	int err;
26 
27 	err = fscrypt_setup_filename(dir, iname, lookup, &name);
28 	if (err)
29 		return err;
30 
31 	ext4_fname_from_fscrypt_name(fname, &name);
32 
33 #if IS_ENABLED(CONFIG_UNICODE)
34 	err = ext4_fname_setup_ci_filename(dir, iname, fname);
35 #endif
36 	return err;
37 }
38 
39 int ext4_fname_prepare_lookup(struct inode *dir, struct dentry *dentry,
40 			      struct ext4_filename *fname)
41 {
42 	struct fscrypt_name name;
43 	int err;
44 
45 	err = fscrypt_prepare_lookup(dir, dentry, &name);
46 	if (err)
47 		return err;
48 
49 	ext4_fname_from_fscrypt_name(fname, &name);
50 
51 #if IS_ENABLED(CONFIG_UNICODE)
52 	err = ext4_fname_setup_ci_filename(dir, &dentry->d_name, fname);
53 #endif
54 	return err;
55 }
56 
57 void ext4_fname_free_filename(struct ext4_filename *fname)
58 {
59 	struct fscrypt_name name;
60 
61 	name.crypto_buf = fname->crypto_buf;
62 	fscrypt_free_filename(&name);
63 
64 	fname->crypto_buf.name = NULL;
65 	fname->usr_fname = NULL;
66 	fname->disk_name.name = NULL;
67 
68 #if IS_ENABLED(CONFIG_UNICODE)
69 	kfree(fname->cf_name.name);
70 	fname->cf_name.name = NULL;
71 #endif
72 }
73 
74 static int ext4_get_context(struct inode *inode, void *ctx, size_t len)
75 {
76 	return ext4_xattr_get(inode, EXT4_XATTR_INDEX_ENCRYPTION,
77 				 EXT4_XATTR_NAME_ENCRYPTION_CONTEXT, ctx, len);
78 }
79 
80 static int ext4_set_context(struct inode *inode, const void *ctx, size_t len,
81 							void *fs_data)
82 {
83 	handle_t *handle = fs_data;
84 	int res, res2, credits, retries = 0;
85 
86 	/*
87 	 * Encrypting the root directory is not allowed because e2fsck expects
88 	 * lost+found to exist and be unencrypted, and encrypting the root
89 	 * directory would imply encrypting the lost+found directory as well as
90 	 * the filename "lost+found" itself.
91 	 */
92 	if (inode->i_ino == EXT4_ROOT_INO)
93 		return -EPERM;
94 
95 	if (WARN_ON_ONCE(IS_DAX(inode) && i_size_read(inode)))
96 		return -EINVAL;
97 
98 	if (ext4_test_inode_flag(inode, EXT4_INODE_DAX))
99 		return -EOPNOTSUPP;
100 
101 	res = ext4_convert_inline_data(inode);
102 	if (res)
103 		return res;
104 
105 	/*
106 	 * If a journal handle was specified, then the encryption context is
107 	 * being set on a new inode via inheritance and is part of a larger
108 	 * transaction to create the inode.  Otherwise the encryption context is
109 	 * being set on an existing inode in its own transaction.  Only in the
110 	 * latter case should the "retry on ENOSPC" logic be used.
111 	 */
112 
113 	if (handle) {
114 		res = ext4_xattr_set_handle(handle, inode,
115 					    EXT4_XATTR_INDEX_ENCRYPTION,
116 					    EXT4_XATTR_NAME_ENCRYPTION_CONTEXT,
117 					    ctx, len, 0);
118 		if (!res) {
119 			ext4_set_inode_flag(inode, EXT4_INODE_ENCRYPT);
120 			ext4_clear_inode_state(inode,
121 					EXT4_STATE_MAY_INLINE_DATA);
122 			/*
123 			 * Update inode->i_flags - S_ENCRYPTED will be enabled,
124 			 * S_DAX may be disabled
125 			 */
126 			ext4_set_inode_flags(inode, false);
127 		}
128 		return res;
129 	}
130 
131 	res = dquot_initialize(inode);
132 	if (res)
133 		return res;
134 retry:
135 	res = ext4_xattr_set_credits(inode, len, false /* is_create */,
136 				     &credits);
137 	if (res)
138 		return res;
139 
140 	handle = ext4_journal_start(inode, EXT4_HT_MISC, credits);
141 	if (IS_ERR(handle))
142 		return PTR_ERR(handle);
143 
144 	res = ext4_xattr_set_handle(handle, inode, EXT4_XATTR_INDEX_ENCRYPTION,
145 				    EXT4_XATTR_NAME_ENCRYPTION_CONTEXT,
146 				    ctx, len, 0);
147 	if (!res) {
148 		ext4_set_inode_flag(inode, EXT4_INODE_ENCRYPT);
149 		/*
150 		 * Update inode->i_flags - S_ENCRYPTED will be enabled,
151 		 * S_DAX may be disabled
152 		 */
153 		ext4_set_inode_flags(inode, false);
154 		res = ext4_mark_inode_dirty(handle, inode);
155 		if (res)
156 			EXT4_ERROR_INODE(inode, "Failed to mark inode dirty");
157 	}
158 	res2 = ext4_journal_stop(handle);
159 
160 	if (res == -ENOSPC && ext4_should_retry_alloc(inode->i_sb, &retries))
161 		goto retry;
162 	if (!res)
163 		res = res2;
164 	return res;
165 }
166 
167 static const union fscrypt_policy *ext4_get_dummy_policy(struct super_block *sb)
168 {
169 	return EXT4_SB(sb)->s_dummy_enc_policy.policy;
170 }
171 
172 static bool ext4_has_stable_inodes(struct super_block *sb)
173 {
174 	return ext4_has_feature_stable_inodes(sb);
175 }
176 
177 static void ext4_get_ino_and_lblk_bits(struct super_block *sb,
178 				       int *ino_bits_ret, int *lblk_bits_ret)
179 {
180 	*ino_bits_ret = 8 * sizeof(EXT4_SB(sb)->s_es->s_inodes_count);
181 	*lblk_bits_ret = 8 * sizeof(ext4_lblk_t);
182 }
183 
184 const struct fscrypt_operations ext4_cryptops = {
185 	.key_prefix		= "ext4:",
186 	.get_context		= ext4_get_context,
187 	.set_context		= ext4_set_context,
188 	.get_dummy_policy	= ext4_get_dummy_policy,
189 	.empty_dir		= ext4_empty_dir,
190 	.has_stable_inodes	= ext4_has_stable_inodes,
191 	.get_ino_and_lblk_bits	= ext4_get_ino_and_lblk_bits,
192 };
193