lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <20260204205903.GA2197@quark>
Date: Wed, 4 Feb 2026 12:59:03 -0800
From: Eric Biggers <ebiggers@...nel.org>
To: Simon Weber <simon.weber.39@...il.com>
Cc: linux-ext4@...r.kernel.org, linux-kernel@...r.kernel.org,
	Theodore Ts'o <tytso@....edu>,
	Andreas Dilger <adilger.kernel@...ger.ca>, anthonydev@...tmail.com
Subject: Re: [PATCH v1] ext4: fix journal credit check when setting fscrypt
 context xattr

On Wed, Feb 04, 2026 at 04:09:02PM +0100, Simon Weber wrote:
> From: Simon Weber <simon.weber.39@...il.com>
> 
> When creating a new inode, the required number of jbd2 journalling credits
> is conservatively estimated by summing up the credits required for various
> actions. This includes setting the xattrs for example for ACLs and the
> fscrypt context. Since the inode is new and has no xattrs, the estimation
> of credits needed for creating these xattrs is performed by passing
> is_create=true into the function __ext4_xattr_set_credits, which yields a
> lower number of credits than when is_create is false. However, following
> the control flow until the fscrypt context xattr is actually set, the
> XATTR_CREATE flag is not passed by ext4_set_context to
> ext4_xattr_set_handle. This causes the latter function to compare the
> remaining credits against the value of __ext4_xattr_set_credits(...,
> is_create=false), which may be too much. This flawed design does not
> usually cause any issues unless the filesystem features has_journal,
> ea_inode, and encrypt are all present at the same time. In this case,
> creating a file in any fscrypt-encrypted directory will always return
> ENOSPC.
> This patch fixes this issue by passing the XATTR_CREATE flag in the
> ext4_set_context function. This is safe since ext4_set_context is only
> called when creating a new inode (in which case the context xattr is not
> present yet) or when setting the encryption policy on an existing file
> using the FS_IOC_SET_ENCRYPTION_POLICY ioctl, which however first checks
> that the file does not currently have an encryption policy set. When
> calling ext4_set_context it is therefore not undesirable behaviour to
> possibly fail with an EEXIST error due to the XATTR_CREATE flag and the
> context xattr already being present.
> 
> Co-developed-by: Anthony Durrer <anthonydev@...tmail.com>
> Signed-off-by: Anthony Durrer <anthonydev@...tmail.com>
> Signed-off-by: Simon Weber <simon.weber.39@...il.com>
> ---
>  fs/ext4/crypto.c | 12 +++++++++++-
>  1 file changed, 11 insertions(+), 1 deletion(-)
> 
> diff --git a/fs/ext4/crypto.c b/fs/ext4/crypto.c
> index cf0a0970c095..5b665f85f6a7 100644
> --- a/fs/ext4/crypto.c
> +++ b/fs/ext4/crypto.c
> @@ -163,10 +163,20 @@ static int ext4_set_context(struct inode *inode, const void *ctx, size_t len,
>       */
>  
>      if (handle) {
> +        /*
> +         * Set the xattr using the XATTR_CREATE flag, since this function should
> +         * only be called on inodes that do not have an encryption context yet.
> +         * Since when estimating the number of credits needed for the new inode
> +         * we called ext4_xattr_set with is_create = true, we need to pass this
> +         * flag, otherwise the check for remaining credits is too conservative
> +         * and may fail.
> +         * If for some reason the inode already has an encryption context, this
> +         * fails with EEXIST, which is desirable behaviour.
> +         */
>          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,
> 

Thanks!  A few comments:

This patch doesn't actually apply to the stated base-commit, likely
because of corrupted whitespace.  Make sure to use 'git send-email' as
described in Documentation/process/submitting-patches.rst.

The commit message should be broken into paragraphs, and ideally
shortened a bit.  The code comment maybe could be shortened as well.

Since this is a bug fix, please include an appropriate Fixes tag.

As for the actual change, it's *probably* fine.  The equivalent code in
f2fs already uses XATTR_CREATE.

However, I'm wondering a bit more about the possibility of inodes that
have an encryption xattr but not the encrypt flag.  ext4 sets these
together in a journal transaction, so normally it indeed isn't possible.

However, ext4 also supports a no-journal mode.  In no-journal mode,
e2fsck is relied on to correct filesystem inconsistencies.

It looks like e2fsck doesn't currently remove loose encryption xattrs.
So I'm wondering if that would need to be added.

The specific scenario I'm concerned about is:

    - FS_IOC_SET_ENCRYPTION_POLICY tries to set a directory to encrypted
    - A crash occurs (in no-journal mode), leaving the inode having an
      encryption xattr on-disk but not the encrypt flag
    - e2fsck doesn't correct the inconsistency
    - Userspace sees that the directory isn't encrypted yet and retries
      FS_IOC_SET_ENCRYPTION_POLICY.  Due to XATTR_CREATE, it fails.

Any thoughts on whether this could be a problem?

- Eric

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