]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/blame - releases/2.6.31.8/0017-ext4-Fix-wrong-comparisons-in-mext_check_arguments.patch
4.14-stable patches
[thirdparty/kernel/stable-queue.git] / releases / 2.6.31.8 / 0017-ext4-Fix-wrong-comparisons-in-mext_check_arguments.patch
CommitLineData
7f041dd7
GKH
1From 5b927cfba5b756c8f401e30fe2890b22a0b1fbb8 Mon Sep 17 00:00:00 2001
2From: Akira Fujita <a-fujita@rs.jp.nec.com>
3Date: Wed, 16 Sep 2009 14:28:22 -0400
4Subject: [PATCH 17/85] ext4: Fix wrong comparisons in mext_check_arguments()
5
6(cherry picked from commit 70d5d3dcea47c16058d2b093c29e07fdf61b56ad)
7
8The mext_check_arguments() function in move_extents.c has wrong
9comparisons. orig_start which is passed from user-space is block
10unit, but i_size of inode is byte unit, therefore the checks do not
11work fine. This mis-check leads to the overflow of 'len' and then
12hits BUG_ON() in ext4_move_extents(). The patch fixes this issue.
13
14Signed-off-by: Akira Fujita <a-fujita@rs.jp.nec.com>
15Reviewed-by: Greg Freemyer <greg.freemyer@gmail.com>
16Signed-off-by: "Theodore Ts'o" <tytso@mit.edu>
17Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
18---
19 fs/ext4/move_extent.c | 46 +++++++++++++++++++++++++++-------------------
20 1 file changed, 27 insertions(+), 19 deletions(-)
21
22--- a/fs/ext4/move_extent.c
23+++ b/fs/ext4/move_extent.c
24@@ -898,6 +898,10 @@ mext_check_arguments(struct inode *orig_
25 struct inode *donor_inode, __u64 orig_start,
26 __u64 donor_start, __u64 *len, __u64 moved_len)
27 {
28+ ext4_lblk_t orig_blocks, donor_blocks;
29+ unsigned int blkbits = orig_inode->i_blkbits;
30+ unsigned int blocksize = 1 << blkbits;
31+
32 /* Regular file check */
33 if (!S_ISREG(orig_inode->i_mode) || !S_ISREG(donor_inode->i_mode)) {
34 ext4_debug("ext4 move extent: The argument files should be "
35@@ -972,43 +976,47 @@ mext_check_arguments(struct inode *orig_
36 }
37
38 if (orig_inode->i_size > donor_inode->i_size) {
39- if (orig_start >= donor_inode->i_size) {
40+ donor_blocks = (donor_inode->i_size + blocksize - 1) >> blkbits;
41+ /* TODO: eliminate this artificial restriction */
42+ if (orig_start >= donor_blocks) {
43 ext4_debug("ext4 move extent: orig start offset "
44- "[%llu] should be less than donor file size "
45- "[%lld] [ino:orig %lu, donor_inode %lu]\n",
46- orig_start, donor_inode->i_size,
47+ "[%llu] should be less than donor file blocks "
48+ "[%u] [ino:orig %lu, donor %lu]\n",
49+ orig_start, donor_blocks,
50 orig_inode->i_ino, donor_inode->i_ino);
51 return -EINVAL;
52 }
53
54- if (orig_start + *len > donor_inode->i_size) {
55+ /* TODO: eliminate this artificial restriction */
56+ if (orig_start + *len > donor_blocks) {
57 ext4_debug("ext4 move extent: End offset [%llu] should "
58- "be less than donor file size [%lld]."
59- "So adjust length from %llu to %lld "
60+ "be less than donor file blocks [%u]."
61+ "So adjust length from %llu to %llu "
62 "[ino:orig %lu, donor %lu]\n",
63- orig_start + *len, donor_inode->i_size,
64- *len, donor_inode->i_size - orig_start,
65+ orig_start + *len, donor_blocks,
66+ *len, donor_blocks - orig_start,
67 orig_inode->i_ino, donor_inode->i_ino);
68- *len = donor_inode->i_size - orig_start;
69+ *len = donor_blocks - orig_start;
70 }
71 } else {
72- if (orig_start >= orig_inode->i_size) {
73+ orig_blocks = (orig_inode->i_size + blocksize - 1) >> blkbits;
74+ if (orig_start >= orig_blocks) {
75 ext4_debug("ext4 move extent: start offset [%llu] "
76- "should be less than original file size "
77- "[%lld] [inode:orig %lu, donor %lu]\n",
78- orig_start, orig_inode->i_size,
79+ "should be less than original file blocks "
80+ "[%u] [ino:orig %lu, donor %lu]\n",
81+ orig_start, orig_blocks,
82 orig_inode->i_ino, donor_inode->i_ino);
83 return -EINVAL;
84 }
85
86- if (orig_start + *len > orig_inode->i_size) {
87+ if (orig_start + *len > orig_blocks) {
88 ext4_debug("ext4 move extent: Adjust length "
89- "from %llu to %lld. Because it should be "
90- "less than original file size "
91+ "from %llu to %llu. Because it should be "
92+ "less than original file blocks "
93 "[ino:orig %lu, donor %lu]\n",
94- *len, orig_inode->i_size - orig_start,
95+ *len, orig_blocks - orig_start,
96 orig_inode->i_ino, donor_inode->i_ino);
97- *len = orig_inode->i_size - orig_start;
98+ *len = orig_blocks - orig_start;
99 }
100 }
101