diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h index 44b0d418143c..dbd062f80c22 100644 --- a/fs/ext4/ext4.h +++ b/fs/ext4/ext4.h @@ -2834,7 +2834,7 @@ extern int ext4_find_dest_de(struct inode *dir, struct inode *inode, void *buf, int buf_size, struct ext4_filename *fname, struct ext4_dir_entry_2 **dest_de); -void ext4_insert_dentry(struct inode *dir, struct inode *inode, +int ext4_insert_dentry(struct inode *dir, struct inode *inode, struct ext4_dir_entry_2 *de, int buf_size, struct ext4_filename *fname); diff --git a/fs/ext4/inline.c b/fs/ext4/inline.c index 3536ca7e4fcc..e318b13459d1 100644 --- a/fs/ext4/inline.c +++ b/fs/ext4/inline.c @@ -1022,7 +1022,9 @@ static int ext4_add_dirent_to_inline(handle_t *handle, EXT4_JTR_NONE); if (err) return err; - ext4_insert_dentry(dir, inode, de, inline_size, fname); + err = ext4_insert_dentry(dir, inode, de, inline_size, fname); + if (err) + return err; ext4_show_inline_dir(dir, iloc->bh, inline_start, inline_size); diff --git a/fs/ext4/namei.c b/fs/ext4/namei.c index 790db7eac6c2..4ce1b207a4c0 100644 --- a/fs/ext4/namei.c +++ b/fs/ext4/namei.c @@ -2084,24 +2084,38 @@ int ext4_find_dest_de(struct inode *dir, struct inode *inode, return 0; } -void ext4_insert_dentry(struct inode *dir, +int ext4_check_next_dentry(struct inode *dir, struct inode *inode, struct ext4_dir_entry_2 *de, int buf_size, struct ext4_filename *fname) { - int nlen, rlen; nlen = ext4_dir_rec_len(de->name_len, dir); rlen = ext4_rec_len_from_disk(de->rec_len, buf_size); if (de->inode) { - struct ext4_dir_entry_2 *de1 = + struct ext4_dir_entry_2 *nde = (struct ext4_dir_entry_2 *)((char *)de + nlen); - de1->rec_len = ext4_rec_len_to_disk(rlen - nlen, buf_size); + nde->rec_len = ext4_rec_len_to_disk(rlen - nlen, buf_size); de->rec_len = ext4_rec_len_to_disk(nlen, buf_size); - de = de1; + de = nde; + rlen = ext4_rec_len_from_disk(de->rec_len, buf_size); + return fname_len(fname) > rlen - EXT4_BASE_DIR_LEN; } + + return 0; +} + +int ext4_insert_dentry(struct inode *dir, + struct inode *inode, + struct ext4_dir_entry_2 *de, + int buf_size, + struct ext4_filename *fname) +{ + if (ext4_check_next_dentry(dir, inode, de, buf_size, fname)) + return -EINVAL; + de->file_type = EXT4_FT_UNKNOWN; de->inode = cpu_to_le32(inode->i_ino); ext4_set_de_type(inode->i_sb, de, inode->i_mode); @@ -2114,6 +2128,8 @@ void ext4_insert_dentry(struct inode *dir, EXT4_DIRENT_HASHES(de)->minor_hash = cpu_to_le32(hinfo->minor_hash); } + + return 0; } /* @@ -2151,7 +2167,11 @@ static int add_dirent_to_buf(handle_t *handle, struct ext4_filename *fname, } /* By now the buffer is marked for journaling */ - ext4_insert_dentry(dir, inode, de, blocksize, fname); + err = ext4_insert_dentry(dir, inode, de, blocksize, fname); + if (err) { + ext4_std_error(dir->i_sb, err); + return err; + } /* * XXX shouldn't update any times until successful