[PATCH v2 05/10] ntfs: distinguish empty EA values from removal
From: Baolin Liu
Date: Sun Sep 20 2026 - 04:32:46 EST
From: Baolin Liu <liubaolin@xxxxxxxxxx>
The EA setter identifies removal using a zero value length together
with XATTR_REPLACE. A replacement with a valid empty value is therefore
mistaken for deletion.
Use a NULL value to identify removal and keep zero-length values valid.
Reject removal or XATTR_REPLACE for an absent entry before creating
metadata, including when the file has no EA attributes.
Signed-off-by: Baolin Liu <liubaolin@xxxxxxxxxx>
---
fs/ntfs/ea.c | 14 ++++++++------
1 file changed, 8 insertions(+), 6 deletions(-)
diff --git a/fs/ntfs/ea.c b/fs/ntfs/ea.c
index f5a112495fc9..15bfcdddc7ee 100644
--- a/fs/ntfs/ea.c
+++ b/fs/ntfs/ea.c
@@ -244,6 +244,8 @@ static int ntfs_set_ea(struct inode *inode, const char *name, size_t name_len,
if (!err != !ea_err)
return -EUCLEAN;
has_ea = !err;
+ if (!has_ea && (!value || (flags & XATTR_REPLACE)))
+ return -ENODATA;
if (has_ea) {
p_ea_info = ntfs_attr_readall(ni, AT_EA_INFORMATION, NULL, 0,
&ea_info_size);
@@ -308,7 +310,7 @@ static int ntfs_set_ea(struct inode *inode, const char *name, size_t name_len,
err = -EEXIST;
goto out;
}
- if ((flags & XATTR_REPLACE) && !val_size) {
+ if (!value) {
old_ea_info = *p_ea_info;
old_ea_buf = kvmemdup(ea_buf, all_ea_size, GFP_NOFS);
if (!old_ea_buf) {
@@ -318,7 +320,7 @@ static int ntfs_set_ea(struct inode *inode, const char *name, size_t name_len,
}
/* Check the final $EA size before removing the old entry. */
- if (val_size &&
+ if (value &&
ntfs_attr_size_bounds_check(ni->vol, AT_EA,
ea_info_qsize - ea_size + new_ea_size)) {
err = -EFBIG;
@@ -327,7 +329,7 @@ static int ntfs_set_ea(struct inode *inode, const char *name, size_t name_len,
p_ea = (struct ea_attr *)(ea_buf + ea_off);
- if (val_size &&
+ if (value &&
le16_to_cpu(p_ea->ea_value_length) == val_size &&
!memcmp(p_ea->ea_name + p_ea->ea_name_length + 1, value,
val_size))
@@ -342,7 +344,7 @@ static int ntfs_set_ea(struct inode *inode, const char *name, size_t name_len,
ea_info_qsize -= ea_size;
p_ea_info->ea_query_length = cpu_to_le32(ea_info_qsize);
- if ((flags & XATTR_REPLACE) && !val_size && !ea_info_qsize) {
+ if (!value && !ea_info_qsize) {
err = ntfs_attr_remove(ni, AT_EA, AT_UNNAMED, 0);
if (err)
goto out;
@@ -357,7 +359,7 @@ static int ntfs_set_ea(struct inode *inode, const char *name, size_t name_len,
goto out;
}
- if ((flags & XATTR_REPLACE) && !val_size) {
+ if (!value) {
err = ntfs_write_ea(ni, AT_EA, ea_buf, 0, ea_info_qsize,
true);
if (err) {
@@ -378,7 +380,7 @@ static int ntfs_set_ea(struct inode *inode, const char *name, size_t name_len,
goto out;
}
} else {
- if (flags & XATTR_REPLACE) {
+ if (!value || (flags & XATTR_REPLACE)) {
err = -ENODATA;
goto out;
}
--
2.51.0