From: "Kirill A. Shutemov" <kirill@shutemov.name>
To: qemu-devel@nongnu.org
Cc: "Kirill A. Shutemov" <kirill@shutemov.name>
Subject: [Qemu-devel] [PATCH] Fix and cleanup IPCOP_sem* ipc calls handling
Date: Wed, 3 Dec 2008 13:29:45 +0200 [thread overview]
Message-ID: <1228303789-25653-10-git-send-email-kirill@shutemov.name> (raw)
In-Reply-To: <1228303789-25653-9-git-send-email-kirill@shutemov.name>
Signed-off-by: Kirill A. Shutemov <kirill@shutemov.name>
---
linux-user/syscall.c | 319 +++++++++++++++++++++++++++++++-------------------
1 files changed, 198 insertions(+), 121 deletions(-)
diff --git a/linux-user/syscall.c b/linux-user/syscall.c
index dc65a77..ee61e1e 100644
--- a/linux-user/syscall.c
+++ b/linux-user/syscall.c
@@ -1645,14 +1645,14 @@ struct target_ipc_perm
struct target_semid_ds
{
- struct target_ipc_perm sem_perm;
- abi_ulong sem_otime;
- abi_ulong __unused1;
- abi_ulong sem_ctime;
- abi_ulong __unused2;
- abi_ulong sem_nsems;
- abi_ulong __unused3;
- abi_ulong __unused4;
+ struct target_ipc_perm sem_perm;
+ abi_ulong sem_otime;
+ abi_ulong __unused1;
+ abi_ulong sem_ctime;
+ abi_ulong __unused2;
+ abi_ulong sem_nsems;
+ abi_ulong __unused3;
+ abi_ulong __unused4;
};
static inline abi_long target_to_host_ipc_perm(struct ipc_perm *host_ip,
@@ -1700,7 +1700,8 @@ static inline abi_long target_to_host_semid_ds(struct semid_ds *host_sd,
if (!lock_user_struct(VERIFY_READ, target_sd, target_addr, 1))
return -TARGET_EFAULT;
- target_to_host_ipc_perm(&(host_sd->sem_perm),target_addr);
+ if (target_to_host_ipc_perm(&(host_sd->sem_perm),target_addr))
+ return -TARGET_EFAULT;
host_sd->sem_nsems = tswapl(target_sd->sem_nsems);
host_sd->sem_otime = tswapl(target_sd->sem_otime);
host_sd->sem_ctime = tswapl(target_sd->sem_ctime);
@@ -1715,7 +1716,8 @@ static inline abi_long host_to_target_semid_ds(abi_ulong target_addr,
if (!lock_user_struct(VERIFY_WRITE, target_sd, target_addr, 0))
return -TARGET_EFAULT;
- host_to_target_ipc_perm(target_addr,&(host_sd->sem_perm));
+ if (host_to_target_ipc_perm(target_addr,&(host_sd->sem_perm)))
+ return -TARGET_EFAULT;;
target_sd->sem_nsems = tswapl(host_sd->sem_nsems);
target_sd->sem_otime = tswapl(host_sd->sem_otime);
target_sd->sem_ctime = tswapl(host_sd->sem_ctime);
@@ -1723,135 +1725,215 @@ static inline abi_long host_to_target_semid_ds(abi_ulong target_addr,
return 0;
}
+struct target_seminfo {
+ int semmap;
+ int semmni;
+ int semmns;
+ int semmnu;
+ int semmsl;
+ int semopm;
+ int semume;
+ int semusz;
+ int semvmx;
+ int semaem;
+};
+
+static inline abi_long host_to_target_seminfo(abi_ulong target_addr,
+ struct seminfo *host_seminfo)
+{
+ struct target_seminfo *target_seminfo;
+ if (!lock_user_struct(VERIFY_WRITE, target_seminfo, target_addr, 0))
+ return -TARGET_EFAULT;
+ __put_user(host_seminfo->semmap, &target_seminfo->semmap);
+ __put_user(host_seminfo->semmni, &target_seminfo->semmni);
+ __put_user(host_seminfo->semmns, &target_seminfo->semmns);
+ __put_user(host_seminfo->semmnu, &target_seminfo->semmnu);
+ __put_user(host_seminfo->semmsl, &target_seminfo->semmsl);
+ __put_user(host_seminfo->semopm, &target_seminfo->semopm);
+ __put_user(host_seminfo->semume, &target_seminfo->semume);
+ __put_user(host_seminfo->semusz, &target_seminfo->semusz);
+ __put_user(host_seminfo->semvmx, &target_seminfo->semvmx);
+ __put_user(host_seminfo->semaem, &target_seminfo->semaem);
+ unlock_user_struct(target_seminfo, target_addr, 1);
+ return 0;
+}
+
union semun {
- int val;
- struct semid_ds *buf;
- unsigned short *array;
+ int val;
+ struct semid_ds *buf;
+ unsigned short *array;
+ struct seminfo *__buf;
};
union target_semun {
- int val;
- abi_long buf;
- unsigned short int *array;
+ int val;
+ abi_ulong buf;
+ abi_ulong array;
+ abi_ulong __buf;
};
-static inline abi_long target_to_host_semun(int cmd,
- union semun *host_su,
- abi_ulong target_addr,
- struct semid_ds *ds)
+static inline abi_long target_to_host_semarray(int semid, unsigned short **host_array,
+ abi_ulong target_addr)
{
- union target_semun *target_su;
-
- switch( cmd ) {
- case IPC_STAT:
- case IPC_SET:
- if (!lock_user_struct(VERIFY_READ, target_su, target_addr, 1))
- return -TARGET_EFAULT;
- target_to_host_semid_ds(ds,target_su->buf);
- host_su->buf = ds;
- unlock_user_struct(target_su, target_addr, 0);
- break;
- case GETVAL:
- case SETVAL:
- if (!lock_user_struct(VERIFY_READ, target_su, target_addr, 1))
- return -TARGET_EFAULT;
- host_su->val = tswapl(target_su->val);
- unlock_user_struct(target_su, target_addr, 0);
- break;
- case GETALL:
- case SETALL:
- if (!lock_user_struct(VERIFY_READ, target_su, target_addr, 1))
- return -TARGET_EFAULT;
- *host_su->array = tswap16(*target_su->array);
- unlock_user_struct(target_su, target_addr, 0);
- break;
- default:
- gemu_log("semun operation not fully supported: %d\n", (int)cmd);
+ int nsems;
+ unsigned short *array;
+ union semun semun;
+ struct semid_ds semid_ds;
+ int i, ret;
+
+ semun.buf = &semid_ds;
+
+ ret = semctl(semid, 0, IPC_STAT, semun);
+ if (ret == -1)
+ return get_errno(ret);
+
+ nsems = semid_ds.sem_nsems;
+
+ *host_array = malloc(nsems*sizeof(unsigned short));
+ array = lock_user(VERIFY_READ, target_addr,
+ nsems*sizeof(unsigned short), 1);
+ if (!array)
+ return -TARGET_EFAULT;
+
+ for(i=0; i<nsems; i++) {
+ __get_user((*host_array)[i], &array[i]);
}
+ unlock_user(array, target_addr, 0);
+
return 0;
}
-static inline abi_long host_to_target_semun(int cmd,
- abi_ulong target_addr,
- union semun *host_su,
- struct semid_ds *ds)
+static inline abi_long host_to_target_semarray(int semid, abi_ulong target_addr,
+ unsigned short **host_array)
{
- union target_semun *target_su;
-
- switch( cmd ) {
- case IPC_STAT:
- case IPC_SET:
- if (lock_user_struct(VERIFY_WRITE, target_su, target_addr, 0))
- return -TARGET_EFAULT;
- host_to_target_semid_ds(target_su->buf,ds);
- unlock_user_struct(target_su, target_addr, 1);
- break;
- case GETVAL:
- case SETVAL:
- if (lock_user_struct(VERIFY_WRITE, target_su, target_addr, 0))
- return -TARGET_EFAULT;
- target_su->val = tswapl(host_su->val);
- unlock_user_struct(target_su, target_addr, 1);
- break;
- case GETALL:
- case SETALL:
- if (lock_user_struct(VERIFY_WRITE, target_su, target_addr, 0))
- return -TARGET_EFAULT;
- *target_su->array = tswap16(*host_su->array);
- unlock_user_struct(target_su, target_addr, 1);
- break;
- default:
- gemu_log("semun operation not fully supported: %d\n", (int)cmd);
+ int nsems;
+ unsigned short *array;
+ union semun semun;
+ struct semid_ds semid_ds;
+ int i, ret;
+
+ semun.buf = &semid_ds;
+
+ ret = semctl(semid, 0, IPC_STAT, semun);
+ if (ret == -1)
+ return get_errno(ret);
+
+ nsems = semid_ds.sem_nsems;
+
+ array = lock_user(VERIFY_WRITE, target_addr,
+ nsems*sizeof(unsigned short), 0);
+ if (!array)
+ return -TARGET_EFAULT;
+
+ for(i=0; i<nsems; i++) {
+ __put_user((*host_array)[i], &array[i]);
}
+ free(*host_array);
+ unlock_user(array, target_addr, 1);
+
return 0;
}
-static inline abi_long do_semctl(int first, int second, int third,
- abi_long ptr)
+static inline abi_long do_semctl(int semid, int semnum, int cmd,
+ union target_semun target_su)
{
union semun arg;
struct semid_ds dsarg;
- int cmd = third&0xff;
- abi_long ret = 0;
+ unsigned short *array;
+ struct seminfo seminfo;
+ abi_long ret = -TARGET_EINVAL;
+ abi_long err;
- switch( cmd ) {
- case GETVAL:
- target_to_host_semun(cmd,&arg,ptr,&dsarg);
- ret = get_errno(semctl(first, second, cmd, arg));
- host_to_target_semun(cmd,ptr,&arg,&dsarg);
- break;
- case SETVAL:
- target_to_host_semun(cmd,&arg,ptr,&dsarg);
- ret = get_errno(semctl(first, second, cmd, arg));
- host_to_target_semun(cmd,ptr,&arg,&dsarg);
- break;
- case GETALL:
- target_to_host_semun(cmd,&arg,ptr,&dsarg);
- ret = get_errno(semctl(first, second, cmd, arg));
- host_to_target_semun(cmd,ptr,&arg,&dsarg);
- break;
- case SETALL:
- target_to_host_semun(cmd,&arg,ptr,&dsarg);
- ret = get_errno(semctl(first, second, cmd, arg));
- host_to_target_semun(cmd,ptr,&arg,&dsarg);
- break;
- case IPC_STAT:
- target_to_host_semun(cmd,&arg,ptr,&dsarg);
- ret = get_errno(semctl(first, second, cmd, arg));
- host_to_target_semun(cmd,ptr,&arg,&dsarg);
- break;
- case IPC_SET:
- target_to_host_semun(cmd,&arg,ptr,&dsarg);
- ret = get_errno(semctl(first, second, cmd, arg));
- host_to_target_semun(cmd,ptr,&arg,&dsarg);
- break;
- default:
- ret = get_errno(semctl(first, second, cmd, arg));
+ cmd &= 0xff;
+
+ switch (cmd) {
+ case IPC_STAT:
+ case IPC_SET:
+ case SEM_STAT:
+ err = target_to_host_semid_ds(&dsarg, target_su.buf);
+ if (err)
+ 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)
+ return err;
+ break;
+ case GETVAL:
+ case SETVAL:
+ arg.val = tswapl(target_su.val);
+ ret = get_errno(semctl(semid, semnum, cmd, arg));
+ target_su.val = tswapl(arg.val);
+ break;
+ case GETALL:
+ case SETALL:
+ err = target_to_host_semarray(semid, &array, target_su.array);
+ if (err)
+ 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)
+ 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)
+ return err;
+ break;
+ case IPC_RMID:
+ case GETPID:
+ case GETNCNT:
+ case GETZCNT:
+ ret = get_errno(semctl(semid, semnum, cmd, NULL));
+ break;
}
return ret;
}
+struct target_sembuf {
+ unsigned short sem_num;
+ short sem_op;
+ short sem_flg;
+};
+
+static inline abi_long target_to_host_sembuf(struct sembuf *host_sembuf,
+ abi_ulong target_addr,
+ unsigned nsops)
+{
+ struct target_sembuf *target_sembuf;
+ int i;
+
+ target_sembuf = lock_user(VERIFY_READ, target_addr,
+ nsops*sizeof(struct target_sembuf), 1);
+ if (!target_sembuf)
+ return -TARGET_EFAULT;
+
+ for(i=0; i<nsops; i++) {
+ __put_user(target_sembuf[i].sem_num, &host_sembuf[i].sem_num);
+ __put_user(target_sembuf[i].sem_op, &host_sembuf[i].sem_op);
+ __put_user(target_sembuf[i].sem_flg, &host_sembuf[i].sem_flg);
+ }
+
+ unlock_user(target_sembuf, target_addr, 0);
+
+ return 0;
+}
+
+static inline abi_long do_semop(int semid, abi_long ptr, unsigned nsops)
+{
+ struct sembuf sops[nsops];
+
+ if (target_to_host_sembuf(sops, ptr, nsops))
+ return -TARGET_EFAULT;
+
+ return semop(semid, sops, nsops);
+}
+
struct target_msqid_ds
{
struct target_ipc_perm msg_perm;
@@ -2055,7 +2137,7 @@ static abi_long do_ipc(unsigned int call, int first,
switch (call) {
case IPCOP_semop:
- ret = get_errno(semop(first,(struct sembuf *)g2h(ptr), second));
+ ret = do_semop(first, ptr, second);
break;
case IPCOP_semget:
@@ -2063,12 +2145,7 @@ static abi_long do_ipc(unsigned int call, int first,
break;
case IPCOP_semctl:
- ret = do_semctl(first, second, third, ptr);
- break;
-
- case IPCOP_semtimedop:
- gemu_log("Unsupported ipc call: %d (version %d)\n", call, version);
- ret = -TARGET_ENOSYS;
+ ret = do_semctl(first, second, third, (union target_semun)(abi_ulong) ptr);
break;
case IPCOP_msgget:
--
1.6.0.2.GIT
next prev parent reply other threads:[~2008-12-03 11:28 UTC|newest]
Thread overview: 49+ messages / expand[flat|nested] mbox.gz Atom feed top
2008-12-03 11:29 [Qemu-devel] [PATCH] Introduce --enable-binfmt-misc configure option Kirill A. Shutemov
2008-12-03 11:29 ` [Qemu-devel] [PATCH] Fix fstatat64()/newfstatat() syscall implementation Kirill A. Shutemov
2008-12-03 11:29 ` [Qemu-devel] [PATCH] Move abi_* typedefs into qemu-types.h Kirill A. Shutemov
2008-12-03 11:29 ` [Qemu-devel] [PATCH] linux-user: Safety belt for h2g Kirill A. Shutemov
2008-12-03 11:29 ` [Qemu-devel] [PATCH] linux-user: Introduce h2g_valid Kirill A. Shutemov
2008-12-03 11:29 ` [Qemu-devel] [PATCH] linux-user: Fix h2g usage in page_find_alloc Kirill A. Shutemov
2008-12-03 11:29 ` [Qemu-devel] [PATCH] Rewrite mmap_find_vma() to work fine on 64-bit hosts with 32-bit targets Kirill A. Shutemov
2008-12-03 11:29 ` [Qemu-devel] [PATCH] mmap: add check if requested memory area fits target address space Kirill A. Shutemov
2008-12-03 11:29 ` [Qemu-devel] [PATCH] mremap(): handle MREMAP_FIXED and MREMAP_MAYMOVE correctly Kirill A. Shutemov
2008-12-03 11:29 ` Kirill A. Shutemov [this message]
2008-12-03 11:29 ` [Qemu-devel] [PATCH] Implement sem* syscalls Kirill A. Shutemov
2008-12-03 11:29 ` [Qemu-devel] [PATCH] Fix and cleanup IPCOP_shm* ipc calls handling Kirill A. Shutemov
2008-12-03 11:29 ` [Qemu-devel] [PATCH] Implement shm* syscalls Kirill A. Shutemov
2008-12-03 11:29 ` [Qemu-devel] [PATCH] shmat(): use mmap_find_vma to find free memory area Kirill A. Shutemov
2008-12-06 19:51 ` [Qemu-devel] [PATCH] mremap(): handle MREMAP_FIXED and MREMAP_MAYMOVE correctly Edgar E. Iglesias
2008-12-06 20:03 ` Kirill A. Shutemov
2008-12-08 18:17 ` Aurelien Jarno
2008-12-06 19:46 ` [Qemu-devel] [PATCH] mmap: add check if requested memory area fits target address space Edgar E. Iglesias
2008-12-06 20:00 ` Kirill A. Shutemov
2008-12-08 18:16 ` Aurelien Jarno
2008-12-03 12:34 ` [Qemu-devel] [PATCH] Rewrite mmap_find_vma() to work fine on 64-bit hosts with 32-bit targets Paul Brook
2008-12-03 12:43 ` Christoph Egger
2008-12-03 12:48 ` Paul Brook
2008-12-03 12:50 ` Kirill A. Shutemov
2008-12-08 20:48 ` Kirill A. Shutemov
2008-12-08 20:54 ` Martin Mohring
2008-12-08 20:59 ` Martin Mohring
2008-12-08 21:57 ` Kirill A. Shutemov
2008-12-08 21:02 ` Martin Mohring
2008-12-08 22:14 ` [Qemu-devel] qemu and glibc version Kirill A. Shutemov
2008-12-09 12:25 ` [Qemu-devel] [PATCH] Rewrite mmap_find_vma() to work fine on 64-bit hosts with 32-bit targets Robert Reif
2008-12-09 13:26 ` Kirill A. Shutemov
2008-12-08 23:42 ` Paul Brook
2008-12-09 6:20 ` Kirill A. Shutemov
2008-12-06 20:08 ` [Qemu-devel] [PATCH] linux-user: Fix h2g usage in page_find_alloc Edgar E. Iglesias
2008-12-06 20:13 ` Kirill A. Shutemov
2008-12-08 18:16 ` Aurelien Jarno
2008-12-08 18:15 ` [Qemu-devel] [PATCH] linux-user: Introduce h2g_valid Aurelien Jarno
2008-12-06 20:04 ` [Qemu-devel] [PATCH] linux-user: Safety belt for h2g Edgar E. Iglesias
2008-12-08 18:15 ` Aurelien Jarno
2008-12-08 19:25 ` Andreas Färber
2008-12-09 7:34 ` Jan Kiszka
2008-12-07 21:56 ` [Qemu-devel] [PATCH] Move abi_* typedefs into qemu-types.h Aurelien Jarno
2008-12-08 6:09 ` Kirill A. Shutemov
2008-12-08 18:13 ` Aurelien Jarno
2009-01-12 14:18 ` [Qemu-devel] [PATCH] Introduce --enable-binfmt-misc configure option Riku Voipio
-- strict thread matches above, loose matches on Subject: below --
2008-10-13 10:10 [Qemu-devel] [PATCH] Add readahead syscall Kirill A. Shutemov
2008-10-13 10:10 ` [Qemu-devel] [PATCH] Fix getdents* syscalls Kirill A. Shutemov
2008-10-13 10:10 ` [Qemu-devel] [PATCH] Fix and cleanup IPCOP_msg* ipc calls handling Kirill A. Shutemov
2008-10-13 10:10 ` [Qemu-devel] [PATCH] Implement msg* syscalls Kirill A. Shutemov
2008-10-13 10:10 ` [Qemu-devel] [PATCH] Fix and cleanup IPCOP_sem* ipc calls handling Kirill A. Shutemov
2008-10-08 18:54 [Qemu-devel] [PATCH] Add readahead syscall Kirill A. Shutemov
2008-10-08 18:54 ` [Qemu-devel] [PATCH] Fix getdents* syscalls Kirill A. Shutemov
2008-10-08 18:54 ` [Qemu-devel] [PATCH] Fix and cleanup IPCOP_msg* ipc calls handling Kirill A. Shutemov
2008-10-08 18:54 ` [Qemu-devel] [PATCH] Implement msg* syscalls Kirill A. Shutemov
2008-10-08 18:54 ` [Qemu-devel] [PATCH] Fix and cleanup IPCOP_sem* ipc calls handling Kirill A. Shutemov
2008-10-01 13:56 [Qemu-devel] [PATCH] Add fadvise64 stubs Kirill A. Shutemov
2008-10-01 13:56 ` [Qemu-devel] [PATCH] Add mincore syscall Kirill A. Shutemov
2008-10-01 13:56 ` [Qemu-devel] [PATCH] Add readahead syscall Kirill A. Shutemov
2008-10-01 13:56 ` [Qemu-devel] [PATCH] Add inotify syscall family Kirill A. Shutemov
2008-10-01 13:56 ` [Qemu-devel] [PATCH] Fix getdents* syscalls Kirill A. Shutemov
2008-10-01 13:56 ` [Qemu-devel] [PATCH] Fix and cleanup IPCOP_msg* ipc calls handling Kirill A. Shutemov
2008-10-01 13:56 ` [Qemu-devel] [PATCH] Implement msg* syscalls Kirill A. Shutemov
2008-10-01 13:56 ` [Qemu-devel] [PATCH] Fix and cleanup IPCOP_sem* ipc calls handling Kirill A. Shutemov
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=1228303789-25653-10-git-send-email-kirill@shutemov.name \
--to=kirill@shutemov.name \
--cc=qemu-devel@nongnu.org \
/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).