Commit 1c54ff97bbde07f4a05dfae719ff2d1d13911265
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 | { | ... | ... |