| /* | |
| * 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; | |
| } |