Revision e5289087 linux-user/syscall.c
b/linux-user/syscall.c | ||
---|---|---|
2006 | 2006 |
|
2007 | 2007 |
if (!lock_user_struct(VERIFY_READ, target_sd, target_addr, 1)) |
2008 | 2008 |
return -TARGET_EFAULT; |
2009 |
target_to_host_ipc_perm(&(host_sd->sem_perm),target_addr); |
|
2009 |
if (target_to_host_ipc_perm(&(host_sd->sem_perm),target_addr)) |
|
2010 |
return -TARGET_EFAULT; |
|
2010 | 2011 |
host_sd->sem_nsems = tswapl(target_sd->sem_nsems); |
2011 | 2012 |
host_sd->sem_otime = tswapl(target_sd->sem_otime); |
2012 | 2013 |
host_sd->sem_ctime = tswapl(target_sd->sem_ctime); |
... | ... | |
2021 | 2022 |
|
2022 | 2023 |
if (!lock_user_struct(VERIFY_WRITE, target_sd, target_addr, 0)) |
2023 | 2024 |
return -TARGET_EFAULT; |
2024 |
host_to_target_ipc_perm(target_addr,&(host_sd->sem_perm)); |
|
2025 |
if (host_to_target_ipc_perm(target_addr,&(host_sd->sem_perm))) |
|
2026 |
return -TARGET_EFAULT;; |
|
2025 | 2027 |
target_sd->sem_nsems = tswapl(host_sd->sem_nsems); |
2026 | 2028 |
target_sd->sem_otime = tswapl(host_sd->sem_otime); |
2027 | 2029 |
target_sd->sem_ctime = tswapl(host_sd->sem_ctime); |
... | ... | |
2029 | 2031 |
return 0; |
2030 | 2032 |
} |
2031 | 2033 |
|
2034 |
struct target_seminfo { |
|
2035 |
int semmap; |
|
2036 |
int semmni; |
|
2037 |
int semmns; |
|
2038 |
int semmnu; |
|
2039 |
int semmsl; |
|
2040 |
int semopm; |
|
2041 |
int semume; |
|
2042 |
int semusz; |
|
2043 |
int semvmx; |
|
2044 |
int semaem; |
|
2045 |
}; |
|
2046 |
|
|
2047 |
static inline abi_long host_to_target_seminfo(abi_ulong target_addr, |
|
2048 |
struct seminfo *host_seminfo) |
|
2049 |
{ |
|
2050 |
struct target_seminfo *target_seminfo; |
|
2051 |
if (!lock_user_struct(VERIFY_WRITE, target_seminfo, target_addr, 0)) |
|
2052 |
return -TARGET_EFAULT; |
|
2053 |
__put_user(host_seminfo->semmap, &target_seminfo->semmap); |
|
2054 |
__put_user(host_seminfo->semmni, &target_seminfo->semmni); |
|
2055 |
__put_user(host_seminfo->semmns, &target_seminfo->semmns); |
|
2056 |
__put_user(host_seminfo->semmnu, &target_seminfo->semmnu); |
|
2057 |
__put_user(host_seminfo->semmsl, &target_seminfo->semmsl); |
|
2058 |
__put_user(host_seminfo->semopm, &target_seminfo->semopm); |
|
2059 |
__put_user(host_seminfo->semume, &target_seminfo->semume); |
|
2060 |
__put_user(host_seminfo->semusz, &target_seminfo->semusz); |
|
2061 |
__put_user(host_seminfo->semvmx, &target_seminfo->semvmx); |
|
2062 |
__put_user(host_seminfo->semaem, &target_seminfo->semaem); |
|
2063 |
unlock_user_struct(target_seminfo, target_addr, 1); |
|
2064 |
return 0; |
|
2065 |
} |
|
2066 |
|
|
2032 | 2067 |
union semun { |
2033 | 2068 |
int val; |
2034 | 2069 |
struct semid_ds *buf; |
2035 | 2070 |
unsigned short *array; |
2071 |
struct seminfo *__buf; |
|
2036 | 2072 |
}; |
2037 | 2073 |
|
2038 | 2074 |
union target_semun { |
2039 | 2075 |
int val; |
2040 |
abi_long buf; |
|
2041 |
unsigned short int *array; |
|
2076 |
abi_ulong buf; |
|
2077 |
abi_ulong array; |
|
2078 |
abi_ulong __buf; |
|
2042 | 2079 |
}; |
2043 | 2080 |
|
2044 |
static inline abi_long target_to_host_semun(int cmd, |
|
2045 |
union semun *host_su, |
|
2046 |
abi_ulong target_addr, |
|
2047 |
struct semid_ds *ds) |
|
2081 |
static inline abi_long target_to_host_semarray(int semid, unsigned short **host_array, |
|
2082 |
abi_ulong target_addr) |
|
2048 | 2083 |
{ |
2049 |
union target_semun *target_su; |
|
2084 |
int nsems; |
|
2085 |
unsigned short *array; |
|
2086 |
union semun semun; |
|
2087 |
struct semid_ds semid_ds; |
|
2088 |
int i, ret; |
|
2050 | 2089 |
|
2051 |
switch( cmd ) { |
|
2052 |
case IPC_STAT: |
|
2053 |
case IPC_SET: |
|
2054 |
if (!lock_user_struct(VERIFY_READ, target_su, target_addr, 1)) |
|
2055 |
return -TARGET_EFAULT; |
|
2056 |
target_to_host_semid_ds(ds,target_su->buf); |
|
2057 |
host_su->buf = ds; |
|
2058 |
unlock_user_struct(target_su, target_addr, 0); |
|
2059 |
break; |
|
2060 |
case GETVAL: |
|
2061 |
case SETVAL: |
|
2062 |
if (!lock_user_struct(VERIFY_READ, target_su, target_addr, 1)) |
|
2063 |
return -TARGET_EFAULT; |
|
2064 |
host_su->val = tswapl(target_su->val); |
|
2065 |
unlock_user_struct(target_su, target_addr, 0); |
|
2066 |
break; |
|
2067 |
case GETALL: |
|
2068 |
case SETALL: |
|
2069 |
if (!lock_user_struct(VERIFY_READ, target_su, target_addr, 1)) |
|
2070 |
return -TARGET_EFAULT; |
|
2071 |
*host_su->array = tswap16(*target_su->array); |
|
2072 |
unlock_user_struct(target_su, target_addr, 0); |
|
2073 |
break; |
|
2074 |
default: |
|
2075 |
gemu_log("semun operation not fully supported: %d\n", (int)cmd); |
|
2090 |
semun.buf = &semid_ds; |
|
2091 |
|
|
2092 |
ret = semctl(semid, 0, IPC_STAT, semun); |
|
2093 |
if (ret == -1) |
|
2094 |
return get_errno(ret); |
|
2095 |
|
|
2096 |
nsems = semid_ds.sem_nsems; |
|
2097 |
|
|
2098 |
*host_array = malloc(nsems*sizeof(unsigned short)); |
|
2099 |
array = lock_user(VERIFY_READ, target_addr, |
|
2100 |
nsems*sizeof(unsigned short), 1); |
|
2101 |
if (!array) |
|
2102 |
return -TARGET_EFAULT; |
|
2103 |
|
|
2104 |
for(i=0; i<nsems; i++) { |
|
2105 |
__get_user((*host_array)[i], &array[i]); |
|
2076 | 2106 |
} |
2107 |
unlock_user(array, target_addr, 0); |
|
2108 |
|
|
2077 | 2109 |
return 0; |
2078 | 2110 |
} |
2079 | 2111 |
|
2080 |
static inline abi_long host_to_target_semun(int cmd, |
|
2081 |
abi_ulong target_addr, |
|
2082 |
union semun *host_su, |
|
2083 |
struct semid_ds *ds) |
|
2112 |
static inline abi_long host_to_target_semarray(int semid, abi_ulong target_addr, |
|
2113 |
unsigned short **host_array) |
|
2084 | 2114 |
{ |
2085 |
union target_semun *target_su; |
|
2115 |
int nsems; |
|
2116 |
unsigned short *array; |
|
2117 |
union semun semun; |
|
2118 |
struct semid_ds semid_ds; |
|
2119 |
int i, ret; |
|
2086 | 2120 |
|
2087 |
switch( cmd ) { |
|
2088 |
case IPC_STAT: |
|
2089 |
case IPC_SET: |
|
2090 |
if (lock_user_struct(VERIFY_WRITE, target_su, target_addr, 0)) |
|
2091 |
return -TARGET_EFAULT; |
|
2092 |
host_to_target_semid_ds(target_su->buf,ds); |
|
2093 |
unlock_user_struct(target_su, target_addr, 1); |
|
2094 |
break; |
|
2095 |
case GETVAL: |
|
2096 |
case SETVAL: |
|
2097 |
if (lock_user_struct(VERIFY_WRITE, target_su, target_addr, 0)) |
|
2098 |
return -TARGET_EFAULT; |
|
2099 |
target_su->val = tswapl(host_su->val); |
|
2100 |
unlock_user_struct(target_su, target_addr, 1); |
|
2101 |
break; |
|
2102 |
case GETALL: |
|
2103 |
case SETALL: |
|
2104 |
if (lock_user_struct(VERIFY_WRITE, target_su, target_addr, 0)) |
|
2105 |
return -TARGET_EFAULT; |
|
2106 |
*target_su->array = tswap16(*host_su->array); |
|
2107 |
unlock_user_struct(target_su, target_addr, 1); |
|
2108 |
break; |
|
2109 |
default: |
|
2110 |
gemu_log("semun operation not fully supported: %d\n", (int)cmd); |
|
2121 |
semun.buf = &semid_ds; |
|
2122 |
|
|
2123 |
ret = semctl(semid, 0, IPC_STAT, semun); |
|
2124 |
if (ret == -1) |
|
2125 |
return get_errno(ret); |
|
2126 |
|
|
2127 |
nsems = semid_ds.sem_nsems; |
|
2128 |
|
|
2129 |
array = lock_user(VERIFY_WRITE, target_addr, |
|
2130 |
nsems*sizeof(unsigned short), 0); |
|
2131 |
if (!array) |
|
2132 |
return -TARGET_EFAULT; |
|
2133 |
|
|
2134 |
for(i=0; i<nsems; i++) { |
|
2135 |
__put_user((*host_array)[i], &array[i]); |
|
2111 | 2136 |
} |
2137 |
free(*host_array); |
|
2138 |
unlock_user(array, target_addr, 1); |
|
2139 |
|
|
2112 | 2140 |
return 0; |
2113 | 2141 |
} |
2114 | 2142 |
|
2115 |
static inline abi_long do_semctl(int first, int second, int third,
|
|
2116 |
abi_long ptr)
|
|
2143 |
static inline abi_long do_semctl(int semid, int semnum, int cmd,
|
|
2144 |
union target_semun target_su)
|
|
2117 | 2145 |
{ |
2118 | 2146 |
union semun arg; |
2119 | 2147 |
struct semid_ds dsarg; |
2120 |
int cmd = third&0xff; |
|
2121 |
abi_long ret = 0; |
|
2148 |
unsigned short *array; |
|
2149 |
struct seminfo seminfo; |
|
2150 |
abi_long ret = -TARGET_EINVAL; |
|
2151 |
abi_long err; |
|
2152 |
cmd &= 0xff; |
|
2122 | 2153 |
|
2123 | 2154 |
switch( cmd ) { |
2124 | 2155 |
case GETVAL: |
2125 |
target_to_host_semun(cmd,&arg,ptr,&dsarg); |
|
2126 |
ret = get_errno(semctl(first, second, cmd, arg)); |
|
2127 |
host_to_target_semun(cmd,ptr,&arg,&dsarg); |
|
2128 |
break; |
|
2129 | 2156 |
case SETVAL: |
2130 |
target_to_host_semun(cmd,&arg,ptr,&dsarg);
|
|
2131 |
ret = get_errno(semctl(first, second, cmd, arg));
|
|
2132 |
host_to_target_semun(cmd,ptr,&arg,&dsarg);
|
|
2157 |
arg.val = tswapl(target_su.val);
|
|
2158 |
ret = get_errno(semctl(semid, semnum, cmd, arg));
|
|
2159 |
target_su.val = tswapl(arg.val);
|
|
2133 | 2160 |
break; |
2134 | 2161 |
case GETALL: |
2135 |
target_to_host_semun(cmd,&arg,ptr,&dsarg); |
|
2136 |
ret = get_errno(semctl(first, second, cmd, arg)); |
|
2137 |
host_to_target_semun(cmd,ptr,&arg,&dsarg); |
|
2138 |
break; |
|
2139 | 2162 |
case SETALL: |
2140 |
target_to_host_semun(cmd,&arg,ptr,&dsarg); |
|
2141 |
ret = get_errno(semctl(first, second, cmd, arg)); |
|
2142 |
host_to_target_semun(cmd,ptr,&arg,&dsarg); |
|
2163 |
err = target_to_host_semarray(semid, &array, target_su.array); |
|
2164 |
if (err) |
|
2165 |
return err; |
|
2166 |
arg.array = array; |
|
2167 |
ret = get_errno(semctl(semid, semnum, cmd, arg)); |
|
2168 |
err = host_to_target_semarray(semid, target_su.array, &array); |
|
2169 |
if (err) |
|
2170 |
return err; |
|
2143 | 2171 |
break; |
2144 | 2172 |
case IPC_STAT: |
2145 |
target_to_host_semun(cmd,&arg,ptr,&dsarg); |
|
2146 |
ret = get_errno(semctl(first, second, cmd, arg)); |
|
2147 |
host_to_target_semun(cmd,ptr,&arg,&dsarg); |
|
2148 |
break; |
|
2149 | 2173 |
case IPC_SET: |
2150 |
target_to_host_semun(cmd,&arg,ptr,&dsarg); |
|
2151 |
ret = get_errno(semctl(first, second, cmd, arg)); |
|
2152 |
host_to_target_semun(cmd,ptr,&arg,&dsarg); |
|
2174 |
case SEM_STAT: |
|
2175 |
err = target_to_host_semid_ds(&dsarg, target_su.buf); |
|
2176 |
if (err) |
|
2177 |
return err; |
|
2178 |
arg.buf = &dsarg; |
|
2179 |
ret = get_errno(semctl(semid, semnum, cmd, arg)); |
|
2180 |
err = host_to_target_semid_ds(target_su.buf, &dsarg); |
|
2181 |
if (err) |
|
2182 |
return err; |
|
2183 |
break; |
|
2184 |
case IPC_INFO: |
|
2185 |
case SEM_INFO: |
|
2186 |
arg.__buf = &seminfo; |
|
2187 |
ret = get_errno(semctl(semid, semnum, cmd, arg)); |
|
2188 |
err = host_to_target_seminfo(target_su.__buf, &seminfo); |
|
2189 |
if (err) |
|
2190 |
return err; |
|
2191 |
break; |
|
2192 |
case IPC_RMID: |
|
2193 |
case GETPID: |
|
2194 |
case GETNCNT: |
|
2195 |
case GETZCNT: |
|
2196 |
ret = get_errno(semctl(semid, semnum, cmd, NULL)); |
|
2153 | 2197 |
break; |
2154 |
default: |
|
2155 |
ret = get_errno(semctl(first, second, cmd, arg)); |
|
2156 | 2198 |
} |
2157 | 2199 |
|
2158 | 2200 |
return ret; |
2159 | 2201 |
} |
2160 | 2202 |
|
2203 |
struct target_sembuf { |
|
2204 |
unsigned short sem_num; |
|
2205 |
short sem_op; |
|
2206 |
short sem_flg; |
|
2207 |
}; |
|
2208 |
|
|
2209 |
static inline abi_long target_to_host_sembuf(struct sembuf *host_sembuf, |
|
2210 |
abi_ulong target_addr, |
|
2211 |
unsigned nsops) |
|
2212 |
{ |
|
2213 |
struct target_sembuf *target_sembuf; |
|
2214 |
int i; |
|
2215 |
|
|
2216 |
target_sembuf = lock_user(VERIFY_READ, target_addr, |
|
2217 |
nsops*sizeof(struct target_sembuf), 1); |
|
2218 |
if (!target_sembuf) |
|
2219 |
return -TARGET_EFAULT; |
|
2220 |
|
|
2221 |
for(i=0; i<nsops; i++) { |
|
2222 |
__get_user(host_sembuf[i].sem_num, &target_sembuf[i].sem_num); |
|
2223 |
__get_user(host_sembuf[i].sem_op, &target_sembuf[i].sem_op); |
|
2224 |
__get_user(host_sembuf[i].sem_flg, &target_sembuf[i].sem_flg); |
|
2225 |
} |
|
2226 |
|
|
2227 |
unlock_user(target_sembuf, target_addr, 0); |
|
2228 |
|
|
2229 |
return 0; |
|
2230 |
} |
|
2231 |
|
|
2232 |
static inline abi_long do_semop(int semid, abi_long ptr, unsigned nsops) |
|
2233 |
{ |
|
2234 |
struct sembuf sops[nsops]; |
|
2235 |
|
|
2236 |
if (target_to_host_sembuf(sops, ptr, nsops)) |
|
2237 |
return -TARGET_EFAULT; |
|
2238 |
|
|
2239 |
return semop(semid, sops, nsops); |
|
2240 |
} |
|
2241 |
|
|
2161 | 2242 |
struct target_msqid_ds |
2162 | 2243 |
{ |
2163 | 2244 |
struct target_ipc_perm msg_perm; |
... | ... | |
2361 | 2442 |
|
2362 | 2443 |
switch (call) { |
2363 | 2444 |
case IPCOP_semop: |
2364 |
ret = get_errno(semop(first,(struct sembuf *)g2h(ptr), second));
|
|
2445 |
ret = do_semop(first, ptr, second);
|
|
2365 | 2446 |
break; |
2366 | 2447 |
|
2367 | 2448 |
case IPCOP_semget: |
... | ... | |
2369 | 2450 |
break; |
2370 | 2451 |
|
2371 | 2452 |
case IPCOP_semctl: |
2372 |
ret = do_semctl(first, second, third, ptr); |
|
2373 |
break; |
|
2374 |
|
|
2375 |
case IPCOP_semtimedop: |
|
2376 |
gemu_log("Unsupported ipc call: %d (version %d)\n", call, version); |
|
2377 |
ret = -TARGET_ENOSYS; |
|
2453 |
ret = do_semctl(first, second, third, (union target_semun)(abi_ulong) ptr); |
|
2378 | 2454 |
break; |
2379 | 2455 |
|
2380 | 2456 |
case IPCOP_msgget: |
... | ... | |
5200 | 5276 |
ret = do_ipc(arg1, arg2, arg3, arg4, arg5, arg6); |
5201 | 5277 |
break; |
5202 | 5278 |
#endif |
5203 |
|
|
5279 |
#ifdef TARGET_NR_semget |
|
5280 |
case TARGET_NR_semget: |
|
5281 |
ret = get_errno(semget(arg1, arg2, arg3)); |
|
5282 |
break; |
|
5283 |
#endif |
|
5284 |
#ifdef TARGET_NR_semop |
|
5285 |
case TARGET_NR_semop: |
|
5286 |
ret = get_errno(do_semop(arg1, arg2, arg3)); |
|
5287 |
break; |
|
5288 |
#endif |
|
5289 |
#ifdef TARGET_NR_semctl |
|
5290 |
case TARGET_NR_semctl: |
|
5291 |
ret = do_semctl(arg1, arg2, arg3, (union target_semun)(abi_ulong)arg4); |
|
5292 |
break; |
|
5293 |
#endif |
|
5204 | 5294 |
#ifdef TARGET_NR_msgctl |
5205 | 5295 |
case TARGET_NR_msgctl: |
5206 | 5296 |
ret = do_msgctl(arg1, arg2, arg3); |
Also available in: Unified diff