~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/ipc/compat.c

Version: ~ [ linux-5.5 ] ~ [ linux-5.4.15 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.98 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.167 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.211 ] ~ [ linux-4.8.17 ] ~ [ linux-4.7.10 ] ~ [ linux-4.6.7 ] ~ [ linux-4.5.7 ] ~ [ linux-4.4.211 ] ~ [ linux-4.3.6 ] ~ [ linux-4.2.8 ] ~ [ linux-4.1.52 ] ~ [ linux-4.0.9 ] ~ [ linux-3.19.8 ] ~ [ linux-3.18.140 ] ~ [ linux-3.17.8 ] ~ [ linux-3.16.81 ] ~ [ linux-3.15.10 ] ~ [ linux-3.14.79 ] ~ [ linux-3.13.11 ] ~ [ linux-3.12.74 ] ~ [ linux-3.11.10 ] ~ [ linux-3.10.108 ] ~ [ linux-3.9.11 ] ~ [ linux-3.8.13 ] ~ [ linux-3.7.10 ] ~ [ linux-3.6.11 ] ~ [ linux-3.5.7 ] ~ [ linux-3.4.113 ] ~ [ linux-3.3.8 ] ~ [ linux-3.2.102 ] ~ [ linux-3.1.10 ] ~ [ linux-3.0.101 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.5 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  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>
 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>
 29 #include <linux/slab.h>
 30 #include <linux/syscalls.h>
 31 
 32 #include <linux/mutex.h>
 33 #include <asm/uaccess.h>
 34 
 35 #include "util.h"
 36 
 37 struct compat_msgbuf {
 38         compat_long_t mtype;
 39         char mtext[1];
 40 };
 41 
 42 struct compat_ipc_perm {
 43         key_t key;
 44         __compat_uid_t uid;
 45         __compat_gid_t gid;
 46         __compat_uid_t cuid;
 47         __compat_gid_t cgid;
 48         compat_mode_t mode;
 49         unsigned short seq;
 50 };
 51 
 52 struct compat_semid_ds {
 53         struct compat_ipc_perm sem_perm;
 54         compat_time_t sem_otime;
 55         compat_time_t sem_ctime;
 56         compat_uptr_t sem_base;
 57         compat_uptr_t sem_pending;
 58         compat_uptr_t sem_pending_last;
 59         compat_uptr_t undo;
 60         unsigned short sem_nsems;
 61 };
 62 
 63 struct compat_msqid_ds {
 64         struct compat_ipc_perm msg_perm;
 65         compat_uptr_t msg_first;
 66         compat_uptr_t msg_last;
 67         compat_time_t msg_stime;
 68         compat_time_t msg_rtime;
 69         compat_time_t msg_ctime;
 70         compat_ulong_t msg_lcbytes;
 71         compat_ulong_t msg_lqbytes;
 72         unsigned short msg_cbytes;
 73         unsigned short msg_qnum;
 74         unsigned short msg_qbytes;
 75         compat_ipc_pid_t msg_lspid;
 76         compat_ipc_pid_t msg_lrpid;
 77 };
 78 
 79 struct compat_shmid_ds {
 80         struct compat_ipc_perm shm_perm;
 81         int shm_segsz;
 82         compat_time_t shm_atime;
 83         compat_time_t shm_dtime;
 84         compat_time_t shm_ctime;
 85         compat_ipc_pid_t shm_cpid;
 86         compat_ipc_pid_t shm_lpid;
 87         unsigned short shm_nattch;
 88         unsigned short shm_unused;
 89         compat_uptr_t shm_unused2;
 90         compat_uptr_t shm_unused3;
 91 };
 92 
 93 struct compat_ipc_kludge {
 94         compat_uptr_t msgp;
 95         compat_long_t msgtyp;
 96 };
 97 
 98 struct compat_shminfo64 {
 99         compat_ulong_t shmmax;
100         compat_ulong_t shmmin;
101         compat_ulong_t shmmni;
102         compat_ulong_t shmseg;
103         compat_ulong_t shmall;
104         compat_ulong_t __unused1;
105         compat_ulong_t __unused2;
106         compat_ulong_t __unused3;
107         compat_ulong_t __unused4;
108 };
109 
110 struct compat_shm_info {
111         compat_int_t used_ids;
112         compat_ulong_t shm_tot, shm_rss, shm_swp;
113         compat_ulong_t swap_attempts, swap_successes;
114 };
115 
116 extern int sem_ctls[];
117 #define sc_semopm       (sem_ctls[2])
118 
119 static inline int compat_ipc_parse_version(int *cmd)
120 {
121         int version = *cmd & IPC_64;
122 
123         /* this is tricky: architectures that have support for the old
124          * ipc structures in 64 bit binaries need to have IPC_64 set
125          * in cmd, the others need to have it cleared */
126 #ifndef ipc_parse_version
127         *cmd |= IPC_64;
128 #else
129         *cmd &= ~IPC_64;
130 #endif
131         return version;
132 }
133 
134 static inline int __get_compat_ipc64_perm(struct ipc64_perm *p64,
135                                           struct compat_ipc64_perm __user *up64)
136 {
137         int err;
138 
139         err  = __get_user(p64->uid, &up64->uid);
140         err |= __get_user(p64->gid, &up64->gid);
141         err |= __get_user(p64->mode, &up64->mode);
142         return err;
143 }
144 
145 static inline int __get_compat_ipc_perm(struct ipc64_perm *p,
146                                         struct compat_ipc_perm __user *up)
147 {
148         int err;
149 
150         err  = __get_user(p->uid, &up->uid);
151         err |= __get_user(p->gid, &up->gid);
152         err |= __get_user(p->mode, &up->mode);
153         return err;
154 }
155 
156 static inline int __put_compat_ipc64_perm(struct ipc64_perm *p64,
157                                           struct compat_ipc64_perm __user *up64)
158 {
159         int err;
160 
161         err  = __put_user(p64->key, &up64->key);
162         err |= __put_user(p64->uid, &up64->uid);
163         err |= __put_user(p64->gid, &up64->gid);
164         err |= __put_user(p64->cuid, &up64->cuid);
165         err |= __put_user(p64->cgid, &up64->cgid);
166         err |= __put_user(p64->mode, &up64->mode);
167         err |= __put_user(p64->seq, &up64->seq);
168         return err;
169 }
170 
171 static inline int __put_compat_ipc_perm(struct ipc64_perm *p,
172                                         struct compat_ipc_perm __user *up)
173 {
174         int err;
175         __compat_uid_t u;
176         __compat_gid_t g;
177 
178         err  = __put_user(p->key, &up->key);
179         SET_UID(u, p->uid);
180         err |= __put_user(u, &up->uid);
181         SET_GID(g, p->gid);
182         err |= __put_user(g, &up->gid);
183         SET_UID(u, p->cuid);
184         err |= __put_user(u, &up->cuid);
185         SET_GID(g, p->cgid);
186         err |= __put_user(g, &up->cgid);
187         err |= __put_user(p->mode, &up->mode);
188         err |= __put_user(p->seq, &up->seq);
189         return err;
190 }
191 
192 static inline int get_compat_semid64_ds(struct semid64_ds *s64,
193                                         struct compat_semid64_ds __user *up64)
194 {
195         if (!access_ok (VERIFY_READ, up64, sizeof(*up64)))
196                 return -EFAULT;
197         return __get_compat_ipc64_perm(&s64->sem_perm, &up64->sem_perm);
198 }
199 
200 static inline int get_compat_semid_ds(struct semid64_ds *s,
201                                       struct compat_semid_ds __user *up)
202 {
203         if (!access_ok (VERIFY_READ, up, sizeof(*up)))
204                 return -EFAULT;
205         return __get_compat_ipc_perm(&s->sem_perm, &up->sem_perm);
206 }
207 
208 static inline int put_compat_semid64_ds(struct semid64_ds *s64,
209                                         struct compat_semid64_ds __user *up64)
210 {
211         int err;
212 
213         if (!access_ok (VERIFY_WRITE, up64, sizeof(*up64)))
214                 return -EFAULT;
215         err  = __put_compat_ipc64_perm(&s64->sem_perm, &up64->sem_perm);
216         err |= __put_user(s64->sem_otime, &up64->sem_otime);
217         err |= __put_user(s64->sem_ctime, &up64->sem_ctime);
218         err |= __put_user(s64->sem_nsems, &up64->sem_nsems);
219         return err;
220 }
221 
222 static inline int put_compat_semid_ds(struct semid64_ds *s,
223                                       struct compat_semid_ds __user *up)
224 {
225         int err;
226 
227         if (!access_ok (VERIFY_WRITE, up, sizeof(*up)))
228                 return -EFAULT;
229         err  = __put_compat_ipc_perm(&s->sem_perm, &up->sem_perm);
230         err |= __put_user(s->sem_otime, &up->sem_otime);
231         err |= __put_user(s->sem_ctime, &up->sem_ctime);
232         err |= __put_user(s->sem_nsems, &up->sem_nsems);
233         return err;
234 }
235 
236 long compat_sys_semctl(int first, int second, int third, void __user *uptr)
237 {
238         union semun fourth;
239         u32 pad;
240         int err, err2;
241         struct semid64_ds s64;
242         struct semid64_ds __user *up64;
243         int version = compat_ipc_parse_version(&third);
244 
245         memset(&s64, 0, sizeof(s64));
246 
247         if (!uptr)
248                 return -EINVAL;
249         if (get_user(pad, (u32 __user *) uptr))
250                 return -EFAULT;
251         if ((third & (~IPC_64)) == SETVAL)
252                 fourth.val = (int) pad;
253         else
254                 fourth.__pad = compat_ptr(pad);
255         switch (third & (~IPC_64)) {
256         case IPC_INFO:
257         case IPC_RMID:
258         case SEM_INFO:
259         case GETVAL:
260         case GETPID:
261         case GETNCNT:
262         case GETZCNT:
263         case GETALL:
264         case SETVAL:
265         case SETALL:
266                 err = sys_semctl(first, second, third, fourth);
267                 break;
268 
269         case IPC_STAT:
270         case SEM_STAT:
271                 up64 = compat_alloc_user_space(sizeof(s64));
272                 fourth.__pad = up64;
273                 err = sys_semctl(first, second, third, fourth);
274                 if (err < 0)
275                         break;
276                 if (copy_from_user(&s64, up64, sizeof(s64)))
277                         err2 = -EFAULT;
278                 else if (version == IPC_64)
279                         err2 = put_compat_semid64_ds(&s64, compat_ptr(pad));
280                 else
281                         err2 = put_compat_semid_ds(&s64, compat_ptr(pad));
282                 if (err2)
283                         err = -EFAULT;
284                 break;
285 
286         case IPC_SET:
287                 if (version == IPC_64) {
288                         err = get_compat_semid64_ds(&s64, compat_ptr(pad));
289                 } else {
290                         err = get_compat_semid_ds(&s64, compat_ptr(pad));
291                 }
292                 up64 = compat_alloc_user_space(sizeof(s64));
293                 if (copy_to_user(up64, &s64, sizeof(s64)))
294                         err = -EFAULT;
295                 if (err)
296                         break;
297 
298                 fourth.__pad = up64;
299                 err = sys_semctl(first, second, third, fourth);
300                 break;
301 
302         default:
303                 err = -EINVAL;
304                 break;
305         }
306         return err;
307 }
308 
309 long compat_sys_msgsnd(int first, int second, int third, void __user *uptr)
310 {
311         struct compat_msgbuf __user *up = uptr;
312         long type;
313 
314         if (first < 0)
315                 return -EINVAL;
316         if (second < 0)
317                 return -EINVAL;
318 
319         if (get_user(type, &up->mtype))
320                 return -EFAULT;
321 
322         return do_msgsnd(first, type, up->mtext, second, third);
323 }
324 
325 long compat_sys_msgrcv(int first, int second, int msgtyp, int third,
326                            int version, void __user *uptr)
327 {
328         struct compat_msgbuf __user *up;
329         long type;
330         int err;
331 
332         if (first < 0)
333                 return -EINVAL;
334         if (second < 0)
335                 return -EINVAL;
336 
337         if (!version) {
338                 struct compat_ipc_kludge ipck;
339                 err = -EINVAL;
340                 if (!uptr)
341                         goto out;
342                 err = -EFAULT;
343                 if (copy_from_user (&ipck, uptr, sizeof(ipck)))
344                         goto out;
345                 uptr = compat_ptr(ipck.msgp);
346                 msgtyp = ipck.msgtyp;
347         }
348         up = uptr;
349         err = do_msgrcv(first, &type, up->mtext, second, msgtyp, third);
350         if (err < 0)
351                 goto out;
352         if (put_user(type, &up->mtype))
353                 err = -EFAULT;
354 out:
355         return err;
356 }
357 
358 static inline int get_compat_msqid64(struct msqid64_ds *m64,
359                                      struct compat_msqid64_ds __user *up64)
360 {
361         int err;
362 
363         if (!access_ok(VERIFY_READ, up64, sizeof(*up64)))
364                 return -EFAULT;
365         err  = __get_compat_ipc64_perm(&m64->msg_perm, &up64->msg_perm);
366         err |= __get_user(m64->msg_qbytes, &up64->msg_qbytes);
367         return err;
368 }
369 
370 static inline int get_compat_msqid(struct msqid64_ds *m,
371                                    struct compat_msqid_ds __user *up)
372 {
373         int err;
374 
375         if (!access_ok(VERIFY_READ, up, sizeof(*up)))
376                 return -EFAULT;
377         err  = __get_compat_ipc_perm(&m->msg_perm, &up->msg_perm);
378         err |= __get_user(m->msg_qbytes, &up->msg_qbytes);
379         return err;
380 }
381 
382 static inline int put_compat_msqid64_ds(struct msqid64_ds *m64,
383                                  struct compat_msqid64_ds __user *up64)
384 {
385         int err;
386 
387         if (!access_ok(VERIFY_WRITE, up64, sizeof(*up64)))
388                 return -EFAULT;
389         err  = __put_compat_ipc64_perm(&m64->msg_perm, &up64->msg_perm);
390         err |= __put_user(m64->msg_stime, &up64->msg_stime);
391         err |= __put_user(m64->msg_rtime, &up64->msg_rtime);
392         err |= __put_user(m64->msg_ctime, &up64->msg_ctime);
393         err |= __put_user(m64->msg_cbytes, &up64->msg_cbytes);
394         err |= __put_user(m64->msg_qnum, &up64->msg_qnum);
395         err |= __put_user(m64->msg_qbytes, &up64->msg_qbytes);
396         err |= __put_user(m64->msg_lspid, &up64->msg_lspid);
397         err |= __put_user(m64->msg_lrpid, &up64->msg_lrpid);
398         return err;
399 }
400 
401 static inline int put_compat_msqid_ds(struct msqid64_ds *m,
402                                       struct compat_msqid_ds __user *up)
403 {
404         int err;
405 
406         if (!access_ok(VERIFY_WRITE, up, sizeof(*up)))
407                 return -EFAULT;
408         err  = __put_compat_ipc_perm(&m->msg_perm, &up->msg_perm);
409         err |= __put_user(m->msg_stime, &up->msg_stime);
410         err |= __put_user(m->msg_rtime, &up->msg_rtime);
411         err |= __put_user(m->msg_ctime, &up->msg_ctime);
412         err |= __put_user(m->msg_cbytes, &up->msg_cbytes);
413         err |= __put_user(m->msg_qnum, &up->msg_qnum);
414         err |= __put_user(m->msg_qbytes, &up->msg_qbytes);
415         err |= __put_user(m->msg_lspid, &up->msg_lspid);
416         err |= __put_user(m->msg_lrpid, &up->msg_lrpid);
417         return err;
418 }
419 
420 long compat_sys_msgctl(int first, int second, void __user *uptr)
421 {
422         int err, err2;
423         struct msqid64_ds m64;
424         int version = compat_ipc_parse_version(&second);
425         void __user *p;
426 
427         memset(&m64, 0, sizeof(m64));
428 
429         switch (second & (~IPC_64)) {
430         case IPC_INFO:
431         case IPC_RMID:
432         case MSG_INFO:
433                 err = sys_msgctl(first, second, uptr);
434                 break;
435 
436         case IPC_SET:
437                 if (version == IPC_64) {
438                         err = get_compat_msqid64(&m64, uptr);
439                 } else {
440                         err = get_compat_msqid(&m64, uptr);
441                 }
442                 if (err)
443                         break;
444                 p = compat_alloc_user_space(sizeof(m64));
445                 if (copy_to_user(p, &m64, sizeof(m64)))
446                         err = -EFAULT;
447                 else
448                         err = sys_msgctl(first, second, p);
449                 break;
450 
451         case IPC_STAT:
452         case MSG_STAT:
453                 p = compat_alloc_user_space(sizeof(m64));
454                 err = sys_msgctl(first, second, p);
455                 if (err < 0)
456                         break;
457                 if (copy_from_user(&m64, p, sizeof(m64)))
458                         err2 = -EFAULT;
459                 else if (version == IPC_64)
460                         err2 = put_compat_msqid64_ds(&m64, uptr);
461                 else
462                         err2 = put_compat_msqid_ds(&m64, uptr);
463                 if (err2)
464                         err = -EFAULT;
465                 break;
466 
467         default:
468                 err = -EINVAL;
469                 break;
470         }
471         return err;
472 }
473 
474 long compat_sys_shmat(int first, int second, compat_uptr_t third, int version,
475                         void __user *uptr)
476 {
477         int err;
478         unsigned long raddr;
479         compat_ulong_t __user *uaddr;
480 
481         if (version == 1)
482                 return -EINVAL;
483         err = do_shmat(first, uptr, second, &raddr);
484         if (err < 0)
485                 return err;
486         uaddr = compat_ptr(third);
487         return put_user(raddr, uaddr);
488 }
489 
490 static inline int get_compat_shmid64_ds(struct shmid64_ds *s64,
491                                         struct compat_shmid64_ds __user *up64)
492 {
493         if (!access_ok(VERIFY_READ, up64, sizeof(*up64)))
494                 return -EFAULT;
495         return __get_compat_ipc64_perm(&s64->shm_perm, &up64->shm_perm);
496 }
497 
498 static inline int get_compat_shmid_ds(struct shmid64_ds *s,
499                                       struct compat_shmid_ds __user *up)
500 {
501         if (!access_ok(VERIFY_READ, up, sizeof(*up)))
502                 return -EFAULT;
503         return __get_compat_ipc_perm(&s->shm_perm, &up->shm_perm);
504 }
505 
506 static inline int put_compat_shmid64_ds(struct shmid64_ds *s64,
507                                         struct compat_shmid64_ds __user *up64)
508 {
509         int err;
510 
511         if (!access_ok(VERIFY_WRITE, up64, sizeof(*up64)))
512                 return -EFAULT;
513         err  = __put_compat_ipc64_perm(&s64->shm_perm, &up64->shm_perm);
514         err |= __put_user(s64->shm_atime, &up64->shm_atime);
515         err |= __put_user(s64->shm_dtime, &up64->shm_dtime);
516         err |= __put_user(s64->shm_ctime, &up64->shm_ctime);
517         err |= __put_user(s64->shm_segsz, &up64->shm_segsz);
518         err |= __put_user(s64->shm_nattch, &up64->shm_nattch);
519         err |= __put_user(s64->shm_cpid, &up64->shm_cpid);
520         err |= __put_user(s64->shm_lpid, &up64->shm_lpid);
521         return err;
522 }
523 
524 static inline int put_compat_shmid_ds(struct shmid64_ds *s,
525                                       struct compat_shmid_ds __user *up)
526 {
527         int err;
528 
529         if (!access_ok(VERIFY_WRITE, up, sizeof(*up)))
530                 return -EFAULT;
531         err  = __put_compat_ipc_perm(&s->shm_perm, &up->shm_perm);
532         err |= __put_user(s->shm_atime, &up->shm_atime);
533         err |= __put_user(s->shm_dtime, &up->shm_dtime);
534         err |= __put_user(s->shm_ctime, &up->shm_ctime);
535         err |= __put_user(s->shm_segsz, &up->shm_segsz);
536         err |= __put_user(s->shm_nattch, &up->shm_nattch);
537         err |= __put_user(s->shm_cpid, &up->shm_cpid);
538         err |= __put_user(s->shm_lpid, &up->shm_lpid);
539         return err;
540 }
541 
542 static inline int put_compat_shminfo64(struct shminfo64 *smi,
543                                        struct compat_shminfo64 __user *up64)
544 {
545         int err;
546 
547         if (!access_ok(VERIFY_WRITE, up64, sizeof(*up64)))
548                 return -EFAULT;
549         if (smi->shmmax > INT_MAX)
550                 smi->shmmax = INT_MAX;
551         err  = __put_user(smi->shmmax, &up64->shmmax);
552         err |= __put_user(smi->shmmin, &up64->shmmin);
553         err |= __put_user(smi->shmmni, &up64->shmmni);
554         err |= __put_user(smi->shmseg, &up64->shmseg);
555         err |= __put_user(smi->shmall, &up64->shmall);
556         return err;
557 }
558 
559 static inline int put_compat_shminfo(struct shminfo64 *smi,
560                                      struct shminfo __user *up)
561 {
562         int err;
563 
564         if (!access_ok(VERIFY_WRITE, up, sizeof(*up)))
565                 return -EFAULT;
566         if (smi->shmmax > INT_MAX)
567                 smi->shmmax = INT_MAX;
568         err  = __put_user(smi->shmmax, &up->shmmax);
569         err |= __put_user(smi->shmmin, &up->shmmin);
570         err |= __put_user(smi->shmmni, &up->shmmni);
571         err |= __put_user(smi->shmseg, &up->shmseg);
572         err |= __put_user(smi->shmall, &up->shmall);
573         return err;
574 }
575 
576 static inline int put_compat_shm_info(struct shm_info __user *ip,
577                                       struct compat_shm_info __user *uip)
578 {
579         int err;
580         struct shm_info si;
581 
582         if (!access_ok(VERIFY_WRITE, uip, sizeof(*uip)) ||
583             copy_from_user(&si, ip, sizeof(si)))
584                 return -EFAULT;
585         err  = __put_user(si.used_ids, &uip->used_ids);
586         err |= __put_user(si.shm_tot, &uip->shm_tot);
587         err |= __put_user(si.shm_rss, &uip->shm_rss);
588         err |= __put_user(si.shm_swp, &uip->shm_swp);
589         err |= __put_user(si.swap_attempts, &uip->swap_attempts);
590         err |= __put_user(si.swap_successes, &uip->swap_successes);
591         return err;
592 }
593 
594 long compat_sys_shmctl(int first, int second, void __user *uptr)
595 {
596         void __user *p;
597         struct shmid64_ds s64;
598         struct shminfo64 smi;
599         int err, err2;
600         int version = compat_ipc_parse_version(&second);
601 
602         memset(&s64, 0, sizeof(s64));
603 
604         switch (second & (~IPC_64)) {
605         case IPC_RMID:
606         case SHM_LOCK:
607         case SHM_UNLOCK:
608                 err = sys_shmctl(first, second, uptr);
609                 break;
610 
611         case IPC_INFO:
612                 p = compat_alloc_user_space(sizeof(smi));
613                 err = sys_shmctl(first, second, p);
614                 if (err < 0)
615                         break;
616                 if (copy_from_user(&smi, p, sizeof(smi)))
617                         err2 = -EFAULT;
618                 else if (version == IPC_64)
619                         err2 = put_compat_shminfo64(&smi, uptr);
620                 else
621                         err2 = put_compat_shminfo(&smi, uptr);
622                 if (err2)
623                         err = -EFAULT;
624                 break;
625 
626 
627         case IPC_SET:
628                 if (version == IPC_64) {
629                         err = get_compat_shmid64_ds(&s64, uptr);
630                 } else {
631                         err = get_compat_shmid_ds(&s64, uptr);
632                 }
633                 if (err)
634                         break;
635                 p = compat_alloc_user_space(sizeof(s64));
636                 if (copy_to_user(p, &s64, sizeof(s64)))
637                         err = -EFAULT;
638                 else
639                         err = sys_shmctl(first, second, p);
640                 break;
641 
642         case IPC_STAT:
643         case SHM_STAT:
644                 p = compat_alloc_user_space(sizeof(s64));
645                 err = sys_shmctl(first, second, p);
646                 if (err < 0)
647                         break;
648                 if (copy_from_user(&s64, p, sizeof(s64)))
649                         err2 = -EFAULT;
650                 else if (version == IPC_64)
651                         err2 = put_compat_shmid64_ds(&s64, uptr);
652                 else
653                         err2 = put_compat_shmid_ds(&s64, uptr);
654                 if (err2)
655                         err = -EFAULT;
656                 break;
657 
658         case SHM_INFO:
659                 p = compat_alloc_user_space(sizeof(struct shm_info));
660                 err = sys_shmctl(first, second, p);
661                 if (err < 0)
662                         break;
663                 err2 = put_compat_shm_info(p, uptr);
664                 if (err2)
665                         err = -EFAULT;
666                 break;
667 
668         default:
669                 err = -EINVAL;
670                 break;
671         }
672         return err;
673 }
674 
675 long compat_sys_semtimedop(int semid, struct sembuf __user *tsems,
676                 unsigned nsops, const struct compat_timespec __user *timeout)
677 {
678         struct timespec __user *ts64 = NULL;
679         if (timeout) {
680                 struct timespec ts;
681                 ts64 = compat_alloc_user_space(sizeof(*ts64));
682                 if (get_compat_timespec(&ts, timeout))
683                         return -EFAULT;
684                 if (copy_to_user(ts64, &ts, sizeof(ts)))
685                         return -EFAULT;
686         }
687         return sys_semtimedop(semid, tsems, nsops, ts64);
688 }
689 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | Wiki (Japanese) | Wiki (English) | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

osdn.jp