]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
ext4: fix journal credit check when setting fscrypt context
authorSimon Weber <simon.weber.39@gmail.com>
Sat, 7 Feb 2026 09:53:03 +0000 (10:53 +0100)
committerTheodore Ts'o <tytso@mit.edu>
Sat, 28 Mar 2026 03:30:25 +0000 (23:30 -0400)
Fix an issue arising when ext4 features has_journal, ea_inode, and encrypt
are activated simultaneously, leading to ENOSPC when creating an encrypted
file.

Fix by passing XATTR_CREATE flag to xattr_set_handle function if a handle
is specified, i.e., when the function is called in the control flow of
creating a new inode. This aligns the number of jbd2 credits set_handle
checks for with the number allocated for creating a new inode.

ext4_set_context must not be called with a non-null handle (fs_data) if
fscrypt context xattr is not guaranteed to not exist yet. The only other
usage of this function currently is when handling the ioctl
FS_IOC_SET_ENCRYPTION_POLICY, which calls it with fs_data=NULL.

Fixes: c1a5d5f6ab21eb7e ("ext4: improve journal credit handling in set xattr paths")
Co-developed-by: Anthony Durrer <anthonydev@fastmail.com>
Signed-off-by: Anthony Durrer <anthonydev@fastmail.com>
Signed-off-by: Simon Weber <simon.weber.39@gmail.com>
Reviewed-by: Eric Biggers <ebiggers@kernel.org>
Link: https://patch.msgid.link/20260207100148.724275-4-simon.weber.39@gmail.com
Signed-off-by: Theodore Ts'o <tytso@mit.edu>
Cc: stable@kernel.org
fs/ext4/crypto.c

index cf0a0970c095620ef4591a66c869bc3b3e009879..f41f320f4437b9969781ef06e1fd6f08b056de40 100644 (file)
@@ -163,10 +163,17 @@ static int ext4_set_context(struct inode *inode, const void *ctx, size_t len,
         */
 
        if (handle) {
+               /*
+                * Since the inode is new it is ok to pass the
+                * XATTR_CREATE flag. This is necessary to match the
+                * remaining journal credits check in the set_handle
+                * function with the credits allocated for the new
+                * inode.
+                */
                res = ext4_xattr_set_handle(handle, inode,
                                            EXT4_XATTR_INDEX_ENCRYPTION,
                                            EXT4_XATTR_NAME_ENCRYPTION_CONTEXT,
-                                           ctx, len, 0);
+                                           ctx, len, XATTR_CREATE);
                if (!res) {
                        ext4_set_inode_flag(inode, EXT4_INODE_ENCRYPT);
                        ext4_clear_inode_state(inode,