xfstest splats
OGAWA Hirofumi
hirofumi at mail.parknet.co.jp
Tue Apr 29 04:56:04 PDT 2014
"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().
[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