diff mbox

[03/12] linux-user: Properly Handle semun Structure In Cross-Endian Situations

Message ID 1407170739-12237-4-git-send-email-tommusta@gmail.com
State New
Headers show

Commit Message

Tom Musta Aug. 4, 2014, 4:45 p.m. UTC
The semun union used in the semctl system call contains both an int (val) and
pointers.  In cross-endian situations on 64 bit targets, the target memory
must be byte swapped, otherwise the wrong 32 bits are used for the val
field.

Signed-off-by: Tom Musta <tommusta@gmail.com>

Comments

Peter Maydell Aug. 4, 2014, 5:23 p.m. UTC | #1
On 4 August 2014 17:45, Tom Musta <tommusta@gmail.com> wrote:
> The semun union used in the semctl system call contains both an int (val) and
> pointers.  In cross-endian situations on 64 bit targets, the target memory
> must be byte swapped, otherwise the wrong 32 bits are used for the val
> field.
>
> Signed-off-by: Tom Musta <tommusta@gmail.com>
>
> diff --git a/linux-user/syscall.c b/linux-user/syscall.c
> index 229c482..fb03e96 100644
> --- a/linux-user/syscall.c
> +++ b/linux-user/syscall.c
> @@ -2647,9 +2647,14 @@ static inline abi_long do_semctl(int semid, int semnum, int cmd,
>      switch( cmd ) {
>         case GETVAL:
>         case SETVAL:
> +#if TARGET_ABI_BITS == 64
> +            /* In 64 bit cross endian situations, we will erroneously pick up
> +             * the wrong half of the union for the "val" element.  To rectify
> +             * this, the entire structure is byteswaped. */

"byteswapped".

> +            target_su.buf = tswapal(target_su.buf);
> +#endif

This feels weird; surely there's a way of phrasing this
that doesn't require an #ifdef on TARGET_ABI_BITS?

>              arg.val = tswap32(target_su.val);
>              ret = get_errno(semctl(semid, semnum, cmd, arg));
> -            target_su.val = tswap32(arg.val);

This deleted line isn't mentioned in the commit message...

>              break;
>         case GETALL:
>         case SETALL:

thanks
-- PMM
diff mbox

Patch

diff --git a/linux-user/syscall.c b/linux-user/syscall.c
index 229c482..fb03e96 100644
--- a/linux-user/syscall.c
+++ b/linux-user/syscall.c
@@ -2647,9 +2647,14 @@  static inline abi_long do_semctl(int semid, int semnum, int cmd,
     switch( cmd ) {
 	case GETVAL:
 	case SETVAL:
+#if TARGET_ABI_BITS == 64
+            /* In 64 bit cross endian situations, we will erroneously pick up
+             * the wrong half of the union for the "val" element.  To rectify
+             * this, the entire structure is byteswaped. */
+            target_su.buf = tswapal(target_su.buf);
+#endif
             arg.val = tswap32(target_su.val);
             ret = get_errno(semctl(semid, semnum, cmd, arg));
-            target_su.val = tswap32(arg.val);
             break;
 	case GETALL:
 	case SETALL: