1 /* $NetBSD: netbsd32_ipc.c,v 1.19 2019/01/27 02:08:40 pgoyette Exp $ */ 2 3 /* 4 * Copyright (c) 1998, 2001 Matthew R. Green 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 17 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 18 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 19 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 20 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 21 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 23 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 24 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 26 * SUCH DAMAGE. 27 */ 28 29 #include <sys/cdefs.h> 30 __KERNEL_RCSID(0, "$NetBSD: netbsd32_ipc.c,v 1.19 2019/01/27 02:08:40 pgoyette Exp $"); 31 32 #if defined(_KERNEL_OPT) 33 #include "opt_sysv.h" 34 #endif 35 36 #include <sys/param.h> 37 #include <sys/systm.h> 38 #include <sys/ipc.h> 39 #include <sys/msg.h> 40 #include <sys/sem.h> 41 #include <sys/shm.h> 42 #include <sys/mount.h> 43 #include <sys/module.h> 44 #include <sys/dirent.h> 45 #include <sys/syscallvar.h> 46 47 #include <sys/syscallargs.h> 48 #include <sys/proc.h> 49 50 #include <compat/netbsd32/netbsd32.h> 51 #include <compat/netbsd32/netbsd32_syscall.h> 52 #include <compat/netbsd32/netbsd32_syscallargs.h> 53 #include <compat/netbsd32/netbsd32_conv.h> 54 55 #define _PKG_ENTRY(name) \ 56 { NETBSD32_SYS_ ## name, 0, (sy_call_t *)name } 57 58 #define _PKG_ENTRY2(code, name) \ 59 { NETBSD32_SYS_ ## code, 0, (sy_call_t *)name } 60 61 static const struct syscall_package compat_sysvipc_syscalls[] = { 62 #if defined(SYSVSEM) 63 _PKG_ENTRY(netbsd32_____semctl50), 64 _PKG_ENTRY(netbsd32_semget), 65 _PKG_ENTRY(netbsd32_semop), 66 _PKG_ENTRY(netbsd32_semconfig), 67 #endif /* SYSVSEM */ 68 69 #if defined(SYSVSHM) 70 _PKG_ENTRY(netbsd32_shmat), 71 _PKG_ENTRY(netbsd32___shmctl50), 72 _PKG_ENTRY(netbsd32_shmdt), 73 _PKG_ENTRY(netbsd32_shmget), 74 #endif /* SYSVSHM */ 75 76 #if defined(SYSVMSG) 77 _PKG_ENTRY(netbsd32___msgctl50), 78 _PKG_ENTRY(netbsd32_msgget), 79 _PKG_ENTRY(netbsd32_msgsnd), 80 _PKG_ENTRY(netbsd32_msgrcv), 81 #endif /* SYSVMSG */ 82 { 0, 0, NULL } 83 }; 84 85 MODULE(MODULE_CLASS_EXEC, compat_netbsd32_sysvipc, 86 "compat_netbsd32,sysv_ipc"); 87 88 static int 89 compat_netbsd32_sysvipc_modcmd(modcmd_t cmd, void *arg) 90 { 91 int error; 92 93 switch (cmd) { 94 case MODULE_CMD_INIT: 95 error = syscall_establish(&emul_netbsd32, 96 compat_sysvipc_syscalls); 97 break; 98 case MODULE_CMD_FINI: 99 error = syscall_disestablish(&emul_netbsd32, 100 compat_sysvipc_syscalls); 101 break; 102 default: 103 error = ENOTTY; 104 break; 105 } 106 return error; 107 } 108 109 110 #if defined(SYSVSEM) 111 112 int 113 netbsd32_____semctl50(struct lwp *l, const struct netbsd32_____semctl50_args *uap, register_t *retval) 114 { 115 /* { 116 syscallarg(int) semid; 117 syscallarg(int) semnum; 118 syscallarg(int) cmd; 119 syscallarg(netbsd32_semunp_t) arg; 120 } */ 121 struct semid_ds sembuf; 122 struct netbsd32_semid_ds sembuf32; 123 int cmd, error; 124 void *pass_arg; 125 union __semun karg; 126 union netbsd32_semun karg32; 127 128 cmd = SCARG(uap, cmd); 129 130 switch (cmd) { 131 case IPC_SET: 132 case IPC_STAT: 133 pass_arg = &sembuf; 134 break; 135 136 case GETALL: 137 case SETVAL: 138 case SETALL: 139 pass_arg = &karg; 140 break; 141 default: 142 pass_arg = NULL; 143 break; 144 } 145 146 if (pass_arg) { 147 error = copyin(SCARG_P32(uap, arg), &karg32, sizeof(karg32)); 148 if (error) 149 return error; 150 if (pass_arg == &karg) { 151 switch (cmd) { 152 case GETALL: 153 case SETALL: 154 karg.array = NETBSD32PTR64(karg32.array); 155 break; 156 case SETVAL: 157 karg.val = karg32.val; 158 break; 159 } 160 } 161 if (cmd == IPC_SET) { 162 error = copyin(NETBSD32PTR64(karg32.buf), &sembuf32, 163 sizeof(sembuf32)); 164 if (error) 165 return (error); 166 netbsd32_to_semid_ds(&sembuf32, &sembuf); 167 } 168 } 169 170 error = semctl1(l, SCARG(uap, semid), SCARG(uap, semnum), cmd, 171 pass_arg, retval); 172 173 if (error == 0 && cmd == IPC_STAT) { 174 netbsd32_from_semid_ds(&sembuf, &sembuf32); 175 error = copyout(&sembuf32, NETBSD32PTR64(karg32.buf), 176 sizeof(sembuf32)); 177 } 178 179 return (error); 180 } 181 182 int 183 netbsd32_semget(struct lwp *l, const struct netbsd32_semget_args *uap, register_t *retval) 184 { 185 /* { 186 syscallarg(netbsd32_key_t) key; 187 syscallarg(int) nsems; 188 syscallarg(int) semflg; 189 } */ 190 struct sys_semget_args ua; 191 192 NETBSD32TOX_UAP(key, key_t); 193 NETBSD32TO64_UAP(nsems); 194 NETBSD32TO64_UAP(semflg); 195 return (sys_semget(l, &ua, retval)); 196 } 197 198 int 199 netbsd32_semop(struct lwp *l, const struct netbsd32_semop_args *uap, register_t *retval) 200 { 201 /* { 202 syscallarg(int) semid; 203 syscallarg(netbsd32_sembufp_t) sops; 204 syscallarg(netbsd32_size_t) nsops; 205 } */ 206 struct sys_semop_args ua; 207 208 NETBSD32TO64_UAP(semid); 209 NETBSD32TOP_UAP(sops, struct sembuf); 210 NETBSD32TOX_UAP(nsops, size_t); 211 return (sys_semop(l, &ua, retval)); 212 } 213 214 int 215 netbsd32_semconfig(struct lwp *l, const struct netbsd32_semconfig_args *uap, register_t *retval) 216 { 217 /* { 218 syscallarg(int) flag; 219 } */ 220 struct sys_semconfig_args ua; 221 222 NETBSD32TO64_UAP(flag); 223 return (sys_semconfig(l, &ua, retval)); 224 } 225 #endif /* SYSVSEM */ 226 227 #if defined(SYSVMSG) 228 229 int 230 netbsd32___msgctl50(struct lwp *l, const struct netbsd32___msgctl50_args *uap, 231 register_t *retval) 232 { 233 /* { 234 syscallarg(int) msqid; 235 syscallarg(int) cmd; 236 syscallarg(netbsd32_msqid_dsp_t) buf; 237 } */ 238 struct msqid_ds ds; 239 struct netbsd32_msqid_ds ds32; 240 int error, cmd; 241 242 cmd = SCARG(uap, cmd); 243 if (cmd == IPC_SET) { 244 error = copyin(SCARG_P32(uap, buf), &ds32, sizeof(ds32)); 245 if (error) 246 return error; 247 netbsd32_to_msqid_ds(&ds32, &ds); 248 } 249 250 error = msgctl1(l, SCARG(uap, msqid), cmd, 251 (cmd == IPC_SET || cmd == IPC_STAT) ? &ds : NULL); 252 253 if (error == 0 && cmd == IPC_STAT) { 254 netbsd32_from_msqid_ds(&ds, &ds32); 255 error = copyout(&ds32, SCARG_P32(uap, buf), sizeof(ds32)); 256 } 257 258 return error; 259 } 260 261 int 262 netbsd32_msgget(struct lwp *l, const struct netbsd32_msgget_args *uap, register_t *retval) 263 { 264 /* { 265 syscallarg(netbsd32_key_t) key; 266 syscallarg(int) msgflg; 267 } */ 268 struct sys_msgget_args ua; 269 270 NETBSD32TOX_UAP(key, key_t); 271 NETBSD32TO64_UAP(msgflg); 272 return sys_msgget(l, &ua, retval); 273 } 274 275 static int 276 netbsd32_msgsnd_fetch_type(const void *src, void *dst, size_t size) 277 { 278 netbsd32_long l32; 279 long *l = dst; 280 int error; 281 282 KASSERT(size == sizeof(netbsd32_long)); 283 284 error = copyin(src, &l32, sizeof(l32)); 285 if (!error) 286 *l = l32; 287 return error; 288 } 289 290 int 291 netbsd32_msgsnd(struct lwp *l, const struct netbsd32_msgsnd_args *uap, register_t *retval) 292 { 293 /* { 294 syscallarg(int) msqid; 295 syscallarg(const netbsd32_voidp) msgp; 296 syscallarg(netbsd32_size_t) msgsz; 297 syscallarg(int) msgflg; 298 } */ 299 300 return msgsnd1(l, SCARG(uap, msqid), 301 SCARG_P32(uap, msgp), SCARG(uap, msgsz), 302 SCARG(uap, msgflg), sizeof(netbsd32_long), 303 netbsd32_msgsnd_fetch_type); 304 } 305 306 static int 307 netbsd32_msgrcv_put_type(const void *src, void *dst, size_t size) 308 { 309 netbsd32_long l32; 310 const long *l = src; 311 312 KASSERT(size == sizeof(netbsd32_long)); 313 314 l32 = (netbsd32_long)(*l); 315 return copyout(&l32, dst, sizeof(l32)); 316 } 317 318 int 319 netbsd32_msgrcv(struct lwp *l, const struct netbsd32_msgrcv_args *uap, register_t *retval) 320 { 321 /* { 322 syscallarg(int) msqid; 323 syscallarg(netbsd32_voidp) msgp; 324 syscallarg(netbsd32_size_t) msgsz; 325 syscallarg(netbsd32_long) msgtyp; 326 syscallarg(int) msgflg; 327 } */ 328 329 return msgrcv1(l, SCARG(uap, msqid), 330 SCARG_P32(uap, msgp), SCARG(uap, msgsz), 331 SCARG(uap, msgtyp), SCARG(uap, msgflg), sizeof(netbsd32_long), 332 netbsd32_msgrcv_put_type, retval); 333 } 334 #endif /* SYSVMSG */ 335 336 #if defined(SYSVSHM) 337 338 int 339 netbsd32_shmat(struct lwp *l, const struct netbsd32_shmat_args *uap, register_t *retval) 340 { 341 /* { 342 syscallarg(int) shmid; 343 syscallarg(const netbsd32_voidp) shmaddr; 344 syscallarg(int) shmflg; 345 } */ 346 struct sys_shmat_args ua; 347 348 NETBSD32TO64_UAP(shmid); 349 NETBSD32TOP_UAP(shmaddr, void); 350 NETBSD32TO64_UAP(shmflg); 351 return sys_shmat(l, &ua, retval); 352 } 353 354 int 355 netbsd32___shmctl50(struct lwp *l, const struct netbsd32___shmctl50_args *uap, 356 register_t *retval) 357 { 358 /* { 359 syscallarg(int) shmid; 360 syscallarg(int) cmd; 361 syscallarg(netbsd32_shmid_dsp_t) buf; 362 } */ 363 struct shmid_ds ds; 364 struct netbsd32_shmid_ds ds32; 365 int error, cmd; 366 367 cmd = SCARG(uap, cmd); 368 if (cmd == IPC_SET) { 369 error = copyin(SCARG_P32(uap, buf), &ds32, sizeof(ds32)); 370 if (error) 371 return error; 372 netbsd32_to_shmid_ds(&ds32, &ds); 373 } 374 375 error = shmctl1(l, SCARG(uap, shmid), cmd, 376 (cmd == IPC_SET || cmd == IPC_STAT) ? &ds : NULL); 377 378 if (error == 0 && cmd == IPC_STAT) { 379 netbsd32_from_shmid_ds(&ds, &ds32); 380 error = copyout(&ds32, SCARG_P32(uap, buf), sizeof(ds32)); 381 } 382 383 return error; 384 } 385 386 int 387 netbsd32_shmdt(struct lwp *l, const struct netbsd32_shmdt_args *uap, register_t *retval) 388 { 389 /* { 390 syscallarg(const netbsd32_voidp) shmaddr; 391 } */ 392 struct sys_shmdt_args ua; 393 394 NETBSD32TOP_UAP(shmaddr, const char); 395 return (sys_shmdt(l, &ua, retval)); 396 } 397 398 int 399 netbsd32_shmget(struct lwp *l, const struct netbsd32_shmget_args *uap, register_t *retval) 400 { 401 /* { 402 syscallarg(netbsd32_key_t) key; 403 syscallarg(netbsd32_size_t) size; 404 syscallarg(int) shmflg; 405 } */ 406 struct sys_shmget_args ua; 407 408 NETBSD32TOX_UAP(key, key_t); 409 NETBSD32TOX_UAP(size, size_t); 410 NETBSD32TO64_UAP(shmflg); 411 return (sys_shmget(l, &ua, retval)); 412 } 413 #endif /* SYSVSHM */ 414