Whamcloud - gitweb
LU-4708 ldiskfs: do not copy NUL terminator from direntry
[fs/lustre-release.git] / ldiskfs / kernel_patches / patches / sles11sp2 / revert-ext4-avoid-uninitialized-memory-references-in-ext3_htree_next_block.patch
1 From: Jeff Mahoney <jeffm@suse.com>
2 Subject: revert: ext4: avoid uninitialized memory references in ext3_htree_next_block()
3
4 The data in dirent code depends on being able to store data in the
5 .. entry.  We need to revert this commit because it will skip the dx
6 lookup on . and ..
7
8   Original commit message:
9   ---->8----
10   From: Theodore Ts'o <tytso@mit.edu>
11   Date: Wed, 27 Oct 2010 21:30:08 -0400
12   Subject: ext4: avoid uninitialized memory references in ext3_htree_next_block()
13   Git-commit: 8941ec8b
14   Patch-mainline: v2.6.37-rc1
15
16   If the first block of htree directory is missing '.' or '..' but is
17   otherwise a valid directory, and we do a lookup for '.' or '..', it's
18   possible to dereference an uninitialized memory pointer in
19   ext4_htree_next_block().
20
21   We avoid this by moving the special case from ext4_dx_find_entry() to
22   ext4_find_entry(); this also means we can optimize ext4_find_entry()
23   slightly when NFS looks up "..".
24
25   Thanks to Brad Spengler for pointing a Clang warning that led me to
26   look more closely at this code.  The warning was harmless, but it was
27   useful in pointing out code that was too ugly to live.  This warning was
28   also reported by Roman Borisov.
29
30   Signed-off-by: "Theodore Ts'o" <tytso@mit.edu>
31   Cc: Brad Spengler <spender@grsecurity.net>
32   ----8<----
33
34 Signed-off-by: Jeff Mahoney <jeffm@suse.com>
35 --
36
37  fs/ext4/namei.c |   32 +++++++++++++++++---------------
38  1 file changed, 17 insertions(+), 15 deletions(-)
39
40 --- a/fs/ext4/namei.c
41 +++ b/fs/ext4/namei.c
42 @@ -857,7 +857,6 @@ static struct buffer_head * ext4_find_en
43         struct buffer_head *bh_use[NAMEI_RA_SIZE];
44         struct buffer_head *bh, *ret = NULL;
45         ext4_lblk_t start, block, b;
46 -       const u8 *name = d_name->name;
47         int ra_max = 0;         /* Number of bh's in the readahead
48                                    buffer, bh_use[] */
49         int ra_ptr = 0;         /* Current index into readahead
50 @@ -872,16 +871,6 @@ static struct buffer_head * ext4_find_en
51         namelen = d_name->len;
52         if (namelen > EXT4_NAME_LEN)
53                 return NULL;
54 -       if ((namelen <= 2) && (name[0] == '.') &&
55 -           (name[1] == '.' || name[1] == '\0')) {
56 -               /*
57 -                * "." or ".." will only be in the first block
58 -                * NFS may look up ".."; "." should be handled by the VFS
59 -                */
60 -               block = start = 0;
61 -               nblocks = 1;
62 -               goto restart;
63 -       }
64         if (is_dx(dir)) {
65                 bh = ext4_dx_find_entry(dir, d_name, res_dir, &err);
66                 /*
67 @@ -972,15 +961,28 @@ cleanup_and_exit:
68  static struct buffer_head * ext4_dx_find_entry(struct inode *dir, const struct qstr *d_name,
69                        struct ext4_dir_entry_2 **res_dir, int *err)
70  {
71 -       struct super_block * sb = dir->i_sb;
72 +       struct super_block * sb;
73         struct dx_hash_info     hinfo;
74 +       u32 hash;
75         struct dx_frame frames[2], *frame;
76         struct buffer_head *bh;
77         ext4_lblk_t block;
78         int retval;
79 +       int namelen = d_name->len;
80 +       const u8 *name = d_name->name;
81
82 -       if (!(frame = dx_probe(d_name, dir, &hinfo, frames, err)))
83 -               return NULL;
84 +       sb = dir->i_sb;
85 +       /* NFS may look up ".." - look at dx_root directory block */
86 +       if (namelen > 2 || name[0] != '.'||(name[1] != '.' && name[1] != '\0')){
87 +               if (!(frame = dx_probe(d_name, dir, &hinfo, frames, err)))
88 +                       return NULL;
89 +       } else {
90 +               frame = frames;
91 +               frame->bh = NULL;                       /* for dx_release() */
92 +               frame->at = (struct dx_entry *)frames;  /* hack for zero entry*/
93 +               dx_set_block(frame->at, 0);             /* dx_root block is 0 */
94 +       }
95 +       hash = hinfo.hash;
96         do {
97                 block = dx_get_block(frame->at);
98                 if (!(bh = ext4_bread(NULL, dir, block, 0, err)))
99 @@ -1000,7 +1002,7 @@ static struct buffer_head * ext4_dx_find
100                 }
101
102                 /* Check to see if we should continue to search */
103 -               retval = ext4_htree_next_block(dir, hinfo.hash, frame,
104 +               retval = ext4_htree_next_block(dir, hash, frame,
105                                                frames, NULL);
106                 if (retval < 0) {
107                         ext4_warning(sb,