master
c 192 lines 5.96 KB
Raw
1 /*
2 * BSD misc system call conversions routines
3 *
4 * Copyright (c) 2013 Stacey D. Son
5 *
6 * SPDX-License-Identifier: GPL-2.0-or-later
7 */
8 #include "qemu/osdep.h"
9
10 #define _WANT_SEMUN
11 #include <sys/types.h>
12 #include <sys/ipc.h>
13 #include <sys/msg.h>
14 #include <sys/sem.h>
15 #include <sys/uuid.h>
16
17 #include "qemu.h"
18 #include "qemu-bsd.h"
19
20 /*
21 * BSD uuidgen(2) struct uuid conversion
22 */
23 abi_long host_to_target_uuid(abi_ulong target_addr, struct uuid *host_uuid)
24 {
25 struct target_uuid *target_uuid;
26
27 if (!lock_user_struct(VERIFY_WRITE, target_uuid, target_addr, 0)) {
28 return -TARGET_EFAULT;
29 }
30 __put_user(host_uuid->time_low, &target_uuid->time_low);
31 __put_user(host_uuid->time_mid, &target_uuid->time_mid);
32 __put_user(host_uuid->time_hi_and_version,
33 &target_uuid->time_hi_and_version);
34 host_uuid->clock_seq_hi_and_reserved =
35 target_uuid->clock_seq_hi_and_reserved;
36 host_uuid->clock_seq_low = target_uuid->clock_seq_low;
37 memcpy(host_uuid->node, target_uuid->node, TARGET_UUID_NODE_LEN);
38 unlock_user_struct(target_uuid, target_addr, 1);
39 return 0;
40 }
41
42 abi_long target_to_host_semarray(int semid, unsigned short **host_array,
43 abi_ulong target_addr)
44 {
45 abi_long ret;
46 int nsems, i;
47 unsigned short *array;
48 union semun semun;
49 struct semid_ds semid_ds;
50
51 semun.buf = &semid_ds;
52 ret = semctl(semid, 0, IPC_STAT, semun);
53 if (ret == -1) {
54 return get_errno(ret);
55 }
56 nsems = semid_ds.sem_nsems;
57 *host_array = g_new(unsigned short, nsems);
58 array = lock_user(VERIFY_READ, target_addr,
59 nsems * sizeof(unsigned short), 1);
60 if (array == NULL) {
61 free(*host_array);
62 return -TARGET_EFAULT;
63 }
64 for (i = 0; i < nsems; i++) {
65 __get_user((*host_array)[i], array + i);
66 }
67 unlock_user(array, target_addr, 0);
68
69 return 0;
70 }
71
72 abi_long host_to_target_semarray(int semid, abi_ulong target_addr,
73 unsigned short **host_arrayp)
74 {
75 g_autofree unsigned short *host_array = *host_arrayp;
76 abi_long ret;
77 int nsems, i;
78 unsigned short *array;
79 union semun semun;
80 struct semid_ds semid_ds;
81
82 semun.buf = &semid_ds;
83
84 ret = semctl(semid, 0, IPC_STAT, semun);
85 if (ret == -1) {
86 return get_errno(ret);
87 }
88
89 nsems = semid_ds.sem_nsems;
90 array = (unsigned short *)lock_user(VERIFY_WRITE, target_addr,
91 nsems * sizeof(unsigned short), 0);
92 if (array == NULL) {
93 return -TARGET_EFAULT;
94 }
95 for (i = 0; i < nsems; i++) {
96 __put_user(array[i], host_array + i);
97 }
98 unlock_user(array, target_addr, 1);
99 return 0;
100 }
101
102 abi_long target_to_host_semid_ds(struct semid_ds *host_sd,
103 abi_ulong target_addr)
104 {
105 struct target_semid_ds *target_sd;
106
107 if (!lock_user_struct(VERIFY_READ, target_sd, target_addr, 1)) {
108 return -TARGET_EFAULT;
109 }
110 target_to_host_ipc_perm__locked(&host_sd->sem_perm, &target_sd->sem_perm);
111 /* sem_base is not used by kernel for IPC_STAT/IPC_SET */
112 /* host_sd->sem_base = g2h_untagged(target_sd->sem_base); */
113 __get_user(host_sd->sem_nsems, &target_sd->sem_nsems);
114 __get_user(host_sd->sem_otime, &target_sd->sem_otime);
115 __get_user(host_sd->sem_ctime, &target_sd->sem_ctime);
116 unlock_user_struct(target_sd, target_addr, 0);
117 return 0;
118 }
119
120 abi_long host_to_target_semid_ds(abi_ulong target_addr,
121 struct semid_ds *host_sd)
122 {
123 struct target_semid_ds *target_sd;
124
125 if (!lock_user_struct(VERIFY_WRITE, target_sd, target_addr, 0)) {
126 return -TARGET_EFAULT;
127 }
128 host_to_target_ipc_perm__locked(&target_sd->sem_perm,
129 &host_sd->sem_perm);
130 /* sem_base is not used by kernel for IPC_STAT/IPC_SET */
131 /* target_sd->sem_base = h2g((void *)host_sd->sem_base); */
132 __put_user(target_sd->sem_nsems, &host_sd->sem_nsems);
133 __put_user(target_sd->sem_otime, &host_sd->sem_otime);
134 __put_user(target_sd->sem_ctime, &host_sd->sem_ctime);
135 unlock_user_struct(target_sd, target_addr, 1);
136
137 return 0;
138 }
139
140 abi_long target_to_host_msqid_ds(struct msqid_ds *host_md,
141 abi_ulong target_addr)
142 {
143 struct target_msqid_ds *target_md;
144
145 if (!lock_user_struct(VERIFY_READ, target_md, target_addr, 1)) {
146 return -TARGET_EFAULT;
147 }
148
149 memset(host_md, 0, sizeof(struct msqid_ds));
150 target_to_host_ipc_perm__locked(&host_md->msg_perm,
151 &target_md->msg_perm);
152
153 /* msg_first and msg_last are not used by IPC_SET/IPC_STAT in kernel. */
154 __get_user(host_md->msg_cbytes, &target_md->msg_cbytes);
155 __get_user(host_md->msg_qnum, &target_md->msg_qnum);
156 __get_user(host_md->msg_qbytes, &target_md->msg_qbytes);
157 __get_user(host_md->msg_lspid, &target_md->msg_lspid);
158 __get_user(host_md->msg_lrpid, &target_md->msg_lrpid);
159 __get_user(host_md->msg_stime, &target_md->msg_stime);
160 __get_user(host_md->msg_rtime, &target_md->msg_rtime);
161 __get_user(host_md->msg_ctime, &target_md->msg_ctime);
162 unlock_user_struct(target_md, target_addr, 0);
163
164 return 0;
165 }
166
167 abi_long host_to_target_msqid_ds(abi_ulong target_addr,
168 struct msqid_ds *host_md)
169 {
170 struct target_msqid_ds *target_md;
171
172 if (!lock_user_struct(VERIFY_WRITE, target_md, target_addr, 0)) {
173 return -TARGET_EFAULT;
174 }
175
176 memset(target_md, 0, sizeof(struct target_msqid_ds));
177 host_to_target_ipc_perm__locked(&target_md->msg_perm,
178 &host_md->msg_perm);
179
180 /* msg_first and msg_last are not used by IPC_SET/IPC_STAT in kernel. */
181 __put_user(target_md->msg_cbytes, &host_md->msg_cbytes);
182 __put_user(target_md->msg_qnum, &host_md->msg_qnum);
183 __put_user(target_md->msg_qbytes, &host_md->msg_qbytes);
184 __put_user(target_md->msg_lspid, &host_md->msg_lspid);
185 __put_user(target_md->msg_lrpid, &host_md->msg_lrpid);
186 __put_user(target_md->msg_stime, &host_md->msg_stime);
187 __put_user(target_md->msg_rtime, &host_md->msg_rtime);
188 __put_user(target_md->msg_ctime, &host_md->msg_ctime);
189 unlock_user_struct(target_md, target_addr, 1);
190
191 return 0;
192 }