xref: /openbmc/linux/ipc/syscall.c (revision 20bc2a3aff5a88a666e81182fd277ea2a521fd3d)
1baed7fc9SChristoph Hellwig /*
2baed7fc9SChristoph Hellwig  * sys_ipc() is the old de-multiplexer for the SysV IPC calls.
3baed7fc9SChristoph Hellwig  *
4baed7fc9SChristoph Hellwig  * This is really horribly ugly, and new architectures should just wire up
5baed7fc9SChristoph Hellwig  * the individual syscalls instead.
6baed7fc9SChristoph Hellwig  */
7baed7fc9SChristoph Hellwig #include <linux/unistd.h>
8*20bc2a3aSAl Viro #include <linux/syscalls.h>
9baed7fc9SChristoph Hellwig 
10baed7fc9SChristoph Hellwig #ifdef __ARCH_WANT_SYS_IPC
11baed7fc9SChristoph Hellwig #include <linux/errno.h>
12baed7fc9SChristoph Hellwig #include <linux/ipc.h>
13baed7fc9SChristoph Hellwig #include <linux/shm.h>
14baed7fc9SChristoph Hellwig #include <linux/uaccess.h>
15baed7fc9SChristoph Hellwig 
1645575f5aSAnton Blanchard SYSCALL_DEFINE6(ipc, unsigned int, call, int, first, unsigned long, second,
17baed7fc9SChristoph Hellwig 		unsigned long, third, void __user *, ptr, long, fifth)
18baed7fc9SChristoph Hellwig {
19baed7fc9SChristoph Hellwig 	int version, ret;
20baed7fc9SChristoph Hellwig 
21baed7fc9SChristoph Hellwig 	version = call >> 16; /* hack for backward compatibility */
22baed7fc9SChristoph Hellwig 	call &= 0xffff;
23baed7fc9SChristoph Hellwig 
24baed7fc9SChristoph Hellwig 	switch (call) {
25baed7fc9SChristoph Hellwig 	case SEMOP:
26baed7fc9SChristoph Hellwig 		return sys_semtimedop(first, (struct sembuf __user *)ptr,
27baed7fc9SChristoph Hellwig 				      second, NULL);
28baed7fc9SChristoph Hellwig 	case SEMTIMEDOP:
29baed7fc9SChristoph Hellwig 		return sys_semtimedop(first, (struct sembuf __user *)ptr,
30baed7fc9SChristoph Hellwig 				      second,
31baed7fc9SChristoph Hellwig 				      (const struct timespec __user *)fifth);
32baed7fc9SChristoph Hellwig 
33baed7fc9SChristoph Hellwig 	case SEMGET:
34baed7fc9SChristoph Hellwig 		return sys_semget(first, second, third);
35baed7fc9SChristoph Hellwig 	case SEMCTL: {
36e1fd1f49SAl Viro 		unsigned long arg;
37baed7fc9SChristoph Hellwig 		if (!ptr)
38baed7fc9SChristoph Hellwig 			return -EINVAL;
39e1fd1f49SAl Viro 		if (get_user(arg, (unsigned long __user *) ptr))
40baed7fc9SChristoph Hellwig 			return -EFAULT;
41e1fd1f49SAl Viro 		return sys_semctl(first, second, third, arg);
42baed7fc9SChristoph Hellwig 	}
43baed7fc9SChristoph Hellwig 
44baed7fc9SChristoph Hellwig 	case MSGSND:
45baed7fc9SChristoph Hellwig 		return sys_msgsnd(first, (struct msgbuf __user *) ptr,
46baed7fc9SChristoph Hellwig 				  second, third);
47baed7fc9SChristoph Hellwig 	case MSGRCV:
48baed7fc9SChristoph Hellwig 		switch (version) {
49baed7fc9SChristoph Hellwig 		case 0: {
50baed7fc9SChristoph Hellwig 			struct ipc_kludge tmp;
51baed7fc9SChristoph Hellwig 			if (!ptr)
52baed7fc9SChristoph Hellwig 				return -EINVAL;
53baed7fc9SChristoph Hellwig 
54baed7fc9SChristoph Hellwig 			if (copy_from_user(&tmp,
55baed7fc9SChristoph Hellwig 					   (struct ipc_kludge __user *) ptr,
56baed7fc9SChristoph Hellwig 					   sizeof(tmp)))
57baed7fc9SChristoph Hellwig 				return -EFAULT;
58baed7fc9SChristoph Hellwig 			return sys_msgrcv(first, tmp.msgp, second,
59baed7fc9SChristoph Hellwig 					   tmp.msgtyp, third);
60baed7fc9SChristoph Hellwig 		}
61baed7fc9SChristoph Hellwig 		default:
62baed7fc9SChristoph Hellwig 			return sys_msgrcv(first,
63baed7fc9SChristoph Hellwig 					   (struct msgbuf __user *) ptr,
64baed7fc9SChristoph Hellwig 					   second, fifth, third);
65baed7fc9SChristoph Hellwig 		}
66baed7fc9SChristoph Hellwig 	case MSGGET:
67baed7fc9SChristoph Hellwig 		return sys_msgget((key_t) first, second);
68baed7fc9SChristoph Hellwig 	case MSGCTL:
69baed7fc9SChristoph Hellwig 		return sys_msgctl(first, second, (struct msqid_ds __user *)ptr);
70baed7fc9SChristoph Hellwig 
71baed7fc9SChristoph Hellwig 	case SHMAT:
72baed7fc9SChristoph Hellwig 		switch (version) {
73baed7fc9SChristoph Hellwig 		default: {
74baed7fc9SChristoph Hellwig 			unsigned long raddr;
75baed7fc9SChristoph Hellwig 			ret = do_shmat(first, (char __user *)ptr,
76079a96aeSWill Deacon 				       second, &raddr, SHMLBA);
77baed7fc9SChristoph Hellwig 			if (ret)
78baed7fc9SChristoph Hellwig 				return ret;
79baed7fc9SChristoph Hellwig 			return put_user(raddr, (unsigned long __user *) third);
80baed7fc9SChristoph Hellwig 		}
81baed7fc9SChristoph Hellwig 		case 1:
82baed7fc9SChristoph Hellwig 			/*
83baed7fc9SChristoph Hellwig 			 * This was the entry point for kernel-originating calls
84baed7fc9SChristoph Hellwig 			 * from iBCS2 in 2.2 days.
85baed7fc9SChristoph Hellwig 			 */
86baed7fc9SChristoph Hellwig 			return -EINVAL;
87baed7fc9SChristoph Hellwig 		}
88baed7fc9SChristoph Hellwig 	case SHMDT:
89baed7fc9SChristoph Hellwig 		return sys_shmdt((char __user *)ptr);
90baed7fc9SChristoph Hellwig 	case SHMGET:
91baed7fc9SChristoph Hellwig 		return sys_shmget(first, second, third);
92baed7fc9SChristoph Hellwig 	case SHMCTL:
93baed7fc9SChristoph Hellwig 		return sys_shmctl(first, second,
94baed7fc9SChristoph Hellwig 				   (struct shmid_ds __user *) ptr);
95baed7fc9SChristoph Hellwig 	default:
96baed7fc9SChristoph Hellwig 		return -ENOSYS;
97baed7fc9SChristoph Hellwig 	}
98baed7fc9SChristoph Hellwig }
99baed7fc9SChristoph Hellwig #endif
100*20bc2a3aSAl Viro 
101*20bc2a3aSAl Viro #ifdef CONFIG_COMPAT
102*20bc2a3aSAl Viro #include <linux/compat.h>
103*20bc2a3aSAl Viro 
104*20bc2a3aSAl Viro #ifndef COMPAT_SHMLBA
105*20bc2a3aSAl Viro #define COMPAT_SHMLBA	SHMLBA
106*20bc2a3aSAl Viro #endif
107*20bc2a3aSAl Viro 
108*20bc2a3aSAl Viro struct compat_ipc_kludge {
109*20bc2a3aSAl Viro 	compat_uptr_t msgp;
110*20bc2a3aSAl Viro 	compat_long_t msgtyp;
111*20bc2a3aSAl Viro };
112*20bc2a3aSAl Viro 
113*20bc2a3aSAl Viro #ifdef CONFIG_ARCH_WANT_OLD_COMPAT_IPC
114*20bc2a3aSAl Viro COMPAT_SYSCALL_DEFINE6(ipc, u32, call, int, first, int, second,
115*20bc2a3aSAl Viro 	u32, third, compat_uptr_t, ptr, u32, fifth)
116*20bc2a3aSAl Viro {
117*20bc2a3aSAl Viro 	int version;
118*20bc2a3aSAl Viro 	u32 pad;
119*20bc2a3aSAl Viro 
120*20bc2a3aSAl Viro 	version = call >> 16; /* hack for backward compatibility */
121*20bc2a3aSAl Viro 	call &= 0xffff;
122*20bc2a3aSAl Viro 
123*20bc2a3aSAl Viro 	switch (call) {
124*20bc2a3aSAl Viro 	case SEMOP:
125*20bc2a3aSAl Viro 		/* struct sembuf is the same on 32 and 64bit :)) */
126*20bc2a3aSAl Viro 		return sys_semtimedop(first, compat_ptr(ptr), second, NULL);
127*20bc2a3aSAl Viro 	case SEMTIMEDOP:
128*20bc2a3aSAl Viro 		return compat_sys_semtimedop(first, compat_ptr(ptr), second,
129*20bc2a3aSAl Viro 						compat_ptr(fifth));
130*20bc2a3aSAl Viro 	case SEMGET:
131*20bc2a3aSAl Viro 		return sys_semget(first, second, third);
132*20bc2a3aSAl Viro 	case SEMCTL:
133*20bc2a3aSAl Viro 		if (!ptr)
134*20bc2a3aSAl Viro 			return -EINVAL;
135*20bc2a3aSAl Viro 		if (get_user(pad, (u32 __user *) compat_ptr(ptr)))
136*20bc2a3aSAl Viro 			return -EFAULT;
137*20bc2a3aSAl Viro 		return compat_sys_semctl(first, second, third, pad);
138*20bc2a3aSAl Viro 
139*20bc2a3aSAl Viro 	case MSGSND:
140*20bc2a3aSAl Viro 		return compat_sys_msgsnd(first, ptr, second, third);
141*20bc2a3aSAl Viro 
142*20bc2a3aSAl Viro 	case MSGRCV: {
143*20bc2a3aSAl Viro 		void __user *uptr = compat_ptr(ptr);
144*20bc2a3aSAl Viro 
145*20bc2a3aSAl Viro 		if (first < 0 || second < 0)
146*20bc2a3aSAl Viro 			return -EINVAL;
147*20bc2a3aSAl Viro 
148*20bc2a3aSAl Viro 		if (!version) {
149*20bc2a3aSAl Viro 			struct compat_ipc_kludge ipck;
150*20bc2a3aSAl Viro 			if (!uptr)
151*20bc2a3aSAl Viro 				return -EINVAL;
152*20bc2a3aSAl Viro 			if (copy_from_user(&ipck, uptr, sizeof(ipck)))
153*20bc2a3aSAl Viro 				return -EFAULT;
154*20bc2a3aSAl Viro 			return compat_sys_msgrcv(first, ipck.msgp, second,
155*20bc2a3aSAl Viro 						 ipck.msgtyp, third);
156*20bc2a3aSAl Viro 		}
157*20bc2a3aSAl Viro 		return compat_sys_msgrcv(first, ptr, second, fifth, third);
158*20bc2a3aSAl Viro 	}
159*20bc2a3aSAl Viro 	case MSGGET:
160*20bc2a3aSAl Viro 		return sys_msgget(first, second);
161*20bc2a3aSAl Viro 	case MSGCTL:
162*20bc2a3aSAl Viro 		return compat_sys_msgctl(first, second, compat_ptr(ptr));
163*20bc2a3aSAl Viro 
164*20bc2a3aSAl Viro 	case SHMAT: {
165*20bc2a3aSAl Viro 		int err;
166*20bc2a3aSAl Viro 		unsigned long raddr;
167*20bc2a3aSAl Viro 
168*20bc2a3aSAl Viro 		if (version == 1)
169*20bc2a3aSAl Viro 			return -EINVAL;
170*20bc2a3aSAl Viro 		err = do_shmat(first, compat_ptr(ptr), second, &raddr,
171*20bc2a3aSAl Viro 			       COMPAT_SHMLBA);
172*20bc2a3aSAl Viro 		if (err < 0)
173*20bc2a3aSAl Viro 			return err;
174*20bc2a3aSAl Viro 		return put_user(raddr, (compat_ulong_t *)compat_ptr(third));
175*20bc2a3aSAl Viro 	}
176*20bc2a3aSAl Viro 	case SHMDT:
177*20bc2a3aSAl Viro 		return sys_shmdt(compat_ptr(ptr));
178*20bc2a3aSAl Viro 	case SHMGET:
179*20bc2a3aSAl Viro 		return sys_shmget(first, (unsigned)second, third);
180*20bc2a3aSAl Viro 	case SHMCTL:
181*20bc2a3aSAl Viro 		return compat_sys_shmctl(first, second, compat_ptr(ptr));
182*20bc2a3aSAl Viro 	}
183*20bc2a3aSAl Viro 
184*20bc2a3aSAl Viro 	return -ENOSYS;
185*20bc2a3aSAl Viro }
186*20bc2a3aSAl Viro #endif
187*20bc2a3aSAl Viro #endif
188