blob: 847f919c84d9cc382889935baac16b6b8a1064e2 [file] [log] [blame]
Michael Halcrowd5d0e8c2015-04-12 00:56:17 -04001/*
2 * linux/fs/ext4/crypto_fname.c
3 *
4 * Copyright (C) 2015, Google, Inc.
5 *
6 * This contains functions for filename crypto management in ext4
7 *
8 * Written by Uday Savagaonkar, 2014.
9 *
10 * This has not yet undergone a rigorous security audit.
11 *
12 */
13
14#include <crypto/hash.h>
15#include <crypto/sha.h>
16#include <keys/encrypted-type.h>
17#include <keys/user-type.h>
18#include <linux/crypto.h>
19#include <linux/gfp.h>
20#include <linux/kernel.h>
21#include <linux/key.h>
Michael Halcrowd5d0e8c2015-04-12 00:56:17 -040022#include <linux/list.h>
23#include <linux/mempool.h>
24#include <linux/random.h>
25#include <linux/scatterlist.h>
26#include <linux/spinlock_types.h>
27
28#include "ext4.h"
29#include "ext4_crypto.h"
30#include "xattr.h"
31
32/**
33 * ext4_dir_crypt_complete() -
34 */
35static void ext4_dir_crypt_complete(struct crypto_async_request *req, int res)
36{
37 struct ext4_completion_result *ecr = req->data;
38
39 if (res == -EINPROGRESS)
40 return;
41 ecr->res = res;
42 complete(&ecr->completion);
43}
44
45bool ext4_valid_filenames_enc_mode(uint32_t mode)
46{
47 return (mode == EXT4_ENCRYPTION_MODE_AES_256_CTS);
48}
49
Theodore Ts'ob7236e22015-05-18 13:17:47 -040050static unsigned max_name_len(struct inode *inode)
51{
52 return S_ISLNK(inode->i_mode) ? inode->i_sb->s_blocksize :
53 EXT4_NAME_LEN;
54}
55
Michael Halcrowd5d0e8c2015-04-12 00:56:17 -040056/**
57 * ext4_fname_encrypt() -
58 *
59 * This function encrypts the input filename, and returns the length of the
60 * ciphertext. Errors are returned as negative numbers. We trust the caller to
61 * allocate sufficient memory to oname string.
62 */
Theodore Ts'ob7236e22015-05-18 13:17:47 -040063static int ext4_fname_encrypt(struct inode *inode,
Michael Halcrowd5d0e8c2015-04-12 00:56:17 -040064 const struct qstr *iname,
65 struct ext4_str *oname)
66{
67 u32 ciphertext_len;
68 struct ablkcipher_request *req = NULL;
69 DECLARE_EXT4_COMPLETION_RESULT(ecr);
Theodore Ts'ob7236e22015-05-18 13:17:47 -040070 struct ext4_crypt_info *ci = EXT4_I(inode)->i_crypt_info;
71 struct crypto_ablkcipher *tfm = ci->ci_ctfm;
Michael Halcrowd5d0e8c2015-04-12 00:56:17 -040072 int res = 0;
73 char iv[EXT4_CRYPTO_BLOCK_SIZE];
Theodore Ts'od2299592015-05-18 13:15:47 -040074 struct scatterlist src_sg, dst_sg;
Theodore Ts'ob7236e22015-05-18 13:17:47 -040075 int padding = 4 << (ci->ci_flags & EXT4_POLICY_FLAGS_PAD_MASK);
Theodore Ts'od2299592015-05-18 13:15:47 -040076 char *workbuf, buf[32], *alloc_buf = NULL;
Theodore Ts'ob7236e22015-05-18 13:17:47 -040077 unsigned lim = max_name_len(inode);
Michael Halcrowd5d0e8c2015-04-12 00:56:17 -040078
Theodore Ts'ob7236e22015-05-18 13:17:47 -040079 if (iname->len <= 0 || iname->len > lim)
Michael Halcrowd5d0e8c2015-04-12 00:56:17 -040080 return -EIO;
81
82 ciphertext_len = (iname->len < EXT4_CRYPTO_BLOCK_SIZE) ?
83 EXT4_CRYPTO_BLOCK_SIZE : iname->len;
Theodore Ts'oa44cd7a2015-05-01 16:56:50 -040084 ciphertext_len = ext4_fname_crypto_round_up(ciphertext_len, padding);
Theodore Ts'ob7236e22015-05-18 13:17:47 -040085 ciphertext_len = (ciphertext_len > lim)
86 ? lim : ciphertext_len;
Michael Halcrowd5d0e8c2015-04-12 00:56:17 -040087
Theodore Ts'od2299592015-05-18 13:15:47 -040088 if (ciphertext_len <= sizeof(buf)) {
89 workbuf = buf;
90 } else {
91 alloc_buf = kmalloc(ciphertext_len, GFP_NOFS);
92 if (!alloc_buf)
93 return -ENOMEM;
94 workbuf = alloc_buf;
95 }
96
Michael Halcrowd5d0e8c2015-04-12 00:56:17 -040097 /* Allocate request */
98 req = ablkcipher_request_alloc(tfm, GFP_NOFS);
99 if (!req) {
100 printk_ratelimited(
101 KERN_ERR "%s: crypto_request_alloc() failed\n", __func__);
Theodore Ts'od2299592015-05-18 13:15:47 -0400102 kfree(alloc_buf);
Michael Halcrowd5d0e8c2015-04-12 00:56:17 -0400103 return -ENOMEM;
104 }
105 ablkcipher_request_set_callback(req,
106 CRYPTO_TFM_REQ_MAY_BACKLOG | CRYPTO_TFM_REQ_MAY_SLEEP,
107 ext4_dir_crypt_complete, &ecr);
108
Michael Halcrowd5d0e8c2015-04-12 00:56:17 -0400109 /* Copy the input */
110 memcpy(workbuf, iname->name, iname->len);
111 if (iname->len < ciphertext_len)
112 memset(workbuf + iname->len, 0, ciphertext_len - iname->len);
113
114 /* Initialize IV */
115 memset(iv, 0, EXT4_CRYPTO_BLOCK_SIZE);
116
117 /* Create encryption request */
Theodore Ts'od2299592015-05-18 13:15:47 -0400118 sg_init_one(&src_sg, workbuf, ciphertext_len);
119 sg_init_one(&dst_sg, oname->name, ciphertext_len);
120 ablkcipher_request_set_crypt(req, &src_sg, &dst_sg, ciphertext_len, iv);
Michael Halcrowd5d0e8c2015-04-12 00:56:17 -0400121 res = crypto_ablkcipher_encrypt(req);
122 if (res == -EINPROGRESS || res == -EBUSY) {
123 BUG_ON(req->base.data != &ecr);
124 wait_for_completion(&ecr.completion);
125 res = ecr.res;
126 }
Theodore Ts'od2299592015-05-18 13:15:47 -0400127 kfree(alloc_buf);
Michael Halcrowd5d0e8c2015-04-12 00:56:17 -0400128 ablkcipher_request_free(req);
129 if (res < 0) {
130 printk_ratelimited(
131 KERN_ERR "%s: Error (error code %d)\n", __func__, res);
132 }
133 oname->len = ciphertext_len;
134 return res;
135}
136
137/*
138 * ext4_fname_decrypt()
139 * This function decrypts the input filename, and returns
140 * the length of the plaintext.
141 * Errors are returned as negative numbers.
142 * We trust the caller to allocate sufficient memory to oname string.
143 */
Theodore Ts'ob7236e22015-05-18 13:17:47 -0400144static int ext4_fname_decrypt(struct inode *inode,
Michael Halcrowd5d0e8c2015-04-12 00:56:17 -0400145 const struct ext4_str *iname,
146 struct ext4_str *oname)
147{
148 struct ext4_str tmp_in[2], tmp_out[1];
149 struct ablkcipher_request *req = NULL;
150 DECLARE_EXT4_COMPLETION_RESULT(ecr);
Theodore Ts'od2299592015-05-18 13:15:47 -0400151 struct scatterlist src_sg, dst_sg;
Theodore Ts'ob7236e22015-05-18 13:17:47 -0400152 struct ext4_crypt_info *ci = EXT4_I(inode)->i_crypt_info;
153 struct crypto_ablkcipher *tfm = ci->ci_ctfm;
Michael Halcrowd5d0e8c2015-04-12 00:56:17 -0400154 int res = 0;
155 char iv[EXT4_CRYPTO_BLOCK_SIZE];
Theodore Ts'ob7236e22015-05-18 13:17:47 -0400156 unsigned lim = max_name_len(inode);
Michael Halcrowd5d0e8c2015-04-12 00:56:17 -0400157
Theodore Ts'ob7236e22015-05-18 13:17:47 -0400158 if (iname->len <= 0 || iname->len > lim)
Michael Halcrowd5d0e8c2015-04-12 00:56:17 -0400159 return -EIO;
160
161 tmp_in[0].name = iname->name;
162 tmp_in[0].len = iname->len;
163 tmp_out[0].name = oname->name;
164
165 /* Allocate request */
166 req = ablkcipher_request_alloc(tfm, GFP_NOFS);
167 if (!req) {
168 printk_ratelimited(
169 KERN_ERR "%s: crypto_request_alloc() failed\n", __func__);
170 return -ENOMEM;
171 }
172 ablkcipher_request_set_callback(req,
173 CRYPTO_TFM_REQ_MAY_BACKLOG | CRYPTO_TFM_REQ_MAY_SLEEP,
174 ext4_dir_crypt_complete, &ecr);
175
Michael Halcrowd5d0e8c2015-04-12 00:56:17 -0400176 /* Initialize IV */
177 memset(iv, 0, EXT4_CRYPTO_BLOCK_SIZE);
178
179 /* Create encryption request */
Theodore Ts'od2299592015-05-18 13:15:47 -0400180 sg_init_one(&src_sg, iname->name, iname->len);
181 sg_init_one(&dst_sg, oname->name, oname->len);
182 ablkcipher_request_set_crypt(req, &src_sg, &dst_sg, iname->len, iv);
Michael Halcrowd5d0e8c2015-04-12 00:56:17 -0400183 res = crypto_ablkcipher_decrypt(req);
184 if (res == -EINPROGRESS || res == -EBUSY) {
185 BUG_ON(req->base.data != &ecr);
186 wait_for_completion(&ecr.completion);
187 res = ecr.res;
188 }
Michael Halcrowd5d0e8c2015-04-12 00:56:17 -0400189 ablkcipher_request_free(req);
190 if (res < 0) {
191 printk_ratelimited(
192 KERN_ERR "%s: Error in ext4_fname_encrypt (error code %d)\n",
193 __func__, res);
194 return res;
195 }
196
197 oname->len = strnlen(oname->name, iname->len);
198 return oname->len;
199}
200
Theodore Ts'o5de0b4d2015-05-01 16:56:45 -0400201static const char *lookup_table =
202 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+,";
203
Michael Halcrowd5d0e8c2015-04-12 00:56:17 -0400204/**
205 * ext4_fname_encode_digest() -
206 *
207 * Encodes the input digest using characters from the set [a-zA-Z0-9_+].
208 * The encoded string is roughly 4/3 times the size of the input string.
209 */
Theodore Ts'o5de0b4d2015-05-01 16:56:45 -0400210static int digest_encode(const char *src, int len, char *dst)
Michael Halcrowd5d0e8c2015-04-12 00:56:17 -0400211{
Theodore Ts'o5de0b4d2015-05-01 16:56:45 -0400212 int i = 0, bits = 0, ac = 0;
213 char *cp = dst;
Michael Halcrowd5d0e8c2015-04-12 00:56:17 -0400214
Theodore Ts'o5de0b4d2015-05-01 16:56:45 -0400215 while (i < len) {
216 ac += (((unsigned char) src[i]) << bits);
217 bits += 8;
218 do {
219 *cp++ = lookup_table[ac & 0x3f];
220 ac >>= 6;
221 bits -= 6;
222 } while (bits >= 6);
Michael Halcrowd5d0e8c2015-04-12 00:56:17 -0400223 i++;
224 }
Theodore Ts'o5de0b4d2015-05-01 16:56:45 -0400225 if (bits)
226 *cp++ = lookup_table[ac & 0x3f];
227 return cp - dst;
Michael Halcrowd5d0e8c2015-04-12 00:56:17 -0400228}
229
Theodore Ts'o5de0b4d2015-05-01 16:56:45 -0400230static int digest_decode(const char *src, int len, char *dst)
Michael Halcrowd5d0e8c2015-04-12 00:56:17 -0400231{
Theodore Ts'o5de0b4d2015-05-01 16:56:45 -0400232 int i = 0, bits = 0, ac = 0;
233 const char *p;
234 char *cp = dst;
Michael Halcrowd5d0e8c2015-04-12 00:56:17 -0400235
Theodore Ts'o5de0b4d2015-05-01 16:56:45 -0400236 while (i < len) {
237 p = strchr(lookup_table, src[i]);
238 if (p == NULL || src[i] == 0)
239 return -2;
240 ac += (p - lookup_table) << bits;
241 bits += 6;
242 if (bits >= 8) {
243 *cp++ = ac & 0xff;
244 ac >>= 8;
245 bits -= 8;
246 }
247 i++;
Michael Halcrowd5d0e8c2015-04-12 00:56:17 -0400248 }
Theodore Ts'o5de0b4d2015-05-01 16:56:45 -0400249 if (ac)
250 return -1;
251 return cp - dst;
Michael Halcrowd5d0e8c2015-04-12 00:56:17 -0400252}
253
Michael Halcrowd5d0e8c2015-04-12 00:56:17 -0400254/**
255 * ext4_fname_crypto_round_up() -
256 *
257 * Return: The next multiple of block size
258 */
259u32 ext4_fname_crypto_round_up(u32 size, u32 blksize)
260{
261 return ((size+blksize-1)/blksize)*blksize;
262}
263
Theodore Ts'o4d3c4e52015-05-31 13:35:32 -0400264unsigned ext4_fname_encrypted_size(struct inode *inode, u32 ilen)
265{
266 struct ext4_crypt_info *ci = EXT4_I(inode)->i_crypt_info;
267 int padding = 32;
268
269 if (ci)
270 padding = 4 << (ci->ci_flags & EXT4_POLICY_FLAGS_PAD_MASK);
271 if (ilen < EXT4_CRYPTO_BLOCK_SIZE)
272 ilen = EXT4_CRYPTO_BLOCK_SIZE;
273 return ext4_fname_crypto_round_up(ilen, padding);
274}
275
276/*
277 * ext4_fname_crypto_alloc_buffer() -
Michael Halcrowd5d0e8c2015-04-12 00:56:17 -0400278 *
279 * Allocates an output buffer that is sufficient for the crypto operation
280 * specified by the context and the direction.
281 */
Theodore Ts'ob7236e22015-05-18 13:17:47 -0400282int ext4_fname_crypto_alloc_buffer(struct inode *inode,
Michael Halcrowd5d0e8c2015-04-12 00:56:17 -0400283 u32 ilen, struct ext4_str *crypto_str)
284{
Theodore Ts'o4d3c4e52015-05-31 13:35:32 -0400285 unsigned int olen = ext4_fname_encrypted_size(inode, ilen);
Michael Halcrowd5d0e8c2015-04-12 00:56:17 -0400286
Michael Halcrowd5d0e8c2015-04-12 00:56:17 -0400287 crypto_str->len = olen;
288 if (olen < EXT4_FNAME_CRYPTO_DIGEST_SIZE*2)
289 olen = EXT4_FNAME_CRYPTO_DIGEST_SIZE*2;
290 /* Allocated buffer can hold one more character to null-terminate the
291 * string */
292 crypto_str->name = kmalloc(olen+1, GFP_NOFS);
293 if (!(crypto_str->name))
294 return -ENOMEM;
295 return 0;
296}
297
298/**
299 * ext4_fname_crypto_free_buffer() -
300 *
301 * Frees the buffer allocated for crypto operation.
302 */
303void ext4_fname_crypto_free_buffer(struct ext4_str *crypto_str)
304{
305 if (!crypto_str)
306 return;
307 kfree(crypto_str->name);
308 crypto_str->name = NULL;
309}
310
311/**
312 * ext4_fname_disk_to_usr() - converts a filename from disk space to user space
313 */
Theodore Ts'ob7236e22015-05-18 13:17:47 -0400314int _ext4_fname_disk_to_usr(struct inode *inode,
Theodore Ts'o5de0b4d2015-05-01 16:56:45 -0400315 struct dx_hash_info *hinfo,
316 const struct ext4_str *iname,
317 struct ext4_str *oname)
Michael Halcrowd5d0e8c2015-04-12 00:56:17 -0400318{
Theodore Ts'o5de0b4d2015-05-01 16:56:45 -0400319 char buf[24];
320 int ret;
321
Michael Halcrowd5d0e8c2015-04-12 00:56:17 -0400322 if (iname->len < 3) {
323 /*Check for . and .. */
324 if (iname->name[0] == '.' && iname->name[iname->len-1] == '.') {
325 oname->name[0] = '.';
326 oname->name[iname->len-1] = '.';
327 oname->len = iname->len;
328 return oname->len;
329 }
330 }
Theodore Ts'o27977b62015-07-17 11:33:16 -0400331 if (iname->len < EXT4_CRYPTO_BLOCK_SIZE) {
332 EXT4_ERROR_INODE(inode, "encrypted inode too small");
333 return -EUCLEAN;
334 }
Theodore Ts'ob7236e22015-05-18 13:17:47 -0400335 if (EXT4_I(inode)->i_crypt_info)
336 return ext4_fname_decrypt(inode, iname, oname);
Theodore Ts'o5de0b4d2015-05-01 16:56:45 -0400337
338 if (iname->len <= EXT4_FNAME_CRYPTO_DIGEST_SIZE) {
339 ret = digest_encode(iname->name, iname->len, oname->name);
340 oname->len = ret;
341 return ret;
342 }
343 if (hinfo) {
344 memcpy(buf, &hinfo->hash, 4);
345 memcpy(buf+4, &hinfo->minor_hash, 4);
346 } else
347 memset(buf, 0, 8);
348 memcpy(buf + 8, iname->name + iname->len - 16, 16);
349 oname->name[0] = '_';
350 ret = digest_encode(buf, 24, oname->name+1);
351 oname->len = ret + 1;
352 return ret + 1;
Michael Halcrowd5d0e8c2015-04-12 00:56:17 -0400353}
354
Theodore Ts'ob7236e22015-05-18 13:17:47 -0400355int ext4_fname_disk_to_usr(struct inode *inode,
Theodore Ts'o5de0b4d2015-05-01 16:56:45 -0400356 struct dx_hash_info *hinfo,
Michael Halcrowd5d0e8c2015-04-12 00:56:17 -0400357 const struct ext4_dir_entry_2 *de,
358 struct ext4_str *oname)
359{
360 struct ext4_str iname = {.name = (unsigned char *) de->name,
361 .len = de->name_len };
362
Theodore Ts'ob7236e22015-05-18 13:17:47 -0400363 return _ext4_fname_disk_to_usr(inode, hinfo, &iname, oname);
Michael Halcrowd5d0e8c2015-04-12 00:56:17 -0400364}
365
366
367/**
368 * ext4_fname_usr_to_disk() - converts a filename from user space to disk space
369 */
Theodore Ts'ob7236e22015-05-18 13:17:47 -0400370int ext4_fname_usr_to_disk(struct inode *inode,
Michael Halcrowd5d0e8c2015-04-12 00:56:17 -0400371 const struct qstr *iname,
372 struct ext4_str *oname)
373{
374 int res;
Theodore Ts'ob7236e22015-05-18 13:17:47 -0400375 struct ext4_crypt_info *ci = EXT4_I(inode)->i_crypt_info;
Michael Halcrowd5d0e8c2015-04-12 00:56:17 -0400376
Michael Halcrowd5d0e8c2015-04-12 00:56:17 -0400377 if (iname->len < 3) {
378 /*Check for . and .. */
379 if (iname->name[0] == '.' &&
380 iname->name[iname->len-1] == '.') {
381 oname->name[0] = '.';
382 oname->name[iname->len-1] = '.';
383 oname->len = iname->len;
384 return oname->len;
385 }
386 }
Theodore Ts'ob7236e22015-05-18 13:17:47 -0400387 if (ci) {
388 res = ext4_fname_encrypt(inode, iname, oname);
Michael Halcrowd5d0e8c2015-04-12 00:56:17 -0400389 return res;
390 }
391 /* Without a proper key, a user is not allowed to modify the filenames
392 * in a directory. Consequently, a user space name cannot be mapped to
393 * a disk-space name */
394 return -EACCES;
395}
396
Theodore Ts'o5b643f92015-05-18 13:14:47 -0400397int ext4_fname_setup_filename(struct inode *dir, const struct qstr *iname,
398 int lookup, struct ext4_filename *fname)
Michael Halcrowd5d0e8c2015-04-12 00:56:17 -0400399{
Theodore Ts'ob7236e22015-05-18 13:17:47 -0400400 struct ext4_crypt_info *ci;
Theodore Ts'o5b643f92015-05-18 13:14:47 -0400401 int ret = 0, bigname = 0;
Michael Halcrowd5d0e8c2015-04-12 00:56:17 -0400402
Theodore Ts'o5b643f92015-05-18 13:14:47 -0400403 memset(fname, 0, sizeof(struct ext4_filename));
404 fname->usr_fname = iname;
405
Theodore Ts'ob7236e22015-05-18 13:17:47 -0400406 if (!ext4_encrypted_inode(dir) ||
Michael Halcrowd5d0e8c2015-04-12 00:56:17 -0400407 ((iname->name[0] == '.') &&
408 ((iname->len == 1) ||
409 ((iname->name[1] == '.') && (iname->len == 2))))) {
Theodore Ts'o5b643f92015-05-18 13:14:47 -0400410 fname->disk_name.name = (unsigned char *) iname->name;
411 fname->disk_name.len = iname->len;
Theodore Ts'o82d0d3e2015-05-31 13:35:22 -0400412 return 0;
Michael Halcrowd5d0e8c2015-04-12 00:56:17 -0400413 }
Theodore Ts'oc936e1e2015-05-31 13:34:22 -0400414 ret = ext4_get_encryption_info(dir);
Theodore Ts'ob7236e22015-05-18 13:17:47 -0400415 if (ret)
416 return ret;
417 ci = EXT4_I(dir)->i_crypt_info;
418 if (ci) {
419 ret = ext4_fname_crypto_alloc_buffer(dir, iname->len,
Theodore Ts'o5b643f92015-05-18 13:14:47 -0400420 &fname->crypto_buf);
421 if (ret < 0)
Theodore Ts'o82d0d3e2015-05-31 13:35:22 -0400422 return ret;
Theodore Ts'ob7236e22015-05-18 13:17:47 -0400423 ret = ext4_fname_encrypt(dir, iname, &fname->crypto_buf);
Theodore Ts'o5b643f92015-05-18 13:14:47 -0400424 if (ret < 0)
Theodore Ts'o82d0d3e2015-05-31 13:35:22 -0400425 goto errout;
Theodore Ts'o5b643f92015-05-18 13:14:47 -0400426 fname->disk_name.name = fname->crypto_buf.name;
427 fname->disk_name.len = fname->crypto_buf.len;
Theodore Ts'o82d0d3e2015-05-31 13:35:22 -0400428 return 0;
Theodore Ts'o5b643f92015-05-18 13:14:47 -0400429 }
Theodore Ts'o82d0d3e2015-05-31 13:35:22 -0400430 if (!lookup)
431 return -EACCES;
Michael Halcrowd5d0e8c2015-04-12 00:56:17 -0400432
Theodore Ts'o5b643f92015-05-18 13:14:47 -0400433 /* We don't have the key and we are doing a lookup; decode the
434 * user-supplied name
435 */
436 if (iname->name[0] == '_')
437 bigname = 1;
438 if ((bigname && (iname->len != 33)) ||
Theodore Ts'o82d0d3e2015-05-31 13:35:22 -0400439 (!bigname && (iname->len > 43)))
440 return -ENOENT;
441
Theodore Ts'o5b643f92015-05-18 13:14:47 -0400442 fname->crypto_buf.name = kmalloc(32, GFP_KERNEL);
Theodore Ts'o82d0d3e2015-05-31 13:35:22 -0400443 if (fname->crypto_buf.name == NULL)
444 return -ENOMEM;
Theodore Ts'o5b643f92015-05-18 13:14:47 -0400445 ret = digest_decode(iname->name + bigname, iname->len - bigname,
446 fname->crypto_buf.name);
447 if (ret < 0) {
448 ret = -ENOENT;
Theodore Ts'o82d0d3e2015-05-31 13:35:22 -0400449 goto errout;
Theodore Ts'o5b643f92015-05-18 13:14:47 -0400450 }
451 fname->crypto_buf.len = ret;
452 if (bigname) {
453 memcpy(&fname->hinfo.hash, fname->crypto_buf.name, 4);
454 memcpy(&fname->hinfo.minor_hash, fname->crypto_buf.name + 4, 4);
455 } else {
456 fname->disk_name.name = fname->crypto_buf.name;
457 fname->disk_name.len = fname->crypto_buf.len;
458 }
Theodore Ts'o82d0d3e2015-05-31 13:35:22 -0400459 return 0;
460errout:
461 kfree(fname->crypto_buf.name);
462 fname->crypto_buf.name = NULL;
Michael Halcrowd5d0e8c2015-04-12 00:56:17 -0400463 return ret;
464}
465
Theodore Ts'o5b643f92015-05-18 13:14:47 -0400466void ext4_fname_free_filename(struct ext4_filename *fname)
Michael Halcrowd5d0e8c2015-04-12 00:56:17 -0400467{
Theodore Ts'o5b643f92015-05-18 13:14:47 -0400468 kfree(fname->crypto_buf.name);
469 fname->crypto_buf.name = NULL;
470 fname->usr_fname = NULL;
471 fname->disk_name.name = NULL;
Michael Halcrowd5d0e8c2015-04-12 00:56:17 -0400472}