Home | History | Annotate | Line # | Download | only in common
      1 /*	$NetBSD: linux_ipccall.c,v 1.34 2021/09/23 06:56:27 ryo Exp $	*/
      2 
      3 /*-
      4  * Copyright (c) 1998 The NetBSD Foundation, Inc.
      5  * All rights reserved.
      6  *
      7  * This code is derived from software contributed to The NetBSD Foundation
      8  * by Frank van der Linden and Eric Haszlakiewicz.
      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 
     32 #include <sys/cdefs.h>
     33 __KERNEL_RCSID(0, "$NetBSD: linux_ipccall.c,v 1.34 2021/09/23 06:56:27 ryo Exp $");
     34 
     35 #if defined(_KERNEL_OPT)
     36 #include "opt_sysv.h"
     37 #endif
     38 
     39 #include <sys/param.h>
     40 #include <sys/shm.h>
     41 #include <sys/sem.h>
     42 #include <sys/msg.h>
     43 #include <sys/proc.h>
     44 #include <sys/systm.h>
     45 
     46 /* real syscalls */
     47 #include <sys/mount.h>
     48 #include <sys/syscallargs.h>
     49 
     50 /* sys_ipc + args prototype */
     51 #include <compat/linux/common/linux_types.h>
     52 #include <compat/linux/common/linux_signal.h>
     53 
     54 #include <compat/linux/linux_syscallargs.h>
     55 #include <compat/linux/linux_syscall.h>
     56 
     57 /* general ipc defines */
     58 #include <compat/linux/common/linux_ipc.h>
     59 
     60 /* prototypes for real/normal linux-emul syscalls */
     61 #include <compat/linux/common/linux_msg.h>
     62 #include <compat/linux/common/linux_shm.h>
     63 #include <compat/linux/common/linux_sem.h>
     64 
     65 /* prototypes for sys_ipc stuff */
     66 #include <compat/linux/common/linux_ipccall.h>
     67 
     68 /* Used on: arm, i386, m68k, mips, ppc, sparc, sparc64 */
     69 /* Not used on: aarch64, alpha */
     70 
     71 /*
     72  * Stuff to deal with the SysV ipc/shm/semaphore interface in Linux.
     73  * The main difference is, that Linux handles it all via one
     74  * system call, which has the usual maximum amount of 5 arguments.
     75  * This results in a kludge for calls that take 6 of them.
     76  *
     77  * The SYSV??? options have to be enabled to get the appropriate
     78  * functions to work.
     79  */
     80 
     81 int
     82 linux_sys_ipc(struct lwp *l, const struct linux_sys_ipc_args *uap, register_t *retval)
     83 {
     84 	/* {
     85 		syscallarg(int) what;
     86 		syscallarg(int) a1;
     87 		syscallarg(int) a2;
     88 		syscallarg(int) a3;
     89 		syscallarg(void *) ptr;
     90 	} */
     91 
     92 	switch (SCARG(uap, what)) {
     93 #ifdef SYSVSEM
     94 	case LINUX_SYS_SEMOP:
     95 		return linux_semop(l, uap, retval);
     96 	case LINUX_SYS_SEMGET:
     97 		return linux_semget(l, uap, retval);
     98 	case LINUX_SYS_SEMCTL: {
     99 		struct linux_sys_semctl_args bsa;
    100 		union linux_semun arg;
    101 		int error;
    102 
    103 		SCARG(&bsa, semid) = SCARG(uap, a1);
    104 		SCARG(&bsa, semnum) = SCARG(uap, a2);
    105 		SCARG(&bsa, cmd) = SCARG(uap, a3);
    106 		/* Convert from (union linux_semun *) to (union linux_semun) */
    107 		if ((error = copyin(SCARG(uap, ptr), &arg, sizeof arg)))
    108 			return error;
    109 		SCARG(&bsa, arg) = arg;
    110 
    111 		return linux_sys_semctl(l, &bsa, retval);
    112 	    }
    113 #endif
    114 #ifdef SYSVMSG
    115 	case LINUX_SYS_MSGSND:
    116 		return linux_msgsnd(l, uap, retval);
    117 	case LINUX_SYS_MSGRCV:
    118 		return linux_msgrcv(l, uap, retval);
    119 	case LINUX_SYS_MSGGET:
    120 		return linux_msgget(l, uap, retval);
    121 	case LINUX_SYS_MSGCTL: {
    122 		struct linux_sys_msgctl_args bsa;
    123 
    124 		SCARG(&bsa, msqid) = SCARG(uap, a1);
    125 		SCARG(&bsa, cmd) = SCARG(uap, a2);
    126 		SCARG(&bsa, buf) = (struct linux_msqid_ds *)SCARG(uap, ptr);
    127 
    128 		return linux_sys_msgctl(l, &bsa, retval);
    129 	    }
    130 #endif
    131 #ifdef SYSVSHM
    132 	case LINUX_SYS_SHMAT: {
    133 		struct linux_sys_shmat_args bsa;
    134 
    135 		SCARG(&bsa, shmid) = SCARG(uap, a1);
    136 		SCARG(&bsa, shmaddr) = (void *)SCARG(uap, ptr);
    137 		SCARG(&bsa, shmflg) = SCARG(uap, a2);
    138 		/* XXX passing pointer inside int here */
    139 		SCARG(&bsa, raddr) = (u_long *)SCARG(uap, a3);
    140 
    141 		return linux_sys_shmat(l, &bsa, retval);
    142 	    }
    143 	case LINUX_SYS_SHMDT:
    144 		return linux_shmdt(l, uap, retval);
    145 	case LINUX_SYS_SHMGET:
    146 		return linux_shmget(l, uap, retval);
    147 	case LINUX_SYS_SHMCTL: {
    148 		struct linux_sys_shmctl_args bsa;
    149 
    150 		SCARG(&bsa, shmid) = SCARG(uap, a1);
    151 		SCARG(&bsa, cmd) = SCARG(uap, a2);
    152 		SCARG(&bsa, buf) = (struct linux_shmid_ds *)SCARG(uap, ptr);
    153 
    154 		return linux_sys_shmctl(l, &bsa, retval);
    155 	    }
    156 #endif
    157 	default:
    158 		return ENOSYS;
    159 	}
    160 }
    161 
    162 #ifdef SYSVSEM
    163 int
    164 linux_semop(struct lwp *l, const struct linux_sys_ipc_args *uap, register_t *retval)
    165 {
    166 	/* {
    167 		syscallarg(int) what;
    168 		syscallarg(int) a1;
    169 		syscallarg(int) a2;
    170 		syscallarg(int) a3;
    171 		syscallarg(void *) ptr;
    172 	} */
    173 	struct sys_semop_args bsa;
    174 
    175 	SCARG(&bsa, semid) = SCARG(uap, a1);
    176 	SCARG(&bsa, sops) = (struct sembuf *)SCARG(uap, ptr);
    177 	SCARG(&bsa, nsops) = SCARG(uap, a2);
    178 
    179 	return sys_semop(l, &bsa, retval);
    180 }
    181 
    182 int
    183 linux_semget(struct lwp *l, const struct linux_sys_ipc_args *uap, register_t *retval)
    184 {
    185 	/* {
    186 		syscallarg(int) what;
    187 		syscallarg(int) a1;
    188 		syscallarg(int) a2;
    189 		syscallarg(int) a3;
    190 		syscallarg(void *) ptr;
    191 	} */
    192 	struct sys_semget_args bsa;
    193 
    194 	SCARG(&bsa, key) = (key_t)SCARG(uap, a1);
    195 	SCARG(&bsa, nsems) = SCARG(uap, a2);
    196 	SCARG(&bsa, semflg) = SCARG(uap, a3);
    197 
    198 	return sys_semget(l, &bsa, retval);
    199 }
    200 
    201 #endif /* SYSVSEM */
    202 
    203 #ifdef SYSVMSG
    204 
    205 int
    206 linux_msgsnd(struct lwp *l, const struct linux_sys_ipc_args *uap, register_t *retval)
    207 {
    208 	struct sys_msgsnd_args bma;
    209 
    210 	SCARG(&bma, msqid) = SCARG(uap, a1);
    211 	SCARG(&bma, msgp) = SCARG(uap, ptr);
    212 	SCARG(&bma, msgsz) = SCARG(uap, a2);
    213 	SCARG(&bma, msgflg) = SCARG(uap, a3);
    214 
    215 	return sys_msgsnd(l, &bma, retval);
    216 }
    217 
    218 int
    219 linux_msgrcv(struct lwp *l, const struct linux_sys_ipc_args *uap, register_t *retval)
    220 {
    221 	struct sys_msgrcv_args bma;
    222 	struct linux_msgrcv_msgarg kluge;
    223 	int error;
    224 
    225 	if ((error = copyin(SCARG(uap, ptr), &kluge, sizeof kluge)))
    226 		return error;
    227 
    228 	SCARG(&bma, msqid) = SCARG(uap, a1);
    229 	SCARG(&bma, msgp) = kluge.msg;
    230 	SCARG(&bma, msgsz) = SCARG(uap, a2);
    231 	SCARG(&bma, msgtyp) = kluge.type;
    232 	SCARG(&bma, msgflg) = SCARG(uap, a3);
    233 
    234 	return sys_msgrcv(l, &bma, retval);
    235 }
    236 
    237 int
    238 linux_msgget(struct lwp *l, const struct linux_sys_ipc_args *uap, register_t *retval)
    239 {
    240 	struct sys_msgget_args bma;
    241 
    242 	SCARG(&bma, key) = (key_t)SCARG(uap, a1);
    243 	SCARG(&bma, msgflg) = SCARG(uap, a2);
    244 
    245 	return sys_msgget(l, &bma, retval);
    246 }
    247 
    248 #endif /* SYSVMSG */
    249 
    250 #ifdef SYSVSHM
    251 /*
    252  * shmdt(): this could have been mapped directly, if it wasn't for
    253  * the extra indirection by the linux_ipc system call.
    254  */
    255 int
    256 linux_shmdt(struct lwp *l, const struct linux_sys_ipc_args *uap, register_t *retval)
    257 {
    258 	struct sys_shmdt_args bsa;
    259 
    260 	SCARG(&bsa, shmaddr) = SCARG(uap, ptr);
    261 
    262 	return sys_shmdt(l, &bsa, retval);
    263 }
    264 
    265 /*
    266  * Same story as shmdt.
    267  */
    268 int
    269 linux_shmget(struct lwp *l, const struct linux_sys_ipc_args *uap, register_t *retval)
    270 {
    271 	struct linux_sys_shmget_args bsa;
    272 
    273 	SCARG(&bsa, key) = SCARG(uap, a1);
    274 	SCARG(&bsa, size) = SCARG(uap, a2);
    275 	SCARG(&bsa, shmflg) = SCARG(uap, a3);
    276 
    277 	return linux_sys_shmget(l, &bsa, retval);
    278 }
    279 
    280 #endif /* SYSVSHM */
    281