diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2015-05-03 21:23:53 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2015-05-03 21:23:53 -0400 |
commit | 8663da2c0919896788321cd8a0016af08588c656 (patch) | |
tree | 9e92edcab3fa5187f8af2b02cdc791453b21c8b8 /fs | |
parent | 101a6fd387801bbe164eafea3950b98f8e6440bb (diff) | |
parent | 2c869b262a10ca99cb866d04087d75311587a30c (diff) |
Merge tag 'for_linus_stable' of git://git.kernel.org/pub/scm/linux/kernel/git/tytso/ext4
Pull ext4 fixes from Ted Ts'o:
"Some miscellaneous bug fixes and some final on-disk and ABI changes
for ext4 encryption which provide better security and performance"
* tag 'for_linus_stable' of git://git.kernel.org/pub/scm/linux/kernel/git/tytso/ext4:
ext4: fix growing of tiny filesystems
ext4: move check under lock scope to close a race.
ext4: fix data corruption caused by unwritten and delayed extents
ext4 crypto: remove duplicated encryption mode definitions
ext4 crypto: do not select from EXT4_FS_ENCRYPTION
ext4 crypto: add padding to filenames before encrypting
ext4 crypto: simplify and speed up filename encryption
Diffstat (limited to 'fs')
-rw-r--r-- | fs/ext4/Kconfig | 9 | ||||
-rw-r--r-- | fs/ext4/crypto_fname.c | 280 | ||||
-rw-r--r-- | fs/ext4/crypto_key.c | 1 | ||||
-rw-r--r-- | fs/ext4/crypto_policy.c | 14 | ||||
-rw-r--r-- | fs/ext4/dir.c | 2 | ||||
-rw-r--r-- | fs/ext4/ext4.h | 16 | ||||
-rw-r--r-- | fs/ext4/ext4_crypto.h | 11 | ||||
-rw-r--r-- | fs/ext4/extents.c | 15 | ||||
-rw-r--r-- | fs/ext4/extents_status.c | 8 | ||||
-rw-r--r-- | fs/ext4/inode.c | 2 | ||||
-rw-r--r-- | fs/ext4/namei.c | 72 | ||||
-rw-r--r-- | fs/ext4/resize.c | 7 | ||||
-rw-r--r-- | fs/ext4/symlink.c | 2 |
13 files changed, 210 insertions, 229 deletions
diff --git a/fs/ext4/Kconfig b/fs/ext4/Kconfig index 18228c201f7f..024f2284d3f6 100644 --- a/fs/ext4/Kconfig +++ b/fs/ext4/Kconfig | |||
@@ -64,8 +64,8 @@ config EXT4_FS_SECURITY | |||
64 | If you are not using a security module that requires using | 64 | If you are not using a security module that requires using |
65 | extended attributes for file security labels, say N. | 65 | extended attributes for file security labels, say N. |
66 | 66 | ||
67 | config EXT4_FS_ENCRYPTION | 67 | config EXT4_ENCRYPTION |
68 | bool "Ext4 Encryption" | 68 | tristate "Ext4 Encryption" |
69 | depends on EXT4_FS | 69 | depends on EXT4_FS |
70 | select CRYPTO_AES | 70 | select CRYPTO_AES |
71 | select CRYPTO_CBC | 71 | select CRYPTO_CBC |
@@ -81,6 +81,11 @@ config EXT4_FS_ENCRYPTION | |||
81 | efficient since it avoids caching the encrypted and | 81 | efficient since it avoids caching the encrypted and |
82 | decrypted pages in the page cache. | 82 | decrypted pages in the page cache. |
83 | 83 | ||
84 | config EXT4_FS_ENCRYPTION | ||
85 | bool | ||
86 | default y | ||
87 | depends on EXT4_ENCRYPTION | ||
88 | |||
84 | config EXT4_DEBUG | 89 | config EXT4_DEBUG |
85 | bool "EXT4 debugging support" | 90 | bool "EXT4 debugging support" |
86 | depends on EXT4_FS | 91 | depends on EXT4_FS |
diff --git a/fs/ext4/crypto_fname.c b/fs/ext4/crypto_fname.c index ca2f5948c1ac..fded02f72299 100644 --- a/fs/ext4/crypto_fname.c +++ b/fs/ext4/crypto_fname.c | |||
@@ -66,6 +66,7 @@ static int ext4_fname_encrypt(struct ext4_fname_crypto_ctx *ctx, | |||
66 | int res = 0; | 66 | int res = 0; |
67 | char iv[EXT4_CRYPTO_BLOCK_SIZE]; | 67 | char iv[EXT4_CRYPTO_BLOCK_SIZE]; |
68 | struct scatterlist sg[1]; | 68 | struct scatterlist sg[1]; |
69 | int padding = 4 << (ctx->flags & EXT4_POLICY_FLAGS_PAD_MASK); | ||
69 | char *workbuf; | 70 | char *workbuf; |
70 | 71 | ||
71 | if (iname->len <= 0 || iname->len > ctx->lim) | 72 | if (iname->len <= 0 || iname->len > ctx->lim) |
@@ -73,6 +74,7 @@ static int ext4_fname_encrypt(struct ext4_fname_crypto_ctx *ctx, | |||
73 | 74 | ||
74 | ciphertext_len = (iname->len < EXT4_CRYPTO_BLOCK_SIZE) ? | 75 | ciphertext_len = (iname->len < EXT4_CRYPTO_BLOCK_SIZE) ? |
75 | EXT4_CRYPTO_BLOCK_SIZE : iname->len; | 76 | EXT4_CRYPTO_BLOCK_SIZE : iname->len; |
77 | ciphertext_len = ext4_fname_crypto_round_up(ciphertext_len, padding); | ||
76 | ciphertext_len = (ciphertext_len > ctx->lim) | 78 | ciphertext_len = (ciphertext_len > ctx->lim) |
77 | ? ctx->lim : ciphertext_len; | 79 | ? ctx->lim : ciphertext_len; |
78 | 80 | ||
@@ -101,7 +103,7 @@ static int ext4_fname_encrypt(struct ext4_fname_crypto_ctx *ctx, | |||
101 | /* Create encryption request */ | 103 | /* Create encryption request */ |
102 | sg_init_table(sg, 1); | 104 | sg_init_table(sg, 1); |
103 | sg_set_page(sg, ctx->workpage, PAGE_SIZE, 0); | 105 | sg_set_page(sg, ctx->workpage, PAGE_SIZE, 0); |
104 | ablkcipher_request_set_crypt(req, sg, sg, iname->len, iv); | 106 | ablkcipher_request_set_crypt(req, sg, sg, ciphertext_len, iv); |
105 | res = crypto_ablkcipher_encrypt(req); | 107 | res = crypto_ablkcipher_encrypt(req); |
106 | if (res == -EINPROGRESS || res == -EBUSY) { | 108 | if (res == -EINPROGRESS || res == -EBUSY) { |
107 | BUG_ON(req->base.data != &ecr); | 109 | BUG_ON(req->base.data != &ecr); |
@@ -198,106 +200,57 @@ static int ext4_fname_decrypt(struct ext4_fname_crypto_ctx *ctx, | |||
198 | return oname->len; | 200 | return oname->len; |
199 | } | 201 | } |
200 | 202 | ||
203 | static const char *lookup_table = | ||
204 | "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+,"; | ||
205 | |||
201 | /** | 206 | /** |
202 | * ext4_fname_encode_digest() - | 207 | * ext4_fname_encode_digest() - |
203 | * | 208 | * |
204 | * Encodes the input digest using characters from the set [a-zA-Z0-9_+]. | 209 | * 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. | 210 | * The encoded string is roughly 4/3 times the size of the input string. |
206 | */ | 211 | */ |
207 | int ext4_fname_encode_digest(char *dst, char *src, u32 len) | 212 | static int digest_encode(const char *src, int len, char *dst) |
208 | { | 213 | { |
209 | static const char *lookup_table = | 214 | int i = 0, bits = 0, ac = 0; |
210 | "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_+"; | 215 | char *cp = dst; |
211 | u32 current_chunk, num_chunks, i; | 216 | |
212 | char tmp_buf[3]; | 217 | while (i < len) { |
213 | u32 c0, c1, c2, c3; | 218 | ac += (((unsigned char) src[i]) << bits); |
214 | 219 | bits += 8; | |
215 | current_chunk = 0; | 220 | do { |
216 | num_chunks = len/3; | 221 | *cp++ = lookup_table[ac & 0x3f]; |
217 | for (i = 0; i < num_chunks; i++) { | 222 | ac >>= 6; |
218 | c0 = src[3*i] & 0x3f; | 223 | bits -= 6; |
219 | c1 = (((src[3*i]>>6)&0x3) | ((src[3*i+1] & 0xf)<<2)) & 0x3f; | 224 | } 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++; | 225 | i++; |
239 | } | 226 | } |
240 | return (i * 4); | 227 | if (bits) |
228 | *cp++ = lookup_table[ac & 0x3f]; | ||
229 | return cp - dst; | ||
241 | } | 230 | } |
242 | 231 | ||
243 | /** | 232 | 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 | { | 233 | { |
255 | struct scatterlist sg; | 234 | int i = 0, bits = 0, ac = 0; |
256 | struct hash_desc desc = { | 235 | const char *p; |
257 | .tfm = (struct crypto_hash *)ctx->htfm, | 236 | char *cp = dst; |
258 | .flags = CRYPTO_TFM_REQ_MAY_SLEEP | 237 | |
259 | }; | 238 | while (i < len) { |
260 | int res = 0; | 239 | p = strchr(lookup_table, src[i]); |
261 | 240 | if (p == NULL || src[i] == 0) | |
262 | if (iname->len <= EXT4_FNAME_CRYPTO_DIGEST_SIZE) { | 241 | return -2; |
263 | res = ext4_fname_encode_digest(oname->name, iname->name, | 242 | ac += (p - lookup_table) << bits; |
264 | iname->len); | 243 | bits += 6; |
265 | oname->len = res; | 244 | if (bits >= 8) { |
266 | return res; | 245 | *cp++ = ac & 0xff; |
267 | } | 246 | ac >>= 8; |
268 | 247 | bits -= 8; | |
269 | sg_init_one(&sg, iname->name, iname->len); | 248 | } |
270 | res = crypto_hash_init(&desc); | 249 | 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 | } | 250 | } |
292 | /* Encode the digest as a printable string--this will increase the | 251 | if (ac) |
293 | * size of the digest */ | 252 | return -1; |
294 | oname->name[0] = 'I'; | 253 | 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 | } | 254 | } |
302 | 255 | ||
303 | /** | 256 | /** |
@@ -405,6 +358,7 @@ struct ext4_fname_crypto_ctx *ext4_get_fname_crypto_ctx( | |||
405 | if (IS_ERR(ctx)) | 358 | if (IS_ERR(ctx)) |
406 | return ctx; | 359 | return ctx; |
407 | 360 | ||
361 | ctx->flags = ei->i_crypt_policy_flags; | ||
408 | if (ctx->has_valid_key) { | 362 | if (ctx->has_valid_key) { |
409 | if (ctx->key.mode != EXT4_ENCRYPTION_MODE_AES_256_CTS) { | 363 | if (ctx->key.mode != EXT4_ENCRYPTION_MODE_AES_256_CTS) { |
410 | printk_once(KERN_WARNING | 364 | printk_once(KERN_WARNING |
@@ -517,6 +471,7 @@ int ext4_fname_crypto_namelen_on_disk(struct ext4_fname_crypto_ctx *ctx, | |||
517 | u32 namelen) | 471 | u32 namelen) |
518 | { | 472 | { |
519 | u32 ciphertext_len; | 473 | u32 ciphertext_len; |
474 | int padding = 4 << (ctx->flags & EXT4_POLICY_FLAGS_PAD_MASK); | ||
520 | 475 | ||
521 | if (ctx == NULL) | 476 | if (ctx == NULL) |
522 | return -EIO; | 477 | return -EIO; |
@@ -524,6 +479,7 @@ int ext4_fname_crypto_namelen_on_disk(struct ext4_fname_crypto_ctx *ctx, | |||
524 | return -EACCES; | 479 | return -EACCES; |
525 | ciphertext_len = (namelen < EXT4_CRYPTO_BLOCK_SIZE) ? | 480 | ciphertext_len = (namelen < EXT4_CRYPTO_BLOCK_SIZE) ? |
526 | EXT4_CRYPTO_BLOCK_SIZE : namelen; | 481 | EXT4_CRYPTO_BLOCK_SIZE : namelen; |
482 | ciphertext_len = ext4_fname_crypto_round_up(ciphertext_len, padding); | ||
527 | ciphertext_len = (ciphertext_len > ctx->lim) | 483 | ciphertext_len = (ciphertext_len > ctx->lim) |
528 | ? ctx->lim : ciphertext_len; | 484 | ? ctx->lim : ciphertext_len; |
529 | return (int) ciphertext_len; | 485 | return (int) ciphertext_len; |
@@ -539,10 +495,13 @@ int ext4_fname_crypto_alloc_buffer(struct ext4_fname_crypto_ctx *ctx, | |||
539 | u32 ilen, struct ext4_str *crypto_str) | 495 | u32 ilen, struct ext4_str *crypto_str) |
540 | { | 496 | { |
541 | unsigned int olen; | 497 | unsigned int olen; |
498 | int padding = 4 << (ctx->flags & EXT4_POLICY_FLAGS_PAD_MASK); | ||
542 | 499 | ||
543 | if (!ctx) | 500 | if (!ctx) |
544 | return -EIO; | 501 | return -EIO; |
545 | olen = ext4_fname_crypto_round_up(ilen, EXT4_CRYPTO_BLOCK_SIZE); | 502 | if (padding < EXT4_CRYPTO_BLOCK_SIZE) |
503 | padding = EXT4_CRYPTO_BLOCK_SIZE; | ||
504 | olen = ext4_fname_crypto_round_up(ilen, padding); | ||
546 | crypto_str->len = olen; | 505 | crypto_str->len = olen; |
547 | if (olen < EXT4_FNAME_CRYPTO_DIGEST_SIZE*2) | 506 | if (olen < EXT4_FNAME_CRYPTO_DIGEST_SIZE*2) |
548 | olen = EXT4_FNAME_CRYPTO_DIGEST_SIZE*2; | 507 | olen = EXT4_FNAME_CRYPTO_DIGEST_SIZE*2; |
@@ -571,9 +530,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 | 530 | * ext4_fname_disk_to_usr() - converts a filename from disk space to user space |
572 | */ | 531 | */ |
573 | int _ext4_fname_disk_to_usr(struct ext4_fname_crypto_ctx *ctx, | 532 | int _ext4_fname_disk_to_usr(struct ext4_fname_crypto_ctx *ctx, |
574 | const struct ext4_str *iname, | 533 | struct dx_hash_info *hinfo, |
575 | struct ext4_str *oname) | 534 | const struct ext4_str *iname, |
535 | struct ext4_str *oname) | ||
576 | { | 536 | { |
537 | char buf[24]; | ||
538 | int ret; | ||
539 | |||
577 | if (ctx == NULL) | 540 | if (ctx == NULL) |
578 | return -EIO; | 541 | return -EIO; |
579 | if (iname->len < 3) { | 542 | if (iname->len < 3) { |
@@ -587,18 +550,33 @@ int _ext4_fname_disk_to_usr(struct ext4_fname_crypto_ctx *ctx, | |||
587 | } | 550 | } |
588 | if (ctx->has_valid_key) | 551 | if (ctx->has_valid_key) |
589 | return ext4_fname_decrypt(ctx, iname, oname); | 552 | return ext4_fname_decrypt(ctx, iname, oname); |
590 | else | 553 | |
591 | return ext4_fname_hash(ctx, iname, oname); | 554 | if (iname->len <= EXT4_FNAME_CRYPTO_DIGEST_SIZE) { |
555 | ret = digest_encode(iname->name, iname->len, oname->name); | ||
556 | oname->len = ret; | ||
557 | return ret; | ||
558 | } | ||
559 | if (hinfo) { | ||
560 | memcpy(buf, &hinfo->hash, 4); | ||
561 | memcpy(buf+4, &hinfo->minor_hash, 4); | ||
562 | } else | ||
563 | memset(buf, 0, 8); | ||
564 | memcpy(buf + 8, iname->name + iname->len - 16, 16); | ||
565 | oname->name[0] = '_'; | ||
566 | ret = digest_encode(buf, 24, oname->name+1); | ||
567 | oname->len = ret + 1; | ||
568 | return ret + 1; | ||
592 | } | 569 | } |
593 | 570 | ||
594 | int ext4_fname_disk_to_usr(struct ext4_fname_crypto_ctx *ctx, | 571 | int ext4_fname_disk_to_usr(struct ext4_fname_crypto_ctx *ctx, |
572 | struct dx_hash_info *hinfo, | ||
595 | const struct ext4_dir_entry_2 *de, | 573 | const struct ext4_dir_entry_2 *de, |
596 | struct ext4_str *oname) | 574 | struct ext4_str *oname) |
597 | { | 575 | { |
598 | struct ext4_str iname = {.name = (unsigned char *) de->name, | 576 | struct ext4_str iname = {.name = (unsigned char *) de->name, |
599 | .len = de->name_len }; | 577 | .len = de->name_len }; |
600 | 578 | ||
601 | return _ext4_fname_disk_to_usr(ctx, &iname, oname); | 579 | return _ext4_fname_disk_to_usr(ctx, hinfo, &iname, oname); |
602 | } | 580 | } |
603 | 581 | ||
604 | 582 | ||
@@ -640,10 +618,11 @@ int ext4_fname_usr_to_hash(struct ext4_fname_crypto_ctx *ctx, | |||
640 | const struct qstr *iname, | 618 | const struct qstr *iname, |
641 | struct dx_hash_info *hinfo) | 619 | struct dx_hash_info *hinfo) |
642 | { | 620 | { |
643 | struct ext4_str tmp, tmp2; | 621 | struct ext4_str tmp; |
644 | int ret = 0; | 622 | int ret = 0; |
623 | char buf[EXT4_FNAME_CRYPTO_DIGEST_SIZE+1]; | ||
645 | 624 | ||
646 | if (!ctx || !ctx->has_valid_key || | 625 | if (!ctx || |
647 | ((iname->name[0] == '.') && | 626 | ((iname->name[0] == '.') && |
648 | ((iname->len == 1) || | 627 | ((iname->len == 1) || |
649 | ((iname->name[1] == '.') && (iname->len == 2))))) { | 628 | ((iname->name[1] == '.') && (iname->len == 2))))) { |
@@ -651,59 +630,90 @@ int ext4_fname_usr_to_hash(struct ext4_fname_crypto_ctx *ctx, | |||
651 | return 0; | 630 | return 0; |
652 | } | 631 | } |
653 | 632 | ||
633 | if (!ctx->has_valid_key && iname->name[0] == '_') { | ||
634 | if (iname->len != 33) | ||
635 | return -ENOENT; | ||
636 | ret = digest_decode(iname->name+1, iname->len, buf); | ||
637 | if (ret != 24) | ||
638 | return -ENOENT; | ||
639 | memcpy(&hinfo->hash, buf, 4); | ||
640 | memcpy(&hinfo->minor_hash, buf + 4, 4); | ||
641 | return 0; | ||
642 | } | ||
643 | |||
644 | if (!ctx->has_valid_key && iname->name[0] != '_') { | ||
645 | if (iname->len > 43) | ||
646 | return -ENOENT; | ||
647 | ret = digest_decode(iname->name, iname->len, buf); | ||
648 | ext4fs_dirhash(buf, ret, hinfo); | ||
649 | return 0; | ||
650 | } | ||
651 | |||
654 | /* First encrypt the plaintext name */ | 652 | /* First encrypt the plaintext name */ |
655 | ret = ext4_fname_crypto_alloc_buffer(ctx, iname->len, &tmp); | 653 | ret = ext4_fname_crypto_alloc_buffer(ctx, iname->len, &tmp); |
656 | if (ret < 0) | 654 | if (ret < 0) |
657 | return ret; | 655 | return ret; |
658 | 656 | ||
659 | ret = ext4_fname_encrypt(ctx, iname, &tmp); | 657 | ret = ext4_fname_encrypt(ctx, iname, &tmp); |
660 | if (ret < 0) | 658 | if (ret >= 0) { |
661 | goto out; | 659 | ext4fs_dirhash(tmp.name, tmp.len, hinfo); |
662 | 660 | 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 | } | 661 | } |
669 | 662 | ||
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); | 663 | ext4_fname_crypto_free_buffer(&tmp); |
676 | return ret; | 664 | return ret; |
677 | } | 665 | } |
678 | 666 | ||
679 | /** | 667 | 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 | 668 | int len, const char * const name, |
681 | */ | 669 | 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 | { | 670 | { |
686 | struct ext4_str iname = {.name = (unsigned char *) de->name, | 671 | int ret = -ENOENT; |
687 | .len = de->name_len}; | 672 | int bigname = (*name == '_'); |
688 | struct ext4_str tmp; | ||
689 | int ret; | ||
690 | 673 | ||
691 | if (!ctx || | 674 | if (ctx->has_valid_key) { |
692 | ((iname.name[0] == '.') && | 675 | if (cstr->name == NULL) { |
693 | ((iname.len == 1) || | 676 | struct qstr istr; |
694 | ((iname.name[1] == '.') && (iname.len == 2))))) { | 677 | |
695 | ext4fs_dirhash(iname.name, iname.len, hinfo); | 678 | ret = ext4_fname_crypto_alloc_buffer(ctx, len, cstr); |
696 | return 0; | 679 | if (ret < 0) |
680 | goto errout; | ||
681 | istr.name = name; | ||
682 | istr.len = len; | ||
683 | ret = ext4_fname_encrypt(ctx, &istr, cstr); | ||
684 | if (ret < 0) | ||
685 | goto errout; | ||
686 | } | ||
687 | } else { | ||
688 | if (cstr->name == NULL) { | ||
689 | cstr->name = kmalloc(32, GFP_KERNEL); | ||
690 | if (cstr->name == NULL) | ||
691 | return -ENOMEM; | ||
692 | if ((bigname && (len != 33)) || | ||
693 | (!bigname && (len > 43))) | ||
694 | goto errout; | ||
695 | ret = digest_decode(name+bigname, len-bigname, | ||
696 | cstr->name); | ||
697 | if (ret < 0) { | ||
698 | ret = -ENOENT; | ||
699 | goto errout; | ||
700 | } | ||
701 | cstr->len = ret; | ||
702 | } | ||
703 | if (bigname) { | ||
704 | if (de->name_len < 16) | ||
705 | return 0; | ||
706 | ret = memcmp(de->name + de->name_len - 16, | ||
707 | cstr->name + 8, 16); | ||
708 | return (ret == 0) ? 1 : 0; | ||
709 | } | ||
697 | } | 710 | } |
698 | 711 | if (de->name_len != cstr->len) | |
699 | tmp.len = (4 * ((EXT4_FNAME_CRYPTO_DIGEST_SIZE + 2) / 3)) + 1; | 712 | return 0; |
700 | tmp.name = kmalloc(tmp.len + 1, GFP_KERNEL); | 713 | ret = memcmp(de->name, cstr->name, cstr->len); |
701 | if (tmp.name == NULL) | 714 | return (ret == 0) ? 1 : 0; |
702 | return -ENOMEM; | 715 | errout: |
703 | 716 | kfree(cstr->name); | |
704 | ret = ext4_fname_hash(ctx, &iname, &tmp); | 717 | 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; | 718 | return ret; |
709 | } | 719 | } |
diff --git a/fs/ext4/crypto_key.c b/fs/ext4/crypto_key.c index c8392af8abbb..52170d0b7c40 100644 --- a/fs/ext4/crypto_key.c +++ b/fs/ext4/crypto_key.c | |||
@@ -110,6 +110,7 @@ int ext4_generate_encryption_key(struct inode *inode) | |||
110 | } | 110 | } |
111 | res = 0; | 111 | res = 0; |
112 | 112 | ||
113 | ei->i_crypt_policy_flags = ctx.flags; | ||
113 | if (S_ISREG(inode->i_mode)) | 114 | if (S_ISREG(inode->i_mode)) |
114 | crypt_key->mode = ctx.contents_encryption_mode; | 115 | crypt_key->mode = ctx.contents_encryption_mode; |
115 | else if (S_ISDIR(inode->i_mode) || S_ISLNK(inode->i_mode)) | 116 | else if (S_ISDIR(inode->i_mode) || S_ISLNK(inode->i_mode)) |
diff --git a/fs/ext4/crypto_policy.c b/fs/ext4/crypto_policy.c index 30eaf9e9864a..a6d6291aea16 100644 --- a/fs/ext4/crypto_policy.c +++ b/fs/ext4/crypto_policy.c | |||
@@ -37,6 +37,8 @@ static int ext4_is_encryption_context_consistent_with_policy( | |||
37 | return 0; | 37 | return 0; |
38 | return (memcmp(ctx.master_key_descriptor, policy->master_key_descriptor, | 38 | return (memcmp(ctx.master_key_descriptor, policy->master_key_descriptor, |
39 | EXT4_KEY_DESCRIPTOR_SIZE) == 0 && | 39 | EXT4_KEY_DESCRIPTOR_SIZE) == 0 && |
40 | (ctx.flags == | ||
41 | policy->flags) && | ||
40 | (ctx.contents_encryption_mode == | 42 | (ctx.contents_encryption_mode == |
41 | policy->contents_encryption_mode) && | 43 | policy->contents_encryption_mode) && |
42 | (ctx.filenames_encryption_mode == | 44 | (ctx.filenames_encryption_mode == |
@@ -56,25 +58,25 @@ static int ext4_create_encryption_context_from_policy( | |||
56 | printk(KERN_WARNING | 58 | printk(KERN_WARNING |
57 | "%s: Invalid contents encryption mode %d\n", __func__, | 59 | "%s: Invalid contents encryption mode %d\n", __func__, |
58 | policy->contents_encryption_mode); | 60 | policy->contents_encryption_mode); |
59 | res = -EINVAL; | 61 | return -EINVAL; |
60 | goto out; | ||
61 | } | 62 | } |
62 | if (!ext4_valid_filenames_enc_mode(policy->filenames_encryption_mode)) { | 63 | if (!ext4_valid_filenames_enc_mode(policy->filenames_encryption_mode)) { |
63 | printk(KERN_WARNING | 64 | printk(KERN_WARNING |
64 | "%s: Invalid filenames encryption mode %d\n", __func__, | 65 | "%s: Invalid filenames encryption mode %d\n", __func__, |
65 | policy->filenames_encryption_mode); | 66 | policy->filenames_encryption_mode); |
66 | res = -EINVAL; | 67 | return -EINVAL; |
67 | goto out; | ||
68 | } | 68 | } |
69 | if (policy->flags & ~EXT4_POLICY_FLAGS_VALID) | ||
70 | return -EINVAL; | ||
69 | ctx.contents_encryption_mode = policy->contents_encryption_mode; | 71 | ctx.contents_encryption_mode = policy->contents_encryption_mode; |
70 | ctx.filenames_encryption_mode = policy->filenames_encryption_mode; | 72 | ctx.filenames_encryption_mode = policy->filenames_encryption_mode; |
73 | ctx.flags = policy->flags; | ||
71 | BUILD_BUG_ON(sizeof(ctx.nonce) != EXT4_KEY_DERIVATION_NONCE_SIZE); | 74 | BUILD_BUG_ON(sizeof(ctx.nonce) != EXT4_KEY_DERIVATION_NONCE_SIZE); |
72 | get_random_bytes(ctx.nonce, EXT4_KEY_DERIVATION_NONCE_SIZE); | 75 | get_random_bytes(ctx.nonce, EXT4_KEY_DERIVATION_NONCE_SIZE); |
73 | 76 | ||
74 | res = ext4_xattr_set(inode, EXT4_XATTR_INDEX_ENCRYPTION, | 77 | res = ext4_xattr_set(inode, EXT4_XATTR_INDEX_ENCRYPTION, |
75 | EXT4_XATTR_NAME_ENCRYPTION_CONTEXT, &ctx, | 78 | EXT4_XATTR_NAME_ENCRYPTION_CONTEXT, &ctx, |
76 | sizeof(ctx), 0); | 79 | sizeof(ctx), 0); |
77 | out: | ||
78 | if (!res) | 80 | if (!res) |
79 | ext4_set_inode_flag(inode, EXT4_INODE_ENCRYPT); | 81 | ext4_set_inode_flag(inode, EXT4_INODE_ENCRYPT); |
80 | return res; | 82 | return res; |
@@ -115,6 +117,7 @@ int ext4_get_policy(struct inode *inode, struct ext4_encryption_policy *policy) | |||
115 | policy->version = 0; | 117 | policy->version = 0; |
116 | policy->contents_encryption_mode = ctx.contents_encryption_mode; | 118 | policy->contents_encryption_mode = ctx.contents_encryption_mode; |
117 | policy->filenames_encryption_mode = ctx.filenames_encryption_mode; | 119 | policy->filenames_encryption_mode = ctx.filenames_encryption_mode; |
120 | policy->flags = ctx.flags; | ||
118 | memcpy(&policy->master_key_descriptor, ctx.master_key_descriptor, | 121 | memcpy(&policy->master_key_descriptor, ctx.master_key_descriptor, |
119 | EXT4_KEY_DESCRIPTOR_SIZE); | 122 | EXT4_KEY_DESCRIPTOR_SIZE); |
120 | return 0; | 123 | return 0; |
@@ -176,6 +179,7 @@ int ext4_inherit_context(struct inode *parent, struct inode *child) | |||
176 | EXT4_ENCRYPTION_MODE_AES_256_XTS; | 179 | EXT4_ENCRYPTION_MODE_AES_256_XTS; |
177 | ctx.filenames_encryption_mode = | 180 | ctx.filenames_encryption_mode = |
178 | EXT4_ENCRYPTION_MODE_AES_256_CTS; | 181 | EXT4_ENCRYPTION_MODE_AES_256_CTS; |
182 | ctx.flags = 0; | ||
179 | memset(ctx.master_key_descriptor, 0x42, | 183 | memset(ctx.master_key_descriptor, 0x42, |
180 | EXT4_KEY_DESCRIPTOR_SIZE); | 184 | EXT4_KEY_DESCRIPTOR_SIZE); |
181 | res = 0; | 185 | res = 0; |
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 ef267adce19a..009a0590b20f 100644 --- a/fs/ext4/ext4.h +++ b/fs/ext4/ext4.h | |||
@@ -911,6 +911,7 @@ struct ext4_inode_info { | |||
911 | 911 | ||
912 | /* on-disk additional length */ | 912 | /* on-disk additional length */ |
913 | __u16 i_extra_isize; | 913 | __u16 i_extra_isize; |
914 | char i_crypt_policy_flags; | ||
914 | 915 | ||
915 | /* Indicate the inline data space. */ | 916 | /* Indicate the inline data space. */ |
916 | u16 i_inline_off; | 917 | u16 i_inline_off; |
@@ -1066,12 +1067,6 @@ extern void ext4_set_bits(void *bm, int cur, int len); | |||
1066 | /* Metadata checksum algorithm codes */ | 1067 | /* Metadata checksum algorithm codes */ |
1067 | #define EXT4_CRC32C_CHKSUM 1 | 1068 | #define EXT4_CRC32C_CHKSUM 1 |
1068 | 1069 | ||
1069 | /* Encryption algorithms */ | ||
1070 | #define EXT4_ENCRYPTION_MODE_INVALID 0 | ||
1071 | #define EXT4_ENCRYPTION_MODE_AES_256_XTS 1 | ||
1072 | #define EXT4_ENCRYPTION_MODE_AES_256_GCM 2 | ||
1073 | #define EXT4_ENCRYPTION_MODE_AES_256_CBC 3 | ||
1074 | |||
1075 | /* | 1070 | /* |
1076 | * Structure of the super block | 1071 | * Structure of the super block |
1077 | */ | 1072 | */ |
@@ -2093,9 +2088,11 @@ u32 ext4_fname_crypto_round_up(u32 size, u32 blksize); | |||
2093 | int ext4_fname_crypto_alloc_buffer(struct ext4_fname_crypto_ctx *ctx, | 2088 | int ext4_fname_crypto_alloc_buffer(struct ext4_fname_crypto_ctx *ctx, |
2094 | u32 ilen, struct ext4_str *crypto_str); | 2089 | u32 ilen, struct ext4_str *crypto_str); |
2095 | int _ext4_fname_disk_to_usr(struct ext4_fname_crypto_ctx *ctx, | 2090 | int _ext4_fname_disk_to_usr(struct ext4_fname_crypto_ctx *ctx, |
2091 | struct dx_hash_info *hinfo, | ||
2096 | const struct ext4_str *iname, | 2092 | const struct ext4_str *iname, |
2097 | struct ext4_str *oname); | 2093 | struct ext4_str *oname); |
2098 | int ext4_fname_disk_to_usr(struct ext4_fname_crypto_ctx *ctx, | 2094 | int ext4_fname_disk_to_usr(struct ext4_fname_crypto_ctx *ctx, |
2095 | struct dx_hash_info *hinfo, | ||
2099 | const struct ext4_dir_entry_2 *de, | 2096 | const struct ext4_dir_entry_2 *de, |
2100 | struct ext4_str *oname); | 2097 | struct ext4_str *oname); |
2101 | int ext4_fname_usr_to_disk(struct ext4_fname_crypto_ctx *ctx, | 2098 | int ext4_fname_usr_to_disk(struct ext4_fname_crypto_ctx *ctx, |
@@ -2104,11 +2101,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, | 2101 | int ext4_fname_usr_to_hash(struct ext4_fname_crypto_ctx *ctx, |
2105 | const struct qstr *iname, | 2102 | const struct qstr *iname, |
2106 | struct dx_hash_info *hinfo); | 2103 | 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, | 2104 | int ext4_fname_crypto_namelen_on_disk(struct ext4_fname_crypto_ctx *ctx, |
2111 | u32 namelen); | 2105 | u32 namelen); |
2106 | int ext4_fname_match(struct ext4_fname_crypto_ctx *ctx, struct ext4_str *cstr, | ||
2107 | int len, const char * const name, | ||
2108 | struct ext4_dir_entry_2 *de); | ||
2109 | |||
2112 | 2110 | ||
2113 | #ifdef CONFIG_EXT4_FS_ENCRYPTION | 2111 | #ifdef CONFIG_EXT4_FS_ENCRYPTION |
2114 | void ext4_put_fname_crypto_ctx(struct ext4_fname_crypto_ctx **ctx); | 2112 | void ext4_put_fname_crypto_ctx(struct ext4_fname_crypto_ctx **ctx); |
diff --git a/fs/ext4/ext4_crypto.h b/fs/ext4/ext4_crypto.h index c2ba35a914b6..d75159c101ce 100644 --- a/fs/ext4/ext4_crypto.h +++ b/fs/ext4/ext4_crypto.h | |||
@@ -20,12 +20,20 @@ struct ext4_encryption_policy { | |||
20 | char version; | 20 | char version; |
21 | char contents_encryption_mode; | 21 | char contents_encryption_mode; |
22 | char filenames_encryption_mode; | 22 | char filenames_encryption_mode; |
23 | char flags; | ||
23 | char master_key_descriptor[EXT4_KEY_DESCRIPTOR_SIZE]; | 24 | char master_key_descriptor[EXT4_KEY_DESCRIPTOR_SIZE]; |
24 | } __attribute__((__packed__)); | 25 | } __attribute__((__packed__)); |
25 | 26 | ||
26 | #define EXT4_ENCRYPTION_CONTEXT_FORMAT_V1 1 | 27 | #define EXT4_ENCRYPTION_CONTEXT_FORMAT_V1 1 |
27 | #define EXT4_KEY_DERIVATION_NONCE_SIZE 16 | 28 | #define EXT4_KEY_DERIVATION_NONCE_SIZE 16 |
28 | 29 | ||
30 | #define EXT4_POLICY_FLAGS_PAD_4 0x00 | ||
31 | #define EXT4_POLICY_FLAGS_PAD_8 0x01 | ||
32 | #define EXT4_POLICY_FLAGS_PAD_16 0x02 | ||
33 | #define EXT4_POLICY_FLAGS_PAD_32 0x03 | ||
34 | #define EXT4_POLICY_FLAGS_PAD_MASK 0x03 | ||
35 | #define EXT4_POLICY_FLAGS_VALID 0x03 | ||
36 | |||
29 | /** | 37 | /** |
30 | * Encryption context for inode | 38 | * Encryption context for inode |
31 | * | 39 | * |
@@ -41,7 +49,7 @@ struct ext4_encryption_context { | |||
41 | char format; | 49 | char format; |
42 | char contents_encryption_mode; | 50 | char contents_encryption_mode; |
43 | char filenames_encryption_mode; | 51 | char filenames_encryption_mode; |
44 | char reserved; | 52 | char flags; |
45 | char master_key_descriptor[EXT4_KEY_DESCRIPTOR_SIZE]; | 53 | char master_key_descriptor[EXT4_KEY_DESCRIPTOR_SIZE]; |
46 | char nonce[EXT4_KEY_DERIVATION_NONCE_SIZE]; | 54 | char nonce[EXT4_KEY_DERIVATION_NONCE_SIZE]; |
47 | } __attribute__((__packed__)); | 55 | } __attribute__((__packed__)); |
@@ -120,6 +128,7 @@ struct ext4_fname_crypto_ctx { | |||
120 | struct crypto_hash *htfm; | 128 | struct crypto_hash *htfm; |
121 | struct page *workpage; | 129 | struct page *workpage; |
122 | struct ext4_encryption_key key; | 130 | struct ext4_encryption_key key; |
131 | unsigned flags : 8; | ||
123 | unsigned has_valid_key : 1; | 132 | unsigned has_valid_key : 1; |
124 | unsigned ctfm_key_is_ready : 1; | 133 | unsigned ctfm_key_is_ready : 1; |
125 | }; | 134 | }; |
diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c index 973816bfe4a9..d74e08029643 100644 --- a/fs/ext4/extents.c +++ b/fs/ext4/extents.c | |||
@@ -4927,13 +4927,6 @@ long ext4_fallocate(struct file *file, int mode, loff_t offset, loff_t len) | |||
4927 | if (ret) | 4927 | if (ret) |
4928 | return ret; | 4928 | return ret; |
4929 | 4929 | ||
4930 | /* | ||
4931 | * currently supporting (pre)allocate mode for extent-based | ||
4932 | * files _only_ | ||
4933 | */ | ||
4934 | if (!(ext4_test_inode_flag(inode, EXT4_INODE_EXTENTS))) | ||
4935 | return -EOPNOTSUPP; | ||
4936 | |||
4937 | if (mode & FALLOC_FL_COLLAPSE_RANGE) | 4930 | if (mode & FALLOC_FL_COLLAPSE_RANGE) |
4938 | return ext4_collapse_range(inode, offset, len); | 4931 | return ext4_collapse_range(inode, offset, len); |
4939 | 4932 | ||
@@ -4955,6 +4948,14 @@ long ext4_fallocate(struct file *file, int mode, loff_t offset, loff_t len) | |||
4955 | 4948 | ||
4956 | mutex_lock(&inode->i_mutex); | 4949 | mutex_lock(&inode->i_mutex); |
4957 | 4950 | ||
4951 | /* | ||
4952 | * We only support preallocation for extent-based files only | ||
4953 | */ | ||
4954 | if (!(ext4_test_inode_flag(inode, EXT4_INODE_EXTENTS))) { | ||
4955 | ret = -EOPNOTSUPP; | ||
4956 | goto out; | ||
4957 | } | ||
4958 | |||
4958 | if (!(mode & FALLOC_FL_KEEP_SIZE) && | 4959 | if (!(mode & FALLOC_FL_KEEP_SIZE) && |
4959 | offset + len > i_size_read(inode)) { | 4960 | offset + len > i_size_read(inode)) { |
4960 | new_size = offset + len; | 4961 | new_size = offset + len; |
diff --git a/fs/ext4/extents_status.c b/fs/ext4/extents_status.c index d33d5a6852b9..26724aeece73 100644 --- a/fs/ext4/extents_status.c +++ b/fs/ext4/extents_status.c | |||
@@ -703,6 +703,14 @@ int ext4_es_insert_extent(struct inode *inode, ext4_lblk_t lblk, | |||
703 | 703 | ||
704 | BUG_ON(end < lblk); | 704 | BUG_ON(end < lblk); |
705 | 705 | ||
706 | if ((status & EXTENT_STATUS_DELAYED) && | ||
707 | (status & EXTENT_STATUS_WRITTEN)) { | ||
708 | ext4_warning(inode->i_sb, "Inserting extent [%u/%u] as " | ||
709 | " delayed and written which can potentially " | ||
710 | " cause data loss.\n", lblk, len); | ||
711 | WARN_ON(1); | ||
712 | } | ||
713 | |||
706 | newes.es_lblk = lblk; | 714 | newes.es_lblk = lblk; |
707 | newes.es_len = len; | 715 | newes.es_len = len; |
708 | ext4_es_store_pblock_status(&newes, pblk, status); | 716 | ext4_es_store_pblock_status(&newes, pblk, status); |
diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c index cbd0654a2675..55b187c3bac1 100644 --- a/fs/ext4/inode.c +++ b/fs/ext4/inode.c | |||
@@ -531,6 +531,7 @@ int ext4_map_blocks(handle_t *handle, struct inode *inode, | |||
531 | status = map->m_flags & EXT4_MAP_UNWRITTEN ? | 531 | status = map->m_flags & EXT4_MAP_UNWRITTEN ? |
532 | EXTENT_STATUS_UNWRITTEN : EXTENT_STATUS_WRITTEN; | 532 | EXTENT_STATUS_UNWRITTEN : EXTENT_STATUS_WRITTEN; |
533 | if (!(flags & EXT4_GET_BLOCKS_DELALLOC_RESERVE) && | 533 | if (!(flags & EXT4_GET_BLOCKS_DELALLOC_RESERVE) && |
534 | !(status & EXTENT_STATUS_WRITTEN) && | ||
534 | ext4_find_delalloc_range(inode, map->m_lblk, | 535 | ext4_find_delalloc_range(inode, map->m_lblk, |
535 | map->m_lblk + map->m_len - 1)) | 536 | map->m_lblk + map->m_len - 1)) |
536 | status |= EXTENT_STATUS_DELAYED; | 537 | status |= EXTENT_STATUS_DELAYED; |
@@ -635,6 +636,7 @@ found: | |||
635 | status = map->m_flags & EXT4_MAP_UNWRITTEN ? | 636 | status = map->m_flags & EXT4_MAP_UNWRITTEN ? |
636 | EXTENT_STATUS_UNWRITTEN : EXTENT_STATUS_WRITTEN; | 637 | EXTENT_STATUS_UNWRITTEN : EXTENT_STATUS_WRITTEN; |
637 | if (!(flags & EXT4_GET_BLOCKS_DELALLOC_RESERVE) && | 638 | if (!(flags & EXT4_GET_BLOCKS_DELALLOC_RESERVE) && |
639 | !(status & EXTENT_STATUS_WRITTEN) && | ||
638 | ext4_find_delalloc_range(inode, map->m_lblk, | 640 | ext4_find_delalloc_range(inode, map->m_lblk, |
639 | map->m_lblk + map->m_len - 1)) | 641 | map->m_lblk + map->m_len - 1)) |
640 | status |= EXTENT_STATUS_DELAYED; | 642 | status |= EXTENT_STATUS_DELAYED; |
diff --git a/fs/ext4/namei.c b/fs/ext4/namei.c index 7223b0b4bc38..814f3beb4369 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/resize.c b/fs/ext4/resize.c index 8a8ec6293b19..cf0c472047e3 100644 --- a/fs/ext4/resize.c +++ b/fs/ext4/resize.c | |||
@@ -1432,12 +1432,15 @@ static int ext4_flex_group_add(struct super_block *sb, | |||
1432 | goto exit; | 1432 | goto exit; |
1433 | /* | 1433 | /* |
1434 | * We will always be modifying at least the superblock and GDT | 1434 | * We will always be modifying at least the superblock and GDT |
1435 | * block. If we are adding a group past the last current GDT block, | 1435 | * blocks. If we are adding a group past the last current GDT block, |
1436 | * we will also modify the inode and the dindirect block. If we | 1436 | * we will also modify the inode and the dindirect block. If we |
1437 | * are adding a group with superblock/GDT backups we will also | 1437 | * are adding a group with superblock/GDT backups we will also |
1438 | * modify each of the reserved GDT dindirect blocks. | 1438 | * modify each of the reserved GDT dindirect blocks. |
1439 | */ | 1439 | */ |
1440 | credit = flex_gd->count * 4 + reserved_gdb; | 1440 | credit = 3; /* sb, resize inode, resize inode dindirect */ |
1441 | /* GDT blocks */ | ||
1442 | credit += 1 + DIV_ROUND_UP(flex_gd->count, EXT4_DESC_PER_BLOCK(sb)); | ||
1443 | credit += reserved_gdb; /* Reserved GDT dindirect blocks */ | ||
1441 | handle = ext4_journal_start_sb(sb, EXT4_HT_RESIZE, credit); | 1444 | handle = ext4_journal_start_sb(sb, EXT4_HT_RESIZE, credit); |
1442 | if (IS_ERR(handle)) { | 1445 | if (IS_ERR(handle)) { |
1443 | err = PTR_ERR(handle); | 1446 | err = PTR_ERR(handle); |
diff --git a/fs/ext4/symlink.c b/fs/ext4/symlink.c index 19f78f20975e..187b78920314 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 */ |