linux-user: fix and cleanup IPCOP_msg* ipc calls handling
Signed-off-by: Kirill A. Shutemov <kirill@shutemov.name> Signed-off-by: Aurelien Jarno <aurelien@aurel32.net> git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@5483 c046a42c-6fe2-441c-8c8c-71466251a162
This commit is contained in:
parent
a0a83536e0
commit
1c54ff97bb
@ -1611,7 +1611,6 @@ static abi_long do_socketcall(int num, abi_ulong vptr)
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef TARGET_NR_ipc
|
|
||||||
#define N_SHM_REGIONS 32
|
#define N_SHM_REGIONS 32
|
||||||
|
|
||||||
static struct shm_region {
|
static struct shm_region {
|
||||||
@ -1847,11 +1846,17 @@ struct target_msqid_ds
|
|||||||
{
|
{
|
||||||
struct target_ipc_perm msg_perm;
|
struct target_ipc_perm msg_perm;
|
||||||
abi_ulong msg_stime;
|
abi_ulong msg_stime;
|
||||||
|
#if TARGET_ABI_BITS == 32
|
||||||
abi_ulong __unused1;
|
abi_ulong __unused1;
|
||||||
|
#endif
|
||||||
abi_ulong msg_rtime;
|
abi_ulong msg_rtime;
|
||||||
|
#if TARGET_ABI_BITS == 32
|
||||||
abi_ulong __unused2;
|
abi_ulong __unused2;
|
||||||
|
#endif
|
||||||
abi_ulong msg_ctime;
|
abi_ulong msg_ctime;
|
||||||
|
#if TARGET_ABI_BITS == 32
|
||||||
abi_ulong __unused3;
|
abi_ulong __unused3;
|
||||||
|
#endif
|
||||||
abi_ulong __msg_cbytes;
|
abi_ulong __msg_cbytes;
|
||||||
abi_ulong msg_qnum;
|
abi_ulong msg_qnum;
|
||||||
abi_ulong msg_qbytes;
|
abi_ulong msg_qbytes;
|
||||||
@ -1868,7 +1873,8 @@ static inline abi_long target_to_host_msqid_ds(struct msqid_ds *host_md,
|
|||||||
|
|
||||||
if (!lock_user_struct(VERIFY_READ, target_md, target_addr, 1))
|
if (!lock_user_struct(VERIFY_READ, target_md, target_addr, 1))
|
||||||
return -TARGET_EFAULT;
|
return -TARGET_EFAULT;
|
||||||
target_to_host_ipc_perm(&(host_md->msg_perm),target_addr);
|
if (target_to_host_ipc_perm(&(host_md->msg_perm),target_addr))
|
||||||
|
return -TARGET_EFAULT;
|
||||||
host_md->msg_stime = tswapl(target_md->msg_stime);
|
host_md->msg_stime = tswapl(target_md->msg_stime);
|
||||||
host_md->msg_rtime = tswapl(target_md->msg_rtime);
|
host_md->msg_rtime = tswapl(target_md->msg_rtime);
|
||||||
host_md->msg_ctime = tswapl(target_md->msg_ctime);
|
host_md->msg_ctime = tswapl(target_md->msg_ctime);
|
||||||
@ -1888,7 +1894,8 @@ static inline abi_long host_to_target_msqid_ds(abi_ulong target_addr,
|
|||||||
|
|
||||||
if (!lock_user_struct(VERIFY_WRITE, target_md, target_addr, 0))
|
if (!lock_user_struct(VERIFY_WRITE, target_md, target_addr, 0))
|
||||||
return -TARGET_EFAULT;
|
return -TARGET_EFAULT;
|
||||||
host_to_target_ipc_perm(target_addr,&(host_md->msg_perm));
|
if (host_to_target_ipc_perm(target_addr,&(host_md->msg_perm)))
|
||||||
|
return -TARGET_EFAULT;
|
||||||
target_md->msg_stime = tswapl(host_md->msg_stime);
|
target_md->msg_stime = tswapl(host_md->msg_stime);
|
||||||
target_md->msg_rtime = tswapl(host_md->msg_rtime);
|
target_md->msg_rtime = tswapl(host_md->msg_rtime);
|
||||||
target_md->msg_ctime = tswapl(host_md->msg_ctime);
|
target_md->msg_ctime = tswapl(host_md->msg_ctime);
|
||||||
@ -1901,25 +1908,68 @@ static inline abi_long host_to_target_msqid_ds(abi_ulong target_addr,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline abi_long do_msgctl(int first, int second, abi_long ptr)
|
struct target_msginfo {
|
||||||
|
int msgpool;
|
||||||
|
int msgmap;
|
||||||
|
int msgmax;
|
||||||
|
int msgmnb;
|
||||||
|
int msgmni;
|
||||||
|
int msgssz;
|
||||||
|
int msgtql;
|
||||||
|
unsigned short int msgseg;
|
||||||
|
};
|
||||||
|
|
||||||
|
static inline abi_long host_to_target_msginfo(abi_ulong target_addr,
|
||||||
|
struct msginfo *host_msginfo)
|
||||||
|
{
|
||||||
|
struct target_msginfo *target_msginfo;
|
||||||
|
if (!lock_user_struct(VERIFY_WRITE, target_msginfo, target_addr, 0))
|
||||||
|
return -TARGET_EFAULT;
|
||||||
|
__put_user(host_msginfo->msgpool, &target_msginfo->msgpool);
|
||||||
|
__put_user(host_msginfo->msgmap, &target_msginfo->msgmap);
|
||||||
|
__put_user(host_msginfo->msgmax, &target_msginfo->msgmax);
|
||||||
|
__put_user(host_msginfo->msgmnb, &target_msginfo->msgmnb);
|
||||||
|
__put_user(host_msginfo->msgmni, &target_msginfo->msgmni);
|
||||||
|
__put_user(host_msginfo->msgssz, &target_msginfo->msgssz);
|
||||||
|
__put_user(host_msginfo->msgtql, &target_msginfo->msgtql);
|
||||||
|
__put_user(host_msginfo->msgseg, &target_msginfo->msgseg);
|
||||||
|
unlock_user_struct(target_msginfo, target_addr, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline abi_long do_msgctl(int msgid, int cmd, abi_long ptr)
|
||||||
{
|
{
|
||||||
struct msqid_ds dsarg;
|
struct msqid_ds dsarg;
|
||||||
int cmd = second&0xff;
|
struct msginfo msginfo;
|
||||||
abi_long ret = 0;
|
abi_long ret = -TARGET_EINVAL;
|
||||||
|
|
||||||
|
cmd &= 0xff;
|
||||||
|
|
||||||
switch (cmd) {
|
switch (cmd) {
|
||||||
case IPC_STAT:
|
case IPC_STAT:
|
||||||
case IPC_SET:
|
case IPC_SET:
|
||||||
target_to_host_msqid_ds(&dsarg,ptr);
|
case MSG_STAT:
|
||||||
ret = get_errno(msgctl(first, cmd, &dsarg));
|
if (target_to_host_msqid_ds(&dsarg,ptr))
|
||||||
host_to_target_msqid_ds(ptr,&dsarg);
|
return -TARGET_EFAULT;
|
||||||
default:
|
ret = get_errno(msgctl(msgid, cmd, &dsarg));
|
||||||
ret = get_errno(msgctl(first, cmd, &dsarg));
|
if (host_to_target_msqid_ds(ptr,&dsarg))
|
||||||
|
return -TARGET_EFAULT;
|
||||||
|
break;
|
||||||
|
case IPC_RMID:
|
||||||
|
ret = get_errno(msgctl(msgid, cmd, NULL));
|
||||||
|
break;
|
||||||
|
case IPC_INFO:
|
||||||
|
case MSG_INFO:
|
||||||
|
ret = get_errno(msgctl(msgid, cmd, (struct msqid_ds *)&msginfo));
|
||||||
|
if (host_to_target_msginfo(ptr, &msginfo))
|
||||||
|
return -TARGET_EFAULT;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct target_msgbuf {
|
struct target_msgbuf {
|
||||||
abi_ulong mtype;
|
abi_long mtype;
|
||||||
char mtext[1];
|
char mtext[1];
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -1933,7 +1983,7 @@ static inline abi_long do_msgsnd(int msqid, abi_long msgp,
|
|||||||
if (!lock_user_struct(VERIFY_READ, target_mb, msgp, 0))
|
if (!lock_user_struct(VERIFY_READ, target_mb, msgp, 0))
|
||||||
return -TARGET_EFAULT;
|
return -TARGET_EFAULT;
|
||||||
host_mb = malloc(msgsz+sizeof(long));
|
host_mb = malloc(msgsz+sizeof(long));
|
||||||
host_mb->mtype = tswapl(target_mb->mtype);
|
host_mb->mtype = (abi_long) tswapl(target_mb->mtype);
|
||||||
memcpy(host_mb->mtext, target_mb->mtext, msgsz);
|
memcpy(host_mb->mtext, target_mb->mtext, msgsz);
|
||||||
ret = get_errno(msgsnd(msqid, host_mb, msgsz, msgflg));
|
ret = get_errno(msgsnd(msqid, host_mb, msgsz, msgflg));
|
||||||
free(host_mb);
|
free(host_mb);
|
||||||
@ -1943,7 +1993,7 @@ static inline abi_long do_msgsnd(int msqid, abi_long msgp,
|
|||||||
}
|
}
|
||||||
|
|
||||||
static inline abi_long do_msgrcv(int msqid, abi_long msgp,
|
static inline abi_long do_msgrcv(int msqid, abi_long msgp,
|
||||||
unsigned int msgsz, int msgtype,
|
unsigned int msgsz, abi_long msgtyp,
|
||||||
int msgflg)
|
int msgflg)
|
||||||
{
|
{
|
||||||
struct target_msgbuf *target_mb;
|
struct target_msgbuf *target_mb;
|
||||||
@ -1953,8 +2003,10 @@ static inline abi_long do_msgrcv(int msqid, abi_long msgp,
|
|||||||
|
|
||||||
if (!lock_user_struct(VERIFY_WRITE, target_mb, msgp, 0))
|
if (!lock_user_struct(VERIFY_WRITE, target_mb, msgp, 0))
|
||||||
return -TARGET_EFAULT;
|
return -TARGET_EFAULT;
|
||||||
|
|
||||||
host_mb = malloc(msgsz+sizeof(long));
|
host_mb = malloc(msgsz+sizeof(long));
|
||||||
ret = get_errno(msgrcv(msqid, host_mb, msgsz, 1, msgflg));
|
ret = get_errno(msgrcv(msqid, host_mb, msgsz, tswapl(msgtyp), msgflg));
|
||||||
|
|
||||||
if (ret > 0) {
|
if (ret > 0) {
|
||||||
abi_ulong target_mtext_addr = msgp + sizeof(abi_ulong);
|
abi_ulong target_mtext_addr = msgp + sizeof(abi_ulong);
|
||||||
target_mtext = lock_user(VERIFY_WRITE, target_mtext_addr, ret, 0);
|
target_mtext = lock_user(VERIFY_WRITE, target_mtext_addr, ret, 0);
|
||||||
@ -1965,6 +2017,7 @@ static inline abi_long do_msgrcv(int msqid, abi_long msgp,
|
|||||||
memcpy(target_mb->mtext, host_mb->mtext, ret);
|
memcpy(target_mb->mtext, host_mb->mtext, ret);
|
||||||
unlock_user(target_mtext, target_mtext_addr, ret);
|
unlock_user(target_mtext, target_mtext_addr, ret);
|
||||||
}
|
}
|
||||||
|
|
||||||
target_mb->mtype = tswapl(host_mb->mtype);
|
target_mb->mtype = tswapl(host_mb->mtype);
|
||||||
free(host_mb);
|
free(host_mb);
|
||||||
|
|
||||||
@ -1974,6 +2027,7 @@ end:
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef TARGET_NR_ipc
|
||||||
/* ??? This only works with linear mappings. */
|
/* ??? This only works with linear mappings. */
|
||||||
/* do_ipc() must return target values and target errnos. */
|
/* do_ipc() must return target values and target errnos. */
|
||||||
static abi_long do_ipc(unsigned int call, int first,
|
static abi_long do_ipc(unsigned int call, int first,
|
||||||
@ -2019,19 +2073,26 @@ static abi_long do_ipc(unsigned int call, int first,
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case IPCOP_msgrcv:
|
case IPCOP_msgrcv:
|
||||||
|
switch (version) {
|
||||||
|
case 0:
|
||||||
{
|
{
|
||||||
/* XXX: this code is not correct */
|
struct target_ipc_kludge {
|
||||||
struct ipc_kludge
|
abi_long msgp;
|
||||||
{
|
abi_long msgtyp;
|
||||||
void *__unbounded msgp;
|
} *tmp;
|
||||||
long int msgtyp;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct ipc_kludge *foo = (struct ipc_kludge *)g2h(ptr);
|
if (!lock_user_struct(VERIFY_READ, tmp, ptr, 1)) {
|
||||||
struct msgbuf *msgp = (struct msgbuf *) foo->msgp;
|
ret = -TARGET_EFAULT;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
ret = do_msgrcv(first, (long)msgp, second, 0, third);
|
ret = do_msgrcv(first, tmp->msgp, second, tmp->msgtyp, third);
|
||||||
|
|
||||||
|
unlock_user_struct(tmp, ptr, 0);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
ret = do_msgrcv(first, ptr, second, fifth, third);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user