diff options
Diffstat (limited to 'ipc/syscall.c')
-rw-r--r-- | ipc/syscall.c | 90 |
1 files changed, 89 insertions, 1 deletions
diff --git a/ipc/syscall.c b/ipc/syscall.c index 52429489cde0..667022746ca5 100644 --- a/ipc/syscall.c +++ b/ipc/syscall.c | |||
@@ -5,12 +5,12 @@ | |||
5 | * the individual syscalls instead. | 5 | * the individual syscalls instead. |
6 | */ | 6 | */ |
7 | #include <linux/unistd.h> | 7 | #include <linux/unistd.h> |
8 | #include <linux/syscalls.h> | ||
8 | 9 | ||
9 | #ifdef __ARCH_WANT_SYS_IPC | 10 | #ifdef __ARCH_WANT_SYS_IPC |
10 | #include <linux/errno.h> | 11 | #include <linux/errno.h> |
11 | #include <linux/ipc.h> | 12 | #include <linux/ipc.h> |
12 | #include <linux/shm.h> | 13 | #include <linux/shm.h> |
13 | #include <linux/syscalls.h> | ||
14 | #include <linux/uaccess.h> | 14 | #include <linux/uaccess.h> |
15 | 15 | ||
16 | SYSCALL_DEFINE6(ipc, unsigned int, call, int, first, unsigned long, second, | 16 | SYSCALL_DEFINE6(ipc, unsigned int, call, int, first, unsigned long, second, |
@@ -97,3 +97,91 @@ SYSCALL_DEFINE6(ipc, unsigned int, call, int, first, unsigned long, second, | |||
97 | } | 97 | } |
98 | } | 98 | } |
99 | #endif | 99 | #endif |
100 | |||
101 | #ifdef CONFIG_COMPAT | ||
102 | #include <linux/compat.h> | ||
103 | |||
104 | #ifndef COMPAT_SHMLBA | ||
105 | #define COMPAT_SHMLBA SHMLBA | ||
106 | #endif | ||
107 | |||
108 | struct compat_ipc_kludge { | ||
109 | compat_uptr_t msgp; | ||
110 | compat_long_t msgtyp; | ||
111 | }; | ||
112 | |||
113 | #ifdef CONFIG_ARCH_WANT_OLD_COMPAT_IPC | ||
114 | COMPAT_SYSCALL_DEFINE6(ipc, u32, call, int, first, int, second, | ||
115 | u32, third, compat_uptr_t, ptr, u32, fifth) | ||
116 | { | ||
117 | int version; | ||
118 | u32 pad; | ||
119 | |||
120 | version = call >> 16; /* hack for backward compatibility */ | ||
121 | call &= 0xffff; | ||
122 | |||
123 | switch (call) { | ||
124 | case SEMOP: | ||
125 | /* struct sembuf is the same on 32 and 64bit :)) */ | ||
126 | return sys_semtimedop(first, compat_ptr(ptr), second, NULL); | ||
127 | case SEMTIMEDOP: | ||
128 | return compat_sys_semtimedop(first, compat_ptr(ptr), second, | ||
129 | compat_ptr(fifth)); | ||
130 | case SEMGET: | ||
131 | return sys_semget(first, second, third); | ||
132 | case SEMCTL: | ||
133 | if (!ptr) | ||
134 | return -EINVAL; | ||
135 | if (get_user(pad, (u32 __user *) compat_ptr(ptr))) | ||
136 | return -EFAULT; | ||
137 | return compat_sys_semctl(first, second, third, pad); | ||
138 | |||
139 | case MSGSND: | ||
140 | return compat_sys_msgsnd(first, ptr, second, third); | ||
141 | |||
142 | case MSGRCV: { | ||
143 | void __user *uptr = compat_ptr(ptr); | ||
144 | |||
145 | if (first < 0 || second < 0) | ||
146 | return -EINVAL; | ||
147 | |||
148 | if (!version) { | ||
149 | struct compat_ipc_kludge ipck; | ||
150 | if (!uptr) | ||
151 | return -EINVAL; | ||
152 | if (copy_from_user(&ipck, uptr, sizeof(ipck))) | ||
153 | return -EFAULT; | ||
154 | return compat_sys_msgrcv(first, ipck.msgp, second, | ||
155 | ipck.msgtyp, third); | ||
156 | } | ||
157 | return compat_sys_msgrcv(first, ptr, second, fifth, third); | ||
158 | } | ||
159 | case MSGGET: | ||
160 | return sys_msgget(first, second); | ||
161 | case MSGCTL: | ||
162 | return compat_sys_msgctl(first, second, compat_ptr(ptr)); | ||
163 | |||
164 | case SHMAT: { | ||
165 | int err; | ||
166 | unsigned long raddr; | ||
167 | |||
168 | if (version == 1) | ||
169 | return -EINVAL; | ||
170 | err = do_shmat(first, compat_ptr(ptr), second, &raddr, | ||
171 | COMPAT_SHMLBA); | ||
172 | if (err < 0) | ||
173 | return err; | ||
174 | return put_user(raddr, (compat_ulong_t *)compat_ptr(third)); | ||
175 | } | ||
176 | case SHMDT: | ||
177 | return sys_shmdt(compat_ptr(ptr)); | ||
178 | case SHMGET: | ||
179 | return sys_shmget(first, (unsigned)second, third); | ||
180 | case SHMCTL: | ||
181 | return compat_sys_shmctl(first, second, compat_ptr(ptr)); | ||
182 | } | ||
183 | |||
184 | return -ENOSYS; | ||
185 | } | ||
186 | #endif | ||
187 | #endif | ||