mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
* [PATCH 0/2] ntfs: enforce the encrypted-file policy on the read paths
@ 2026-10-12  6:20 Zhan Xusheng
  2026-10-12  6:20 ` [PATCH 1/2] ntfs: do not read ahead encrypted files Zhan Xusheng
                   ` (4 more replies)
  0 siblings, 5 replies; 8+ messages in thread
From: Zhan Xusheng @ 2026-10-12  6:20 UTC (permalink / raw)
  To: Namjae Jeon; +Cc: Hyunchul Lee, ntfs, linux-kernel, Zhan Xusheng

From: Zhan Xusheng <zhanxusheng@xiaomi.com>

EFS-encrypted attributes are refused with -EOPNOTSUPP in exactly one
place, ntfs_read_folio(), because decryption is not implemented.  Two
read paths get there without passing that test and return the raw
on-disk ciphertext instead, so the same read returns either ciphertext
or -EOPNOTSUPP depending on which path serves it.

Patch 1 is readahead, which marks the folios uptodate so ->read_folio
is never called.  read(), mmap(), splice() and fadvise() all populate
the page cache this way, so one test closes all four.

Patch 2 is direct I/O, which bypasses the page cache entirely and has
no such backstop.

Both commits are in v7.1.  I have not added Cc: stable; returning
ciphertext rather than an error is a correctness bug but not a
privilege boundary crossing, so that call is better made by the
maintainers.

Found by reading the code.  I have no EFS-encrypted NTFS volume, so
there is no reproducer; the paths were traced in the source.

Zhan Xusheng (2):
  ntfs: do not read ahead encrypted files
  ntfs: reject direct I/O reads of encrypted files

 fs/ntfs/aops.c | 7 ++++---
 fs/ntfs/file.c | 4 ++--
 2 files changed, 6 insertions(+), 5 deletions(-)


base-commit: d6d3455d8751854e0d1820f14184682e23ac4475
-- 
2.43.0


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

* [PATCH 1/2] ntfs: do not read ahead encrypted files
  2026-10-12  6:20 [PATCH 0/2] ntfs: enforce the encrypted-file policy on the read paths Zhan Xusheng
@ 2026-10-12  6:20 ` Zhan Xusheng
  2026-10-12  8:49   ` liubaolin
  2026-10-12  6:20 ` [PATCH 2/2] ntfs: reject direct I/O reads of " Zhan Xusheng
                   ` (3 subsequent siblings)
  4 siblings, 1 reply; 8+ messages in thread
From: Zhan Xusheng @ 2026-10-12  6:20 UTC (permalink / raw)
  To: Namjae Jeon; +Cc: Hyunchul Lee, ntfs, linux-kernel, Zhan Xusheng

From: Zhan Xusheng <zhanxusheng@xiaomi.com>

ntfs_read_folio() refuses EFS-encrypted files with -EOPNOTSUPP because
decryption is not implemented.  ntfs_readahead() has no NInoEncrypted()
test and passes them to iomap_readahead(), which maps the runlist and
fills the folios with the raw on-disk ciphertext.  The folios are
marked uptodate, so the read that follows never reaches ->read_folio
and returns ciphertext instead of -EOPNOTSUPP.

ntfs_read_locked_inode() sets NInoEncrypted() and NInoNonResident() for
a non-resident encrypted $DATA attribute and rejects the
encrypted-and-compressed combination, so none of the three existing
conditions fires.  read(), mmap(), splice() and fadvise() all populate
the page cache through readahead.

Skipping readahead leaves the folio unpopulated, so the read falls back
to ntfs_read_folio() and gets the intended error.

Signed-off-by: Zhan Xusheng <zhanxusheng@xiaomi.com>
Fixes: b041ca562526 ("ntfs: update iomap and address space operations")
---
 fs/ntfs/aops.c | 7 ++++---
 1 file changed, 4 insertions(+), 3 deletions(-)

