qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
From: Laurent Vivier <laurent@vivier.eu>
To: Peter Maydell <peter.maydell@linaro.org>
Cc: Riku Voipio <riku.voipio@iki.fi>,
	qemu-devel@nongnu.org, Laurent Vivier <laurent@vivier.eu>
Subject: [Qemu-devel] [PATCH][v3] linux-user: correct semctl() and shmctl()
Date: Mon, 21 Jan 2013 07:25:23 +0100	[thread overview]
Message-ID: <1358749523-20925-1-git-send-email-laurent@vivier.eu> (raw)
In-Reply-To: <1356037136-19479-1-git-send-email-laurent@vivier.eu>

The parameter "union semun" of semctl() is not a value
but a pointer to the value.

Moreover, all fields of target_su must be swapped (if needed).

The third argument of shmctl is a pointer.

WITHOUT this patch:

$ ipcs

kernel not configured for shared memory

qemu: uncaught target signal 11 (Segmentation fault) - core dumped

WITH this patch:

$ ipcs

------ Shared Memory Segments --------
key        shmid      owner      perms      bytes      nattch     status
0x4e545030 0          root      600        96         1
0x4e545031 32769      root      600        96         1
0x4e545032 65538      root      666        96         1
0x4e545033 98307      root      666        96         1
0x47505344 131076     root      666        8240       1
0x3c81b7f5 163845     laurent   666        4096       0
0x00000000 729513990  laurent   600        393216     2          dest
0x00000000 729546759  laurent   600        393216     2          dest
0x00000000 1879179273 laurent   600        393216     2          dest

------ Semaphore Arrays --------
key        semid      owner      perms      nsems
0x3c81b7f6 32768      laurent   666        1
0x1c44ac47 6586369    laurent   600        1

------ Message Queues --------
key        msqid      owner      perms      used-bytes   messages
0x1c44ac45 458752     laurent    600        0            0
0x1c44ac46 491521     laurent    600        0            0

Signed-off-by: Laurent Vivier <laurent@vivier.eu>
---
v2: move lock_user_struct() in do_semctl()
v3: correctly set the return value

 linux-user/syscall.c |   49 +++++++++++++++++++++++++++++++++----------------
 1 file changed, 33 insertions(+), 16 deletions(-)

