| 1 | /*	$NetBSD: netbsd32_ipc.c,v 1.18 2015/12/03 10:38:21 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.18 2015/12/03 10:38:21 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 | extern struct emul emul_netbsd32; | 
| 56 |  | 
| 57 | #define _PKG_ENTRY(name)	\ | 
| 58 | 	{ NETBSD32_SYS_ ## name, 0, (sy_call_t *)name } | 
| 59 |  | 
| 60 | #define _PKG_ENTRY2(code, name)	\ | 
| 61 | 	{ NETBSD32_SYS_ ## code, 0, (sy_call_t *)name } | 
| 62 |  | 
| 63 | static const struct syscall_package compat_sysvipc_syscalls[] = { | 
| 64 | #if defined(SYSVSEM) | 
| 65 | 	_PKG_ENTRY(netbsd32_____semctl50), | 
| 66 | 	_PKG_ENTRY(netbsd32_semget), | 
| 67 | 	_PKG_ENTRY(netbsd32_semop), | 
| 68 | 	_PKG_ENTRY(netbsd32_semconfig), | 
| 69 | #if defined(COMPAT_10) | 
| 70 | 	_PKG_ENTRY2(compat_10_osemsys, compat_10_netbsd32_semsys), | 
| 71 | #endif | 
| 72 | #if defined(COMPAT_14) | 
| 73 | 	_PKG_ENTRY(compat_14_netbsd32___semctl), | 
| 74 | #endif | 
| 75 | #if defined(COMPAT_50) | 
| 76 | 	_PKG_ENTRY(compat_50_netbsd32___semctl14), | 
| 77 | #endif | 
| 78 | #endif /* SYSVSEM */ | 
| 79 |  | 
| 80 | #if defined(SYSVSHM) | 
| 81 | 	_PKG_ENTRY(netbsd32_shmat), | 
| 82 | 	_PKG_ENTRY(netbsd32___shmctl50), | 
| 83 | 	_PKG_ENTRY(netbsd32_shmdt), | 
| 84 | 	_PKG_ENTRY(netbsd32_shmget), | 
| 85 | #if defined(COMPAT_10) | 
| 86 | 	_PKG_ENTRY2(compat_10_oshmsys, compat_10_netbsd32_shmsys), | 
| 87 | #endif | 
| 88 | #if defined(COMPAT_14) | 
| 89 | 	_PKG_ENTRY(compat_14_netbsd32_shmctl), | 
| 90 | #endif | 
| 91 | #if defined(COMPAT_50) | 
| 92 | 	_PKG_ENTRY(compat_50_netbsd32___shmctl13), | 
| 93 | #endif | 
| 94 | #endif /* SYSVSHM */ | 
| 95 |  | 
| 96 | #if defined(SYSVMSG) | 
| 97 | 	_PKG_ENTRY(netbsd32___msgctl50), | 
| 98 | 	_PKG_ENTRY(netbsd32_msgget), | 
| 99 | 	_PKG_ENTRY(netbsd32_msgsnd), | 
| 100 | 	_PKG_ENTRY(netbsd32_msgrcv), | 
| 101 | #if defined(COMPAT_10) | 
| 102 | 	_PKG_ENTRY2(compat_10_omsgsys, compat_10_netbsd32_msgsys), | 
| 103 | #endif | 
| 104 | #if defined(COMPAT_14) | 
| 105 | 	_PKG_ENTRY(compat_14_netbsd32_msgctl), | 
| 106 | #endif | 
| 107 | #if defined(COMPAT_50) | 
| 108 | 	_PKG_ENTRY(compat_50_netbsd32___msgctl13), | 
| 109 | #endif | 
| 110 | #endif /* SYSVMSG */ | 
| 111 | 	{ 0, 0, NULL } | 
| 112 | }; | 
| 113 |  | 
| 114 | MODULE(MODULE_CLASS_EXEC, compat_netbsd32_sysvipc, "sysv_ipc,compat_netbsd32" ); | 
| 115 |  | 
| 116 | static int | 
| 117 | compat_netbsd32_sysvipc_modcmd(modcmd_t cmd, void *arg) | 
| 118 | { | 
| 119 | 	int error; | 
| 120 |  | 
| 121 | 	switch (cmd) { | 
| 122 | 	case MODULE_CMD_INIT: | 
| 123 | 		error = syscall_establish(&emul_netbsd32, | 
| 124 | 		    compat_sysvipc_syscalls); | 
| 125 | 		break; | 
| 126 | 	case MODULE_CMD_FINI: | 
| 127 | 		error = syscall_disestablish(&emul_netbsd32, | 
| 128 | 		    compat_sysvipc_syscalls); | 
| 129 | 		break; | 
| 130 | 	default: | 
| 131 | 		error = ENOTTY; | 
| 132 | 		break; | 
| 133 | 	} | 
| 134 | 	return error; | 
| 135 | } | 
| 136 |  | 
| 137 |  | 
| 138 | #if defined(SYSVSEM) | 
| 139 |  | 
| 140 | int | 
| 141 | netbsd32_____semctl50(struct lwp *l, const struct netbsd32_____semctl50_args *uap, register_t *retval) | 
| 142 | { | 
| 143 | 	/* { | 
| 144 | 		syscallarg(int) semid; | 
| 145 | 		syscallarg(int) semnum; | 
| 146 | 		syscallarg(int) cmd; | 
| 147 | 		syscallarg(netbsd32_semunp_t) arg; | 
| 148 | 	} */ | 
| 149 | 	struct semid_ds sembuf; | 
| 150 | 	struct netbsd32_semid_ds sembuf32; | 
| 151 | 	int cmd, error; | 
| 152 | 	void *pass_arg; | 
| 153 | 	union __semun karg; | 
| 154 | 	union netbsd32_semun karg32; | 
| 155 |  | 
| 156 | 	cmd = SCARG(uap, cmd); | 
| 157 |  | 
| 158 | 	switch (cmd) { | 
| 159 | 	case IPC_SET: | 
| 160 | 	case IPC_STAT: | 
| 161 | 		pass_arg = &sembuf; | 
| 162 | 		break; | 
| 163 |  | 
| 164 | 	case GETALL: | 
| 165 | 	case SETVAL: | 
| 166 | 	case SETALL: | 
| 167 | 		pass_arg = &karg; | 
| 168 | 		break; | 
| 169 | 	default: | 
| 170 | 		pass_arg = NULL; | 
| 171 | 		break; | 
| 172 | 	} | 
| 173 |  | 
| 174 | 	if (pass_arg) { | 
| 175 | 		error = copyin(SCARG_P32(uap, arg), &karg32, sizeof(karg32)); | 
| 176 | 		if (error) | 
| 177 | 			return error; | 
| 178 | 		if (pass_arg == &karg) { | 
| 179 | 			switch (cmd) { | 
| 180 | 			case GETALL: | 
| 181 | 			case SETALL: | 
| 182 | 				karg.array = NETBSD32PTR64(karg32.array); | 
| 183 | 				break; | 
| 184 | 			case SETVAL: | 
| 185 | 				karg.val = karg32.val; | 
| 186 | 				break; | 
| 187 | 			} | 
| 188 | 		} | 
| 189 | 		if (cmd == IPC_SET) { | 
| 190 | 			error = copyin(NETBSD32PTR64(karg32.buf), &sembuf32, | 
| 191 | 			    sizeof(sembuf32)); | 
| 192 | 			if (error) | 
| 193 | 				return (error); | 
| 194 | 			netbsd32_to_semid_ds(&sembuf32, &sembuf); | 
| 195 | 		} | 
| 196 | 	} | 
| 197 |  | 
| 198 | 	error = semctl1(l, SCARG(uap, semid), SCARG(uap, semnum), cmd, | 
| 199 | 	    pass_arg, retval); | 
| 200 |  | 
| 201 | 	if (error == 0 && cmd == IPC_STAT) { | 
| 202 | 		netbsd32_from_semid_ds(&sembuf, &sembuf32); | 
| 203 | 		error = copyout(&sembuf32, NETBSD32PTR64(karg32.buf), | 
| 204 | 		    sizeof(sembuf32)); | 
| 205 | 	} | 
| 206 |  | 
| 207 | 	return (error); | 
| 208 | } | 
| 209 |  | 
| 210 | int | 
| 211 | netbsd32_semget(struct lwp *l, const struct netbsd32_semget_args *uap, register_t *retval) | 
| 212 | { | 
| 213 | 	/* { | 
| 214 | 		syscallarg(netbsd32_key_t) key; | 
| 215 | 		syscallarg(int) nsems; | 
| 216 | 		syscallarg(int) semflg; | 
| 217 | 	} */ | 
| 218 | 	struct sys_semget_args ua; | 
| 219 |  | 
| 220 | 	NETBSD32TOX_UAP(key, key_t); | 
| 221 | 	NETBSD32TO64_UAP(nsems); | 
| 222 | 	NETBSD32TO64_UAP(semflg); | 
| 223 | 	return (sys_semget(l, &ua, retval)); | 
| 224 | } | 
| 225 |  | 
| 226 | int | 
| 227 | netbsd32_semop(struct lwp *l, const struct netbsd32_semop_args *uap, register_t *retval) | 
| 228 | { | 
| 229 | 	/* { | 
| 230 | 		syscallarg(int) semid; | 
| 231 | 		syscallarg(netbsd32_sembufp_t) sops; | 
| 232 | 		syscallarg(netbsd32_size_t) nsops; | 
| 233 | 	} */ | 
| 234 | 	struct sys_semop_args ua; | 
| 235 |  | 
| 236 | 	NETBSD32TO64_UAP(semid); | 
| 237 | 	NETBSD32TOP_UAP(sops, struct sembuf); | 
| 238 | 	NETBSD32TOX_UAP(nsops, size_t); | 
| 239 | 	return (sys_semop(l, &ua, retval)); | 
| 240 | } | 
| 241 |  | 
| 242 | int | 
| 243 | netbsd32_semconfig(struct lwp *l, const struct netbsd32_semconfig_args *uap, register_t *retval) | 
| 244 | { | 
| 245 | 	/* { | 
| 246 | 		syscallarg(int) flag; | 
| 247 | 	} */ | 
| 248 | 	struct sys_semconfig_args ua; | 
| 249 |  | 
| 250 | 	NETBSD32TO64_UAP(flag); | 
| 251 | 	return (sys_semconfig(l, &ua, retval)); | 
| 252 | } | 
| 253 | #endif /* SYSVSEM */ | 
| 254 |  | 
| 255 | #if defined(SYSVMSG) | 
| 256 |  | 
| 257 | int | 
| 258 | netbsd32___msgctl50(struct lwp *l, const struct netbsd32___msgctl50_args *uap, | 
| 259 |     register_t *retval) | 
| 260 | { | 
| 261 | 	/* { | 
| 262 | 		syscallarg(int) msqid; | 
| 263 | 		syscallarg(int) cmd; | 
| 264 | 		syscallarg(netbsd32_msqid_dsp_t) buf; | 
| 265 | 	} */ | 
| 266 | 	struct msqid_ds ds; | 
| 267 | 	struct netbsd32_msqid_ds ds32; | 
| 268 | 	int error, cmd; | 
| 269 |  | 
| 270 | 	cmd = SCARG(uap, cmd); | 
| 271 | 	if (cmd == IPC_SET) { | 
| 272 | 		error = copyin(SCARG_P32(uap, buf), &ds32, sizeof(ds32)); | 
| 273 | 		if (error) | 
| 274 | 			return error; | 
| 275 | 		netbsd32_to_msqid_ds(&ds32, &ds); | 
| 276 | 	} | 
| 277 |  | 
| 278 | 	error = msgctl1(l, SCARG(uap, msqid), cmd, | 
| 279 | 	    (cmd == IPC_SET || cmd == IPC_STAT) ? &ds : NULL); | 
| 280 |  | 
| 281 | 	if (error == 0 && cmd == IPC_STAT) { | 
| 282 | 		netbsd32_from_msqid_ds(&ds, &ds32); | 
| 283 | 		error = copyout(&ds32, SCARG_P32(uap, buf), sizeof(ds32)); | 
| 284 | 	} | 
| 285 |  | 
| 286 | 	return error; | 
| 287 | } | 
| 288 |  | 
| 289 | int | 
| 290 | netbsd32_msgget(struct lwp *l, const struct netbsd32_msgget_args *uap, register_t *retval) | 
| 291 | { | 
| 292 | 	/* { | 
| 293 | 		syscallarg(netbsd32_key_t) key; | 
| 294 | 		syscallarg(int) msgflg; | 
| 295 | 	} */ | 
| 296 | 	struct sys_msgget_args ua; | 
| 297 |  | 
| 298 | 	NETBSD32TOX_UAP(key, key_t); | 
| 299 | 	NETBSD32TO64_UAP(msgflg); | 
| 300 | 	return sys_msgget(l, &ua, retval); | 
| 301 | } | 
| 302 |  | 
| 303 | static int | 
| 304 | netbsd32_msgsnd_fetch_type(const void *src, void *dst, size_t size) | 
| 305 | { | 
| 306 | 	netbsd32_long l32; | 
| 307 | 	long *l = dst; | 
| 308 | 	int error; | 
| 309 |  | 
| 310 | 	KASSERT(size == sizeof(netbsd32_long)); | 
| 311 |  | 
| 312 | 	error = copyin(src, &l32, sizeof(l32)); | 
| 313 | 	if (!error) | 
| 314 | 		*l = l32; | 
| 315 | 	return error; | 
| 316 | } | 
| 317 |  | 
| 318 | int | 
| 319 | netbsd32_msgsnd(struct lwp *l, const struct netbsd32_msgsnd_args *uap, register_t *retval) | 
| 320 | { | 
| 321 | 	/* { | 
| 322 | 		syscallarg(int) msqid; | 
| 323 | 		syscallarg(const netbsd32_voidp) msgp; | 
| 324 | 		syscallarg(netbsd32_size_t) msgsz; | 
| 325 | 		syscallarg(int) msgflg; | 
| 326 | 	} */ | 
| 327 |  | 
| 328 | 	return msgsnd1(l, SCARG(uap, msqid), | 
| 329 | 	    SCARG_P32(uap, msgp), SCARG(uap, msgsz), | 
| 330 | 	    SCARG(uap, msgflg), sizeof(netbsd32_long), | 
| 331 | 	    netbsd32_msgsnd_fetch_type); | 
| 332 | } | 
| 333 |  | 
| 334 | static int | 
| 335 | netbsd32_msgrcv_put_type(const void *src, void *dst, size_t size) | 
| 336 | { | 
| 337 | 	netbsd32_long l32; | 
| 338 | 	const long *l = src; | 
| 339 |  | 
| 340 | 	KASSERT(size == sizeof(netbsd32_long)); | 
| 341 |  | 
| 342 | 	l32 = (netbsd32_long)(*l); | 
| 343 | 	return copyout(&l32, dst, sizeof(l32)); | 
| 344 | } | 
| 345 |  | 
| 346 | int | 
| 347 | netbsd32_msgrcv(struct lwp *l, const struct netbsd32_msgrcv_args *uap, register_t *retval) | 
| 348 | { | 
| 349 | 	/* { | 
| 350 | 		syscallarg(int) msqid; | 
| 351 | 		syscallarg(netbsd32_voidp) msgp; | 
| 352 | 		syscallarg(netbsd32_size_t) msgsz; | 
| 353 | 		syscallarg(netbsd32_long) msgtyp; | 
| 354 | 		syscallarg(int) msgflg; | 
| 355 | 	} */ | 
| 356 |  | 
| 357 | 	return msgrcv1(l, SCARG(uap, msqid), | 
| 358 | 	    SCARG_P32(uap, msgp), SCARG(uap, msgsz), | 
| 359 | 	    SCARG(uap, msgtyp), SCARG(uap, msgflg), sizeof(netbsd32_long), | 
| 360 | 	    netbsd32_msgrcv_put_type, retval); | 
| 361 | } | 
| 362 | #endif /* SYSVMSG */ | 
| 363 |  | 
| 364 | #if defined(SYSVSHM) | 
| 365 |  | 
| 366 | int | 
| 367 | netbsd32_shmat(struct lwp *l, const struct netbsd32_shmat_args *uap, register_t *retval) | 
| 368 | { | 
| 369 | 	/* { | 
| 370 | 		syscallarg(int) shmid; | 
| 371 | 		syscallarg(const netbsd32_voidp) shmaddr; | 
| 372 | 		syscallarg(int) shmflg; | 
| 373 | 	} */ | 
| 374 | 	struct sys_shmat_args ua; | 
| 375 |  | 
| 376 | 	NETBSD32TO64_UAP(shmid); | 
| 377 | 	NETBSD32TOP_UAP(shmaddr, void); | 
| 378 | 	NETBSD32TO64_UAP(shmflg); | 
| 379 | 	return sys_shmat(l, &ua, retval); | 
| 380 | } | 
| 381 |  | 
| 382 | int | 
| 383 | netbsd32___shmctl50(struct lwp *l, const struct netbsd32___shmctl50_args *uap, | 
| 384 |     register_t *retval) | 
| 385 | { | 
| 386 | 	/* { | 
| 387 | 		syscallarg(int) shmid; | 
| 388 | 		syscallarg(int) cmd; | 
| 389 | 		syscallarg(netbsd32_shmid_dsp_t) buf; | 
| 390 | 	} */ | 
| 391 | 	struct shmid_ds ds; | 
| 392 | 	struct netbsd32_shmid_ds ds32; | 
| 393 | 	int error, cmd; | 
| 394 |  | 
| 395 | 	cmd = SCARG(uap, cmd); | 
| 396 | 	if (cmd == IPC_SET) { | 
| 397 | 		error = copyin(SCARG_P32(uap, buf), &ds32, sizeof(ds32)); | 
| 398 | 		if (error) | 
| 399 | 			return error; | 
| 400 | 		netbsd32_to_shmid_ds(&ds32, &ds); | 
| 401 | 	} | 
| 402 |  | 
| 403 | 	error = shmctl1(l, SCARG(uap, shmid), cmd, | 
| 404 | 	    (cmd == IPC_SET || cmd == IPC_STAT) ? &ds : NULL); | 
| 405 |  | 
| 406 | 	if (error == 0 && cmd == IPC_STAT) { | 
| 407 | 		netbsd32_from_shmid_ds(&ds, &ds32); | 
| 408 | 		error = copyout(&ds32, SCARG_P32(uap, buf), sizeof(ds32)); | 
| 409 | 	} | 
| 410 |  | 
| 411 | 	return error; | 
| 412 | } | 
| 413 |  | 
| 414 | int | 
| 415 | netbsd32_shmdt(struct lwp *l, const struct netbsd32_shmdt_args *uap, register_t *retval) | 
| 416 | { | 
| 417 | 	/* { | 
| 418 | 		syscallarg(const netbsd32_voidp) shmaddr; | 
| 419 | 	} */ | 
| 420 | 	struct sys_shmdt_args ua; | 
| 421 |  | 
| 422 | 	NETBSD32TOP_UAP(shmaddr, const char); | 
| 423 | 	return (sys_shmdt(l, &ua, retval)); | 
| 424 | } | 
| 425 |  | 
| 426 | int | 
| 427 | netbsd32_shmget(struct lwp *l, const struct netbsd32_shmget_args *uap, register_t *retval) | 
| 428 | { | 
| 429 | 	/* { | 
| 430 | 		syscallarg(netbsd32_key_t) key; | 
| 431 | 		syscallarg(netbsd32_size_t) size; | 
| 432 | 		syscallarg(int) shmflg; | 
| 433 | 	} */ | 
| 434 | 	struct sys_shmget_args ua; | 
| 435 |  | 
| 436 | 	NETBSD32TOX_UAP(key, key_t); | 
| 437 | 	NETBSD32TOX_UAP(size, size_t); | 
| 438 | 	NETBSD32TO64_UAP(shmflg); | 
| 439 | 	return (sys_shmget(l, &ua, retval)); | 
| 440 | } | 
| 441 | #endif /* SYSVSHM */ | 
| 442 |  |