1/* $NetBSD: netbsd32_compat_50_sysv.c,v 1.4 2021/01/19 03:20:13 simonb Exp $ */ 2 3/*- 4 * Copyright (c) 2008 The NetBSD Foundation, Inc. 5 * All rights reserved. 6 * 7 * This code is derived from software contributed to The NetBSD Foundation 8 * by Christos Zoulas. 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted provided that the following conditions 12 * are met: 13 * 1. Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in the 17 * documentation and/or other materials provided with the distribution. 18 * 19 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29 * POSSIBILITY OF SUCH DAMAGE. 30 */ 31#include <sys/cdefs.h> 32__KERNEL_RCSID(0, "$NetBSD: netbsd32_compat_50_sysv.c,v 1.4 2021/01/19 03:20:13 simonb Exp $"); 33 34#if defined(_KERNEL_OPT) 35#include "opt_sysv.h" 36#include "opt_compat_netbsd.h" 37#endif 38 39#include <sys/param.h> 40#include <sys/systm.h> 41#include <sys/module.h> 42#include <sys/msg.h> 43#include <sys/sem.h> 44#include <sys/shm.h> 45 46#include <sys/syscallvar.h> 47 48#include <compat/netbsd32/netbsd32.h> 49#include <compat/netbsd32/netbsd32_syscall.h> 50#include <compat/netbsd32/netbsd32_syscallargs.h> 51#include <compat/netbsd32/netbsd32_conv.h> 52 53#if defined(COMPAT_50) 54 55#if defined(SYSVSEM) 56 57int 58compat_50_netbsd32___semctl14(struct lwp *l, const struct compat_50_netbsd32___semctl14_args *uap, register_t *retval) 59{ 60 return do_netbsd32___semctl14(l, uap, retval, NULL); 61} 62 63int 64do_netbsd32___semctl14(struct lwp *l, const struct compat_50_netbsd32___semctl14_args *uap, register_t *retval, void *vkarg) 65{ 66 /* { 67 syscallarg(int) semid; 68 syscallarg(int) semnum; 69 syscallarg(int) cmd; 70 syscallarg(netbsd32_semun50p_t) arg; 71 } */ 72 struct semid_ds sembuf; 73 struct netbsd32_semid_ds50 sembuf32; 74 int cmd, error; 75 void *pass_arg; 76 union __semun karg; 77 union netbsd32_semun50 karg32; 78 79 cmd = SCARG(uap, cmd); 80 81 switch (cmd) { 82 case IPC_SET: 83 case IPC_STAT: 84 pass_arg = &sembuf; 85 break; 86 87 case GETALL: 88 case SETVAL: 89 case SETALL: 90 pass_arg = &karg; 91 break; 92 default: 93 pass_arg = NULL; 94 break; 95 } 96 97 if (pass_arg) { 98 if (vkarg != NULL) 99 karg32 = *(union netbsd32_semun50 *)vkarg; 100 else { 101 error = copyin(SCARG_P32(uap, arg), &karg32, 102 sizeof(karg32)); 103 if (error) 104 return error; 105 } 106 if (pass_arg == &karg) { 107 switch (cmd) { 108 case GETALL: 109 case SETALL: 110 karg.array = NETBSD32PTR64(karg32.array); 111 break; 112 case SETVAL: 113 karg.val = karg32.val; 114 break; 115 } 116 } 117 if (cmd == IPC_SET) { 118 error = copyin(NETBSD32PTR64(karg32.buf), &sembuf32, 119 sizeof(sembuf32)); 120 if (error) 121 return error; 122 netbsd32_to_semid_ds50(&sembuf32, &sembuf); 123 } 124 } 125 126 error = semctl1(l, SCARG(uap, semid), SCARG(uap, semnum), cmd, 127 pass_arg, retval); 128 129 if (error == 0 && cmd == IPC_STAT) { 130 netbsd32_from_semid_ds50(&sembuf, &sembuf32); 131 error = copyout(&sembuf32, NETBSD32PTR64(karg32.buf), 132 sizeof(sembuf32)); 133 } 134 135 return error; 136} 137#endif 138 139#if defined(SYSVMSG) 140 141int 142compat_50_netbsd32___msgctl13(struct lwp *l, const struct compat_50_netbsd32___msgctl13_args *uap, register_t *retval) 143{ 144 /* { 145 syscallarg(int) msqid; 146 syscallarg(int) cmd; 147 syscallarg(netbsd32_msqid_ds50p_t) buf; 148 } */ 149 struct msqid_ds ds; 150 struct netbsd32_msqid_ds50 ds32; 151 int error, cmd; 152 153 cmd = SCARG(uap, cmd); 154 if (cmd == IPC_SET) { 155 error = copyin(SCARG_P32(uap, buf), &ds32, sizeof(ds32)); 156 if (error) 157 return error; 158 netbsd32_to_msqid_ds50(&ds32, &ds); 159 } 160 161 error = msgctl1(l, SCARG(uap, msqid), cmd, 162 (cmd == IPC_SET || cmd == IPC_STAT) ? &ds : NULL); 163 164 if (error == 0 && cmd == IPC_STAT) { 165 netbsd32_from_msqid_ds50(&ds, &ds32); 166 error = copyout(&ds32, SCARG_P32(uap, buf), sizeof(ds32)); 167 } 168 169 return error; 170} 171#endif 172 173#if defined(SYSVSHM) 174 175int 176compat_50_netbsd32___shmctl13(struct lwp *l, const struct compat_50_netbsd32___shmctl13_args *uap, register_t *retval) 177{ 178 /* { 179 syscallarg(int) shmid; 180 syscallarg(int) cmd; 181 syscallarg(netbsd32_shmid_ds50p_t) buf; 182 } */ 183 struct shmid_ds ds; 184 struct netbsd32_shmid_ds50 ds32; 185 int error, cmd; 186 187 cmd = SCARG(uap, cmd); 188 if (cmd == IPC_SET) { 189 error = copyin(SCARG_P32(uap, buf), &ds32, sizeof(ds32)); 190 if (error) 191 return error; 192 netbsd32_to_shmid_ds50(&ds32, &ds); 193 } 194 195 error = shmctl1(l, SCARG(uap, shmid), cmd, 196 (cmd == IPC_SET || cmd == IPC_STAT) ? &ds : NULL); 197 198 if (error == 0 && cmd == IPC_STAT) { 199 netbsd32_from_shmid_ds50(&ds, &ds32); 200 error = copyout(&ds32, SCARG_P32(uap, buf), sizeof(ds32)); 201 } 202 203 return error; 204} 205#endif 206 207#define _PKG_ENTRY(name) \ 208 { NETBSD32_SYS_ ## name, 0, (sy_call_t *)name } 209 210static const struct syscall_package compat_sysvipc_50_syscalls[] = { 211#if defined(SYSVSEM) 212 _PKG_ENTRY(compat_50_netbsd32___semctl14), 213#endif 214#if defined(SYSVSHM) 215 _PKG_ENTRY(compat_50_netbsd32___shmctl13), 216#endif 217#if defined(SYSVMSG) 218 _PKG_ENTRY(compat_50_netbsd32___msgctl13), 219#endif 220 { 0, 0, NULL } 221}; 222 223#define REQ1 "sysv_ipc,compat_sysv_50," 224#define REQ2 "compat_netbsd32,compat_netbsd32_sysvipc," 225 226MODULE(MODULE_CLASS_EXEC, compat_netbsd32_sysvipc_50, REQ1 REQ2); 227 228static int 229compat_netbsd32_sysvipc_50_modcmd(modcmd_t cmd, void *arg) 230{ 231 232 switch (cmd) { 233 case MODULE_CMD_INIT: 234 return syscall_establish(&emul_netbsd32, 235 compat_sysvipc_50_syscalls); 236 237 case MODULE_CMD_FINI: 238 return syscall_disestablish(&emul_netbsd32, 239 compat_sysvipc_50_syscalls); 240 241 default: 242 return ENOTTY; 243 } 244} 245 246#endif /* COMPAT_50 */ 247