diff --git a/linux-user/syscall.c b/linux-user/syscall.c
index 693e66f..d44558d 100644
--- a/linux-user/syscall.c
+++ b/linux-user/syscall.c
@@ -2635,8 +2635,9 @@ static inline abi_long host_to_target_semarray(int semid, abi_ulong target_addr,
 }
 
 static inline abi_long do_semctl(int semid, int semnum, int cmd,
-                                 union target_semun target_su)
+                                 abi_ulong ptr)
 {
+    union target_semun *target_su;
     union semun arg;
     struct semid_ds dsarg;
     unsigned short *array = NULL;
@@ -2645,43 +2646,58 @@ static inline abi_long do_semctl(int semid, int semnum, int cmd,
     abi_long err;
     cmd &= 0xff;
 
+    if (!lock_user_struct(VERIFY_READ, target_su, ptr, 1)) {
+        return -TARGET_EFAULT;
+    }
     switch( cmd ) {
 	case GETVAL:
 	case SETVAL:
-            arg.val = tswap32(target_su.val);
+            arg.val = tswap32(target_su->val);
             ret = get_errno(semctl(semid, semnum, cmd, arg));
-            target_su.val = tswap32(arg.val);
+            target_su->val = tswap32(arg.val);
             break;
 	case GETALL:
 	case SETALL:
-            err = target_to_host_semarray(semid, &array, target_su.array);
-            if (err)
+            err = target_to_host_semarray(semid, &array,
+                                          tswapal(target_su->array));
+            if (err) {
+                unlock_user_struct(target_su, ptr, 0);
                 return err;
+            }
             arg.array = array;
             ret = get_errno(semctl(semid, semnum, cmd, arg));
-            err = host_to_target_semarray(semid, target_su.array, &array);
-            if (err)
+            err = host_to_target_semarray(semid, tswapal(target_su->array),
+                                          &array);
+            if (err) {
+                unlock_user_struct(target_su, ptr, 0);
                 return err;
+            }
             break;
 	case IPC_STAT:
 	case IPC_SET:
 	case SEM_STAT:
-            err = target_to_host_semid_ds(&dsarg, target_su.buf);
-            if (err)
+            err = target_to_host_semid_ds(&dsarg, tswapal(target_su->buf));
+            if (err) {
+                unlock_user_struct(target_su, ptr, 0);
                 return err;
+            }
             arg.buf = &dsarg;
             ret = get_errno(semctl(semid, semnum, cmd, arg));
-            err = host_to_target_semid_ds(target_su.buf, &dsarg);
-            if (err)
+            err = host_to_target_semid_ds(tswapal(target_su->buf), &dsarg);
+            if (err) {
+                unlock_user_struct(target_su, ptr, 0);
                 return err;
+            }
             break;
 	case IPC_INFO:
 	case SEM_INFO:
             arg.__buf = &seminfo;
             ret = get_errno(semctl(semid, semnum, cmd, arg));
-            err = host_to_target_seminfo(target_su.__buf, &seminfo);
-            if (err)
+            err = host_to_target_seminfo(tswapal(target_su->__buf), &seminfo);
+            if (err) {
+                unlock_user_struct(target_su, ptr, 0);
                 return err;
+            }
             break;
 	case IPC_RMID:
 	case GETPID:
@@ -2690,6 +2706,7 @@ static inline abi_long do_semctl(int semid, int semnum, int cmd,
             ret = get_errno(semctl(semid, semnum, cmd, NULL));
             break;
     }
+    unlock_user_struct(target_su, ptr, 0);
 
     return ret;
 }
@@ -3160,7 +3177,7 @@ static abi_long do_ipc(unsigned int call, int first,
         break;
 
     case IPCOP_semctl:
-        ret = do_semctl(first, second, third, (union target_semun)(abi_ulong) ptr);
+        ret = do_semctl(first, second, third, ptr);
         break;
 
     case IPCOP_msgget:
@@ -3227,7 +3244,7 @@ static abi_long do_ipc(unsigned int call, int first,
 
 	/* IPC_* and SHM_* command values are the same on all linux platforms */
     case IPCOP_shmctl:
-        ret = do_shmctl(first, second, third);
+        ret = do_shmctl(first, second, ptr);
         break;
     default:
 	gemu_log("Unsupported ipc call: %d (version %d)\n", call, version);
@@ -6909,7 +6926,7 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
 #endif
 #ifdef TARGET_NR_semctl
     case TARGET_NR_semctl:
-        ret = do_semctl(arg1, arg2, arg3, (union target_semun)(abi_ulong)arg4);
+        ret = do_semctl(arg1, arg2, arg3, arg4);
         break;
 #endif
 #ifdef TARGET_NR_msgctl
-- 
1.7.10.4

      parent reply	other threads:[~2013-01-21  6:39 UTC|newest]

Thread overview: 9+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2012-12-20 20:58 [Qemu-devel] [PATCH] linux-user: correct semctl() and shmctl() Laurent Vivier
2013-01-01 23:10 ` Laurent Vivier
2013-01-02  0:00 ` Peter Maydell
2013-01-02 20:38 ` [Qemu-devel] [PATCH][v2] " Laurent Vivier
2013-01-19 23:28   ` Laurent Vivier
2013-01-20 11:24   ` Peter Maydell
2013-01-20 21:12 ` [Qemu-devel] [PATCH] " Laurent Vivier
2013-01-20 21:45   ` Peter Maydell
2013-01-21  6:25 ` Laurent Vivier [this message]

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1358749523-20925-1-git-send-email-laurent@vivier.eu \
    --to=laurent@vivier.eu \
    --cc=peter.maydell@linaro.org \
    --cc=qemu-devel@nongnu.org \
    --cc=riku.voipio@iki.fi \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).