Linux Security Modules development
 help / color / mirror / Atom feed
* [PATCH] evm: fix TOCTOU heap OOB in protected xattr reads
@ 2026-11-07 19:49 Jérémy Jean
  2026-11-07 20:02 ` sashiko-bot
  0 siblings, 1 reply; 2+ messages in thread
From: Jérémy Jean @ 2026-11-07 19:49 UTC (permalink / raw)
  To: Mimi Zohar, Roberto Sassu, Dmitry Kasatkin
  Cc: Eric Snowberg, linux-integrity, linux-security-module,
	linux-kernel, Jérémy Jean, stable

ima_eventinodexattrs_init_common() queries the total size of protected
xattrs, allocates that amount, and calls evm_read_protected_xattrs()
again to fill the buffer. This creates a TOCTOU window: if the
protected xattr changes between the two calls to
evm_read_protected_xattrs(), names and lengths are written without
checking whether the data still fits in the target buffer. This can
yield an OOB heap write that KASAN reports as:

  BUG: KASAN: slab-out-of-bounds in evm_read_protected_xattrs+0x15e/0x280
  Write of size 20 at addr ffff888002c59bcd by task init/62

Reject fields that no longer fit in the target buffer. For xattr
values, use the length actually returned by the copy.

Fixes: 8314b6732ae4e ("ima: Define new template fields xattrnames, xattrlengths and xattrvalues")
Cc: stable@vger.kernel.org
Signed-off-by: Jérémy Jean <Jeremy.Jean@oss.cyber.gouv.fr>
---
 security/integrity/evm/evm_main.c | 13 +++++++++++++
 1 file changed, 13 insertions(+)

diff --git a/security/integrity/evm/evm_main.c b/security/integrity/evm/evm_main.c
index ac8328812e6ef..4b01ca0b4753a 100644
--- a/security/integrity/evm/evm_main.c
+++ b/security/integrity/evm/evm_main.c
@@ -389,6 +389,10 @@ int evm_read_protected_xattrs(struct dentry *dentry, u8 *buffer,
 		case 'n':
 			size = strlen(xattr->name) + 1;
 			if (buffer) {
+				if (total_size > buffer_size ||
+				    size > buffer_size - total_size)
+					return -ERANGE;
+
 				if (total_size)
 					*(buffer + total_size - 1) = '|';
 
@@ -398,6 +402,10 @@ int evm_read_protected_xattrs(struct dentry *dentry, u8 *buffer,
 		case 'l':
 			size = sizeof(u32);
 			if (buffer) {
+				if (total_size > buffer_size ||
+				    size > buffer_size - total_size)
+					return -ERANGE;
+
 				if (canonical_fmt)
 					rc = (__force int)cpu_to_le32(rc);
 
@@ -407,12 +415,17 @@ int evm_read_protected_xattrs(struct dentry *dentry, u8 *buffer,
 		case 'v':
 			size = rc;
 			if (buffer) {
+				if (total_size > buffer_size ||
+				    size > buffer_size - total_size)
+					return -ERANGE;
+
 				rc = __vfs_getxattr(dentry,
 					d_backing_inode(dentry), xattr->name,
 					buffer + total_size,
 					buffer_size - total_size);
 				if (rc < 0)
 					return rc;
+				size = rc;
 			}
 			break;
 		default:
-- 
2.47.3


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

* Re: [PATCH] evm: fix TOCTOU heap OOB in protected xattr reads
  2026-11-07 19:49 [PATCH] evm: fix TOCTOU heap OOB in protected xattr reads Jérémy Jean
@ 2026-11-07 20:02 ` sashiko-bot
  0 siblings, 0 replies; 2+ messages in thread
From: sashiko-bot @ 2026-11-07 20:02 UTC (permalink / raw)
  Cc: linux-security-module

Thank you for your contribution! Sashiko AI review found 1 potential
issue to consider:
- [Medium] evm: incomplete TOCTOU bounds check in
  evm_read_protected_xattrs()
--

commit 94961f480ee0e6be15409d6ea100ede9af939446
Author: Jérémy Jean <Jeremy.Jean@oss.cyber.gouv.fr>

evm: fix TOCTOU heap OOB in protected xattr reads

This commit adds bounds checks in evm_read_protected_xattrs() to reject
protected xattr names, lengths, and values that no longer fit in the
caller's buffer if an xattr changes between the size query and the read.

> diff --git a/security/integrity/evm/evm_main.c b/security/integrity/evm/evm_main.c
> index b59e3f121b8a8..d00b050edb811 100644
> --- a/security/integrity/evm/evm_main.c
> +++ b/security/integrity/evm/evm_main.c
[ ... ]
> @@ -407,12 +415,17 @@ int evm_read_protected_xattrs(struct dentry *dentry, u8 *buffer,
>  		case 'v':
>  			size = rc;
>  			if (buffer) {
> +				if (total_size > buffer_size ||
> +				    size > buffer_size - total_size)
> +					return -ERANGE;
> +
>  				rc = __vfs_getxattr(dentry,
>  					d_backing_inode(dentry), xattr->name,
>  					buffer + total_size,
>  					buffer_size - total_size);
>  				if (rc < 0)
>  					return rc;
> +				size = rc;
>  			}
>  			break;

[Severity: Medium]
Can total_size still exceed buffer_size when total_size == buffer_size and
an xattr grows from 0 bytes between the two __vfs_getxattr() calls?

When the first __vfs_getxattr() returns 0 for an empty xattr and
total_size == buffer_size, the bounds check passes and the second
__vfs_getxattr() is called with a size argument of
buffer_size - total_size == 0. Many filesystem xattr handlers (such as
btrfs_getxattr(), xfs_attr_copy_value(), and fuse_getxattr()) treat a zero
size argument as a length query rather than an empty buffer, so if the
xattr concurrently grew to N > 0 bytes, __vfs_getxattr() returns N instead
of -ERANGE.

Assigning size = rc then advances total_size to buffer_size + N, causing
ima_eventinodexattrs_init_common() -> ima_write_template_field_data() to
memcpy() past the end of buffer (or dereference ZERO_SIZE_PTR when
buffer_size == 0). Skipping the second __vfs_getxattr() call when size == 0
or checking that rc <= buffer_size - total_size would avoid this.

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20261107194909.1061154-2-Jeremy.Jean@oss.cyber.gouv.fr?part=1

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

end of thread, other threads:[~2026-11-07 20:02 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-11-07 19:49 [PATCH] evm: fix TOCTOU heap OOB in protected xattr reads Jérémy Jean
2026-11-07 20:02 ` sashiko-bot

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