In ext2fs_inline_data_dir_iterate(), we must be very careful to undo
any modifications we make to the dir_context pointer passed in by the
caller, because it's entirely possible that the caller will still want
to do something with the ctx or something inside.
Specifically, ext2fs_dblist_dir_iterate() wants to be able to free
ctx->buf, and it reuses the ctx for multiple dblist entries. That
means that assigning ctx->buf will cause weird crashes at the end of
dir_iterate().
Since we're being careful with ctx, we might as well handle adding the
INLINE_DATA flag to ctx->flags for ext2fs_process_dir_block, since the
dblist caller forgets to unset the flag before reusing the ctx.
This fixes some crashes and valgrind complaints in resize2fs, and is
necessary for the next patch, which fixes resize2fs not to corrupt
inline_data filesystems.
Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
Signed-off-by: "Theodore Ts'o" <tytso@mit.edu>
ctx->errcode = ext2fs_read_inode(fs, ctx->dir, &inode);
if (ctx->errcode)
return DBLIST_ABORT;
- if (inode.i_flags & EXT4_INLINE_DATA_FL) {
- ctx->flags = DIRENT_FLAG_INCLUDE_INLINE_DATA;
+ if (inode.i_flags & EXT4_INLINE_DATA_FL)
ret = ext2fs_inline_data_dir_iterate(fs, ctx->dir, ctx);
- } else {
+ else
ret = ext2fs_process_dir_block(fs, &db_info->blk,
db_info->blockcnt, 0, 0,
priv_data);
- }
if ((ret & BLOCK_ABORT) && !ctx->errcode)
return DBLIST_ABORT;
return 0;
if (!block_buf)
ext2fs_free_mem(&ctx.buf);
if (retval == EXT2_ET_INLINE_DATA_CANT_ITERATE) {
- ctx.flags |= DIRENT_FLAG_INCLUDE_INLINE_DATA;
(void) ext2fs_inline_data_dir_iterate(fs, dir, &ctx);
retval = 0;
}
struct ext2_inline_data data;
int ret = BLOCK_ABORT;
e2_blkcnt_t blockcnt = 0;
+ char *old_buf;
+ unsigned int old_buflen;
+ int old_flags;
ctx = (struct dir_context *)priv_data;
+ old_buf = ctx->buf;
+ old_buflen = ctx->buflen;
+ old_flags = ctx->flags;
+ ctx->flags |= DIRENT_FLAG_INCLUDE_INLINE_DATA;
ctx->errcode = ext2fs_read_inode(fs, ino, &inode);
if (ctx->errcode)
out1:
ext2fs_free_mem(&data.ea_data);
- ctx->buf = 0;
-
out:
+ ctx->buf = old_buf;
+ ctx->buflen = old_buflen;
+ ctx->flags = old_flags;
ret &= ~(BLOCK_ABORT | BLOCK_INLINE_DATA_CHANGED);
return ret;
}