]> git.ipfire.org Git - thirdparty/kernel/stable.git/blame - ipc/compat.c
semctl(): move compat to native
[thirdparty/kernel/stable.git] / ipc / compat.c
CommitLineData
1da177e4
LT
1/*
2 * 32 bit compatibility code for System V IPC
3 *
4 * Copyright (C) 1997,1998 Jakub Jelinek (jj@sunsite.mff.cuni.cz)
5 * Copyright (C) 1997 David S. Miller (davem@caip.rutgers.edu)
6 * Copyright (C) 1999 Arun Sharma <arun.sharma@intel.com>
7 * Copyright (C) 2000 VA Linux Co
8 * Copyright (C) 2000 Don Dugger <n0ano@valinux.com>
9 * Copyright (C) 2000 Hewlett-Packard Co.
10 * Copyright (C) 2000 David Mosberger-Tang <davidm@hpl.hp.com>
11 * Copyright (C) 2000 Gerhard Tonn (ton@de.ibm.com)
12 * Copyright (C) 2000-2002 Andi Kleen, SuSE Labs (x86-64 port)
13 * Copyright (C) 2000 Silicon Graphics, Inc.
14 * Copyright (C) 2001 IBM
15 * Copyright (C) 2004 IBM Deutschland Entwicklung GmbH, IBM Corporation
16 * Copyright (C) 2004 Arnd Bergmann (arnd@arndb.de)
17 *
18 * This code is collected from the versions for sparc64, mips64, s390x, ia64,
19 * ppc64 and x86_64, all of which are based on the original sparc64 version
20 * by Jakub Jelinek.
21 *
22 */
23#include <linux/compat.h>
1da177e4
LT
24#include <linux/errno.h>
25#include <linux/highuid.h>
26#include <linux/init.h>
27#include <linux/msg.h>
28#include <linux/shm.h>
1da177e4 29#include <linux/syscalls.h>
48b25c43 30#include <linux/ptrace.h>
1da177e4 31
5f921ae9 32#include <linux/mutex.h>
7153e402 33#include <linux/uaccess.h>
1da177e4
LT
34
35#include "util.h"
36
37struct compat_msgbuf {
38 compat_long_t mtype;
39 char mtext[1];
40};
41
1da177e4
LT
42struct compat_ipc_kludge {
43 compat_uptr_t msgp;
44 compat_long_t msgtyp;
45};
46
c0ebccb6
AV
47int get_compat_ipc64_perm(struct ipc64_perm *to,
48 struct compat_ipc64_perm __user *from)
1da177e4 49{
c0ebccb6
AV
50 struct compat_ipc64_perm v;
51 if (copy_from_user(&v, from, sizeof(v)))
1da177e4 52 return -EFAULT;
c0ebccb6
AV
53 to->uid = v.uid;
54 to->gid = v.gid;
55 to->mode = v.mode;
56 return 0;
1da177e4
LT
57}
58
c0ebccb6
AV
59int get_compat_ipc_perm(struct ipc64_perm *to,
60 struct compat_ipc_perm __user *from)
1da177e4 61{
c0ebccb6
AV
62 struct compat_ipc_perm v;
63 if (copy_from_user(&v, from, sizeof(v)))
1da177e4 64 return -EFAULT;
c0ebccb6
AV
65 to->uid = v.uid;
66 to->gid = v.gid;
67 to->mode = v.mode;
68 return 0;
1da177e4
LT
69}
70
c0ebccb6 71void to_compat_ipc64_perm(struct compat_ipc64_perm *to, struct ipc64_perm *from)
1da177e4 72{
c0ebccb6
AV
73 to->key = from->key;
74 to->uid = from->uid;
75 to->gid = from->gid;
76 to->cuid = from->cuid;
77 to->cgid = from->cgid;
78 to->mode = from->mode;
79 to->seq = from->seq;
1da177e4
LT
80}
81
c0ebccb6 82void to_compat_ipc_perm(struct compat_ipc_perm *to, struct ipc64_perm *from)
1da177e4 83{
c0ebccb6
AV
84 to->key = from->key;
85 SET_UID(to->uid, from->uid);
86 SET_GID(to->gid, from->gid);
87 SET_UID(to->cuid, from->cuid);
88 SET_GID(to->cgid, from->cgid);
89 to->mode = from->mode;
90 to->seq = from->seq;
1da177e4
LT
91}
92
0e65a81b 93static long compat_do_msg_fill(void __user *dest, struct msg_msg *msg, size_t bufsz)
f9dd87f4
SK
94{
95 struct compat_msgbuf __user *msgp = dest;
96 size_t msgsz;
97
98 if (put_user(msg->m_type, &msgp->mtype))
99 return -EFAULT;
100
101 msgsz = (bufsz > msg->m_ts) ? msg->m_ts : bufsz;
102 if (store_msg(msgp->mtext, msg, msgsz))
103 return -EFAULT;
104 return msgsz;
105}
106
0e65a81b
AV
107#ifndef COMPAT_SHMLBA
108#define COMPAT_SHMLBA SHMLBA
109#endif
56e41d3c 110
0e65a81b 111#ifdef CONFIG_ARCH_WANT_OLD_COMPAT_IPC
56e41d3c
AV
112COMPAT_SYSCALL_DEFINE6(ipc, u32, call, int, first, int, second,
113 u32, third, compat_uptr_t, ptr, u32, fifth)
114{
115 int version;
0e65a81b 116 u32 pad;
56e41d3c
AV
117
118 version = call >> 16; /* hack for backward compatibility */
119 call &= 0xffff;
120
121 switch (call) {
122 case SEMOP:
123 /* struct sembuf is the same on 32 and 64bit :)) */
124 return sys_semtimedop(first, compat_ptr(ptr), second, NULL);
125 case SEMTIMEDOP:
126 return compat_sys_semtimedop(first, compat_ptr(ptr), second,
127 compat_ptr(fifth));
128 case SEMGET:
129 return sys_semget(first, second, third);
130 case SEMCTL:
0e65a81b
AV
131 if (!ptr)
132 return -EINVAL;
133 if (get_user(pad, (u32 __user *) compat_ptr(ptr)))
134 return -EFAULT;
c0ebccb6 135 return compat_sys_semctl(first, second, third, pad);
0e65a81b
AV
136
137 case MSGSND: {
138 struct compat_msgbuf __user *up = compat_ptr(ptr);
139 compat_long_t type;
140
141 if (first < 0 || second < 0)
142 return -EINVAL;
56e41d3c 143
0e65a81b
AV
144 if (get_user(type, &up->mtype))
145 return -EFAULT;
146
147 return do_msgsnd(first, type, up->mtext, second, third);
148 }
149 case MSGRCV: {
150 void __user *uptr = compat_ptr(ptr);
151
152 if (first < 0 || second < 0)
153 return -EINVAL;
154
155 if (!version) {
156 struct compat_ipc_kludge ipck;
157 if (!uptr)
158 return -EINVAL;
239521f3 159 if (copy_from_user(&ipck, uptr, sizeof(ipck)))
0e65a81b
AV
160 return -EFAULT;
161 uptr = compat_ptr(ipck.msgp);
162 fifth = ipck.msgtyp;
163 }
e7ca2552 164 return do_msgrcv(first, uptr, second, (s32)fifth, third,
0e65a81b
AV
165 compat_do_msg_fill);
166 }
56e41d3c
AV
167 case MSGGET:
168 return sys_msgget(first, second);
169 case MSGCTL:
170 return compat_sys_msgctl(first, second, compat_ptr(ptr));
171
0e65a81b
AV
172 case SHMAT: {
173 int err;
174 unsigned long raddr;
175
176 if (version == 1)
177 return -EINVAL;
178 err = do_shmat(first, compat_ptr(ptr), second, &raddr,
179 COMPAT_SHMLBA);
180 if (err < 0)
181 return err;
182 return put_user(raddr, (compat_ulong_t *)compat_ptr(third));
183 }
56e41d3c
AV
184 case SHMDT:
185 return sys_shmdt(compat_ptr(ptr));
186 case SHMGET:
187 return sys_shmget(first, (unsigned)second, third);
188 case SHMCTL:
189 return compat_sys_shmctl(first, second, compat_ptr(ptr));
190 }
191
192 return -ENOSYS;
193}
0e65a81b
AV
194#endif
195
0e65a81b
AV
196COMPAT_SYSCALL_DEFINE4(msgsnd, int, msqid, compat_uptr_t, msgp,
197 compat_ssize_t, msgsz, int, msgflg)
48b25c43 198{
0e65a81b 199 struct compat_msgbuf __user *up = compat_ptr(msgp);
48b25c43
CM
200 compat_long_t mtype;
201
0e65a81b 202 if (get_user(mtype, &up->mtype))
48b25c43 203 return -EFAULT;
0e65a81b 204 return do_msgsnd(msqid, mtype, up->mtext, (ssize_t)msgsz, msgflg);
48b25c43
CM
205}
206
0e65a81b 207COMPAT_SYSCALL_DEFINE5(msgrcv, int, msqid, compat_uptr_t, msgp,
291fdb0b 208 compat_ssize_t, msgsz, compat_long_t, msgtyp, int, msgflg)
48b25c43 209{
291fdb0b 210 return do_msgrcv(msqid, compat_ptr(msgp), (ssize_t)msgsz, (long)msgtyp,
0e65a81b 211 msgflg, compat_do_msg_fill);
48b25c43 212}
1da177e4 213
0e65a81b 214COMPAT_SYSCALL_DEFINE3(shmat, int, shmid, compat_uptr_t, shmaddr, int, shmflg)
48b25c43
CM
215{
216 unsigned long ret;
217 long err;
218
079a96ae 219 err = do_shmat(shmid, compat_ptr(shmaddr), shmflg, &ret, COMPAT_SHMLBA);
48b25c43
CM
220 if (err)
221 return err;
222 force_successful_syscall_return();
223 return (long)ret;
224}
1da177e4 225
5d70a596
HC
226COMPAT_SYSCALL_DEFINE4(semtimedop, int, semid, struct sembuf __user *, tsems,
227 unsigned, nsops,
228 const struct compat_timespec __user *, timeout)
1da177e4 229{
81993e81
PA
230 struct timespec __user *ts64;
231 if (compat_convert_timespec(&ts64, timeout))
232 return -EFAULT;
1da177e4
LT
233 return sys_semtimedop(semid, tsems, nsops, ts64);
234}