Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
fork

Configure Feed

Select the types of activity you want to include in your feed.

at v2.6.16-rc4 688 lines 18 kB view raw
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/config.h> 25#include <linux/errno.h> 26#include <linux/highuid.h> 27#include <linux/init.h> 28#include <linux/msg.h> 29#include <linux/shm.h> 30#include <linux/slab.h> 31#include <linux/syscalls.h> 32 33#include <asm/semaphore.h> 34#include <asm/uaccess.h> 35 36#include "util.h" 37 38struct compat_msgbuf { 39 compat_long_t mtype; 40 char mtext[1]; 41}; 42 43struct compat_ipc_perm { 44 key_t key; 45 __compat_uid_t uid; 46 __compat_gid_t gid; 47 __compat_uid_t cuid; 48 __compat_gid_t cgid; 49 compat_mode_t mode; 50 unsigned short seq; 51}; 52 53struct compat_semid_ds { 54 struct compat_ipc_perm sem_perm; 55 compat_time_t sem_otime; 56 compat_time_t sem_ctime; 57 compat_uptr_t sem_base; 58 compat_uptr_t sem_pending; 59 compat_uptr_t sem_pending_last; 60 compat_uptr_t undo; 61 unsigned short sem_nsems; 62}; 63 64struct compat_msqid_ds { 65 struct compat_ipc_perm msg_perm; 66 compat_uptr_t msg_first; 67 compat_uptr_t msg_last; 68 compat_time_t msg_stime; 69 compat_time_t msg_rtime; 70 compat_time_t msg_ctime; 71 compat_ulong_t msg_lcbytes; 72 compat_ulong_t msg_lqbytes; 73 unsigned short msg_cbytes; 74 unsigned short msg_qnum; 75 unsigned short msg_qbytes; 76 compat_ipc_pid_t msg_lspid; 77 compat_ipc_pid_t msg_lrpid; 78}; 79 80struct compat_shmid_ds { 81 struct compat_ipc_perm shm_perm; 82 int shm_segsz; 83 compat_time_t shm_atime; 84 compat_time_t shm_dtime; 85 compat_time_t shm_ctime; 86 compat_ipc_pid_t shm_cpid; 87 compat_ipc_pid_t shm_lpid; 88 unsigned short shm_nattch; 89 unsigned short shm_unused; 90 compat_uptr_t shm_unused2; 91 compat_uptr_t shm_unused3; 92}; 93 94struct compat_ipc_kludge { 95 compat_uptr_t msgp; 96 compat_long_t msgtyp; 97}; 98 99struct compat_shminfo64 { 100 compat_ulong_t shmmax; 101 compat_ulong_t shmmin; 102 compat_ulong_t shmmni; 103 compat_ulong_t shmseg; 104 compat_ulong_t shmall; 105 compat_ulong_t __unused1; 106 compat_ulong_t __unused2; 107 compat_ulong_t __unused3; 108 compat_ulong_t __unused4; 109}; 110 111struct compat_shm_info { 112 compat_int_t used_ids; 113 compat_ulong_t shm_tot, shm_rss, shm_swp; 114 compat_ulong_t swap_attempts, swap_successes; 115}; 116 117extern int sem_ctls[]; 118#define sc_semopm (sem_ctls[2]) 119#define MAXBUF (64*1024) 120 121static inline int compat_ipc_parse_version(int *cmd) 122{ 123 int version = *cmd & IPC_64; 124 125 /* this is tricky: architectures that have support for the old 126 * ipc structures in 64 bit binaries need to have IPC_64 set 127 * in cmd, the others need to have it cleared */ 128#ifndef ipc_parse_version 129 *cmd |= IPC_64; 130#else 131 *cmd &= ~IPC_64; 132#endif 133 return version; 134} 135 136static inline int __get_compat_ipc64_perm(struct ipc64_perm *p64, 137 struct compat_ipc64_perm __user *up64) 138{ 139 int err; 140 141 err = __get_user(p64->uid, &up64->uid); 142 err |= __get_user(p64->gid, &up64->gid); 143 err |= __get_user(p64->mode, &up64->mode); 144 return err; 145} 146 147static inline int __get_compat_ipc_perm(struct ipc64_perm *p, 148 struct compat_ipc_perm __user *up) 149{ 150 int err; 151 152 err = __get_user(p->uid, &up->uid); 153 err |= __get_user(p->gid, &up->gid); 154 err |= __get_user(p->mode, &up->mode); 155 return err; 156} 157 158static inline int __put_compat_ipc64_perm(struct ipc64_perm *p64, 159 struct compat_ipc64_perm __user *up64) 160{ 161 int err; 162 163 err = __put_user(p64->key, &up64->key); 164 err |= __put_user(p64->uid, &up64->uid); 165 err |= __put_user(p64->gid, &up64->gid); 166 err |= __put_user(p64->cuid, &up64->cuid); 167 err |= __put_user(p64->cgid, &up64->cgid); 168 err |= __put_user(p64->mode, &up64->mode); 169 err |= __put_user(p64->seq, &up64->seq); 170 return err; 171} 172 173static inline int __put_compat_ipc_perm(struct ipc64_perm *p, 174 struct compat_ipc_perm __user *up) 175{ 176 int err; 177 __compat_uid_t u; 178 __compat_gid_t g; 179 180 err = __put_user(p->key, &up->key); 181 SET_UID(u, p->uid); 182 err |= __put_user(u, &up->uid); 183 SET_GID(g, p->gid); 184 err |= __put_user(g, &up->gid); 185 SET_UID(u, p->cuid); 186 err |= __put_user(u, &up->cuid); 187 SET_GID(g, p->cgid); 188 err |= __put_user(g, &up->cgid); 189 err |= __put_user(p->mode, &up->mode); 190 err |= __put_user(p->seq, &up->seq); 191 return err; 192} 193 194static inline int get_compat_semid64_ds(struct semid64_ds *s64, 195 struct compat_semid64_ds __user *up64) 196{ 197 if (!access_ok (VERIFY_READ, up64, sizeof(*up64))) 198 return -EFAULT; 199 return __get_compat_ipc64_perm(&s64->sem_perm, &up64->sem_perm); 200} 201 202static inline int get_compat_semid_ds(struct semid64_ds *s, 203 struct compat_semid_ds __user *up) 204{ 205 if (!access_ok (VERIFY_READ, up, sizeof(*up))) 206 return -EFAULT; 207 return __get_compat_ipc_perm(&s->sem_perm, &up->sem_perm); 208} 209 210static inline int put_compat_semid64_ds(struct semid64_ds *s64, 211 struct compat_semid64_ds __user *up64) 212{ 213 int err; 214 215 if (!access_ok (VERIFY_WRITE, up64, sizeof(*up64))) 216 return -EFAULT; 217 err = __put_compat_ipc64_perm(&s64->sem_perm, &up64->sem_perm); 218 err |= __put_user(s64->sem_otime, &up64->sem_otime); 219 err |= __put_user(s64->sem_ctime, &up64->sem_ctime); 220 err |= __put_user(s64->sem_nsems, &up64->sem_nsems); 221 return err; 222} 223 224static inline int put_compat_semid_ds(struct semid64_ds *s, 225 struct compat_semid_ds __user *up) 226{ 227 int err; 228 229 if (!access_ok (VERIFY_WRITE, up, sizeof(*up))) 230 err = -EFAULT; 231 err = __put_compat_ipc_perm(&s->sem_perm, &up->sem_perm); 232 err |= __put_user(s->sem_otime, &up->sem_otime); 233 err |= __put_user(s->sem_ctime, &up->sem_ctime); 234 err |= __put_user(s->sem_nsems, &up->sem_nsems); 235 return err; 236} 237 238long compat_sys_semctl(int first, int second, int third, void __user *uptr) 239{ 240 union semun fourth; 241 u32 pad; 242 int err, err2; 243 struct semid64_ds s64; 244 struct semid64_ds __user *up64; 245 int version = compat_ipc_parse_version(&third); 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 309long compat_sys_msgsnd(int first, int second, int third, void __user *uptr) 310{ 311 struct msgbuf __user *p; 312 struct compat_msgbuf __user *up = uptr; 313 long type; 314 315 if (first < 0) 316 return -EINVAL; 317 if (second < 0 || (second >= MAXBUF - sizeof(struct msgbuf))) 318 return -EINVAL; 319 320 p = compat_alloc_user_space(second + sizeof(struct msgbuf)); 321 if (get_user(type, &up->mtype) || 322 put_user(type, &p->mtype) || 323 copy_in_user(p->mtext, up->mtext, second)) 324 return -EFAULT; 325 326 return sys_msgsnd(first, p, second, third); 327} 328 329long compat_sys_msgrcv(int first, int second, int msgtyp, int third, 330 int version, void __user *uptr) 331{ 332 struct msgbuf __user *p; 333 struct compat_msgbuf __user *up; 334 long type; 335 int err; 336 337 if (first < 0) 338 return -EINVAL; 339 if (second < 0 || (second >= MAXBUF - sizeof(struct msgbuf))) 340 return -EINVAL; 341 342 if (!version) { 343 struct compat_ipc_kludge ipck; 344 err = -EINVAL; 345 if (!uptr) 346 goto out; 347 err = -EFAULT; 348 if (copy_from_user (&ipck, uptr, sizeof(ipck))) 349 goto out; 350 uptr = compat_ptr(ipck.msgp); 351 msgtyp = ipck.msgtyp; 352 } 353 p = compat_alloc_user_space(second + sizeof(struct msgbuf)); 354 err = sys_msgrcv(first, p, second, msgtyp, third); 355 if (err < 0) 356 goto out; 357 up = uptr; 358 if (get_user(type, &p->mtype) || 359 put_user(type, &up->mtype) || 360 copy_in_user(up->mtext, p->mtext, err)) 361 err = -EFAULT; 362out: 363 return err; 364} 365 366static inline int get_compat_msqid64(struct msqid64_ds *m64, 367 struct compat_msqid64_ds __user *up64) 368{ 369 int err; 370 371 if (!access_ok(VERIFY_READ, up64, sizeof(*up64))) 372 return -EFAULT; 373 err = __get_compat_ipc64_perm(&m64->msg_perm, &up64->msg_perm); 374 err |= __get_user(m64->msg_qbytes, &up64->msg_qbytes); 375 return err; 376} 377 378static inline int get_compat_msqid(struct msqid64_ds *m, 379 struct compat_msqid_ds __user *up) 380{ 381 int err; 382 383 if (!access_ok(VERIFY_READ, up, sizeof(*up))) 384 return -EFAULT; 385 err = __get_compat_ipc_perm(&m->msg_perm, &up->msg_perm); 386 err |= __get_user(m->msg_qbytes, &up->msg_qbytes); 387 return err; 388} 389 390static inline int put_compat_msqid64_ds(struct msqid64_ds *m64, 391 struct compat_msqid64_ds __user *up64) 392{ 393 int err; 394 395 if (!access_ok(VERIFY_WRITE, up64, sizeof(*up64))) 396 return -EFAULT; 397 err = __put_compat_ipc64_perm(&m64->msg_perm, &up64->msg_perm); 398 err |= __put_user(m64->msg_stime, &up64->msg_stime); 399 err |= __put_user(m64->msg_rtime, &up64->msg_rtime); 400 err |= __put_user(m64->msg_ctime, &up64->msg_ctime); 401 err |= __put_user(m64->msg_cbytes, &up64->msg_cbytes); 402 err |= __put_user(m64->msg_qnum, &up64->msg_qnum); 403 err |= __put_user(m64->msg_qbytes, &up64->msg_qbytes); 404 err |= __put_user(m64->msg_lspid, &up64->msg_lspid); 405 err |= __put_user(m64->msg_lrpid, &up64->msg_lrpid); 406 return err; 407} 408 409static inline int put_compat_msqid_ds(struct msqid64_ds *m, 410 struct compat_msqid_ds __user *up) 411{ 412 int err; 413 414 if (!access_ok(VERIFY_WRITE, up, sizeof(*up))) 415 return -EFAULT; 416 err = __put_compat_ipc_perm(&m->msg_perm, &up->msg_perm); 417 err |= __put_user(m->msg_stime, &up->msg_stime); 418 err |= __put_user(m->msg_rtime, &up->msg_rtime); 419 err |= __put_user(m->msg_ctime, &up->msg_ctime); 420 err |= __put_user(m->msg_cbytes, &up->msg_cbytes); 421 err |= __put_user(m->msg_qnum, &up->msg_qnum); 422 err |= __put_user(m->msg_qbytes, &up->msg_qbytes); 423 err |= __put_user(m->msg_lspid, &up->msg_lspid); 424 err |= __put_user(m->msg_lrpid, &up->msg_lrpid); 425 return err; 426} 427 428long compat_sys_msgctl(int first, int second, void __user *uptr) 429{ 430 int err, err2; 431 struct msqid64_ds m64; 432 int version = compat_ipc_parse_version(&second); 433 void __user *p; 434 435 switch (second & (~IPC_64)) { 436 case IPC_INFO: 437 case IPC_RMID: 438 case MSG_INFO: 439 err = sys_msgctl(first, second, uptr); 440 break; 441 442 case IPC_SET: 443 if (version == IPC_64) { 444 err = get_compat_msqid64(&m64, uptr); 445 } else { 446 err = get_compat_msqid(&m64, uptr); 447 } 448 if (err) 449 break; 450 p = compat_alloc_user_space(sizeof(m64)); 451 if (copy_to_user(p, &m64, sizeof(m64))) 452 err = -EFAULT; 453 else 454 err = sys_msgctl(first, second, p); 455 break; 456 457 case IPC_STAT: 458 case MSG_STAT: 459 p = compat_alloc_user_space(sizeof(m64)); 460 err = sys_msgctl(first, second, p); 461 if (err < 0) 462 break; 463 if (copy_from_user(&m64, p, sizeof(m64))) 464 err2 = -EFAULT; 465 else if (version == IPC_64) 466 err2 = put_compat_msqid64_ds(&m64, uptr); 467 else 468 err2 = put_compat_msqid_ds(&m64, uptr); 469 if (err2) 470 err = -EFAULT; 471 break; 472 473 default: 474 err = -EINVAL; 475 break; 476 } 477 return err; 478} 479 480long compat_sys_shmat(int first, int second, compat_uptr_t third, int version, 481 void __user *uptr) 482{ 483 int err; 484 unsigned long raddr; 485 compat_ulong_t __user *uaddr; 486 487 if (version == 1) 488 return -EINVAL; 489 err = do_shmat(first, uptr, second, &raddr); 490 if (err < 0) 491 return err; 492 uaddr = compat_ptr(third); 493 return put_user(raddr, uaddr); 494} 495 496static inline int get_compat_shmid64_ds(struct shmid64_ds *s64, 497 struct compat_shmid64_ds __user *up64) 498{ 499 if (!access_ok(VERIFY_READ, up64, sizeof(*up64))) 500 return -EFAULT; 501 return __get_compat_ipc64_perm(&s64->shm_perm, &up64->shm_perm); 502} 503 504static inline int get_compat_shmid_ds(struct shmid64_ds *s, 505 struct compat_shmid_ds __user *up) 506{ 507 if (!access_ok(VERIFY_READ, up, sizeof(*up))) 508 return -EFAULT; 509 return __get_compat_ipc_perm(&s->shm_perm, &up->shm_perm); 510} 511 512static inline int put_compat_shmid64_ds(struct shmid64_ds *s64, 513 struct compat_shmid64_ds __user *up64) 514{ 515 int err; 516 517 if (!access_ok(VERIFY_WRITE, up64, sizeof(*up64))) 518 return -EFAULT; 519 err = __put_compat_ipc64_perm(&s64->shm_perm, &up64->shm_perm); 520 err |= __put_user(s64->shm_atime, &up64->shm_atime); 521 err |= __put_user(s64->shm_dtime, &up64->shm_dtime); 522 err |= __put_user(s64->shm_ctime, &up64->shm_ctime); 523 err |= __put_user(s64->shm_segsz, &up64->shm_segsz); 524 err |= __put_user(s64->shm_nattch, &up64->shm_nattch); 525 err |= __put_user(s64->shm_cpid, &up64->shm_cpid); 526 err |= __put_user(s64->shm_lpid, &up64->shm_lpid); 527 return err; 528} 529 530static inline int put_compat_shmid_ds(struct shmid64_ds *s, 531 struct compat_shmid_ds __user *up) 532{ 533 int err; 534 535 if (!access_ok(VERIFY_WRITE, up, sizeof(*up))) 536 return -EFAULT; 537 err = __put_compat_ipc_perm(&s->shm_perm, &up->shm_perm); 538 err |= __put_user(s->shm_atime, &up->shm_atime); 539 err |= __put_user(s->shm_dtime, &up->shm_dtime); 540 err |= __put_user(s->shm_ctime, &up->shm_ctime); 541 err |= __put_user(s->shm_segsz, &up->shm_segsz); 542 err |= __put_user(s->shm_nattch, &up->shm_nattch); 543 err |= __put_user(s->shm_cpid, &up->shm_cpid); 544 err |= __put_user(s->shm_lpid, &up->shm_lpid); 545 return err; 546} 547 548static inline int put_compat_shminfo64(struct shminfo64 *smi, 549 struct compat_shminfo64 __user *up64) 550{ 551 int err; 552 553 if (!access_ok(VERIFY_WRITE, up64, sizeof(*up64))) 554 return -EFAULT; 555 err = __put_user(smi->shmmax, &up64->shmmax); 556 err |= __put_user(smi->shmmin, &up64->shmmin); 557 err |= __put_user(smi->shmmni, &up64->shmmni); 558 err |= __put_user(smi->shmseg, &up64->shmseg); 559 err |= __put_user(smi->shmall, &up64->shmall); 560 return err; 561} 562 563static inline int put_compat_shminfo(struct shminfo64 *smi, 564 struct shminfo __user *up) 565{ 566 int err; 567 568 if (!access_ok(VERIFY_WRITE, up, sizeof(*up))) 569 return -EFAULT; 570 err = __put_user(smi->shmmax, &up->shmmax); 571 err |= __put_user(smi->shmmin, &up->shmmin); 572 err |= __put_user(smi->shmmni, &up->shmmni); 573 err |= __put_user(smi->shmseg, &up->shmseg); 574 err |= __put_user(smi->shmall, &up->shmall); 575 return err; 576} 577 578static inline int put_compat_shm_info(struct shm_info __user *ip, 579 struct compat_shm_info __user *uip) 580{ 581 int err; 582 struct shm_info si; 583 584 if (!access_ok(VERIFY_WRITE, uip, sizeof(*uip)) || 585 copy_from_user(&si, ip, sizeof(si))) 586 return -EFAULT; 587 err = __put_user(si.used_ids, &uip->used_ids); 588 err |= __put_user(si.shm_tot, &uip->shm_tot); 589 err |= __put_user(si.shm_rss, &uip->shm_rss); 590 err |= __put_user(si.shm_swp, &uip->shm_swp); 591 err |= __put_user(si.swap_attempts, &uip->swap_attempts); 592 err |= __put_user(si.swap_successes, &uip->swap_successes); 593 return err; 594} 595 596long compat_sys_shmctl(int first, int second, void __user *uptr) 597{ 598 void __user *p; 599 struct shmid64_ds s64; 600 struct shminfo64 smi; 601 int err, err2; 602 int version = compat_ipc_parse_version(&second); 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 675long 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}