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