Possible issue with check_dir_not_empty

Bernhard Übelacker bernhardu@mailbox.org
Mon Nov 18 21:32:46 GMT 2024


Hello Corinna,

Am 18.11.24 um 17:52 schrieb Corinna Vinschen:
> Hi Bernhard,
> 
> On Nov 16 23:36, Bernhard Übelacker via Cygwin wrote:
>> Hello everyone,
>>
>> Is is about the buffer allocated in check_dir_not_empty.
>>
>> The pointer pfni gets allocated the buffer at the begin,
>> and is used in the NtQueryDirectoryFile call before the loops.
>> In the loop the pointer pfni is also used as iterator.
>> Therefore it holds no longer the initial buffer at the call
>> to NtQueryDirectoryFile in the while conditition at the bottom.
> 
> Good catch, thank you!

Forgot to mention the background. I actually hit this issue with running
Cygwin's git.exe below a modified Wine checking out the tag 3.5.3 of
newlib-cygwin. Unfortunately reproducing this issue still needs a few 
additional Wine patches to finish Cygwin installation.


>> Attached is a possible modification to always use the allocated buffer.
>>
>> Kind regards,
>> Bernhard
> 
> Thanks for the patch.
> 
> Would you be ok if I apply a simplified version under your authorship?
> 
> Rather than add a pfni_it(erator), use pfni as iterator and add a
> pfni_buf variable.  This is a much smaller patch, and is more in line
> with the usual variable naming in Cygwin.
> 
> I also added a release message text and a Fixes: line to the commit
> message.
> 
> Below is the tweaked patch.  If you're ok with this version, I'll push
> it.


That would be great. Thanks for maintaining Cygwin.

Kind regards,
Bernhard


> 
> Thanks,
> Corinna
> 
> 
>  From fbd8b9d769135d6410b423eb9d82b49be52523bb Mon Sep 17 00:00:00 2001
> From: =?UTF-8?q?Bernhard=20=C3=9Cbelacker?= <bernhardu@mailbox.org>
> Date: Sat, 16 Nov 2024 18:09:50 +0100
> Subject: [PATCH] Cygwin: check_dir_not_empty: Avoid leaving the allocated
>   buffer.
> MIME-Version: 1.0
> Content-Type: text/plain; charset=UTF-8
> Content-Transfer-Encoding: 8bit
> 
> The pointer pfni gets allocated the buffer at the begin,
> and is used in the NtQueryDirectoryFile call before the loops.
> In the loop the pointer pfni is also used as iterator.
> Therefore it holds no longer the initial buffer at the call
> to NtQueryDirectoryFile in the while conditition at the bottom.
> 
> Fixes: 28fa2a72f8106 ("* syscalls.cc (check_dir_not_empty): Check surplus directory entries")
> Signed-off-by: Bernhard Übelacker <bernhardu@mailbox.org>
> ---
>   winsup/cygwin/release/3.5.5 |  3 +++
>   winsup/cygwin/syscalls.cc   | 10 ++++++----
>   2 files changed, 9 insertions(+), 4 deletions(-)
> 
> diff --git a/winsup/cygwin/release/3.5.5 b/winsup/cygwin/release/3.5.5
> index 2ca4572db7ed..3088f8682b6b 100644
> --- a/winsup/cygwin/release/3.5.5
> +++ b/winsup/cygwin/release/3.5.5
> @@ -33,3 +33,6 @@ Fixes:
>   
>   - Fix type of pthread_sigqueue() first parameter to match Linux.
>     Addresses: https://cygwin.com/pipermail/cygwin/2024-September/256439.html
> +
> +- Fix potential stack corruption in rmdir() in a border case.
> +  Addresses: https://cygwin.com/pipermail/cygwin/2024-November/256774.html
> diff --git a/winsup/cygwin/syscalls.cc b/winsup/cygwin/syscalls.cc
> index df7d3a14efd4..433739cda6e0 100644
> --- a/winsup/cygwin/syscalls.cc
> +++ b/winsup/cygwin/syscalls.cc
> @@ -617,9 +617,10 @@ check_dir_not_empty (HANDLE dir, path_conv &pc)
>     IO_STATUS_BLOCK io;
>     const ULONG bufsiz = 3 * sizeof (FILE_NAMES_INFORMATION)
>   		       + 3 * NAME_MAX * sizeof (WCHAR);
> -  PFILE_NAMES_INFORMATION pfni = (PFILE_NAMES_INFORMATION)
> -				 alloca (bufsiz);
> -  NTSTATUS status = NtQueryDirectoryFile (dir, NULL, NULL, 0, &io, pfni,
> +  PFILE_NAMES_INFORMATION pfni_buf = (PFILE_NAMES_INFORMATION)
> +				     alloca (bufsiz);
> +  PFILE_NAMES_INFORMATION pfni;
> +  NTSTATUS status = NtQueryDirectoryFile (dir, NULL, NULL, 0, &io, pfni_buf,
>   					  bufsiz, FileNamesInformation,
>   					  FALSE, NULL, TRUE);
>     if (!NT_SUCCESS (status))
> @@ -631,6 +632,7 @@ check_dir_not_empty (HANDLE dir, path_conv &pc)
>     int cnt = 1;
>     do
>       {
> +      pfni = pfni_buf;
>         while (pfni->NextEntryOffset)
>   	{
>   	  if (++cnt > 2)
> @@ -677,7 +679,7 @@ check_dir_not_empty (HANDLE dir, path_conv &pc)
>   	  pfni = (PFILE_NAMES_INFORMATION) ((caddr_t) pfni + pfni->NextEntryOffset);
>   	}
>       }
> -  while (NT_SUCCESS (NtQueryDirectoryFile (dir, NULL, NULL, 0, &io, pfni,
> +  while (NT_SUCCESS (NtQueryDirectoryFile (dir, NULL, NULL, 0, &io, pfni_buf,
>   					   bufsiz, FileNamesInformation,
>   					   FALSE, NULL, FALSE)));
>     return STATUS_SUCCESS;



More information about the Cygwin mailing list