diff --git a/fs/ntfs/aops.c b/fs/ntfs/aops.c
index 517d9a1563e7d..ad781674fef1a 100644
--- a/fs/ntfs/aops.c
+++ b/fs/ntfs/aops.c
@@ -240,10 +240,11 @@ static void ntfs_readahead(struct readahead_control *rac)
 	};
 
 	/*
-	 * Resident files are not cached in the page cache,
-	 * and readahead is not implemented for compressed files.
+	 * Resident files are not cached in the page cache, readahead is not
+	 * implemented for compressed files, and ntfs_read_folio() refuses
+	 * encrypted files because decryption is not implemented.
 	 */
-	if (!NInoNonResident(ni) || NInoCompressed(ni) ||
+	if (!NInoNonResident(ni) || NInoEncrypted(ni) || NInoCompressed(ni) ||
 	    NInoWofCompressed(ni))
 		return;
 	iomap_readahead(&ntfs_read_iomap_ops, &ctx, NULL);
-- 
2.43.0


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

* [PATCH 2/2] ntfs: reject direct I/O reads of encrypted files
  2026-10-12  6:20 [PATCH 0/2] ntfs: enforce the encrypted-file policy on the read paths Zhan Xusheng
  2026-10-12  6:20 ` [PATCH 1/2] ntfs: do not read ahead encrypted files Zhan Xusheng
@ 2026-10-12  6:20 ` Zhan Xusheng
  2026-10-12  8:49   ` liubaolin
  2026-10-12  8:50 ` [PATCH 0/2] ntfs: enforce the encrypted-file policy on the read paths liubaolin
                   ` (2 subsequent siblings)
  4 siblings, 1 reply; 8+ messages in thread
From: Zhan Xusheng @ 2026-10-12  6:20 UTC (permalink / raw)
  To: Namjae Jeon; +Cc: Hyunchul Lee, ntfs, linux-kernel, Zhan Xusheng

From: Zhan Xusheng <zhanxusheng@xiaomi.com>

ntfs_file_read_iter() refuses direct I/O for compressed and WOF
compressed attributes but lets encrypted ones reach iomap_dio_rw().
ntfs_read_iomap_begin_non_resident() has no NInoEncrypted() test, so it
reports IOMAP_MAPPED for the attribute's real clusters and the raw
on-disk ciphertext is copied to the caller.  Buffered reads are refused
by ntfs_read_folio(), but direct I/O never calls it.

Signed-off-by: Zhan Xusheng <zhanxusheng@xiaomi.com>
Fixes: 9c87959601e8 ("ntfs: update file operations")
---
 fs/ntfs/file.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/fs/ntfs/file.c b/fs/ntfs/file.c
index 007d1614b9ac6..eb8ed1959cd4c 100644
--- a/fs/ntfs/file.c
+++ b/fs/ntfs/file.c
@@ -460,8 +460,8 @@ static ssize_t ntfs_file_read_iter(struct kiocb *iocb, struct iov_iter *to)
 	if (NVolShutdown(NTFS_SB(sb)))
 		return -EIO;
 
-	if ((NInoCompressed(NTFS_I(vi)) || NInoWofCompressed(NTFS_I(vi))) &&
-	    iocb->ki_flags & IOCB_DIRECT)
+	if ((NInoCompressed(NTFS_I(vi)) || NInoWofCompressed(NTFS_I(vi)) ||
+	     NInoEncrypted(NTFS_I(vi))) && iocb->ki_flags & IOCB_DIRECT)
 		return -EOPNOTSUPP;
 
 	inode_lock_shared(vi);
-- 
2.43.0


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

* Re: [PATCH 1/2] ntfs: do not read ahead encrypted files
  2026-10-12  6:20 ` [PATCH 1/2] ntfs: do not read ahead encrypted files Zhan Xusheng
@ 2026-10-12  8:49   ` liubaolin
  0 siblings, 0 replies; 8+ messages in thread
From: liubaolin @ 2026-10-12  8:49 UTC (permalink / raw)
  To: Zhan Xusheng, Namjae Jeon; +Cc: Hyunchul Lee, ntfs, linux-kernel, Zhan Xusheng



在 2026/10/12 14:20, Zhan Xusheng 写道:
> From: Zhan Xusheng <zhanxusheng@xiaomi.com>
> 
> ntfs_read_folio() refuses EFS-encrypted files with -EOPNOTSUPP because
> decryption is not implemented.  ntfs_readahead() has no NInoEncrypted()
> test and passes them to iomap_readahead(), which maps the runlist and
> fills the folios with the raw on-disk ciphertext.  The folios are
> marked uptodate, so the read that follows never reaches ->read_folio
> and returns ciphertext instead of -EOPNOTSUPP.
> 
> ntfs_read_locked_inode() sets NInoEncrypted() and NInoNonResident() for
> a non-resident encrypted $DATA attribute and rejects the
> encrypted-and-compressed combination, so none of the three existing
> conditions fires.  read(), mmap(), splice() and fadvise() all populate
> the page cache through readahead.
> 
> Skipping readahead leaves the folio unpopulated, so the read falls back
> to ntfs_read_folio() and gets the intended error.
> 
> Signed-off-by: Zhan Xusheng <zhanxusheng@xiaomi.com>
> Fixes: b041ca562526 ("ntfs: update iomap and address space operations")
> ---
>   fs/ntfs/aops.c | 7 ++++---
>   1 file changed, 4 insertions(+), 3 deletions(-)
> 
> diff --git a/fs/ntfs/aops.c b/fs/ntfs/aops.c
> index 517d9a1563e7d..ad781674fef1a 100644
> --- a/fs/ntfs/aops.c
> +++ b/fs/ntfs/aops.c
> @@ -240,10 +240,11 @@ static void ntfs_readahead(struct readahead_control *rac)
>   	};
>   
>   	/*
> -	 * Resident files are not cached in the page cache,
> -	 * and readahead is not implemented for compressed files.
> +	 * Resident files are not cached in the page cache, readahead is not
> +	 * implemented for compressed files, and ntfs_read_folio() refuses
> +	 * encrypted files because decryption is not implemented.
>   	 */
> -	if (!NInoNonResident(ni) || NInoCompressed(ni) ||
> +	if (!NInoNonResident(ni) || NInoEncrypted(ni) || NInoCompressed(ni) ||
>   	    NInoWofCompressed(ni))
>   		return;
>   	iomap_readahead(&ntfs_read_iomap_ops, &ctx, NULL);

Looks good to me.

Reviewed-by: Baolin Liu <liubaolin@kylinos.cn>


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

* Re: [PATCH 2/2] ntfs: reject direct I/O reads of encrypted files
  2026-10-12  6:20 ` [PATCH 2/2] ntfs: reject direct I/O reads of " Zhan Xusheng
@ 2026-10-12  8:49   ` liubaolin
  0 siblings, 0 replies; 8+ messages in thread
From: liubaolin @ 2026-10-12  8:49 UTC (permalink / raw)
  To: Zhan Xusheng, Namjae Jeon; +Cc: Hyunchul Lee, ntfs, linux-kernel, Zhan Xusheng



在 2026/10/12 14:20, Zhan Xusheng 写道:
> From: Zhan Xusheng <zhanxusheng@xiaomi.com>
> 
> ntfs_file_read_iter() refuses direct I/O for compressed and WOF
> compressed attributes but lets encrypted ones reach iomap_dio_rw().
> ntfs_read_iomap_begin_non_resident() has no NInoEncrypted() test, so it
> reports IOMAP_MAPPED for the attribute's real clusters and the raw
> on-disk ciphertext is copied to the caller.  Buffered reads are refused
> by ntfs_read_folio(), but direct I/O never calls it.
> 
> Signed-off-by: Zhan Xusheng <zhanxusheng@xiaomi.com>
> Fixes: 9c87959601e8 ("ntfs: update file operations")
> ---
>   fs/ntfs/file.c | 4 ++--
>   1 file changed, 2 insertions(+), 2 deletions(-)
> 
> diff --git a/fs/ntfs/file.c b/fs/ntfs/file.c
> index 007d1614b9ac6..eb8ed1959cd4c 100644
> --- a/fs/ntfs/file.c
> +++ b/fs/ntfs/file.c
> @@ -460,8 +460,8 @@ static ssize_t ntfs_file_read_iter(struct kiocb *iocb, struct iov_iter *to)
>   	if (NVolShutdown(NTFS_SB(sb)))
>   		return -EIO;
>   
> -	if ((NInoCompressed(NTFS_I(vi)) || NInoWofCompressed(NTFS_I(vi))) &&
> -	    iocb->ki_flags & IOCB_DIRECT)
> +	if ((NInoCompressed(NTFS_I(vi)) || NInoWofCompressed(NTFS_I(vi)) ||
> +	     NInoEncrypted(NTFS_I(vi))) && iocb->ki_flags & IOCB_DIRECT)
>   		return -EOPNOTSUPP;
>   
>   	inode_lock_shared(vi);

Looks good to me.

Reviewed-by: Baolin Liu <liubaolin@kylinos.cn>


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

* Re: [PATCH 0/2] ntfs: enforce the encrypted-file policy on the read paths
  2026-10-12  6:20 [PATCH 0/2] ntfs: enforce the encrypted-file policy on the read paths Zhan Xusheng
  2026-10-12  6:20 ` [PATCH 1/2] ntfs: do not read ahead encrypted files Zhan Xusheng
  2026-10-12  6:20 ` [PATCH 2/2] ntfs: reject direct I/O reads of " Zhan Xusheng
@ 2026-10-12  8:50 ` liubaolin
  2026-10-12 10:01 ` Hyunchul Lee
  2026-10-12 11:58 ` Namjae Jeon
  4 siblings, 0 replies; 8+ messages in thread
From: liubaolin @ 2026-10-12  8:50 UTC (permalink / raw)
  To: Zhan Xusheng, Namjae Jeon; +Cc: Hyunchul Lee, ntfs, linux-kernel, Zhan Xusheng



在 2026/10/12 14:20, Zhan Xusheng 写道:
> From: Zhan Xusheng <zhanxusheng@xiaomi.com>
> 
> EFS-encrypted attributes are refused with -EOPNOTSUPP in exactly one
> place, ntfs_read_folio(), because decryption is not implemented.  Two
> read paths get there without passing that test and return the raw
> on-disk ciphertext instead, so the same read returns either ciphertext
> or -EOPNOTSUPP depending on which path serves it.
> 
> Patch 1 is readahead, which marks the folios uptodate so ->read_folio
> is never called.  read(), mmap(), splice() and fadvise() all populate
> the page cache this way, so one test closes all four.
> 
> Patch 2 is direct I/O, which bypasses the page cache entirely and has
> no such backstop.
> 
> Both commits are in v7.1.  I have not added Cc: stable; returning
> ciphertext rather than an error is a correctness bug but not a
> privilege boundary crossing, so that call is better made by the
> maintainers.
> 
> Found by reading the code.  I have no EFS-encrypted NTFS volume, so
> there is no reproducer; the paths were traced in the source.
> 
> Zhan Xusheng (2):
>    ntfs: do not read ahead encrypted files
>    ntfs: reject direct I/O reads of encrypted files
> 
>   fs/ntfs/aops.c | 7 ++++---
>   fs/ntfs/file.c | 4 ++--
>   2 files changed, 6 insertions(+), 5 deletions(-)
> 
> 
> base-commit: d6d3455d8751854e0d1820f14184682e23ac4475

The series looks good to me.

Reviewed-by: Baolin Liu <liubaolin@kylinos.cn>


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

* Re: [PATCH 0/2] ntfs: enforce the encrypted-file policy on the read paths
  2026-10-12  6:20 [PATCH 0/2] ntfs: enforce the encrypted-file policy on the read paths Zhan Xusheng
                   ` (2 preceding siblings ...)
  2026-10-12  8:50 ` [PATCH 0/2] ntfs: enforce the encrypted-file policy on the read paths liubaolin
@ 2026-10-12 10:01 ` Hyunchul Lee
  2026-10-12 11:58 ` Namjae Jeon
  4 siblings, 0 replies; 8+ messages in thread
From: Hyunchul Lee @ 2026-10-12 10:01 UTC (permalink / raw)
  To: Zhan Xusheng; +Cc: Namjae Jeon, ntfs, linux-kernel, Zhan Xusheng

This whole series look good to me.

Reviewed-by: Hyunchul Lee <hyc.lee@gmail.com>

On Mon, Oct 12, 2026 at 02:20:38PM +0800, Zhan Xusheng wrote:
> From: Zhan Xusheng <zhanxusheng@xiaomi.com>
> 
> EFS-encrypted attributes are refused with -EOPNOTSUPP in exactly one
> place, ntfs_read_folio(), because decryption is not implemented.  Two
> read paths get there without passing that test and return the raw
> on-disk ciphertext instead, so the same read returns either ciphertext
> or -EOPNOTSUPP depending on which path serves it.
> 
> Patch 1 is readahead, which marks the folios uptodate so ->read_folio
> is never called.  read(), mmap(), splice() and fadvise() all populate
> the page cache this way, so one test closes all four.
> 
> Patch 2 is direct I/O, which bypasses the page cache entirely and has
> no such backstop.
> 
> Both commits are in v7.1.  I have not added Cc: stable; returning
> ciphertext rather than an error is a correctness bug but not a
> privilege boundary crossing, so that call is better made by the
> maintainers.
> 
> Found by reading the code.  I have no EFS-encrypted NTFS volume, so
> there is no reproducer; the paths were traced in the source.
> 
> Zhan Xusheng (2):
>   ntfs: do not read ahead encrypted files
>   ntfs: reject direct I/O reads of encrypted files
> 
>  fs/ntfs/aops.c | 7 ++++---
>  fs/ntfs/file.c | 4 ++--
>  2 files changed, 6 insertions(+), 5 deletions(-)
> 
> 
> base-commit: d6d3455d8751854e0d1820f14184682e23ac4475
> -- 
> 2.43.0
> 

-- 
Thanks,
Hyunchul

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

* Re: [PATCH 0/2] ntfs: enforce the encrypted-file policy on the read paths
  2026-10-12  6:20 [PATCH 0/2] ntfs: enforce the encrypted-file policy on the read paths Zhan Xusheng
                   ` (3 preceding siblings ...)
  2026-10-12 10:01 ` Hyunchul Lee
@ 2026-10-12 11:58 ` Namjae Jeon
  4 siblings, 0 replies; 8+ messages in thread
From: Namjae Jeon @ 2026-10-12 11:58 UTC (permalink / raw)
  To: Zhan Xusheng; +Cc: Hyunchul Lee, ntfs, linux-kernel, Zhan Xusheng

On Mon, Oct 12, 2026 at 3:20 PM Zhan Xusheng <zhanxusheng1024@gmail.com> wrote:
>
> From: Zhan Xusheng <zhanxusheng@xiaomi.com>
>
> EFS-encrypted attributes are refused with -EOPNOTSUPP in exactly one
> place, ntfs_read_folio(), because decryption is not implemented.  Two
> read paths get there without passing that test and return the raw
> on-disk ciphertext instead, so the same read returns either ciphertext
> or -EOPNOTSUPP depending on which path serves it.
>
> Patch 1 is readahead, which marks the folios uptodate so ->read_folio
> is never called.  read(), mmap(), splice() and fadvise() all populate
> the page cache this way, so one test closes all four.
>
> Patch 2 is direct I/O, which bypasses the page cache entirely and has
> no such backstop.
>
> Both commits are in v7.1.  I have not added Cc: stable; returning
> ciphertext rather than an error is a correctness bug but not a
> privilege boundary crossing, so that call is better made by the
> maintainers.
>
> Found by reading the code.  I have no EFS-encrypted NTFS volume, so
> there is no reproducer; the paths were traced in the source.
>
> Zhan Xusheng (2):
>   ntfs: do not read ahead encrypted files
>   ntfs: reject direct I/O reads of encrypted files
Applied them to #ntfs-next.
Thanks!

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

end of thread, other threads:[~2026-10-12 11:58 UTC | newest]

Thread overview: 8+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-10-12  6:20 [PATCH 0/2] ntfs: enforce the encrypted-file policy on the read paths Zhan Xusheng
2026-10-12  6:20 ` [PATCH 1/2] ntfs: do not read ahead encrypted files Zhan Xusheng
2026-10-12  8:49   ` liubaolin
2026-10-12  6:20 ` [PATCH 2/2] ntfs: reject direct I/O reads of " Zhan Xusheng
2026-10-12  8:49   ` liubaolin
2026-10-12  8:50 ` [PATCH 0/2] ntfs: enforce the encrypted-file policy on the read paths liubaolin
2026-10-12 10:01 ` Hyunchul Lee
2026-10-12 11:58 ` Namjae Jeon

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®