diff options
author | Theodore Ts'o <tytso@mit.edu> | 2015-05-01 16:56:45 -0400 |
---|---|---|
committer | Theodore Ts'o <tytso@mit.edu> | 2015-05-01 16:56:45 -0400 |
commit | 5de0b4d0cd153c471640b13aae6ae6d18d0a4603 (patch) | |
tree | ea42bad982e25f1c880e363b55e8d1ff82e773fe /fs | |
parent | 6ddb2447846a8ece111e316a2863c2355023682d (diff) |
ext4 crypto: simplify and speed up filename encryption
Avoid using SHA-1 when calculating the user-visible filename when the
encryption key is available, and avoid decrypting lots of filenames
when searching for a directory entry in a directory block.
Change-Id: If4655f144784978ba0305b597bfa1c8d7bb69e63
Signed-off-by: Theodore Ts'o <tytso@mit.edu>
Diffstat (limited to 'fs')
-rw-r--r-- | fs/ext4/crypto_fname.c | 268 | ||||
-rw-r--r-- | fs/ext4/dir.c | 2 | ||||
-rw-r--r-- | fs/ext4/ext4.h | 9 | ||||
-rw-r--r-- | fs/ext4/namei.c | 72 | ||||
-rw-r--r-- | fs/ext4/symlink.c | 2 |
5 files changed, 149 insertions, 204 deletions
diff --git a/fs/ext4/crypto_fname.c b/fs/ext4/crypto_fname.c index ca2f5948c1ac..7a877e609e5f 100644 --- a/fs/ext4/crypto_fname.c +++ b/fs/ext4/crypto_fname.c | |||
@@ -198,106 +198,57 @@ static int ext4_fname_decrypt(struct ext4_fname_crypto_ctx *ctx, | |||
198 | return oname->len; | 198 | return oname->len; |
199 | } | 199 | } |
200 | 200 | ||
201 | static const char *lookup_table = | ||
202 | "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+,"; | ||
203 | |||
201 | /** | 204 | /** |
202 | * ext4_fname_encode_digest() - | 205 | * ext4_fname_encode_digest() - |
203 | * | 206 | * |
204 | * Encodes the input digest using characters from the set [a-zA-Z0-9_+]. | 207 | * Encodes the input digest using characters from the set [a-zA-Z0-9_+]. |
205 | * The encoded string is roughly 4/3 times the size of the input string. | 208 | * The encoded string is roughly 4/3 times the size of the input string. |
206 | */ | 209 | */ |
207 | int ext4_fname_encode_digest(char *dst, char *src, u32 len) | 210 | static int digest_encode(const char *src, int len, char *dst) |
208 | { | 211 | { |
209 | static const char *lookup_table = | 212 | int i = 0, bits = 0, ac = 0; |
210 | "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_+"; | 213 | char *cp = dst; |
211 | u32 current_chunk, num_chunks, i; | 214 | |
212 | char tmp_buf[3]; | 215 | while (i < len) { |
213 | u32 c0, c1, c2, c3; | 216 | ac += (((unsigned char) src[i]) << bits); |
214 | 217 | bits += 8; | |
215 | current_chunk = 0; | 218 | do { |
216 | num_chunks = len/3; | 219 | *cp++ = lookup_table[ac & 0x3f]; |
217 | for (i = 0; i < num_chunks; i++) { | 220 | ac >>= 6; |
218 | c0 = src[3*i] & 0x3f; | 221 | bits -= 6; |
219 | c1 = (((src[3*i]>>6)&0x3) | ((src[3*i+1] & 0xf)<<2)) & 0x3f; | 222 | } while (bits >= 6); |
220 | c2 = (((src[3*i+1]>>4)&0xf) | ((src[3*i+2] & 0x3)<<4)) & 0x3f; | ||
221 | c3 = (src[3*i+2]>>2) & 0x3f; | ||
222 | dst[4*i] = lookup_table[c0]; | ||
223 | dst[4*i+1] = lookup_table[c1]; | ||
224 | dst[4*i+2] = lookup_table[c2]; | ||
225 | dst[4*i+3] = lookup_table[c3]; | ||
226 | } | ||
227 | if (i*3 < len) { | ||
228 | memset(tmp_buf, 0, 3); | ||
229 | memcpy(tmp_buf, &src[3*i], len-3*i); | ||
230 | c0 = tmp_buf[0] & 0x3f; | ||
231 | c1 = (((tmp_buf[0]>>6)&0x3) | ((tmp_buf[1] & 0xf)<<2)) & 0x3f; | ||
232 | c2 = (((tmp_buf[1]>>4)&0xf) | ((tmp_buf[2] & 0x3)<<4)) & 0x3f; | ||
233 | c3 = (tmp_buf[2]>>2) & 0x3f; | ||
234 | dst[4*i] = lookup_table[c0]; | ||
235 | dst[4*i+1] = lookup_table[c1]; | ||
236 | dst[4*i+2] = lookup_table[c2]; | ||
237 | dst[4*i+3] = lookup_table[c3]; | ||
238 | i++; | 223 | i++; |
239 | } | 224 | } |
240 | return (i * 4); | 225 | if (bits) |
226 | *cp++ = lookup_table[ac & 0x3f]; | ||
227 | return cp - dst; | ||
241 | } | 228 | } |
242 | 229 | ||
243 | /** | 230 | static int digest_decode(const char *src, int len, char *dst) |
244 | * ext4_fname_hash() - | ||
245 | * | ||
246 | * This function computes the hash of the input filename, and sets the output | ||
247 | * buffer to the *encoded* digest. It returns the length of the digest as its | ||
248 | * return value. Errors are returned as negative numbers. We trust the caller | ||
249 | * to allocate sufficient memory to oname string. | ||
250 | */ | ||
251 | static int ext4_fname_hash(struct ext4_fname_crypto_ctx *ctx, | ||
252 | const struct ext4_str *iname, | ||
253 | struct ext4_str *oname) | ||
254 | { | 231 | { |
255 | struct scatterlist sg; | 232 | int i = 0, bits = 0, ac = 0; |
256 | struct hash_desc desc = { | 233 | const char *p; |
257 | .tfm = (struct crypto_hash *)ctx->htfm, | 234 | char *cp = dst; |
258 | .flags = CRYPTO_TFM_REQ_MAY_SLEEP | 235 | |
259 | }; | 236 | while (i < len) { |
260 | int res = 0; | 237 | p = strchr(lookup_table, src[i]); |
261 | 238 | if (p == NULL || src[i] == 0) | |
262 | if (iname->len <= EXT4_FNAME_CRYPTO_DIGEST_SIZE) { | 239 | return -2; |
263 | res = ext4_fname_encode_digest(oname->name, iname->name, | 240 | ac += (p - lookup_table) << bits; |
264 | iname->len); | 241 | bits += 6; |
265 | oname->len = res; | 242 | if (bits >= 8) { |
266 | return res; | 243 | *cp++ = ac & 0xff; |
267 | } | 244 | ac >>= 8; |
268 | 245 | bits -= 8; | |
269 | sg_init_one(&sg, iname->name, iname->len); | 246 | } |
270 | res = crypto_hash_init(&desc); | 247 | i++; |
271 | if (res) { | ||
272 | printk(KERN_ERR | ||
273 | "%s: Error initializing crypto hash; res = [%d]\n", | ||
274 | __func__, res); | ||
275 | goto out; | ||
276 | } | ||
277 | res = crypto_hash_update(&desc, &sg, iname->len); | ||
278 | if (res) { | ||
279 | printk(KERN_ERR | ||
280 | "%s: Error updating crypto hash; res = [%d]\n", | ||
281 | __func__, res); | ||
282 | goto out; | ||
283 | } | ||
284 | res = crypto_hash_final(&desc, | ||
285 | &oname->name[EXT4_FNAME_CRYPTO_DIGEST_SIZE]); | ||
286 | if (res) { | ||
287 | printk(KERN_ERR | ||
288 | "%s: Error finalizing crypto hash; res = [%d]\n", | ||
289 | __func__, res); | ||
290 | goto out; | ||
291 | } | 248 | } |
292 | /* Encode the digest as a printable string--this will increase the | 249 | if (ac) |
293 | * size of the digest */ | 250 | return -1; |
294 | oname->name[0] = 'I'; | 251 | return cp - dst; |
295 | res = ext4_fname_encode_digest(oname->name+1, | ||
296 | &oname->name[EXT4_FNAME_CRYPTO_DIGEST_SIZE], | ||
297 | EXT4_FNAME_CRYPTO_DIGEST_SIZE) + 1; | ||
298 | oname->len = res; | ||
299 | out: | ||
300 | return res; | ||
301 | } | 252 | } |
302 | 253 | ||
303 | /** | 254 | /** |
@@ -571,9 +522,13 @@ void ext4_fname_crypto_free_buffer(struct ext4_str *crypto_str) | |||
571 | * ext4_fname_disk_to_usr() - converts a filename from disk space to user space | 522 | * ext4_fname_disk_to_usr() - converts a filename from disk space to user space |
572 | */ | 523 | */ |
573 | int _ext4_fname_disk_to_usr(struct ext4_fname_crypto_ctx *ctx, | 524 | int _ext4_fname_disk_to_usr(struct ext4_fname_crypto_ctx *ctx, |
574 | const struct ext4_str *iname, | 525 | struct dx_hash_info *hinfo, |
575 | struct ext4_str *oname) | 526 | const struct ext4_str *iname, |
527 | struct ext4_str *oname) | ||
576 | { | 528 | { |
529 | char buf[24]; | ||
530 | int ret; | ||
531 | |||
577 | if (ctx == NULL) | 532 | if (ctx == NULL) |
578 | return -EIO; | 533 | return -EIO; |
579 | if (iname->len < 3) { | 534 | if (iname->len < 3) { |
@@ -587,18 +542,33 @@ int _ext4_fname_disk_to_usr(struct ext4_fname_crypto_ctx *ctx, | |||
587 | } | 542 | } |
588 | if (ctx->has_valid_key) | 543 | if (ctx->has_valid_key) |
589 | return ext4_fname_decrypt(ctx, iname, oname); | 544 | return ext4_fname_decrypt(ctx, iname, oname); |
590 | else | 545 | |
591 | return ext4_fname_hash(ctx, iname, oname); | 546 | if (iname->len <= EXT4_FNAME_CRYPTO_DIGEST_SIZE) { |
547 | ret = digest_encode(iname->name, iname->len, oname->name); | ||
548 | oname->len = ret; | ||
549 | return ret; | ||
550 | } | ||
551 | if (hinfo) { | ||
552 | memcpy(buf, &hinfo->hash, 4); | ||
553 | memcpy(buf+4, &hinfo->minor_hash, 4); | ||
554 | } else | ||
555 | memset(buf, 0, 8); | ||
556 | memcpy(buf + 8, iname->name + iname->len - 16, 16); | ||
557 | oname->name[0] = '_'; | ||
558 | ret = digest_encode(buf, 24, oname->name+1); | ||
559 | oname->len = ret + 1; | ||
560 | return ret + 1; | ||
592 | } | 561 | } |
593 | 562 | ||
594 | int ext4_fname_disk_to_usr(struct ext4_fname_crypto_ctx *ctx, | 563 | int ext4_fname_disk_to_usr(struct ext4_fname_crypto_ctx *ctx, |
564 | struct dx_hash_info *hinfo, | ||
595 | const struct ext4_dir_entry_2 *de, | 565 | const struct ext4_dir_entry_2 *de, |
596 | struct ext4_str *oname) | 566 | struct ext4_str *oname) |
597 | { | 567 | { |
598 | struct ext4_str iname = {.name = (unsigned char *) de->name, | 568 | struct ext4_str iname = {.name = (unsigned char *) de->name, |
599 | .len = de->name_len }; | 569 | .len = de->name_len }; |
600 | 570 | ||
601 | return _ext4_fname_disk_to_usr(ctx, &iname, oname); | 571 | return _ext4_fname_disk_to_usr(ctx, hinfo, &iname, oname); |
602 | } | 572 | } |
603 | 573 | ||
604 | 574 | ||
@@ -640,10 +610,11 @@ int ext4_fname_usr_to_hash(struct ext4_fname_crypto_ctx *ctx, | |||
640 | const struct qstr *iname, | 610 | const struct qstr *iname, |
641 | struct dx_hash_info *hinfo) | 611 | struct dx_hash_info *hinfo) |
642 | { | 612 | { |
643 | struct ext4_str tmp, tmp2; | 613 | struct ext4_str tmp; |
644 | int ret = 0; | 614 | int ret = 0; |
615 | char buf[EXT4_FNAME_CRYPTO_DIGEST_SIZE+1]; | ||
645 | 616 | ||
646 | if (!ctx || !ctx->has_valid_key || | 617 | if (!ctx || |
647 | ((iname->name[0] == '.') && | 618 | ((iname->name[0] == '.') && |
648 | ((iname->len == 1) || | 619 | ((iname->len == 1) || |
649 | ((iname->name[1] == '.') && (iname->len == 2))))) { | 620 | ((iname->name[1] == '.') && (iname->len == 2))))) { |
@@ -651,59 +622,90 @@ int ext4_fname_usr_to_hash(struct ext4_fname_crypto_ctx *ctx, | |||
651 | return 0; | 622 | return 0; |
652 | } | 623 | } |
653 | 624 | ||
625 | if (!ctx->has_valid_key && iname->name[0] == '_') { | ||
626 | if (iname->len != 33) | ||
627 | return -ENOENT; | ||
628 | ret = digest_decode(iname->name+1, iname->len, buf); | ||
629 | if (ret != 24) | ||
630 | return -ENOENT; | ||
631 | memcpy(&hinfo->hash, buf, 4); | ||
632 | memcpy(&hinfo->minor_hash, buf + 4, 4); | ||
633 | return 0; | ||
634 | } | ||
635 | |||
636 | if (!ctx->has_valid_key && iname->name[0] != '_') { | ||
637 | if (iname->len > 43) | ||
638 | return -ENOENT; | ||
639 | ret = digest_decode(iname->name, iname->len, buf); | ||
640 | ext4fs_dirhash(buf, ret, hinfo); | ||
641 | return 0; | ||
642 | } | ||
643 | |||
654 | /* First encrypt the plaintext name */ | 644 | /* First encrypt the plaintext name */ |
655 | ret = ext4_fname_crypto_alloc_buffer(ctx, iname->len, &tmp); | 645 | ret = ext4_fname_crypto_alloc_buffer(ctx, iname->len, &tmp); |
656 | if (ret < 0) | 646 | if (ret < 0) |
657 | return ret; | 647 | return ret; |
658 | 648 | ||
659 | ret = ext4_fname_encrypt(ctx, iname, &tmp); | 649 | ret = ext4_fname_encrypt(ctx, iname, &tmp); |
660 | if (ret < 0) | 650 | if (ret >= 0) { |
661 | goto out; | 651 | ext4fs_dirhash(tmp.name, tmp.len, hinfo); |
662 | 652 | ret = 0; | |
663 | tmp2.len = (4 * ((EXT4_FNAME_CRYPTO_DIGEST_SIZE + 2) / 3)) + 1; | ||
664 | tmp2.name = kmalloc(tmp2.len + 1, GFP_KERNEL); | ||
665 | if (tmp2.name == NULL) { | ||
666 | ret = -ENOMEM; | ||
667 | goto out; | ||
668 | } | 653 | } |
669 | 654 | ||
670 | ret = ext4_fname_hash(ctx, &tmp, &tmp2); | ||
671 | if (ret > 0) | ||
672 | ext4fs_dirhash(tmp2.name, tmp2.len, hinfo); | ||
673 | ext4_fname_crypto_free_buffer(&tmp2); | ||
674 | out: | ||
675 | ext4_fname_crypto_free_buffer(&tmp); | 655 | ext4_fname_crypto_free_buffer(&tmp); |
676 | return ret; | 656 | return ret; |
677 | } | 657 | } |
678 | 658 | ||
679 | /** | 659 | int ext4_fname_match(struct ext4_fname_crypto_ctx *ctx, struct ext4_str *cstr, |
680 | * ext4_fname_disk_to_htree() - converts a filename from disk space to htree-access string | 660 | int len, const char * const name, |
681 | */ | 661 | struct ext4_dir_entry_2 *de) |
682 | int ext4_fname_disk_to_hash(struct ext4_fname_crypto_ctx *ctx, | ||
683 | const struct ext4_dir_entry_2 *de, | ||
684 | struct dx_hash_info *hinfo) | ||
685 | { | 662 | { |
686 | struct ext4_str iname = {.name = (unsigned char *) de->name, | 663 | int ret = -ENOENT; |
687 | .len = de->name_len}; | 664 | int bigname = (*name == '_'); |
688 | struct ext4_str tmp; | ||
689 | int ret; | ||
690 | 665 | ||
691 | if (!ctx || | 666 | if (ctx->has_valid_key) { |
692 | ((iname.name[0] == '.') && | 667 | if (cstr->name == NULL) { |
693 | ((iname.len == 1) || | 668 | struct qstr istr; |
694 | ((iname.name[1] == '.') && (iname.len == 2))))) { | 669 | |
695 | ext4fs_dirhash(iname.name, iname.len, hinfo); | 670 | ret = ext4_fname_crypto_alloc_buffer(ctx, len, cstr); |
696 | return 0; | 671 | if (ret < 0) |
672 | goto errout; | ||
673 | istr.name = name; | ||
674 | istr.len = len; | ||
675 | ret = ext4_fname_encrypt(ctx, &istr, cstr); | ||
676 | if (ret < 0) | ||
677 | goto errout; | ||
678 | } | ||
679 | } else { | ||
680 | if (cstr->name == NULL) { | ||
681 | cstr->name = kmalloc(32, GFP_KERNEL); | ||
682 | if (cstr->name == NULL) | ||
683 | return -ENOMEM; | ||
684 | if ((bigname && (len != 33)) || | ||
685 | (!bigname && (len > 43))) | ||
686 | goto errout; | ||
687 | ret = digest_decode(name+bigname, len-bigname, | ||
688 | cstr->name); | ||
689 | if (ret < 0) { | ||
690 | ret = -ENOENT; | ||
691 | goto errout; | ||
692 | } | ||
693 | cstr->len = ret; | ||
694 | } | ||
695 | if (bigname) { | ||
696 | if (de->name_len < 16) | ||
697 | return 0; | ||
698 | ret = memcmp(de->name + de->name_len - 16, | ||
699 | cstr->name + 8, 16); | ||
700 | return (ret == 0) ? 1 : 0; | ||
701 | } | ||
697 | } | 702 | } |
698 | 703 | if (de->name_len != cstr->len) | |
699 | tmp.len = (4 * ((EXT4_FNAME_CRYPTO_DIGEST_SIZE + 2) / 3)) + 1; | 704 | return 0; |
700 | tmp.name = kmalloc(tmp.len + 1, GFP_KERNEL); | 705 | ret = memcmp(de->name, cstr->name, cstr->len); |
701 | if (tmp.name == NULL) | 706 | return (ret == 0) ? 1 : 0; |
702 | return -ENOMEM; | 707 | errout: |
703 | 708 | kfree(cstr->name); | |
704 | ret = ext4_fname_hash(ctx, &iname, &tmp); | 709 | cstr->name = NULL; |
705 | if (ret > 0) | ||
706 | ext4fs_dirhash(tmp.name, tmp.len, hinfo); | ||
707 | ext4_fname_crypto_free_buffer(&tmp); | ||
708 | return ret; | 710 | return ret; |
709 | } | 711 | } |
diff --git a/fs/ext4/dir.c b/fs/ext4/dir.c index 61db51a5ce4c..5665d82d2332 100644 --- a/fs/ext4/dir.c +++ b/fs/ext4/dir.c | |||
@@ -249,7 +249,7 @@ static int ext4_readdir(struct file *file, struct dir_context *ctx) | |||
249 | } else { | 249 | } else { |
250 | /* Directory is encrypted */ | 250 | /* Directory is encrypted */ |
251 | err = ext4_fname_disk_to_usr(enc_ctx, | 251 | err = ext4_fname_disk_to_usr(enc_ctx, |
252 | de, &fname_crypto_str); | 252 | NULL, de, &fname_crypto_str); |
253 | if (err < 0) | 253 | if (err < 0) |
254 | goto errout; | 254 | goto errout; |
255 | if (!dir_emit(ctx, | 255 | if (!dir_emit(ctx, |
diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h index 0179654faf79..dfb113816672 100644 --- a/fs/ext4/ext4.h +++ b/fs/ext4/ext4.h | |||
@@ -2093,9 +2093,11 @@ u32 ext4_fname_crypto_round_up(u32 size, u32 blksize); | |||
2093 | int ext4_fname_crypto_alloc_buffer(struct ext4_fname_crypto_ctx *ctx, | 2093 | int ext4_fname_crypto_alloc_buffer(struct ext4_fname_crypto_ctx *ctx, |
2094 | u32 ilen, struct ext4_str *crypto_str); | 2094 | u32 ilen, struct ext4_str *crypto_str); |
2095 | int _ext4_fname_disk_to_usr(struct ext4_fname_crypto_ctx *ctx, | 2095 | int _ext4_fname_disk_to_usr(struct ext4_fname_crypto_ctx *ctx, |
2096 | struct dx_hash_info *hinfo, | ||
2096 | const struct ext4_str *iname, | 2097 | const struct ext4_str *iname, |
2097 | struct ext4_str *oname); | 2098 | struct ext4_str *oname); |
2098 | int ext4_fname_disk_to_usr(struct ext4_fname_crypto_ctx *ctx, | 2099 | int ext4_fname_disk_to_usr(struct ext4_fname_crypto_ctx *ctx, |
2100 | struct dx_hash_info *hinfo, | ||
2099 | const struct ext4_dir_entry_2 *de, | 2101 | const struct ext4_dir_entry_2 *de, |
2100 | struct ext4_str *oname); | 2102 | struct ext4_str *oname); |
2101 | int ext4_fname_usr_to_disk(struct ext4_fname_crypto_ctx *ctx, | 2103 | int ext4_fname_usr_to_disk(struct ext4_fname_crypto_ctx *ctx, |
@@ -2104,11 +2106,12 @@ int ext4_fname_usr_to_disk(struct ext4_fname_crypto_ctx *ctx, | |||
2104 | int ext4_fname_usr_to_hash(struct ext4_fname_crypto_ctx *ctx, | 2106 | int ext4_fname_usr_to_hash(struct ext4_fname_crypto_ctx *ctx, |
2105 | const struct qstr *iname, | 2107 | const struct qstr *iname, |
2106 | struct dx_hash_info *hinfo); | 2108 | struct dx_hash_info *hinfo); |
2107 | int ext4_fname_disk_to_hash(struct ext4_fname_crypto_ctx *ctx, | ||
2108 | const struct ext4_dir_entry_2 *de, | ||
2109 | struct dx_hash_info *hinfo); | ||
2110 | int ext4_fname_crypto_namelen_on_disk(struct ext4_fname_crypto_ctx *ctx, | 2109 | int ext4_fname_crypto_namelen_on_disk(struct ext4_fname_crypto_ctx *ctx, |
2111 | u32 namelen); | 2110 | u32 namelen); |
2111 | int ext4_fname_match(struct ext4_fname_crypto_ctx *ctx, struct ext4_str *cstr, | ||
2112 | int len, const char * const name, | ||
2113 | struct ext4_dir_entry_2 *de); | ||
2114 | |||
2112 | 2115 | ||
2113 | #ifdef CONFIG_EXT4_FS_ENCRYPTION | 2116 | #ifdef CONFIG_EXT4_FS_ENCRYPTION |
2114 | void ext4_put_fname_crypto_ctx(struct ext4_fname_crypto_ctx **ctx); | 2117 | void ext4_put_fname_crypto_ctx(struct ext4_fname_crypto_ctx **ctx); |
diff --git a/fs/ext4/namei.c b/fs/ext4/namei.c index 4f87127f781f..5ea737114716 100644 --- a/fs/ext4/namei.c +++ b/fs/ext4/namei.c | |||
@@ -640,7 +640,7 @@ static struct stats dx_show_leaf(struct inode *dir, | |||
640 | ext4_put_fname_crypto_ctx(&ctx); | 640 | ext4_put_fname_crypto_ctx(&ctx); |
641 | ctx = NULL; | 641 | ctx = NULL; |
642 | } | 642 | } |
643 | res = ext4_fname_disk_to_usr(ctx, de, | 643 | res = ext4_fname_disk_to_usr(ctx, NULL, de, |
644 | &fname_crypto_str); | 644 | &fname_crypto_str); |
645 | if (res < 0) { | 645 | if (res < 0) { |
646 | printk(KERN_WARNING "Error " | 646 | printk(KERN_WARNING "Error " |
@@ -653,15 +653,8 @@ static struct stats dx_show_leaf(struct inode *dir, | |||
653 | name = fname_crypto_str.name; | 653 | name = fname_crypto_str.name; |
654 | len = fname_crypto_str.len; | 654 | len = fname_crypto_str.len; |
655 | } | 655 | } |
656 | res = ext4_fname_disk_to_hash(ctx, de, | 656 | ext4fs_dirhash(de->name, de->name_len, |
657 | &h); | 657 | &h); |
658 | if (res < 0) { | ||
659 | printk(KERN_WARNING "Error " | ||
660 | "converting filename " | ||
661 | "from disk to htree" | ||
662 | "\n"); | ||
663 | h.hash = 0xDEADBEEF; | ||
664 | } | ||
665 | printk("%*.s:(E)%x.%u ", len, name, | 658 | printk("%*.s:(E)%x.%u ", len, name, |
666 | h.hash, (unsigned) ((char *) de | 659 | h.hash, (unsigned) ((char *) de |
667 | - base)); | 660 | - base)); |
@@ -1008,15 +1001,7 @@ static int htree_dirblock_to_tree(struct file *dir_file, | |||
1008 | /* silently ignore the rest of the block */ | 1001 | /* silently ignore the rest of the block */ |
1009 | break; | 1002 | break; |
1010 | } | 1003 | } |
1011 | #ifdef CONFIG_EXT4_FS_ENCRYPTION | ||
1012 | err = ext4_fname_disk_to_hash(ctx, de, hinfo); | ||
1013 | if (err < 0) { | ||
1014 | count = err; | ||
1015 | goto errout; | ||
1016 | } | ||
1017 | #else | ||
1018 | ext4fs_dirhash(de->name, de->name_len, hinfo); | 1004 | ext4fs_dirhash(de->name, de->name_len, hinfo); |
1019 | #endif | ||
1020 | if ((hinfo->hash < start_hash) || | 1005 | if ((hinfo->hash < start_hash) || |
1021 | ((hinfo->hash == start_hash) && | 1006 | ((hinfo->hash == start_hash) && |
1022 | (hinfo->minor_hash < start_minor_hash))) | 1007 | (hinfo->minor_hash < start_minor_hash))) |
@@ -1032,7 +1017,7 @@ static int htree_dirblock_to_tree(struct file *dir_file, | |||
1032 | &tmp_str); | 1017 | &tmp_str); |
1033 | } else { | 1018 | } else { |
1034 | /* Directory is encrypted */ | 1019 | /* Directory is encrypted */ |
1035 | err = ext4_fname_disk_to_usr(ctx, de, | 1020 | err = ext4_fname_disk_to_usr(ctx, hinfo, de, |
1036 | &fname_crypto_str); | 1021 | &fname_crypto_str); |
1037 | if (err < 0) { | 1022 | if (err < 0) { |
1038 | count = err; | 1023 | count = err; |
@@ -1193,26 +1178,10 @@ static int dx_make_map(struct inode *dir, struct ext4_dir_entry_2 *de, | |||
1193 | int count = 0; | 1178 | int count = 0; |
1194 | char *base = (char *) de; | 1179 | char *base = (char *) de; |
1195 | struct dx_hash_info h = *hinfo; | 1180 | struct dx_hash_info h = *hinfo; |
1196 | #ifdef CONFIG_EXT4_FS_ENCRYPTION | ||
1197 | struct ext4_fname_crypto_ctx *ctx = NULL; | ||
1198 | int err; | ||
1199 | |||
1200 | ctx = ext4_get_fname_crypto_ctx(dir, EXT4_NAME_LEN); | ||
1201 | if (IS_ERR(ctx)) | ||
1202 | return PTR_ERR(ctx); | ||
1203 | #endif | ||
1204 | 1181 | ||
1205 | while ((char *) de < base + blocksize) { | 1182 | while ((char *) de < base + blocksize) { |
1206 | if (de->name_len && de->inode) { | 1183 | if (de->name_len && de->inode) { |
1207 | #ifdef CONFIG_EXT4_FS_ENCRYPTION | ||
1208 | err = ext4_fname_disk_to_hash(ctx, de, &h); | ||
1209 | if (err < 0) { | ||
1210 | ext4_put_fname_crypto_ctx(&ctx); | ||
1211 | return err; | ||
1212 | } | ||
1213 | #else | ||
1214 | ext4fs_dirhash(de->name, de->name_len, &h); | 1184 | ext4fs_dirhash(de->name, de->name_len, &h); |
1215 | #endif | ||
1216 | map_tail--; | 1185 | map_tail--; |
1217 | map_tail->hash = h.hash; | 1186 | map_tail->hash = h.hash; |
1218 | map_tail->offs = ((char *) de - base)>>2; | 1187 | map_tail->offs = ((char *) de - base)>>2; |
@@ -1223,9 +1192,6 @@ static int dx_make_map(struct inode *dir, struct ext4_dir_entry_2 *de, | |||
1223 | /* XXX: do we need to check rec_len == 0 case? -Chris */ | 1192 | /* XXX: do we need to check rec_len == 0 case? -Chris */ |
1224 | de = ext4_next_entry(de, blocksize); | 1193 | de = ext4_next_entry(de, blocksize); |
1225 | } | 1194 | } |
1226 | #ifdef CONFIG_EXT4_FS_ENCRYPTION | ||
1227 | ext4_put_fname_crypto_ctx(&ctx); | ||
1228 | #endif | ||
1229 | return count; | 1195 | return count; |
1230 | } | 1196 | } |
1231 | 1197 | ||
@@ -1287,16 +1253,8 @@ static inline int ext4_match(struct ext4_fname_crypto_ctx *ctx, | |||
1287 | return 0; | 1253 | return 0; |
1288 | 1254 | ||
1289 | #ifdef CONFIG_EXT4_FS_ENCRYPTION | 1255 | #ifdef CONFIG_EXT4_FS_ENCRYPTION |
1290 | if (ctx) { | 1256 | if (ctx) |
1291 | /* Directory is encrypted */ | 1257 | return ext4_fname_match(ctx, fname_crypto_str, len, name, de); |
1292 | res = ext4_fname_disk_to_usr(ctx, de, fname_crypto_str); | ||
1293 | if (res < 0) | ||
1294 | return res; | ||
1295 | if (len != res) | ||
1296 | return 0; | ||
1297 | res = memcmp(name, fname_crypto_str->name, len); | ||
1298 | return (res == 0) ? 1 : 0; | ||
1299 | } | ||
1300 | #endif | 1258 | #endif |
1301 | if (len != de->name_len) | 1259 | if (len != de->name_len) |
1302 | return 0; | 1260 | return 0; |
@@ -1324,16 +1282,6 @@ int search_dir(struct buffer_head *bh, char *search_buf, int buf_size, | |||
1324 | if (IS_ERR(ctx)) | 1282 | if (IS_ERR(ctx)) |
1325 | return -1; | 1283 | return -1; |
1326 | 1284 | ||
1327 | if (ctx != NULL) { | ||
1328 | /* Allocate buffer to hold maximum name length */ | ||
1329 | res = ext4_fname_crypto_alloc_buffer(ctx, EXT4_NAME_LEN, | ||
1330 | &fname_crypto_str); | ||
1331 | if (res < 0) { | ||
1332 | ext4_put_fname_crypto_ctx(&ctx); | ||
1333 | return -1; | ||
1334 | } | ||
1335 | } | ||
1336 | |||
1337 | de = (struct ext4_dir_entry_2 *)search_buf; | 1285 | de = (struct ext4_dir_entry_2 *)search_buf; |
1338 | dlimit = search_buf + buf_size; | 1286 | dlimit = search_buf + buf_size; |
1339 | while ((char *) de < dlimit) { | 1287 | while ((char *) de < dlimit) { |
@@ -1872,14 +1820,6 @@ int ext4_find_dest_de(struct inode *dir, struct inode *inode, | |||
1872 | return res; | 1820 | return res; |
1873 | } | 1821 | } |
1874 | reclen = EXT4_DIR_REC_LEN(res); | 1822 | reclen = EXT4_DIR_REC_LEN(res); |
1875 | |||
1876 | /* Allocate buffer to hold maximum name length */ | ||
1877 | res = ext4_fname_crypto_alloc_buffer(ctx, EXT4_NAME_LEN, | ||
1878 | &fname_crypto_str); | ||
1879 | if (res < 0) { | ||
1880 | ext4_put_fname_crypto_ctx(&ctx); | ||
1881 | return -1; | ||
1882 | } | ||
1883 | } | 1823 | } |
1884 | 1824 | ||
1885 | de = (struct ext4_dir_entry_2 *)buf; | 1825 | de = (struct ext4_dir_entry_2 *)buf; |
diff --git a/fs/ext4/symlink.c b/fs/ext4/symlink.c index 136ca0e911fd..ce2ed286ba08 100644 --- a/fs/ext4/symlink.c +++ b/fs/ext4/symlink.c | |||
@@ -74,7 +74,7 @@ static void *ext4_follow_link(struct dentry *dentry, struct nameidata *nd) | |||
74 | goto errout; | 74 | goto errout; |
75 | } | 75 | } |
76 | pstr.name = paddr; | 76 | pstr.name = paddr; |
77 | res = _ext4_fname_disk_to_usr(ctx, &cstr, &pstr); | 77 | res = _ext4_fname_disk_to_usr(ctx, NULL, &cstr, &pstr); |
78 | if (res < 0) | 78 | if (res < 0) |
79 | goto errout; | 79 | goto errout; |
80 | /* Null-terminate the name */ | 80 | /* Null-terminate the name */ |