Commit 1c54ff97bbde07f4a05dfae719ff2d1d13911265

Authored by aurel32
1 parent a0a83536

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
Showing 1 changed file with 116 additions and 55 deletions
linux-user/syscall.c
... ... @@ -1611,7 +1611,6 @@ static abi_long do_socketcall(int num, abi_ulong vptr)
1611 1611 }
1612 1612 #endif
1613 1613  
1614   -#ifdef TARGET_NR_ipc
1615 1614 #define N_SHM_REGIONS 32
1616 1615  
1617 1616 static struct shm_region {
... ... @@ -1845,20 +1844,26 @@ static inline abi_long do_semctl(int first, int second, int third,
1845 1844  
1846 1845 struct target_msqid_ds
1847 1846 {
1848   - struct target_ipc_perm msg_perm;
1849   - abi_ulong msg_stime;
1850   - abi_ulong __unused1;
1851   - abi_ulong msg_rtime;
1852   - abi_ulong __unused2;
1853   - abi_ulong msg_ctime;
1854   - abi_ulong __unused3;
1855   - abi_ulong __msg_cbytes;
1856   - abi_ulong msg_qnum;
1857   - abi_ulong msg_qbytes;
1858   - abi_ulong msg_lspid;
1859   - abi_ulong msg_lrpid;
1860   - abi_ulong __unused4;
1861   - abi_ulong __unused5;
  1847 + struct target_ipc_perm msg_perm;
  1848 + abi_ulong msg_stime;
  1849 +#if TARGET_ABI_BITS == 32
  1850 + abi_ulong __unused1;
  1851 +#endif
  1852 + abi_ulong msg_rtime;
  1853 +#if TARGET_ABI_BITS == 32
  1854 + abi_ulong __unused2;
  1855 +#endif
  1856 + abi_ulong msg_ctime;
  1857 +#if TARGET_ABI_BITS == 32
  1858 + abi_ulong __unused3;
  1859 +#endif
  1860 + abi_ulong __msg_cbytes;
  1861 + abi_ulong msg_qnum;
  1862 + abi_ulong msg_qbytes;
  1863 + abi_ulong msg_lspid;
  1864 + abi_ulong msg_lrpid;
  1865 + abi_ulong __unused4;
  1866 + abi_ulong __unused5;
1862 1867 };
1863 1868  
1864 1869 static inline abi_long target_to_host_msqid_ds(struct msqid_ds *host_md,
... ... @@ -1868,7 +1873,8 @@ static inline abi_long target_to_host_msqid_ds(struct msqid_ds *host_md,
1868 1873  
1869 1874 if (!lock_user_struct(VERIFY_READ, target_md, target_addr, 1))
1870 1875 return -TARGET_EFAULT;
1871   - target_to_host_ipc_perm(&(host_md->msg_perm),target_addr);
  1876 + if (target_to_host_ipc_perm(&(host_md->msg_perm),target_addr))
  1877 + return -TARGET_EFAULT;
1872 1878 host_md->msg_stime = tswapl(target_md->msg_stime);
1873 1879 host_md->msg_rtime = tswapl(target_md->msg_rtime);
1874 1880 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,
1888 1894  
1889 1895 if (!lock_user_struct(VERIFY_WRITE, target_md, target_addr, 0))
1890 1896 return -TARGET_EFAULT;
1891   - host_to_target_ipc_perm(target_addr,&(host_md->msg_perm));
  1897 + if (host_to_target_ipc_perm(target_addr,&(host_md->msg_perm)))
  1898 + return -TARGET_EFAULT;
1892 1899 target_md->msg_stime = tswapl(host_md->msg_stime);
1893 1900 target_md->msg_rtime = tswapl(host_md->msg_rtime);
1894 1901 target_md->msg_ctime = tswapl(host_md->msg_ctime);
... ... @@ -1901,26 +1908,69 @@ static inline abi_long host_to_target_msqid_ds(abi_ulong target_addr,
1901 1908 return 0;
1902 1909 }
1903 1910  
1904   -static inline abi_long do_msgctl(int first, int second, abi_long ptr)
  1911 +struct target_msginfo {
  1912 + int msgpool;
  1913 + int msgmap;
  1914 + int msgmax;
  1915 + int msgmnb;
  1916 + int msgmni;
  1917 + int msgssz;
  1918 + int msgtql;
  1919 + unsigned short int msgseg;
  1920 +};
  1921 +
  1922 +static inline abi_long host_to_target_msginfo(abi_ulong target_addr,
  1923 + struct msginfo *host_msginfo)
  1924 +{
  1925 + struct target_msginfo *target_msginfo;
  1926 + if (!lock_user_struct(VERIFY_WRITE, target_msginfo, target_addr, 0))
  1927 + return -TARGET_EFAULT;
  1928 + __put_user(host_msginfo->msgpool, &target_msginfo->msgpool);
  1929 + __put_user(host_msginfo->msgmap, &target_msginfo->msgmap);
  1930 + __put_user(host_msginfo->msgmax, &target_msginfo->msgmax);
  1931 + __put_user(host_msginfo->msgmnb, &target_msginfo->msgmnb);
  1932 + __put_user(host_msginfo->msgmni, &target_msginfo->msgmni);
  1933 + __put_user(host_msginfo->msgssz, &target_msginfo->msgssz);
  1934 + __put_user(host_msginfo->msgtql, &target_msginfo->msgtql);
  1935 + __put_user(host_msginfo->msgseg, &target_msginfo->msgseg);
  1936 + unlock_user_struct(target_msginfo, target_addr, 1);
  1937 +}
  1938 +
  1939 +static inline abi_long do_msgctl(int msgid, int cmd, abi_long ptr)
1905 1940 {
1906 1941 struct msqid_ds dsarg;
1907   - int cmd = second&0xff;
1908   - abi_long ret = 0;
1909   - switch( cmd ) {
  1942 + struct msginfo msginfo;
  1943 + abi_long ret = -TARGET_EINVAL;
  1944 +
  1945 + cmd &= 0xff;
  1946 +
  1947 + switch (cmd) {
1910 1948 case IPC_STAT:
1911 1949 case IPC_SET:
1912   - target_to_host_msqid_ds(&dsarg,ptr);
1913   - ret = get_errno(msgctl(first, cmd, &dsarg));
1914   - host_to_target_msqid_ds(ptr,&dsarg);
1915   - default:
1916   - ret = get_errno(msgctl(first, cmd, &dsarg));
  1950 + case MSG_STAT:
  1951 + if (target_to_host_msqid_ds(&dsarg,ptr))
  1952 + return -TARGET_EFAULT;
  1953 + ret = get_errno(msgctl(msgid, cmd, &dsarg));
  1954 + if (host_to_target_msqid_ds(ptr,&dsarg))
  1955 + return -TARGET_EFAULT;
  1956 + break;
  1957 + case IPC_RMID:
  1958 + ret = get_errno(msgctl(msgid, cmd, NULL));
  1959 + break;
  1960 + case IPC_INFO:
  1961 + case MSG_INFO:
  1962 + ret = get_errno(msgctl(msgid, cmd, (struct msqid_ds *)&msginfo));
  1963 + if (host_to_target_msginfo(ptr, &msginfo))
  1964 + return -TARGET_EFAULT;
  1965 + break;
1917 1966 }
  1967 +
1918 1968 return ret;
1919 1969 }
1920 1970  
1921 1971 struct target_msgbuf {
1922   - abi_ulong mtype;
1923   - char mtext[1];
  1972 + abi_long mtype;
  1973 + char mtext[1];
1924 1974 };
1925 1975  
1926 1976 static inline abi_long do_msgsnd(int msqid, abi_long msgp,
... ... @@ -1933,8 +1983,8 @@ static inline abi_long do_msgsnd(int msqid, abi_long msgp,
1933 1983 if (!lock_user_struct(VERIFY_READ, target_mb, msgp, 0))
1934 1984 return -TARGET_EFAULT;
1935 1985 host_mb = malloc(msgsz+sizeof(long));
1936   - host_mb->mtype = tswapl(target_mb->mtype);
1937   - memcpy(host_mb->mtext,target_mb->mtext,msgsz);
  1986 + host_mb->mtype = (abi_long) tswapl(target_mb->mtype);
  1987 + memcpy(host_mb->mtext, target_mb->mtext, msgsz);
1938 1988 ret = get_errno(msgsnd(msqid, host_mb, msgsz, msgflg));
1939 1989 free(host_mb);
1940 1990 unlock_user_struct(target_mb, msgp, 0);
... ... @@ -1943,7 +1993,7 @@ static inline abi_long do_msgsnd(int msqid, abi_long msgp,
1943 1993 }
1944 1994  
1945 1995 static inline abi_long do_msgrcv(int msqid, abi_long msgp,
1946   - unsigned int msgsz, int msgtype,
  1996 + unsigned int msgsz, abi_long msgtyp,
1947 1997 int msgflg)
1948 1998 {
1949 1999 struct target_msgbuf *target_mb;
... ... @@ -1953,8 +2003,10 @@ static inline abi_long do_msgrcv(int msqid, abi_long msgp,
1953 2003  
1954 2004 if (!lock_user_struct(VERIFY_WRITE, target_mb, msgp, 0))
1955 2005 return -TARGET_EFAULT;
  2006 +
1956 2007 host_mb = malloc(msgsz+sizeof(long));
1957   - ret = get_errno(msgrcv(msqid, host_mb, msgsz, 1, msgflg));
  2008 + ret = get_errno(msgrcv(msqid, host_mb, msgsz, tswapl(msgtyp), msgflg));
  2009 +
1958 2010 if (ret > 0) {
1959 2011 abi_ulong target_mtext_addr = msgp + sizeof(abi_ulong);
1960 2012 target_mtext = lock_user(VERIFY_WRITE, target_mtext_addr, ret, 0);
... ... @@ -1962,9 +2014,10 @@ static inline abi_long do_msgrcv(int msqid, abi_long msgp,
1962 2014 ret = -TARGET_EFAULT;
1963 2015 goto end;
1964 2016 }
1965   - memcpy(target_mb->mtext, host_mb->mtext, ret);
  2017 + memcpy(target_mb->mtext, host_mb->mtext, ret);
1966 2018 unlock_user(target_mtext, target_mtext_addr, ret);
1967 2019 }
  2020 +
1968 2021 target_mb->mtype = tswapl(host_mb->mtype);
1969 2022 free(host_mb);
1970 2023  
... ... @@ -1974,6 +2027,7 @@ end:
1974 2027 return ret;
1975 2028 }
1976 2029  
  2030 +#ifdef TARGET_NR_ipc
1977 2031 /* ??? This only works with linear mappings. */
1978 2032 /* do_ipc() must return target values and target errnos. */
1979 2033 static abi_long do_ipc(unsigned int call, int first,
... ... @@ -2006,34 +2060,41 @@ static abi_long do_ipc(unsigned int call, int first,
2006 2060 ret = -TARGET_ENOSYS;
2007 2061 break;
2008 2062  
2009   - case IPCOP_msgget:
2010   - ret = get_errno(msgget(first, second));
2011   - break;
  2063 + case IPCOP_msgget:
  2064 + ret = get_errno(msgget(first, second));
  2065 + break;
2012 2066  
2013   - case IPCOP_msgsnd:
2014   - ret = do_msgsnd(first, ptr, second, third);
2015   - break;
  2067 + case IPCOP_msgsnd:
  2068 + ret = do_msgsnd(first, ptr, second, third);
  2069 + break;
2016 2070  
2017   - case IPCOP_msgctl:
2018   - ret = do_msgctl(first, second, ptr);
2019   - break;
  2071 + case IPCOP_msgctl:
  2072 + ret = do_msgctl(first, second, ptr);
  2073 + break;
2020 2074  
2021   - case IPCOP_msgrcv:
2022   - {
2023   - /* XXX: this code is not correct */
2024   - struct ipc_kludge
2025   - {
2026   - void *__unbounded msgp;
2027   - long int msgtyp;
2028   - };
  2075 + case IPCOP_msgrcv:
  2076 + switch (version) {
  2077 + case 0:
  2078 + {
  2079 + struct target_ipc_kludge {
  2080 + abi_long msgp;
  2081 + abi_long msgtyp;
  2082 + } *tmp;
2029 2083  
2030   - struct ipc_kludge *foo = (struct ipc_kludge *)g2h(ptr);
2031   - struct msgbuf *msgp = (struct msgbuf *) foo->msgp;
  2084 + if (!lock_user_struct(VERIFY_READ, tmp, ptr, 1)) {
  2085 + ret = -TARGET_EFAULT;
  2086 + break;
  2087 + }
2032 2088  
2033   - ret = do_msgrcv(first, (long)msgp, second, 0, third);
  2089 + ret = do_msgrcv(first, tmp->msgp, second, tmp->msgtyp, third);
2034 2090  
2035   - }
2036   - break;
  2091 + unlock_user_struct(tmp, ptr, 0);
  2092 + break;
  2093 + }
  2094 + default:
  2095 + ret = do_msgrcv(first, ptr, second, fifth, third);
  2096 + }
  2097 + break;
2037 2098  
2038 2099 case IPCOP_shmat:
2039 2100 {
... ...