mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
* [PATCH] ubifs: propagate ubifs_shash_copy_state() errors
@ 2026-10-30  3:44 shao.mingyin
  2026-10-30  4:44 ` Zhihao Cheng
  0 siblings, 1 reply; 2+ messages in thread
From: shao.mingyin @ 2026-10-30  3:44 UTC (permalink / raw)
  To: richard, linux-mtd; +Cc: chengzhihao1, linux-kernel, stable

From: Shao Mingyin <shao.mingyin@zte.com.cn>

ubifs_shash_copy_state() duplicates the rolling hash state with
crypto_shash_export() and crypto_shash_import().  The export buffer is
allocated with kmalloc(), so the function can fail with -ENOMEM, and
crypto_shash_import() can fail as well.

Five callers ignore the return value.  The target descriptor then has no
valid state, and the crypto_shash_final() that follows computes a digest
from uninitialized data.  When preparing an auth node this stores a
wrong HMAC on the media, so the affected journal head no longer
authenticates after a remount.  During replay it makes the verification
of a valid image fail with -EPERM, and in replay_bud() and
add_replay_bud() it leaves the replay hash state inconsistent with the
media, which corrupts the auth nodes written by later commits.

Check the error at all five call sites and propagate it.  In
add_replay_bud() the descriptor belongs to the new bud, so free it on
the added error path.

Fixes: 6a98bc4614de ("ubifs: Add authentication nodes to journal")
Fixes: da8ef65f9573 ("ubifs: Authenticate replayed journal")
Cc: stable@vger.kernel.org
Signed-off-by: Shao Mingyin <shao.mingyin@zte.com.cn>
---
diff --git a/fs/ubifs/auth.c b/fs/ubifs/auth.c
index 1f770795ee70..62dfacfb6d6b 100644
--- a/fs/ubifs/auth.c
+++ b/fs/ubifs/auth.c
@@ -70,7 +70,10 @@ int ubifs_prepare_auth_node(struct ubifs_info *c, void *node,
 		SHASH_DESC_ON_STACK(hash_desc, c->hash_tfm);

 		hash_desc->tfm = c->hash_tfm;
-		ubifs_shash_copy_state(c, inhash, hash_desc);
+
+		err = ubifs_shash_copy_state(c, inhash, hash_desc);
+		if (err)
+			return err;

 		err = crypto_shash_final(hash_desc, hash);
 		if (err)
diff --git a/fs/ubifs/log.c b/fs/ubifs/log.c
index c6edcbf35ebc..42cadf558a4f 100644
--- a/fs/ubifs/log.c
+++ b/fs/ubifs/log.c
@@ -412,7 +412,11 @@ int ubifs_log_start_commit(struct ubifs_info *c, int *ltail_lnum)
 					 UBIFS_REF_NODE_SZ);
 		if (err)
 			goto out;
-		ubifs_shash_copy_state(c, c->log_hash, c->jheads[i].log_hash);
+
+		err = ubifs_shash_copy_state(c, c->log_hash,
+					     c->jheads[i].log_hash);
+		if (err)
+			goto out;
 	}

 	ubifs_pad(c, buf + len, ALIGN(len, c->min_io_size) - len);
diff --git a/fs/ubifs/replay.c b/fs/ubifs/replay.c
index 263045e05cf1..0b82c67a2dcc 100644
--- a/fs/ubifs/replay.c
+++ b/fs/ubifs/replay.c
@@ -566,10 +566,14 @@ authenticate_sleb_hash(struct ubifs_info *c,
 		       struct shash_desc *log_hash, u8 *hash)
 {
 	SHASH_DESC_ON_STACK(hash_desc, c->hash_tfm);
+	int err;

 	hash_desc->tfm = c->hash_tfm;

-	ubifs_shash_copy_state(c, log_hash, hash_desc);
+	err = ubifs_shash_copy_state(c, log_hash, hash_desc);
+	if (err)
+		return err;
+
 	return crypto_shash_final(hash_desc, hash);
 }

@@ -694,8 +698,10 @@ static int replay_bud(struct ubifs_info *c, struct bud_entry *b)
 		goto out;
 	}

-	ubifs_shash_copy_state(c, b->bud->log_hash,
-			       c->jheads[b->bud->jhead].log_hash);
+	err = ubifs_shash_copy_state(c, b->bud->log_hash,
+				     c->jheads[b->bud->jhead].log_hash);
+	if (err)
+		goto out;

 	/*
 	 * The bud does not have to start from offset zero - the beginning of
@@ -915,7 +921,9 @@ static int add_replay_bud(struct ubifs_info *c, int lnum, int offs, int jhead,
 		goto out;
 	}

-	ubifs_shash_copy_state(c, c->log_hash, bud->log_hash);
+	err = ubifs_shash_copy_state(c, c->log_hash, bud->log_hash);
+	if (err)
+		goto out_free_log_hash;

 	ubifs_add_bud(c, bud);

@@ -924,6 +932,8 @@ static int add_replay_bud(struct ubifs_info *c, int lnum, int offs, int jhead,
 	list_add_tail(&b->list, &c->replay_buds);

 	return 0;
+out_free_log_hash:
+	kfree(bud->log_hash);
 out:
 	kfree(bud);
 	kfree(b);

^ permalink raw reply	[flat|nested] 2+ messages in thread

* Re: [PATCH] ubifs: propagate ubifs_shash_copy_state() errors
  2026-10-30  3:44 [PATCH] ubifs: propagate ubifs_shash_copy_state() errors shao.mingyin
@ 2026-10-30  4:44 ` Zhihao Cheng
  0 siblings, 0 replies; 2+ messages in thread
From: Zhihao Cheng @ 2026-10-30  4:44 UTC (permalink / raw)
  To: shao.mingyin, richard, linux-mtd; +Cc: linux-kernel, stable

