Skip to contentSkip to conversation

f2fs: check memory boundary by insane namelen

PATCH In review Jaegeuk Kim 4 participants 5 messages Nov 15, 2018 – Nov 26, 2018 F2FS file system

lore
Share & tools
lore

Jaegeuk Kim

author maintainer
#0 lore raw

PATCH 1/1 f2fs: check memory boundary by insane namelen

If namelen is corrupted to have very long value, fill_dentries can copy wrong memory area.

---
 fs/f2fs/dir.c | 12 +++++++++++-
 1 file changed, 11 insertions(+), 1 deletion(-)
fs/f2fs/dir.c +11 -1
index bacc667950b6..c0c845da12fa 100644
@@ -808,6 +808,17 @@ int f2fs_fill_dentries(struct dir_context *ctx, struct f2fs_dentry_ptr *d,
 		de_name.name = d->filename[bit_pos];
 		de_name.len = le16_to_cpu(de->name_len);
 
+		/* check memory boundary before moving forward */
+		bit_pos += GET_DENTRY_SLOTS(le16_to_cpu(de->name_len));
+		if (unlikely(bit_pos > d->max)) {
+			f2fs_msg(sbi->sb, KERN_WARNING,
+				"%s: corrupted namelen=%d, run fsck to fix.",
+				__func__, le16_to_cpu(de->name_len));
+			set_sbi_flag(sbi, SBI_NEED_FSCK);
+			err = -EINVAL;
+			goto out;
+		}
+
 		if (f2fs_encrypted_inode(d->inode)) {
 			int save_len = fstr->len;
 
@@ -830,7 +841,6 @@ int f2fs_fill_dentries(struct dir_context *ctx, struct f2fs_dentry_ptr *d,
 		if (readdir_ra)
 			f2fs_ra_node_page(sbi, le32_to_cpu(de->ino));
 
-		bit_pos += GET_DENTRY_SLOTS(le16_to_cpu(de->name_len));
 		ctx->pos = start_pos + bit_pos;
 	}
 out:
Signature · 1 line
2.19.0.605.g01d371f741-goog
#2 lore raw
In reply to Jaegeuk Kim

Hi, Jaegeuk and Chao,

Quoted 3 lines · Jaegeuk Kim

If namelen is corrupted to have very long value, fill_dentries can copy wrong memory area.

Is there any scenario that could hit this corruption? Or this is triggered by fuzzing injection?

thanks,
Sheng Yong

Quoted 36 lines
---
  fs/f2fs/dir.c | 12 +++++++++++-
  1 file changed, 11 insertions(+), 1 deletion(-)
fs/f2fs/dir.c +11 -1
index bacc667950b6..c0c845da12fa 100644
@@ -808,6 +808,17 @@ int f2fs_fill_dentries(struct dir_context *ctx, struct f2fs_dentry_ptr *d,
  		de_name.name = d->filename[bit_pos];
  		de_name.len = le16_to_cpu(de->name_len);
 
+		/* check memory boundary before moving forward */
+		bit_pos += GET_DENTRY_SLOTS(le16_to_cpu(de->name_len));
+		if (unlikely(bit_pos > d->max)) {
+			f2fs_msg(sbi->sb, KERN_WARNING,
+				"%s: corrupted namelen=%d, run fsck to fix.",
+				__func__, le16_to_cpu(de->name_len));
+			set_sbi_flag(sbi, SBI_NEED_FSCK);
+			err = -EINVAL;
+			goto out;
+		}
+
  		if (f2fs_encrypted_inode(d->inode)) {
  			int save_len = fstr->len;
 
@@ -830,7 +841,6 @@ int f2fs_fill_dentries(struct dir_context *ctx, struct f2fs_dentry_ptr *d,
  		if (readdir_ra)
  			f2fs_ra_node_page(sbi, le32_to_cpu(de->ino));
 
-		bit_pos += GET_DENTRY_SLOTS(le16_to_cpu(de->name_len));
  		ctx->pos = start_pos + bit_pos;
  	}
  out:
#3 lore raw

Hi Sheng,

Quoted 7 lines · Sheng Yong

Hi, Jaegeuk and Chao,

Quoted 3 lines · Jaegeuk Kim

If namelen is corrupted to have very long value, fill_dentries can copy wrong memory area.

Is there any scenario that could hit this corruption? Or this is triggered

I didn't see such issue in my test, I guess it may be caused by fuzzing test.

Thanks,

Quoted 50 lines

by fuzzing injection?

thanks,
Sheng Yong

Quoted 29 lines
---
  fs/f2fs/dir.c | 12 +++++++++++-
  1 file changed, 11 insertions(+), 1 deletion(-)
fs/f2fs/dir.c +11 -0
index bacc667950b6..c0c845da12fa 100644
@@ -808,6 +808,17 @@ int f2fs_fill_dentries(struct dir_context *ctx, struct f2fs_dentry_ptr *d,
  		de_name.name = d->filename[bit_pos];
  		de_name.len = le16_to_cpu(de->name_len);
 
+		/* check memory boundary before moving forward */
+		bit_pos += GET_DENTRY_SLOTS(le16_to_cpu(de->name_len));
+		if (unlikely(bit_pos > d->max)) {
+			f2fs_msg(sbi->sb, KERN_WARNING,
+				"%s: corrupted namelen=%d, run fsck to fix.",
+				__func__, le16_to_cpu(de->name_len));
+			set_sbi_flag(sbi, SBI_NEED_FSCK);
+			err = -EINVAL;
+			goto out;
+		}
+
  		if (f2fs_encrypted_inode(d->inode)) {
  			int save_len = fstr->len;
 

fs/f2fs/dir.c int f2fs_fill_dentries(struct dir_context *ctx, struct f2fs_dentry_ptr *d, · line 846

Quoted 7 lines
fs/f2fs/dir.c +0 -1
@@ -830,7 +841,6 @@ int f2fs_fill_dentries(struct dir_context *ctx, struct f2fs_dentry_ptr *d,
  		if (readdir_ra)
  			f2fs_ra_node_page(sbi, le32_to_cpu(de->ino));
 
-		bit_pos += GET_DENTRY_SLOTS(le16_to_cpu(de->name_len));
  		ctx->pos = start_pos + bit_pos;
  	}
  out:

_______________________________________________
Linux-f2fs-devel mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/linux-f2fs-devel

author maintainer
#4 lore raw
In reply to Sheng Yong
Quoted 8 lines · Sheng Yong

Hi, Jaegeuk and Chao,

Quoted 3 lines · Jaegeuk Kim

If namelen is corrupted to have very long value, fill_dentries can copy wrong memory area.

Is there any scenario that could hit this corruption? Or this is triggered by fuzzing injection?

Hi Sheng,

It's from a fuzzing test.

Thanks,

Quoted 37 lines

thanks,
Sheng Yong

Quoted 33 lines
---
  fs/f2fs/dir.c | 12 +++++++++++-
  1 file changed, 11 insertions(+), 1 deletion(-)
fs/f2fs/dir.c +11 -1
index bacc667950b6..c0c845da12fa 100644
@@ -808,6 +808,17 @@ int f2fs_fill_dentries(struct dir_context *ctx, struct f2fs_dentry_ptr *d,
  		de_name.name = d->filename[bit_pos];
  		de_name.len = le16_to_cpu(de->name_len);
+		/* check memory boundary before moving forward */
+		bit_pos += GET_DENTRY_SLOTS(le16_to_cpu(de->name_len));
+		if (unlikely(bit_pos > d->max)) {
+			f2fs_msg(sbi->sb, KERN_WARNING,
+				"%s: corrupted namelen=%d, run fsck to fix.",
+				__func__, le16_to_cpu(de->name_len));
+			set_sbi_flag(sbi, SBI_NEED_FSCK);
+			err = -EINVAL;
+			goto out;
+		}
+
  		if (f2fs_encrypted_inode(d->inode)) {
  			int save_len = fstr->len;
@@ -830,7 +841,6 @@ int f2fs_fill_dentries(struct dir_context *ctx, struct f2fs_dentry_ptr *d,
  		if (readdir_ra)
  			f2fs_ra_node_page(sbi, le32_to_cpu(de->ino));
-		bit_pos += GET_DENTRY_SLOTS(le16_to_cpu(de->name_len));
  		ctx->pos = start_pos + bit_pos;
  	}
  out: