All the mail mirrored from lore.kernel.org
 help / color / mirror / Atom feed
* [Qemu-devel] [PATCH] linux-user: fix emulation of getdents
@ 2012-08-16 21:20 Dmitry V. Levin
  2012-08-17  7:33 ` 陳韋任 (Wei-Ren Chen)
  2012-08-18 14:20 ` Blue Swirl
  0 siblings, 2 replies; 10+ messages in thread
From: Dmitry V. Levin @ 2012-08-16 21:20 UTC (permalink / raw
  To: qemu-devel

In case when TARGET_ABI_BITS == 32 && HOST_LONG_BITS == 64, the last
byte of the target dirent structure (aka d_type byte) was never copied
from the native dirent structure, thus breaking everything that relies
on valid d_type value, e.g. glob(3).

Signed-off-by: Dmitry V. Levin <ldv@altlinux.org>
---
 linux-user/syscall.c      | 7 +++----
 linux-user/syscall_defs.h | 3 ++-
 2 files changed, 5 insertions(+), 5 deletions(-)

diff --git a/linux-user/syscall.c b/linux-user/syscall.c
index 41c869b..2b6025b 100644
--- a/linux-user/syscall.c
+++ b/linux-user/syscall.c
@@ -7030,10 +7030,9 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
                     tde->d_ino = tswapal(de->d_ino);
                     tde->d_off = tswapal(de->d_off);
 		    tnamelen = treclen - (2 * sizeof(abi_long) + 2);
-		    if (tnamelen > 256)
-                        tnamelen = 256;
-                    /* XXX: may not be correct */
-                    pstrcpy(tde->d_name, tnamelen, de->d_name);
+		    if (tnamelen > sizeof(tde->d_name))
+                        tnamelen = sizeof(tde->d_name);
+                    memcpy(tde->d_name, de->d_name, tnamelen);
                     de = (struct linux_dirent *)((char *)de + reclen);
                     len -= reclen;
                     tde = (struct target_dirent *)((char *)tde + treclen);
diff --git a/linux-user/syscall_defs.h b/linux-user/syscall_defs.h
index 2cfda5a..f27a8d4 100644
--- a/linux-user/syscall_defs.h
+++ b/linux-user/syscall_defs.h
@@ -258,7 +258,8 @@ struct target_dirent {
 	abi_long	d_ino;
 	abi_long	d_off;
 	unsigned short	d_reclen;
-	char		d_name[256]; /* We must not include limits.h! */
+	char		d_name[257]; 	/* We must not include limits.h! */
+					/* 257 = NAME_MAX + '\0' + d_type */
 };
 
 struct target_dirent64 {

-- 
ldv

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

* Re: [Qemu-devel] [PATCH] linux-user: fix emulation of getdents
  2012-08-16 21:20 [Qemu-devel] [PATCH] linux-user: fix emulation of getdents Dmitry V. Levin
@ 2012-08-17  7:33 ` 陳韋任 (Wei-Ren Chen)
  2012-08-18 14:20 ` Blue Swirl
  1 sibling, 0 replies; 10+ messages in thread
From: 陳韋任 (Wei-Ren Chen) @ 2012-08-17  7:33 UTC (permalink / raw
  To: qemu-devel; +Cc: Riku Voipio

  CC'ed to linux-user maintainer, Riku.

On Fri, Aug 17, 2012 at 01:20:19AM +0400, Dmitry V. Levin wrote:
> In case when TARGET_ABI_BITS == 32 && HOST_LONG_BITS == 64, the last
> byte of the target dirent structure (aka d_type byte) was never copied
> from the native dirent structure, thus breaking everything that relies
> on valid d_type value, e.g. glob(3).
> 
> Signed-off-by: Dmitry V. Levin <ldv@altlinux.org>
> ---
>  linux-user/syscall.c      | 7 +++----
>  linux-user/syscall_defs.h | 3 ++-
>  2 files changed, 5 insertions(+), 5 deletions(-)
> 
> diff --git a/linux-user/syscall.c b/linux-user/syscall.c
> index 41c869b..2b6025b 100644
> --- a/linux-user/syscall.c
> +++ b/linux-user/syscall.c
> @@ -7030,10 +7030,9 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
>                      tde->d_ino = tswapal(de->d_ino);
>                      tde->d_off = tswapal(de->d_off);
>  		    tnamelen = treclen - (2 * sizeof(abi_long) + 2);
> -		    if (tnamelen > 256)
> -                        tnamelen = 256;
> -                    /* XXX: may not be correct */
> -                    pstrcpy(tde->d_name, tnamelen, de->d_name);
> +		    if (tnamelen > sizeof(tde->d_name))
> +                        tnamelen = sizeof(tde->d_name);
> +                    memcpy(tde->d_name, de->d_name, tnamelen);
>                      de = (struct linux_dirent *)((char *)de + reclen);
>                      len -= reclen;
>                      tde = (struct target_dirent *)((char *)tde + treclen);
> diff --git a/linux-user/syscall_defs.h b/linux-user/syscall_defs.h
> index 2cfda5a..f27a8d4 100644
> --- a/linux-user/syscall_defs.h
> +++ b/linux-user/syscall_defs.h
> @@ -258,7 +258,8 @@ struct target_dirent {
>  	abi_long	d_ino;
>  	abi_long	d_off;
>  	unsigned short	d_reclen;
> -	char		d_name[256]; /* We must not include limits.h! */
> +	char		d_name[257]; 	/* We must not include limits.h! */
> +					/* 257 = NAME_MAX + '\0' + d_type */
>  };
>  
>  struct target_dirent64 {
> 
> -- 
> ldv

-- 
Wei-Ren Chen (陳韋任)
Computer Systems Lab, Institute of Information Science,
Academia Sinica, Taiwan (R.O.C.)
Tel:886-2-2788-3799 #1667
Homepage: http://people.cs.nctu.edu.tw/~chenwj

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

* Re: [Qemu-devel] [PATCH] linux-user: fix emulation of getdents
  2012-08-16 21:20 [Qemu-devel] [PATCH] linux-user: fix emulation of getdents Dmitry V. Levin
  2012-08-17  7:33 ` 陳韋任 (Wei-Ren Chen)
@ 2012-08-18 14:20 ` Blue Swirl
  2012-08-18 21:56   ` [Qemu-devel] [PATCH v2] " Dmitry V. Levin
  1 sibling, 1 reply; 10+ messages in thread
From: Blue Swirl @ 2012-08-18 14:20 UTC (permalink / raw
  To: Dmitry V. Levin; +Cc: qemu-devel

On Thu, Aug 16, 2012 at 9:20 PM, Dmitry V. Levin <ldv@altlinux.org> wrote:
> In case when TARGET_ABI_BITS == 32 && HOST_LONG_BITS == 64, the last
> byte of the target dirent structure (aka d_type byte) was never copied
> from the native dirent structure, thus breaking everything that relies
> on valid d_type value, e.g. glob(3).
>
> Signed-off-by: Dmitry V. Levin <ldv@altlinux.org>
> ---
>  linux-user/syscall.c      | 7 +++----
>  linux-user/syscall_defs.h | 3 ++-
>  2 files changed, 5 insertions(+), 5 deletions(-)
>
> diff --git a/linux-user/syscall.c b/linux-user/syscall.c
> index 41c869b..2b6025b 100644
> --- a/linux-user/syscall.c
> +++ b/linux-user/syscall.c
> @@ -7030,10 +7030,9 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
>                      tde->d_ino = tswapal(de->d_ino);
>                      tde->d_off = tswapal(de->d_off);
>                     tnamelen = treclen - (2 * sizeof(abi_long) + 2);
> -                   if (tnamelen > 256)
> -                        tnamelen = 256;
> -                    /* XXX: may not be correct */
> -                    pstrcpy(tde->d_name, tnamelen, de->d_name);
> +                   if (tnamelen > sizeof(tde->d_name))
> +                        tnamelen = sizeof(tde->d_name);

Missing braces, please read CODING_STYLE.

Otherwise patch looks good.

> +                    memcpy(tde->d_name, de->d_name, tnamelen);
>                      de = (struct linux_dirent *)((char *)de + reclen);
>                      len -= reclen;
>                      tde = (struct target_dirent *)((char *)tde + treclen);
> diff --git a/linux-user/syscall_defs.h b/linux-user/syscall_defs.h
> index 2cfda5a..f27a8d4 100644
> --- a/linux-user/syscall_defs.h
> +++ b/linux-user/syscall_defs.h
> @@ -258,7 +258,8 @@ struct target_dirent {
>         abi_long        d_ino;
>         abi_long        d_off;
>         unsigned short  d_reclen;
> -       char            d_name[256]; /* We must not include limits.h! */
> +       char            d_name[257];    /* We must not include limits.h! */
> +                                       /* 257 = NAME_MAX + '\0' + d_type */
>  };
>
>  struct target_dirent64 {
>
> --
> ldv
>

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

* [Qemu-devel] [PATCH v2] linux-user: fix emulation of getdents
  2012-08-18 14:20 ` Blue Swirl
@ 2012-08-18 21:56   ` Dmitry V. Levin
  2012-08-19 12:59     ` Blue Swirl
  2012-08-20 16:17     ` Peter Maydell
  0 siblings, 2 replies; 10+ messages in thread
From: Dmitry V. Levin @ 2012-08-18 21:56 UTC (permalink / raw
  To: qemu-devel; +Cc: Blue Swirl, Riku Voipio

In case when TARGET_ABI_BITS == 32 && HOST_LONG_BITS == 64, the last
byte of the target dirent structure (aka d_type byte) was never copied
from the host dirent structure, thus breaking everything that relies
on valid d_type value, e.g. glob(3).

Signed-off-by: Dmitry V. Levin <ldv@altlinux.org>
---
 linux-user/syscall.c      | 8 ++++----
 linux-user/syscall_defs.h | 3 ++-
 2 files changed, 6 insertions(+), 5 deletions(-)

diff --git a/linux-user/syscall.c b/linux-user/syscall.c
index 41c869b..adc3270 100644
--- a/linux-user/syscall.c
+++ b/linux-user/syscall.c
@@ -7030,10 +7030,10 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
                     tde->d_ino = tswapal(de->d_ino);
                     tde->d_off = tswapal(de->d_off);
 		    tnamelen = treclen - (2 * sizeof(abi_long) + 2);
-		    if (tnamelen > 256)
-                        tnamelen = 256;
-                    /* XXX: may not be correct */
-                    pstrcpy(tde->d_name, tnamelen, de->d_name);
+                    if (tnamelen > sizeof(tde->d_name)) {
+                        tnamelen = sizeof(tde->d_name);
+                    }
+                    memcpy(tde->d_name, de->d_name, tnamelen);
                     de = (struct linux_dirent *)((char *)de + reclen);
                     len -= reclen;
                     tde = (struct target_dirent *)((char *)tde + treclen);
diff --git a/linux-user/syscall_defs.h b/linux-user/syscall_defs.h
index 2cfda5a..19fe414 100644
--- a/linux-user/syscall_defs.h
+++ b/linux-user/syscall_defs.h
@@ -258,7 +258,8 @@ struct target_dirent {
 	abi_long	d_ino;
 	abi_long	d_off;
 	unsigned short	d_reclen;
-	char		d_name[256]; /* We must not include limits.h! */
+	char		d_name[257];    /* 257 = NAME_MAX + '\0' + d_type, */
+                                        /* we must not include limits.h! */
 };
 
 struct target_dirent64 {

-- 
ldv

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

* Re: [Qemu-devel] [PATCH v2] linux-user: fix emulation of getdents
  2012-08-18 21:56   ` [Qemu-devel] [PATCH v2] " Dmitry V. Levin
@ 2012-08-19 12:59     ` Blue Swirl
  2012-08-20 16:17     ` Peter Maydell
  1 sibling, 0 replies; 10+ messages in thread
From: Blue Swirl @ 2012-08-19 12:59 UTC (permalink / raw
  To: Dmitry V. Levin; +Cc: Riku Voipio, qemu-devel

On Sat, Aug 18, 2012 at 9:56 PM, Dmitry V. Levin <ldv@altlinux.org> wrote:
> In case when TARGET_ABI_BITS == 32 && HOST_LONG_BITS == 64, the last
> byte of the target dirent structure (aka d_type byte) was never copied
> from the host dirent structure, thus breaking everything that relies
> on valid d_type value, e.g. glob(3).
>
> Signed-off-by: Dmitry V. Levin <ldv@altlinux.org>

Acked-by: Blue Swirl <blauwirbel@gmail.com>

> ---
>  linux-user/syscall.c      | 8 ++++----
>  linux-user/syscall_defs.h | 3 ++-
>  2 files changed, 6 insertions(+), 5 deletions(-)
>
> diff --git a/linux-user/syscall.c b/linux-user/syscall.c
> index 41c869b..adc3270 100644
> --- a/linux-user/syscall.c
> +++ b/linux-user/syscall.c
> @@ -7030,10 +7030,10 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
>                      tde->d_ino = tswapal(de->d_ino);
>                      tde->d_off = tswapal(de->d_off);
>                     tnamelen = treclen - (2 * sizeof(abi_long) + 2);
> -                   if (tnamelen > 256)
> -                        tnamelen = 256;
> -                    /* XXX: may not be correct */
> -                    pstrcpy(tde->d_name, tnamelen, de->d_name);
> +                    if (tnamelen > sizeof(tde->d_name)) {
> +                        tnamelen = sizeof(tde->d_name);
> +                    }
> +                    memcpy(tde->d_name, de->d_name, tnamelen);
>                      de = (struct linux_dirent *)((char *)de + reclen);
>                      len -= reclen;
>                      tde = (struct target_dirent *)((char *)tde + treclen);
> diff --git a/linux-user/syscall_defs.h b/linux-user/syscall_defs.h
> index 2cfda5a..19fe414 100644
> --- a/linux-user/syscall_defs.h
> +++ b/linux-user/syscall_defs.h
> @@ -258,7 +258,8 @@ struct target_dirent {
>         abi_long        d_ino;
>         abi_long        d_off;
>         unsigned short  d_reclen;
> -       char            d_name[256]; /* We must not include limits.h! */
> +       char            d_name[257];    /* 257 = NAME_MAX + '\0' + d_type, */
> +                                        /* we must not include limits.h! */
>  };
>
>  struct target_dirent64 {
>
> --
> ldv

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

* Re: [Qemu-devel] [PATCH v2] linux-user: fix emulation of getdents
  2012-08-18 21:56   ` [Qemu-devel] [PATCH v2] " Dmitry V. Levin
  2012-08-19 12:59     ` Blue Swirl
@ 2012-08-20 16:17     ` Peter Maydell
  2012-08-20 21:36       ` [Qemu-devel] [PATCH v3] " Dmitry V. Levin
  1 sibling, 1 reply; 10+ messages in thread
From: Peter Maydell @ 2012-08-20 16:17 UTC (permalink / raw
  To: Dmitry V. Levin; +Cc: Blue Swirl, Riku Voipio, qemu-devel

On 18 August 2012 22:56, Dmitry V. Levin <ldv@altlinux.org> wrote:
> In case when TARGET_ABI_BITS == 32 && HOST_LONG_BITS == 64, the last
> byte of the target dirent structure (aka d_type byte) was never copied
> from the host dirent structure, thus breaking everything that relies
> on valid d_type value, e.g. glob(3).
>
> Signed-off-by: Dmitry V. Levin <ldv@altlinux.org>
> ---
>  linux-user/syscall.c      | 8 ++++----
>  linux-user/syscall_defs.h | 3 ++-
>  2 files changed, 6 insertions(+), 5 deletions(-)
>
> diff --git a/linux-user/syscall.c b/linux-user/syscall.c
> index 41c869b..adc3270 100644
> --- a/linux-user/syscall.c
> +++ b/linux-user/syscall.c
> @@ -7030,10 +7030,10 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
>                      tde->d_ino = tswapal(de->d_ino);
>                      tde->d_off = tswapal(de->d_off);
>                     tnamelen = treclen - (2 * sizeof(abi_long) + 2);

Incidentally I think this would be clearer as
  tnamelen = treclen - offsetof(target_dirent, d_name);

> -                   if (tnamelen > 256)
> -                        tnamelen = 256;
> -                    /* XXX: may not be correct */
> -                    pstrcpy(tde->d_name, tnamelen, de->d_name);
> +                    if (tnamelen > sizeof(tde->d_name)) {
> +                        tnamelen = sizeof(tde->d_name);
> +                    }
> +                    memcpy(tde->d_name, de->d_name, tnamelen);

Why are we limiting the amount copied to sizeof(tde->d_name) in the
first place? The only actual limit we care about is that we mustn't
overrun the guest's overall buffer size (and I assert that we can't
do that because sizeof(target_dirent) <= sizeof(linux_dirent). We
could even assert in the code that we don't write more than 'count'
bytes to the guest buffer...

As far as I can tell the kernel doesn't impose any particular limit
on the filesize; we should just copy all of the record as defined
by d_reclen.

>                      de = (struct linux_dirent *)((char *)de + reclen);
>                      len -= reclen;
>                      tde = (struct target_dirent *)((char *)tde + treclen);
> diff --git a/linux-user/syscall_defs.h b/linux-user/syscall_defs.h
> index 2cfda5a..19fe414 100644
> --- a/linux-user/syscall_defs.h
> +++ b/linux-user/syscall_defs.h
> @@ -258,7 +258,8 @@ struct target_dirent {
>         abi_long        d_ino;
>         abi_long        d_off;
>         unsigned short  d_reclen;
> -       char            d_name[256]; /* We must not include limits.h! */
> +       char            d_name[257];    /* 257 = NAME_MAX + '\0' + d_type, */
> +                                        /* we must not include limits.h! */
>  };

...and if we did that we could make d_name[] a flexible
array member, ie "char d_name[];".

-- PMM

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

* [Qemu-devel] [PATCH v3] linux-user: fix emulation of getdents
  2012-08-20 16:17     ` Peter Maydell
@ 2012-08-20 21:36       ` Dmitry V. Levin
  2012-08-20 22:05         ` Peter Maydell
  0 siblings, 1 reply; 10+ messages in thread
From: Dmitry V. Levin @ 2012-08-20 21:36 UTC (permalink / raw
  To: qemu-devel; +Cc: Blue Swirl, Peter Maydell, Riku Voipio

In case when TARGET_ABI_BITS == 32 && HOST_LONG_BITS == 64, the last
byte of the target dirent structure (aka d_type byte) was never copied
from the host dirent structure, thus breaking everything that relies
on valid d_type value, e.g. glob(3).

Signed-off-by: Dmitry V. Levin <ldv@altlinux.org>
---
 linux-user/syscall.c      | 11 +++++------
 linux-user/syscall_defs.h |  2 +-
 2 files changed, 6 insertions(+), 7 deletions(-)

diff --git a/linux-user/syscall.c b/linux-user/syscall.c
index 41c869b..8a8aaca 100644
--- a/linux-user/syscall.c
+++ b/linux-user/syscall.c
@@ -7025,15 +7025,14 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
 		tde = target_dirp;
                 while (len > 0) {
                     reclen = de->d_reclen;
-		    treclen = reclen - (2 * (sizeof(long) - sizeof(abi_long)));
+                    tnamelen = reclen - offsetof(struct linux_dirent, d_name);
+                    assert(tnamelen >= 0);
+                    treclen = tnamelen + offsetof(struct target_dirent, d_name);
+                    assert(count1 + treclen <= count);
                     tde->d_reclen = tswap16(treclen);
                     tde->d_ino = tswapal(de->d_ino);
                     tde->d_off = tswapal(de->d_off);
-		    tnamelen = treclen - (2 * sizeof(abi_long) + 2);
-		    if (tnamelen > 256)
-                        tnamelen = 256;
-                    /* XXX: may not be correct */
-                    pstrcpy(tde->d_name, tnamelen, de->d_name);
+                    memcpy(tde->d_name, de->d_name, tnamelen);
                     de = (struct linux_dirent *)((char *)de + reclen);
                     len -= reclen;
                     tde = (struct target_dirent *)((char *)tde + treclen);
diff --git a/linux-user/syscall_defs.h b/linux-user/syscall_defs.h
index 2cfda5a..f7271fa 100644
--- a/linux-user/syscall_defs.h
+++ b/linux-user/syscall_defs.h
@@ -258,7 +258,7 @@ struct target_dirent {
 	abi_long	d_ino;
 	abi_long	d_off;
 	unsigned short	d_reclen;
-	char		d_name[256]; /* We must not include limits.h! */
+	char		d_name[];
 };
 
 struct target_dirent64 {

-- 
ldv

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

* Re: [Qemu-devel] [PATCH v3] linux-user: fix emulation of getdents
  2012-08-20 21:36       ` [Qemu-devel] [PATCH v3] " Dmitry V. Levin
@ 2012-08-20 22:05         ` Peter Maydell
  2012-08-20 22:13           ` [Qemu-devel] [PATCH v4] " Dmitry V. Levin
  0 siblings, 1 reply; 10+ messages in thread
From: Peter Maydell @ 2012-08-20 22:05 UTC (permalink / raw
  To: Dmitry V. Levin; +Cc: Blue Swirl, Riku Voipio, qemu-devel

On 20 August 2012 22:36, Dmitry V. Levin <ldv@altlinux.org> wrote:
> In case when TARGET_ABI_BITS == 32 && HOST_LONG_BITS == 64, the last
> byte of the target dirent structure (aka d_type byte) was never copied
> from the host dirent structure, thus breaking everything that relies
> on valid d_type value, e.g. glob(3).

Looks pretty good, just one nit...

> diff --git a/linux-user/syscall_defs.h b/linux-user/syscall_defs.h
> index 2cfda5a..f7271fa 100644
> --- a/linux-user/syscall_defs.h
> +++ b/linux-user/syscall_defs.h
> @@ -258,7 +258,7 @@ struct target_dirent {
>         abi_long        d_ino;
>         abi_long        d_off;
>         unsigned short  d_reclen;
> -       char            d_name[256]; /* We must not include limits.h! */
> +       char            d_name[];
>  };

Can you convert this struct to match coding style while you're touching
it, please? (ie no hardcoded tabs). scripts/checkpatch.pl will let you
know about this kind of thing.

thanks
-- PMM

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

* Re: [Qemu-devel] [PATCH v4] linux-user: fix emulation of getdents
  2012-08-20 22:05         ` Peter Maydell
@ 2012-08-20 22:13           ` Dmitry V. Levin
  2012-08-21 12:03             ` Peter Maydell
  0 siblings, 1 reply; 10+ messages in thread
From: Dmitry V. Levin @ 2012-08-20 22:13 UTC (permalink / raw
  To: qemu-devel; +Cc: Blue Swirl, Peter Maydell, Riku Voipio

In case when TARGET_ABI_BITS == 32 && HOST_LONG_BITS == 64, the last
byte of the target dirent structure (aka d_type byte) was never copied
from the host dirent structure, thus breaking everything that relies
on valid d_type value, e.g. glob(3).

Signed-off-by: Dmitry V. Levin <ldv@altlinux.org>
---
 linux-user/syscall.c      | 11 +++++------
 linux-user/syscall_defs.h |  8 ++++----
 2 files changed, 9 insertions(+), 10 deletions(-)

diff --git a/linux-user/syscall.c b/linux-user/syscall.c
index 41c869b..8a8aaca 100644
--- a/linux-user/syscall.c
+++ b/linux-user/syscall.c
@@ -7025,15 +7025,14 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
 		tde = target_dirp;
                 while (len > 0) {
                     reclen = de->d_reclen;
-		    treclen = reclen - (2 * (sizeof(long) - sizeof(abi_long)));
+                    tnamelen = reclen - offsetof(struct linux_dirent, d_name);
+                    assert(tnamelen >= 0);
+                    treclen = tnamelen + offsetof(struct target_dirent, d_name);
+                    assert(count1 + treclen <= count);
                     tde->d_reclen = tswap16(treclen);
                     tde->d_ino = tswapal(de->d_ino);
                     tde->d_off = tswapal(de->d_off);
-		    tnamelen = treclen - (2 * sizeof(abi_long) + 2);
-		    if (tnamelen > 256)
-                        tnamelen = 256;
-                    /* XXX: may not be correct */
-                    pstrcpy(tde->d_name, tnamelen, de->d_name);
+                    memcpy(tde->d_name, de->d_name, tnamelen);
                     de = (struct linux_dirent *)((char *)de + reclen);
                     len -= reclen;
                     tde = (struct target_dirent *)((char *)tde + treclen);
diff --git a/linux-user/syscall_defs.h b/linux-user/syscall_defs.h
index 2cfda5a..a98cbf7 100644
--- a/linux-user/syscall_defs.h
+++ b/linux-user/syscall_defs.h
@@ -255,10 +255,10 @@ struct kernel_statfs {
 };
 
 struct target_dirent {
-	abi_long	d_ino;
-	abi_long	d_off;
-	unsigned short	d_reclen;
-	char		d_name[256]; /* We must not include limits.h! */
+        abi_long        d_ino;
+        abi_long        d_off;
+        unsigned short  d_reclen;
+        char            d_name[];
 };
 
 struct target_dirent64 {

-- 
ldv

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

* Re: [Qemu-devel] [PATCH v4] linux-user: fix emulation of getdents
  2012-08-20 22:13           ` [Qemu-devel] [PATCH v4] " Dmitry V. Levin
@ 2012-08-21 12:03             ` Peter Maydell
  0 siblings, 0 replies; 10+ messages in thread
From: Peter Maydell @ 2012-08-21 12:03 UTC (permalink / raw
  To: Dmitry V. Levin; +Cc: Blue Swirl, Riku Voipio, qemu-devel

On 20 August 2012 23:13, Dmitry V. Levin <ldv@altlinux.org> wrote:
> In case when TARGET_ABI_BITS == 32 && HOST_LONG_BITS == 64, the last
> byte of the target dirent structure (aka d_type byte) was never copied
> from the host dirent structure, thus breaking everything that relies
> on valid d_type value, e.g. glob(3).
>
> Signed-off-by: Dmitry V. Levin <ldv@altlinux.org>

Reviewed-by: Peter Maydell <peter.maydell@linaro.org>

(though not tested, since the 32 bit target I care about (ARM) uses
getdents64 rather than getdents.)

-- PMM

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

end of thread, other threads:[~2012-08-21 12:03 UTC | newest]

Thread overview: 10+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2012-08-16 21:20 [Qemu-devel] [PATCH] linux-user: fix emulation of getdents Dmitry V. Levin
2012-08-17  7:33 ` 陳韋任 (Wei-Ren Chen)
2012-08-18 14:20 ` Blue Swirl
2012-08-18 21:56   ` [Qemu-devel] [PATCH v2] " Dmitry V. Levin
2012-08-19 12:59     ` Blue Swirl
2012-08-20 16:17     ` Peter Maydell
2012-08-20 21:36       ` [Qemu-devel] [PATCH v3] " Dmitry V. Levin
2012-08-20 22:05         ` Peter Maydell
2012-08-20 22:13           ` [Qemu-devel] [PATCH v4] " Dmitry V. Levin
2012-08-21 12:03             ` Peter Maydell

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.