| /* |
| * BSD misc system call conversions routines |
| * |
| * Copyright (c) 2013 Stacey D. Son |
| * |
| * SPDX-License-Identifier: GPL-2.0-or-later |
| */ |
| #include "qemu/osdep.h" |
| |
| #define _WANT_SEMUN |
| #include <sys/types.h> |
| #include <sys/ipc.h> |
| #include <sys/msg.h> |
| #include <sys/sem.h> |
| #include <sys/uuid.h> |
| |
| #include "qemu.h" |
| #include "qemu-bsd.h" |
| |
| /* |
| * BSD uuidgen(2) struct uuid conversion |
| */ |
| abi_long host_to_target_uuid(abi_ulong target_addr, struct uuid *host_uuid) |
| { |
| struct target_uuid *target_uuid; |
| |
| if (!lock_user_struct(VERIFY_WRITE, target_uuid, target_addr, 0)) { |
| return -TARGET_EFAULT; |
| } |
| __put_user(host_uuid->time_low, &target_uuid->time_low); |
| __put_user(host_uuid->time_mid, &target_uuid->time_mid); |
| __put_user(host_uuid->time_hi_and_version, |
| &target_uuid->time_hi_and_version); |
| host_uuid->clock_seq_hi_and_reserved = |
| target_uuid->clock_seq_hi_and_reserved; |
| host_uuid->clock_seq_low = target_uuid->clock_seq_low; |
| memcpy(host_uuid->node, target_uuid->node, TARGET_UUID_NODE_LEN); |
| unlock_user_struct(target_uuid, target_addr, 1); |
| return 0; |
| } |
| |
| abi_long target_to_host_semarray(int semid, unsigned short **host_array, |
| abi_ulong target_addr) |
| { |
| abi_long ret; |
| int nsems, i; |
| unsigned short *array; |
| union semun semun; |
| struct semid_ds semid_ds; |
| |
| semun.buf = &semid_ds; |
| ret = semctl(semid, 0, IPC_STAT, semun); |
| if (ret == -1) { |
| return get_errno(ret); |
| } |
| nsems = semid_ds.sem_nsems; |
| *host_array = g_new(unsigned short, nsems); |
| array = lock_user(VERIFY_READ, target_addr, |
| nsems * sizeof(unsigned short), 1); |
| if (array == NULL) { |
| free(*host_array); |
| return -TARGET_EFAULT; |
| } |
| for (i = 0; i < nsems; i++) { |
| __get_user((*host_array)[i], array + i); |
| } |
| unlock_user(array, target_addr, 0); |
| |
| return 0; |
| } |
| |
| abi_long host_to_target_semarray(int semid, abi_ulong target_addr, |
| unsigned short **host_arrayp) |
| { |
| g_autofree unsigned short *host_array = *host_arrayp; |
| abi_long ret; |
| int nsems, i; |
| unsigned short *array; |
| union semun semun; |
| struct semid_ds semid_ds; |
| |
| semun.buf = &semid_ds; |
| |
| ret = semctl(semid, 0, IPC_STAT, semun); |
| if (ret == -1) { |
| return get_errno(ret); |
| } |
| |
| nsems = semid_ds.sem_nsems; |
| array = (unsigned short *)lock_user(VERIFY_WRITE, target_addr, |
| nsems * sizeof(unsigned short), 0); |
| if (array == NULL) { |
| return -TARGET_EFAULT; |
| } |
| for (i = 0; i < nsems; i++) { |
| __put_user(array[i], host_array + i); |
| } |
| unlock_user(array, target_addr, 1); |
| return 0; |
| } |
| |
| abi_long target_to_host_semid_ds(struct semid_ds *host_sd, |
| abi_ulong target_addr) |
| { |
| struct target_semid_ds *target_sd; |
| |
| if (!lock_user_struct(VERIFY_READ, target_sd, target_addr, 1)) { |
| return -TARGET_EFAULT; |
| } |
| target_to_host_ipc_perm__locked(&host_sd->sem_perm, &target_sd->sem_perm); |
| /* sem_base is not used by kernel for IPC_STAT/IPC_SET */ |
| /* host_sd->sem_base = g2h_untagged(target_sd->sem_base); */ |
| __get_user(host_sd->sem_nsems, &target_sd->sem_nsems); |
| __get_user(host_sd->sem_otime, &target_sd->sem_otime); |
| __get_user(host_sd->sem_ctime, &target_sd->sem_ctime); |
| unlock_user_struct(target_sd, target_addr, 0); |
| return 0; |
| } |
| |
| abi_long host_to_target_semid_ds(abi_ulong target_addr, |
| struct semid_ds *host_sd) |
| { |
| struct target_semid_ds *target_sd; |
| |
| if (!lock_user_struct(VERIFY_WRITE, target_sd, target_addr, 0)) { |
| return -TARGET_EFAULT; |
| } |
| host_to_target_ipc_perm__locked(&target_sd->sem_perm, |
| &host_sd->sem_perm); |
| /* sem_base is not used by kernel for IPC_STAT/IPC_SET */ |
| /* target_sd->sem_base = h2g((void *)host_sd->sem_base); */ |
| __put_user(target_sd->sem_nsems, &host_sd->sem_nsems); |
| __put_user(target_sd->sem_otime, &host_sd->sem_otime); |
| __put_user(target_sd->sem_ctime, &host_sd->sem_ctime); |
| unlock_user_struct(target_sd, target_addr, 1); |
| |
| return 0; |
| } |
| |
| abi_long target_to_host_msqid_ds(struct msqid_ds *host_md, |
| abi_ulong target_addr) |
| { |
| struct target_msqid_ds *target_md; |
| |
| if (!lock_user_struct(VERIFY_READ, target_md, target_addr, 1)) { |
| return -TARGET_EFAULT; |
| } |
| |
| memset(host_md, 0, sizeof(struct msqid_ds)); |
| target_to_host_ipc_perm__locked(&host_md->msg_perm, |
| &target_md->msg_perm); |
| |
| /* msg_first and msg_last are not used by IPC_SET/IPC_STAT in kernel. */ |
| __get_user(host_md->msg_cbytes, &target_md->msg_cbytes); |
| __get_user(host_md->msg_qnum, &target_md->msg_qnum); |
| __get_user(host_md->msg_qbytes, &target_md->msg_qbytes); |
| __get_user(host_md->msg_lspid, &target_md->msg_lspid); |
| __get_user(host_md->msg_lrpid, &target_md->msg_lrpid); |
| __get_user(host_md->msg_stime, &target_md->msg_stime); |
| __get_user(host_md->msg_rtime, &target_md->msg_rtime); |
| __get_user(host_md->msg_ctime, &target_md->msg_ctime); |
| unlock_user_struct(target_md, target_addr, 0); |
| |
| return 0; |
| } |
| |
| abi_long host_to_target_msqid_ds(abi_ulong target_addr, |
| struct msqid_ds *host_md) |
| { |
| struct target_msqid_ds *target_md; |
| |
| if (!lock_user_struct(VERIFY_WRITE, target_md, target_addr, 0)) { |
| return -TARGET_EFAULT; |
| } |
| |
| memset(target_md, 0, sizeof(struct target_msqid_ds)); |
| host_to_target_ipc_perm__locked(&target_md->msg_perm, |
| &host_md->msg_perm); |
| |
| /* msg_first and msg_last are not used by IPC_SET/IPC_STAT in kernel. */ |
| __put_user(target_md->msg_cbytes, &host_md->msg_cbytes); |
| __put_user(target_md->msg_qnum, &host_md->msg_qnum); |
| __put_user(target_md->msg_qbytes, &host_md->msg_qbytes); |
| __put_user(target_md->msg_lspid, &host_md->msg_lspid); |
| __put_user(target_md->msg_lrpid, &host_md->msg_lrpid); |
| __put_user(target_md->msg_stime, &host_md->msg_stime); |
| __put_user(target_md->msg_rtime, &host_md->msg_rtime); |
| __put_user(target_md->msg_ctime, &host_md->msg_ctime); |
| unlock_user_struct(target_md, target_addr, 1); |
| |
| return 0; |
| } |