[PATCH] linux-user: Use getcwd syscall directly

Andreas Schwab posted 1 patch 3 years, 9 months ago
Test docker-quick@centos7 failed
Test docker-mingw@fedora failed
Test checkpatch failed
Test FreeBSD failed
Patches applied successfully (tree, apply log)
git fetch https://github.com/patchew-project/qemu tags/patchew/mvmmu3qplvi.fsf@suse.de
Maintainers: Laurent Vivier <laurent@vivier.eu>
linux-user/syscall.c | 9 +--------
1 file changed, 1 insertion(+), 8 deletions(-)
[PATCH] linux-user: Use getcwd syscall directly
Posted by Andreas Schwab 3 years, 9 months ago
The glibc getcwd function returns different errors than the getcwd
syscall, which triggers an assertion failure in the glibc getcwd function
when running under the emulation.

Signed-off-by: Andreas Schwab <schwab@suse.de>
---
 linux-user/syscall.c | 9 +--------
 1 file changed, 1 insertion(+), 8 deletions(-)

diff --git a/linux-user/syscall.c b/linux-user/syscall.c
index b9144b18fc..e4e46867e8 100644
--- a/linux-user/syscall.c
+++ b/linux-user/syscall.c
@@ -388,14 +388,7 @@ static bitmask_transtbl fcntl_flags_tbl[] = {
   { 0, 0, 0, 0 }
 };
 
-static int sys_getcwd1(char *buf, size_t size)
-{
-  if (getcwd(buf, size) == NULL) {
-      /* getcwd() sets errno */
-      return (-1);
-  }
-  return strlen(buf)+1;
-}
+_syscall2(int, sys_getcwd1, char *, buf, size_t, size)
 
 #ifdef TARGET_NR_utimensat
 #if defined(__NR_utimensat)
-- 
2.26.2


-- 
Andreas Schwab, SUSE Labs, schwab@suse.de
GPG Key fingerprint = 0196 BAD8 1CE9 1970 F4BE  1748 E4D4 88E3 0EEA B9D7
"And now for something completely different."

Re: [PATCH] linux-user: Use getcwd syscall directly
Posted by Laurent Vivier 3 years, 9 months ago
Le 23/07/2020 à 12:27, Andreas Schwab a écrit :
> The glibc getcwd function returns different errors than the getcwd
> syscall, which triggers an assertion failure in the glibc getcwd function
> when running under the emulation.
> 
> Signed-off-by: Andreas Schwab <schwab@suse.de>
> ---
>  linux-user/syscall.c | 9 +--------
>  1 file changed, 1 insertion(+), 8 deletions(-)
> 
> diff --git a/linux-user/syscall.c b/linux-user/syscall.c
> index b9144b18fc..e4e46867e8 100644
> --- a/linux-user/syscall.c
> +++ b/linux-user/syscall.c
> @@ -388,14 +388,7 @@ static bitmask_transtbl fcntl_flags_tbl[] = {
>    { 0, 0, 0, 0 }
>  };
>  
> -static int sys_getcwd1(char *buf, size_t size)
> -{
> -  if (getcwd(buf, size) == NULL) {
> -      /* getcwd() sets errno */
> -      return (-1);
> -  }
> -  return strlen(buf)+1;
> -}
> +_syscall2(int, sys_getcwd1, char *, buf, size_t, size)
>  
>  #ifdef TARGET_NR_utimensat
>  #if defined(__NR_utimensat)
> 

Reviewed-by: Laurent Vivier <laurent@vivier.eu>

I'll add in the commit message the explanation you did on your previous
attempt:

"When the syscall returns ENAMETOOLONG,
the glibc wrapper uses a fallback implementation that potentially
handles an unlimited path length, and returns with ERANGE if the
provided buffer is too small.  The qemu emulation cannot distinguish the
two cases, and thus always returns ERANGE.  This is unexpected by the
glibc wrapper."

Thanks,
Laurent

Re: [PATCH] linux-user: Use getcwd syscall directly
Posted by Laurent Vivier 3 years, 9 months ago
Le 23/07/2020 à 12:27, Andreas Schwab a écrit :
> The glibc getcwd function returns different errors than the getcwd
> syscall, which triggers an assertion failure in the glibc getcwd function
> when running under the emulation.
> 
> Signed-off-by: Andreas Schwab <schwab@suse.de>
> ---
>  linux-user/syscall.c | 9 +--------
>  1 file changed, 1 insertion(+), 8 deletions(-)
> 
> diff --git a/linux-user/syscall.c b/linux-user/syscall.c
> index b9144b18fc..e4e46867e8 100644
> --- a/linux-user/syscall.c
> +++ b/linux-user/syscall.c
> @@ -388,14 +388,7 @@ static bitmask_transtbl fcntl_flags_tbl[] = {
>    { 0, 0, 0, 0 }
>  };
>  
> -static int sys_getcwd1(char *buf, size_t size)
> -{
> -  if (getcwd(buf, size) == NULL) {
> -      /* getcwd() sets errno */
> -      return (-1);
> -  }
> -  return strlen(buf)+1;
> -}
> +_syscall2(int, sys_getcwd1, char *, buf, size_t, size)
>  
>  #ifdef TARGET_NR_utimensat
>  #if defined(__NR_utimensat)
> 

Applied to my linux-user-for-5.1 branch.

Thanks,
Laurent