xfstest splats

Darrick J. Wong darrick.wong at oracle.com
Wed Apr 30 10:41:06 PDT 2014


On Tue, Apr 29, 2014 at 08:56:04PM +0900, OGAWA Hirofumi wrote:
> "Darrick J. Wong" <darrick.wong at oracle.com> writes:
> 
> > Hi all,
> >
> > I ran xfstests against tux3 on 3.15-rc3, with default options (primarily
> > because I don't know what options exist anyway).  xfstest generic/310 spit out
> > this:
> >
> >  TUX3-fs error (sda): tux_readdir:398: zero length entry at inum 8192, block 15
> 
> This bug was by wrong dir f_pos from 310, and current tux3 behavior is
> error=panic. As a result, it caused of BUG().
> 
> Well, this patch checks pos, and dir entry more (from ext4 checker). And
> additionally, checks f_pos alignment is valid at first.
> 
> And finally, convert from error=panic to just error message if
> readdir().

This fixes the generic/310 problem, thank you!

--D
> 
> [FIXME: If f_pos is invalid, SuSv4 says unspecified behavior. and now,
> skips that block, and continue at next block. What is good behavior?]
> 
> Thanks.
> 
> Signed-off-by: OGAWA Hirofumi <hirofumi at mail.parknet.co.jp>
> ---
> 
>  user/kernel/dir.c  |   47 +++++++++++++++++++++++++++++++++++++++++++----
>  user/kernel/tux3.h |    6 ++++--
>  user/tux3user.h    |    6 ++++--
>  3 files changed, 51 insertions(+), 8 deletions(-)
> 
> diff -puN user/kernel/dir.c~dir-make-robust user/kernel/dir.c
> --- tux3/user/kernel/dir.c~dir-make-robust	2014-04-29 17:56:00.268760455 +0900
> +++ tux3-hirofumi/user/kernel/dir.c	2014-04-29 18:58:44.666310736 +0900
> @@ -363,6 +363,39 @@ static unsigned char filetype[TUX_TYPES]
>  	[TUX_LNK] = DT_LNK,
>  };
>  
> +/*
> + * Return 0 if the directory entry is OK, and 1 if there is a problem
> + */
> +static int __check_dir_entry(const char *func, int line, struct inode *dir,
> +			     struct buffer_head *buffer, tux_dirent *entry)
> +{
> +	struct sb *sb = tux_sb(dir->i_sb);
> +	const char *error_msg = NULL;
> +	const void *base = bufdata(buffer);
> +	const int off = (void *)entry - base;
> +	const int rlen = tux_rec_len_from_disk(entry->rec_len);
> +
> +	if (unlikely(rlen < TUX_REC_LEN(1)))
> +		error_msg = "rec_len is smaller than minimal";
> +	else if (unlikely(rlen % TUX_DIR_ALIGN != 0))
> +		error_msg = "rec_len alignment error";
> +	else if (unlikely(rlen < TUX_REC_LEN(entry->name_len)))
> +		error_msg = "rec_len is too small for name_len";
> +	else if (unlikely(off + rlen > sb->blocksize))
> +		error_msg = "directory entry across range";
> +	else
> +		return 0;
> +
> +	__tux3_err(sb, func, line,
> +		   "bad entry: %s: inum %Lu, block %Lu, off %d, rec_len %d",
> +		   error_msg, tux_inode(dir)->inum, bufindex(buffer),
> +		   off, rlen);
> +
> +	return 1;
> +}
> +#define check_dir_entry(d, b, e)		\
> +	__check_dir_entry(__func__, __LINE__, d, b, e)
> +
>  int tux_readdir(struct file *file, struct dir_context *ctx)
>  {
>  	struct inode *dir = file_inode(file);
> @@ -374,6 +407,12 @@ int tux_readdir(struct file *file, struc
>  
>  	assert(!(dir->i_size & sb->blockmask));
>  
> +	if (offset % TUX_DIR_ALIGN) {
> +		/* Invalid offset, skip to next block */
> +		ctx->pos = (ctx->pos | (sb->blocksize - 1)) + 1;
> +		offset = 0;
> +	}
> +
>  	for (block = ctx->pos >> blockbits; block < blocks; block++) {
>  		struct buffer_head *buffer = blockread(mapping(dir), block);
>  		if (!buffer)
> @@ -393,10 +432,10 @@ int tux_readdir(struct file *file, struc
>  		}
>  		tux_dirent *limit = base + sb->blocksize - TUX_REC_LEN(1);
>  		for (tux_dirent *entry = base + offset; entry <= limit; entry = next_entry(entry)) {
> -			if (entry->rec_len == 0) {
> -				blockput(buffer);
> -				tux_zero_len_error(dir, block);
> -				return -EIO;
> +			if (check_dir_entry(dir, buffer, entry)) {
> +				/* On error, skip to next block */
> +				ctx->pos = (ctx->pos | (sb->blocksize - 1)) + 1;
> +				break;
>  			}
>  			if (!is_deleted(entry)) {
>  				unsigned type = (entry->type < TUX_TYPES) ? filetype[entry->type] : DT_UNKNOWN;
> diff -puN user/kernel/tux3.h~dir-make-robust user/kernel/tux3.h
> --- tux3/user/kernel/tux3.h~dir-make-robust	2014-04-29 18:42:30.553071700 +0900
> +++ tux3-hirofumi/user/kernel/tux3.h	2014-04-29 18:51:29.007547097 +0900
> @@ -704,9 +704,11 @@ int blockio_vec(int rw, struct bufvec *b
>  
>  #define tux3_msg(sb, fmt, ...)						\
>  	__tux3_msg(sb, KERN_INFO, "", fmt, ##__VA_ARGS__)
> -#define tux3_err(sb, fmt, ...)						\
> +#define __tux3_err(sb, func, line, fmt, ...)				\
>  	__tux3_msg(sb, KERN_ERR, " error",				\
> -		   "%s:%d: " fmt, __func__, __LINE__, ##__VA_ARGS__)
> +		   "%s:%d: " fmt, func, line, ##__VA_ARGS__)
> +#define tux3_err(sb, fmt, ...)						\
> +	__tux3_err(sb, __func__, __LINE__, fmt, ##__VA_ARGS__)
>  #define tux3_warn(sb, fmt, ...)					\
>  	__tux3_msg(sb, KERN_WARNING, " warning", fmt, ##__VA_ARGS__)
>  
> diff -puN user/tux3user.h~dir-make-robust user/tux3user.h
> --- tux3/user/tux3user.h~dir-make-robust	2014-04-29 18:43:13.460952866 +0900
> +++ tux3-hirofumi/user/tux3user.h	2014-04-29 18:49:57.279807808 +0900
> @@ -143,9 +143,11 @@ int blockio_vec(int rw, struct bufvec *b
>  
>  #define tux3_msg(sb, fmt, ...)						\
>  	__tux3_msg(sb, "", "", fmt "\n", ##__VA_ARGS__)
> -#define tux3_err(sb, fmt, ...)						\
> +#define __tux3_err(sb, func, line, fmt, ...)				\
>  	__tux3_msg(sb, "", "",						\
> -		   "Error: %s:%d: " fmt "\n", __func__, __LINE__, ##__VA_ARGS__)
> +		   "Error: %s:%d: " fmt "\n", func, line, ##__VA_ARGS__)
> +#define tux3_err(sb, fmt, ...)						\
> +	__tux3_err(sb, __func__, __LINE__, fmt, ##__VA_ARGS__)
>  #define tux3_warn(sb, fmt, ...)					\
>  	__tux3_msg(sb, "", "", "Warning: " fmt "\n", ##__VA_ARGS__)
>  
> _
> -- 
> OGAWA Hirofumi <hirofumi at mail.parknet.co.jp>



More information about the Tux3 mailing list