From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from mailman by lists.gnu.org with tmda-scanned (Exim 4.43) id 1KneAU-0004Mh-WE for qemu-devel@nongnu.org; Wed, 08 Oct 2008 14:53:55 -0400 Received: from exim by lists.gnu.org with spam-scanned (Exim 4.43) id 1KneAU-0004MF-4N for qemu-devel@nongnu.org; Wed, 08 Oct 2008 14:53:54 -0400 Received: from [199.232.76.173] (port=54481 helo=monty-python.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1KneAT-0004MA-V8 for qemu-devel@nongnu.org; Wed, 08 Oct 2008 14:53:54 -0400 Received: from ey-out-1920.google.com ([74.125.78.150]:54196) by monty-python.gnu.org with esmtp (Exim 4.60) (envelope-from ) id 1KneAT-0006x4-Bq for qemu-devel@nongnu.org; Wed, 08 Oct 2008 14:53:53 -0400 Received: by ey-out-1920.google.com with SMTP id 4so1186685eyk.4 for ; Wed, 08 Oct 2008 11:53:51 -0700 (PDT) From: "Kirill A. Shutemov" Date: Wed, 8 Oct 2008 21:54:29 +0300 Message-Id: <1223492074-5677-5-git-send-email-kirill@shutemov.name> In-Reply-To: <1223492074-5677-4-git-send-email-kirill@shutemov.name> References: <1223492074-5677-1-git-send-email-kirill@shutemov.name> <1223492074-5677-2-git-send-email-kirill@shutemov.name> <1223492074-5677-3-git-send-email-kirill@shutemov.name> <1223492074-5677-4-git-send-email-kirill@shutemov.name> Subject: [Qemu-devel] [PATCH] Fix and cleanup IPCOP_sem* ipc calls handling Reply-To: qemu-devel@nongnu.org List-Id: qemu-devel.nongnu.org List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , To: qemu-devel@nongnu.org Cc: "Kirill A. Shutemov" Signed-off-by: Kirill A. Shutemov --- 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 cf0834f..54c53c2 100644 --- a/linux-user/syscall.c +++ b/linux-user/syscall.c @@ -1635,14 +1635,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, @@ -1690,7 +1690,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); @@ -1705,7 +1706,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); @@ -1713,135 +1715,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; ibuf,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