All of lore.kernel.org
 help / color / mirror / Atom feed
From: Ana Bobillo <anabobillo3@gmail.com>
To: Tom Rini <trini@konsulko.com>
Cc: u-boot@lists.u-boot-project.org, Tony Dinh <mibodhi@gmail.com>,
	Simon Glass <sjg@chromium.org>
Subject: [PATCH 4/6] fs: ext4: bound the journal entry tables
Date: Sun, 08 Nov 2026 15:12:14 +0000	[thread overview]
Message-ID: <794fd6f4-fe81-4582-af60-0199af3df225@gmail.com> (raw)
In-Reply-To: <5072bec2-e2e3-405d-91eb-58fe78ea6669@gmail.com>

From: Ana Bobillo <anabobillo3@gmail.com>

A write logs each metadata block it changes in journal_ptr[] and
dirty_block_ptr[], which hold CONFIG_EXT4_MAX_JOURNAL_ENTRIES entries
each. ext4fs_log_journal() and ext4fs_put_metadata() add an entry
without checking for room, so a write that changes more blocks than
that, for example on a filesystem with many block groups whose block
bitmaps it touches, writes past the end of both tables.

Commit 29cb98d515f9 ("fs: ext4fs: Fix: Data abort in ext4fs_log_gdt()")
added a check to ext4fs_log_gdt(), but it compares the number of group
descriptor blocks with the size of the whole table, while
ext4fs_init_journal() has already used one entry for the superblock.

update_descriptor_block() also writes one tag per logged block into a
single journal block, which holds (blksz - 12) / 8 tags: 126 with 1 KiB
blocks. A larger CONFIG_EXT4_MAX_JOURNAL_ENTRIES lets it write past the
end of that block buffer.

Add ext4fs_journal_slots(), the number of entries a transaction may
use, which is the smaller of the table size and the number of tags in a
descriptor block, and check it in ext4fs_log_gdt(), counting the
entries already in use, and in ext4fs_log_journal(). Check the size of
dirty_block_ptr[] in ext4fs_put_metadata(). These return -ENOMEM, and
print their message with printf(), as the rest of the driver does. A
write that needs more entries now fails before its metadata changes
are written.

With the default of 100 entries this does not change what a write can
do: a typical ext4write logs a handful of blocks, and the limit is only
reached on filesystems with very many block groups, or by a write that
allocates blocks in very many of them.

Signed-off-by: Ana Bobillo <anabobillo3@gmail.com>
---
 fs/ext4/ext4_journal.c | 40 ++++++++++++++++++++++++++++++++++++----
 1 file changed, 36 insertions(+), 4 deletions(-)

diff --git a/fs/ext4/ext4_journal.c b/fs/ext4/ext4_journal.c
index 3a2e9f30c12..cb63addea0a 100644
--- a/fs/ext4/ext4_journal.c
+++ b/fs/ext4/ext4_journal.c
@@ -126,15 +126,38 @@ void ext4fs_free_journal(void)
 	jrnl_blk_idx = 1;
 }
 
+/**
+ * ext4fs_journal_slots() - get the number of blocks one transaction can log
+ *
+ * update_descriptor_block() writes a tag for each logged block into a single
+ * descriptor block, so a transaction can log no more blocks than there are
+ * tags in a block, nor more than journal_ptr[] holds.
+ *
+ * Return:	the number of journal_ptr[] entries that may be used
+ */
+static int ext4fs_journal_slots(void)
+{
+	struct ext_filesystem *fs = get_fs();
+	int tags = (fs->blksz - sizeof(struct journal_header_t)) /
+		   sizeof(struct ext3_journal_block_tag);
+
+	return min(tags, MAX_JOURNAL_ENTRIES);
+}
+
 int ext4fs_log_gdt(char *gd_table)
 {
 	struct ext_filesystem *fs = get_fs();
-	short i;
+	u32 i;
 	long int var = fs->gdtable_blkno;
 
-	/* Make sure there is enough journal entries */
-	if (fs->no_blk_pergdt > MAX_JOURNAL_ENTRIES) {
-		log_err("*** Not enough journal entries allocated\n");
+	/*
+	 * Make sure there are enough journal entries left:
+	 * ext4fs_init_journal() has already taken the slots for the
+	 * superblock, so count from gindex rather than from the start of the
+	 * table.
+	 */
+	if (gindex + fs->no_blk_pergdt > ext4fs_journal_slots()) {
+		printf("*** Not enough journal entries allocated\n");
 		return -ENOMEM;
 	}
 
@@ -172,6 +195,11 @@ int ext4fs_log_journal(char *journal_buffer, uint32_t blknr)
 			return 0;
 	}
 
+	if (gindex >= ext4fs_journal_slots()) {
+		printf("*** Not enough journal entries allocated\n");
+		return -ENOMEM;
+	}
+
 	journal_ptr[gindex]->buf = zalloc(fs->blksz);
 	if (!journal_ptr[gindex]->buf)
 		return -ENOMEM;
@@ -194,6 +222,10 @@ int ext4fs_put_metadata(char *metadata_buffer, uint32_t blknr)
 		printf("Invalid input arguments %s\n", __func__);
 		return -EINVAL;
 	}
+	if (gd_index >= MAX_JOURNAL_ENTRIES) {
+		printf("*** Not enough journal entries allocated\n");
+		return -ENOMEM;
+	}
 	if (dirty_block_ptr[gd_index]->buf)
 		assert(dirty_block_ptr[gd_index]->blknr == blknr);
 	else

  parent reply	other threads:[~2026-11-08 15:12 UTC|newest]

Thread overview: 7+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-11-08 15:11 [PATCH 0/6] fs: ext4: check on-disk values in the write path Ana Bobillo
2026-11-08 15:11 ` [PATCH 1/6] fs: ext4: refuse to write with an unexpected first data block Ana Bobillo
2026-11-08 15:12 ` [PATCH 2/6] fs: ext4: use ext4fs_blk_to_group() in ext4fs_get_new_blk_no() Ana Bobillo
2026-11-08 15:12 ` [PATCH 3/6] fs: ext4: check directory entries before using them Ana Bobillo
2026-11-08 15:12 ` Ana Bobillo [this message]
2026-11-08 15:12 ` [PATCH 5/6] fs: ext4: stop the journal scan at the end of the log Ana Bobillo
2026-11-08 15:12 ` [PATCH 6/6] test: fs: ext4: add tests for the write path checks Ana Bobillo

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=794fd6f4-fe81-4582-af60-0199af3df225@gmail.com \
    --to=anabobillo3@gmail.com \
    --cc=mibodhi@gmail.com \
    --cc=sjg@chromium.org \
    --cc=trini@konsulko.com \
    --cc=u-boot@lists.u-boot-project.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.