On 21 August 2012 13:43, Alexander Graf <ag...@suse.de> wrote:
> The statfs syscall should always memset(0) its full struct extent before
> writing to it. Newer versions of the syscall use one of the reserved fields
> for flags, which would otherwise get stale values from uncleaned memory.
>
> This fixes libarchive for me, which got confused about the return value of
> pathconf("/", _PC_REC_XFER_ALIGN) otherwise, as it some times gave old 
> pointers
> as return value.
>
> Signed-off-by: Alexander Graf <ag...@suse.de>
> ---
>  linux-user/syscall.c |   12 ++++++++++++
>  1 files changed, 12 insertions(+), 0 deletions(-)
>
> diff --git a/linux-user/syscall.c b/linux-user/syscall.c
> index d19efb8..61f5718 100644
> --- a/linux-user/syscall.c
> +++ b/linux-user/syscall.c
> @@ -6667,6 +6667,12 @@ abi_long do_syscall(void *cpu_env, int num, abi_long 
> arg1,
>              __put_user(stfs.f_fsid.__val[0], &target_stfs->f_fsid.val[0]);
>              __put_user(stfs.f_fsid.__val[1], &target_stfs->f_fsid.val[1]);
>              __put_user(stfs.f_namelen, &target_stfs->f_namelen);
> +            __put_user(stfs.f_frsize, &target_stfs->f_frsize);
> +            __put_user(0, &target_stfs->f_spare[0]);
> +            __put_user(0, &target_stfs->f_spare[1]);
> +            __put_user(0, &target_stfs->f_spare[2]);
> +            __put_user(0, &target_stfs->f_spare[3]);
> +            __put_user(0, &target_stfs->f_spare[4]);
>              unlock_user_struct(target_stfs, arg2, 1);
>          }
>          break;
> @@ -6695,6 +6701,12 @@ abi_long do_syscall(void *cpu_env, int num, abi_long 
> arg1,
>              __put_user(stfs.f_fsid.__val[0], &target_stfs->f_fsid.val[0]);
>              __put_user(stfs.f_fsid.__val[1], &target_stfs->f_fsid.val[1]);
>              __put_user(stfs.f_namelen, &target_stfs->f_namelen);
> +            __put_user(stfs.f_frsize, &target_stfs->f_frsize);
> +            __put_user(0, &target_stfs->f_spare[0]);
> +            __put_user(0, &target_stfs->f_spare[1]);
> +            __put_user(0, &target_stfs->f_spare[2]);
> +            __put_user(0, &target_stfs->f_spare[3]);
> +            __put_user(0, &target_stfs->f_spare[4]);
>              unlock_user_struct(target_stfs, arg3, 1);
>          }
>          break;

For some targets there are 6 f_spare[] slots, not 5... I suggest
     memset(target_stfs->f_spare, 0, sizeof(target_stfs->f_spare));
instead (which matches how the kernel does this).

-- PMM

Reply via email to