在 2026/10/30 11:44, shao.mingyin@zte.com.cn 写道:
> From: Shao Mingyin <shao.mingyin@zte.com.cn>
> 
> ubifs_shash_copy_state() duplicates the rolling hash state with
> crypto_shash_export() and crypto_shash_import().  The export buffer is
> allocated with kmalloc(), so the function can fail with -ENOMEM, and
> crypto_shash_import() can fail as well.
> 
> Five callers ignore the return value.  The target descriptor then has no
> valid state, and the crypto_shash_final() that follows computes a digest
> from uninitialized data.  When preparing an auth node this stores a
> wrong HMAC on the media, so the affected journal head no longer
> authenticates after a remount.  During replay it makes the verification
> of a valid image fail with -EPERM, and in replay_bud() and
> add_replay_bud() it leaves the replay hash state inconsistent with the
> media, which corrupts the auth nodes written by later commits.
> 
> Check the error at all five call sites and propagate it.  In
> add_replay_bud() the descriptor belongs to the new bud, so free it on
> the added error path.
> 
> Fixes: 6a98bc4614de ("ubifs: Add authentication nodes to journal")
> Fixes: da8ef65f9573 ("ubifs: Authenticate replayed journal")
> Cc: stable@vger.kernel.org
> Signed-off-by: Shao Mingyin <shao.mingyin@zte.com.cn>
> ---

Reviewed-by: Zhihao Cheng <chengzhihao1@huawei.com>
> diff --git a/fs/ubifs/auth.c b/fs/ubifs/auth.c
> index 1f770795ee70..62dfacfb6d6b 100644
> --- a/fs/ubifs/auth.c
> +++ b/fs/ubifs/auth.c
> @@ -70,7 +70,10 @@ int ubifs_prepare_auth_node(struct ubifs_info *c, void *node,
>   		SHASH_DESC_ON_STACK(hash_desc, c->hash_tfm);
> 
>   		hash_desc->tfm = c->hash_tfm;
> -		ubifs_shash_copy_state(c, inhash, hash_desc);
> +
> +		err = ubifs_shash_copy_state(c, inhash, hash_desc);
> +		if (err)
> +			return err;
> 
>   		err = crypto_shash_final(hash_desc, hash);
>   		if (err)
> diff --git a/fs/ubifs/log.c b/fs/ubifs/log.c
> index c6edcbf35ebc..42cadf558a4f 100644
> --- a/fs/ubifs/log.c
> +++ b/fs/ubifs/log.c
> @@ -412,7 +412,11 @@ int ubifs_log_start_commit(struct ubifs_info *c, int *ltail_lnum)
>   					 UBIFS_REF_NODE_SZ);
>   		if (err)
>   			goto out;
> -		ubifs_shash_copy_state(c, c->log_hash, c->jheads[i].log_hash);
> +
> +		err = ubifs_shash_copy_state(c, c->log_hash,
> +					     c->jheads[i].log_hash);
> +		if (err)
> +			goto out;
>   	}
> 
>   	ubifs_pad(c, buf + len, ALIGN(len, c->min_io_size) - len);
> diff --git a/fs/ubifs/replay.c b/fs/ubifs/replay.c
> index 263045e05cf1..0b82c67a2dcc 100644
> --- a/fs/ubifs/replay.c
> +++ b/fs/ubifs/replay.c
> @@ -566,10 +566,14 @@ authenticate_sleb_hash(struct ubifs_info *c,
>   		       struct shash_desc *log_hash, u8 *hash)
>   {
>   	SHASH_DESC_ON_STACK(hash_desc, c->hash_tfm);
> +	int err;
> 
>   	hash_desc->tfm = c->hash_tfm;
> 
> -	ubifs_shash_copy_state(c, log_hash, hash_desc);
> +	err = ubifs_shash_copy_state(c, log_hash, hash_desc);
> +	if (err)
> +		return err;
> +
>   	return crypto_shash_final(hash_desc, hash);
>   }
> 
> @@ -694,8 +698,10 @@ static int replay_bud(struct ubifs_info *c, struct bud_entry *b)
>   		goto out;
>   	}
> 
> -	ubifs_shash_copy_state(c, b->bud->log_hash,
> -			       c->jheads[b->bud->jhead].log_hash);
> +	err = ubifs_shash_copy_state(c, b->bud->log_hash,
> +				     c->jheads[b->bud->jhead].log_hash);
> +	if (err)
> +		goto out;
> 
>   	/*
>   	 * The bud does not have to start from offset zero - the beginning of
> @@ -915,7 +921,9 @@ static int add_replay_bud(struct ubifs_info *c, int lnum, int offs, int jhead,
>   		goto out;
>   	}
> 
> -	ubifs_shash_copy_state(c, c->log_hash, bud->log_hash);
> +	err = ubifs_shash_copy_state(c, c->log_hash, bud->log_hash);
> +	if (err)
> +		goto out_free_log_hash;
> 
>   	ubifs_add_bud(c, bud);
> 
> @@ -924,6 +932,8 @@ static int add_replay_bud(struct ubifs_info *c, int lnum, int offs, int jhead,
>   	list_add_tail(&b->list, &c->replay_buds);
> 
>   	return 0;
> +out_free_log_hash:
> +	kfree(bud->log_hash);
>   out:
>   	kfree(bud);
>   	kfree(b);
> .
> 


^ permalink raw reply	[flat|nested] 2+ messages in thread

end of thread, other threads:[~2026-10-30  4:44 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-10-30  3:44 [PATCH] ubifs: propagate ubifs_shash_copy_state() errors shao.mingyin
2026-10-30  4:44 ` Zhihao Cheng

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox

all inboxes | Powered by JetHome®