Whamcloud - gitweb
LU-4708 ldiskfs: do not copy NUL terminator from direntry 10/9510/2
authorAndreas Dilger <andreas.dilger@intel.com>
Wed, 5 Mar 2014 18:59:30 +0000 (11:59 -0700)
committerOleg Drokin <oleg.drokin@intel.com>
Mon, 10 Mar 2014 23:51:15 +0000 (23:51 +0000)
Do not try to copy a NUL terminator from the source dirent if there
is no dir_data for that record.  This can happen with 1.x filesystems
that do not have a dirdata field in the dirent to store the FID.

The target buffer is expected to be NUL terminated, and this is
handled by using kzalloc() to allocate it and zero out the buffer,
but the source buffer may not have a trailing NUL byte if it is a
multiple of 4 bytes in length.

If the dirent is aligned at the end of the directory block/page this
can cause an oops by accessing beyond the end of the page, or will
otherwise copy a garbage byte to the target buffer.

Signed-off-by: Andreas Dilger <andreas.dilger@intel.com>
Change-Id: Iab52f916d7571b3d2587255280c72a52c60399c9
Reviewed-on: http://review.whamcloud.com/9510
Tested-by: Jenkins
Reviewed-by: Niu Yawei <yawei.niu@intel.com>
Tested-by: Maloo <hpdd-maloo@intel.com>
Reviewed-by: Fan Yong <fan.yong@intel.com>
Reviewed-by: Oleg Drokin <oleg.drokin@intel.com>
ldiskfs/kernel_patches/patches/rhel6.3/ext4-data-in-dirent.patch
ldiskfs/kernel_patches/patches/sles11sp2/ext4-data-in-dirent.patch

index b534162..ae8e51e 100644 (file)
@@ -57,7 +57,7 @@ changes in ext4_add_entry() interface required.
        struct fname *fname, *new_fn;
        struct dir_private_info *info;
        int len;
-+      int extra_data = 1;
++      int extra_data = 0;
  
        info = (struct dir_private_info *) dir_file->private_data;
        p = &info->root.rb_node;
@@ -67,7 +67,7 @@ changes in ext4_add_entry() interface required.
 +      if (dirent->file_type & EXT4_DIRENT_LUFID)
 +              extra_data = ext4_get_dirent_data_len(dirent);
 +
-+      len = sizeof(struct fname) + dirent->name_len + extra_data;
++      len = sizeof(struct fname) + dirent->name_len + extra_data + 1;
 +
        new_fn = kzalloc(len, GFP_KERNEL);
        if (!new_fn)
index ac76bf9..fa8f7ca 100644 (file)
@@ -54,7 +54,7 @@
        struct fname *fname, *new_fn;
        struct dir_private_info *info;
        int len;
-+      int extra_data = 1;
++      int extra_data = 0;
  
        info = dir_file->private_data;
        p = &info->root.rb_node;
@@ -64,7 +64,7 @@
 +      if (dirent->file_type & EXT4_DIRENT_LUFID)
 +              extra_data = ext4_get_dirent_data_len(dirent);
 +
-+      len = sizeof(struct fname) + dirent->name_len + extra_data;
++      len = sizeof(struct fname) + dirent->name_len + extra_data + 1;
 +
        new_fn = kzalloc(len, GFP_KERNEL);
        if (!new_fn)