diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2013-05-01 10:21:43 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2013-05-01 10:21:43 -0400 |
commit | 08d76760832993050ad8c25e63b56773ef2ca303 (patch) | |
tree | abdcf148dfe43cd49f30f204f1dac6978107a508 /ipc | |
parent | 5f56886521d6ddd3648777fae44d82382dd8c87f (diff) | |
parent | 99e621f796d7f0341a51e8cdf32b81663b10b448 (diff) |
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/signal
Pull compat cleanup from Al Viro:
"Mostly about syscall wrappers this time; there will be another pile
with patches in the same general area from various people, but I'd
rather push those after both that and vfs.git pile are in."
* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/signal:
syscalls.h: slightly reduce the jungles of macros
get rid of union semop in sys_semctl(2) arguments
make do_mremap() static
sparc: no need to sign-extend in sync_file_range() wrapper
ppc compat wrappers for add_key(2) and request_key(2) are pointless
x86: trim sys_ia32.h
x86: sys32_kill and sys32_mprotect are pointless
get rid of compat_sys_semctl() and friends in case of ARCH_WANT_OLD_COMPAT_IPC
merge compat sys_ipc instances
consolidate compat lookup_dcookie()
convert vmsplice to COMPAT_SYSCALL_DEFINE
switch getrusage() to COMPAT_SYSCALL_DEFINE
switch epoll_pwait to COMPAT_SYSCALL_DEFINE
convert sendfile{,64} to COMPAT_SYSCALL_DEFINE
switch signalfd{,4}() to COMPAT_SYSCALL_DEFINE
make SYSCALL_DEFINE<n>-generated wrappers do asmlinkage_protect
make HAVE_SYSCALL_WRAPPERS unconditional
consolidate cond_syscall and SYSCALL_ALIAS declarations
teach SYSCALL_DEFINE<n> how to deal with long long/unsigned long long
get rid of duplicate logics in __SC_....[1-6] definitions
Diffstat (limited to 'ipc')
-rw-r--r-- | ipc/compat.c | 174 | ||||
-rw-r--r-- | ipc/sem.c | 123 | ||||
-rw-r--r-- | ipc/syscall.c | 6 |
3 files changed, 177 insertions, 126 deletions
diff --git a/ipc/compat.c b/ipc/compat.c index 2547f29dcd1b..892f6585dd60 100644 --- a/ipc/compat.c +++ b/ipc/compat.c | |||
@@ -240,7 +240,7 @@ static inline int put_compat_semid_ds(struct semid64_ds *s, | |||
240 | 240 | ||
241 | static long do_compat_semctl(int first, int second, int third, u32 pad) | 241 | static long do_compat_semctl(int first, int second, int third, u32 pad) |
242 | { | 242 | { |
243 | union semun fourth; | 243 | unsigned long fourth; |
244 | int err, err2; | 244 | int err, err2; |
245 | struct semid64_ds s64; | 245 | struct semid64_ds s64; |
246 | struct semid64_ds __user *up64; | 246 | struct semid64_ds __user *up64; |
@@ -249,9 +249,13 @@ static long do_compat_semctl(int first, int second, int third, u32 pad) | |||
249 | memset(&s64, 0, sizeof(s64)); | 249 | memset(&s64, 0, sizeof(s64)); |
250 | 250 | ||
251 | if ((third & (~IPC_64)) == SETVAL) | 251 | if ((third & (~IPC_64)) == SETVAL) |
252 | fourth.val = (int) pad; | 252 | #ifdef __BIG_ENDIAN |
253 | fourth = (unsigned long)pad << 32; | ||
254 | #else | ||
255 | fourth = pad; | ||
256 | #endif | ||
253 | else | 257 | else |
254 | fourth.__pad = compat_ptr(pad); | 258 | fourth = (unsigned long)compat_ptr(pad); |
255 | switch (third & (~IPC_64)) { | 259 | switch (third & (~IPC_64)) { |
256 | case IPC_INFO: | 260 | case IPC_INFO: |
257 | case IPC_RMID: | 261 | case IPC_RMID: |
@@ -269,7 +273,7 @@ static long do_compat_semctl(int first, int second, int third, u32 pad) | |||
269 | case IPC_STAT: | 273 | case IPC_STAT: |
270 | case SEM_STAT: | 274 | case SEM_STAT: |
271 | up64 = compat_alloc_user_space(sizeof(s64)); | 275 | up64 = compat_alloc_user_space(sizeof(s64)); |
272 | fourth.__pad = up64; | 276 | fourth = (unsigned long)up64; |
273 | err = sys_semctl(first, second, third, fourth); | 277 | err = sys_semctl(first, second, third, fourth); |
274 | if (err < 0) | 278 | if (err < 0) |
275 | break; | 279 | break; |
@@ -295,7 +299,7 @@ static long do_compat_semctl(int first, int second, int third, u32 pad) | |||
295 | if (err) | 299 | if (err) |
296 | break; | 300 | break; |
297 | 301 | ||
298 | fourth.__pad = up64; | 302 | fourth = (unsigned long)up64; |
299 | err = sys_semctl(first, second, third, fourth); | 303 | err = sys_semctl(first, second, third, fourth); |
300 | break; | 304 | break; |
301 | 305 | ||
@@ -306,7 +310,7 @@ static long do_compat_semctl(int first, int second, int third, u32 pad) | |||
306 | return err; | 310 | return err; |
307 | } | 311 | } |
308 | 312 | ||
309 | long compat_do_msg_fill(void __user *dest, struct msg_msg *msg, size_t bufsz) | 313 | static long compat_do_msg_fill(void __user *dest, struct msg_msg *msg, size_t bufsz) |
310 | { | 314 | { |
311 | struct compat_msgbuf __user *msgp = dest; | 315 | struct compat_msgbuf __user *msgp = dest; |
312 | size_t msgsz; | 316 | size_t msgsz; |
@@ -320,77 +324,117 @@ long compat_do_msg_fill(void __user *dest, struct msg_msg *msg, size_t bufsz) | |||
320 | return msgsz; | 324 | return msgsz; |
321 | } | 325 | } |
322 | 326 | ||
327 | #ifndef COMPAT_SHMLBA | ||
328 | #define COMPAT_SHMLBA SHMLBA | ||
329 | #endif | ||
330 | |||
323 | #ifdef CONFIG_ARCH_WANT_OLD_COMPAT_IPC | 331 | #ifdef CONFIG_ARCH_WANT_OLD_COMPAT_IPC |
324 | long compat_sys_semctl(int first, int second, int third, void __user *uptr) | 332 | COMPAT_SYSCALL_DEFINE6(ipc, u32, call, int, first, int, second, |
333 | u32, third, compat_uptr_t, ptr, u32, fifth) | ||
325 | { | 334 | { |
335 | int version; | ||
326 | u32 pad; | 336 | u32 pad; |
327 | 337 | ||
328 | if (!uptr) | 338 | version = call >> 16; /* hack for backward compatibility */ |
329 | return -EINVAL; | 339 | call &= 0xffff; |
330 | if (get_user(pad, (u32 __user *) uptr)) | 340 | |
331 | return -EFAULT; | 341 | switch (call) { |
332 | return do_compat_semctl(first, second, third, pad); | 342 | case SEMOP: |
333 | } | 343 | /* struct sembuf is the same on 32 and 64bit :)) */ |
344 | return sys_semtimedop(first, compat_ptr(ptr), second, NULL); | ||
345 | case SEMTIMEDOP: | ||
346 | return compat_sys_semtimedop(first, compat_ptr(ptr), second, | ||
347 | compat_ptr(fifth)); | ||
348 | case SEMGET: | ||
349 | return sys_semget(first, second, third); | ||
350 | case SEMCTL: | ||
351 | if (!ptr) | ||
352 | return -EINVAL; | ||
353 | if (get_user(pad, (u32 __user *) compat_ptr(ptr))) | ||
354 | return -EFAULT; | ||
355 | return do_compat_semctl(first, second, third, pad); | ||
334 | 356 | ||
335 | long compat_sys_msgsnd(int first, int second, int third, void __user *uptr) | 357 | case MSGSND: { |
336 | { | 358 | struct compat_msgbuf __user *up = compat_ptr(ptr); |
337 | struct compat_msgbuf __user *up = uptr; | 359 | compat_long_t type; |
338 | long type; | ||
339 | 360 | ||
340 | if (first < 0) | 361 | if (first < 0 || second < 0) |
341 | return -EINVAL; | 362 | return -EINVAL; |
342 | if (second < 0) | ||
343 | return -EINVAL; | ||
344 | 363 | ||
345 | if (get_user(type, &up->mtype)) | 364 | if (get_user(type, &up->mtype)) |
346 | return -EFAULT; | 365 | return -EFAULT; |
347 | 366 | ||
348 | return do_msgsnd(first, type, up->mtext, second, third); | 367 | return do_msgsnd(first, type, up->mtext, second, third); |
349 | } | 368 | } |
369 | case MSGRCV: { | ||
370 | void __user *uptr = compat_ptr(ptr); | ||
350 | 371 | ||
351 | long compat_sys_msgrcv(int first, int second, int msgtyp, int third, | 372 | if (first < 0 || second < 0) |
352 | int version, void __user *uptr) | ||
353 | { | ||
354 | if (first < 0) | ||
355 | return -EINVAL; | ||
356 | if (second < 0) | ||
357 | return -EINVAL; | ||
358 | |||
359 | if (!version) { | ||
360 | struct compat_ipc_kludge ipck; | ||
361 | if (!uptr) | ||
362 | return -EINVAL; | 373 | return -EINVAL; |
363 | if (copy_from_user (&ipck, uptr, sizeof(ipck))) | 374 | |
364 | return -EFAULT; | 375 | if (!version) { |
365 | uptr = compat_ptr(ipck.msgp); | 376 | struct compat_ipc_kludge ipck; |
366 | msgtyp = ipck.msgtyp; | 377 | if (!uptr) |
378 | return -EINVAL; | ||
379 | if (copy_from_user (&ipck, uptr, sizeof(ipck))) | ||
380 | return -EFAULT; | ||
381 | uptr = compat_ptr(ipck.msgp); | ||
382 | fifth = ipck.msgtyp; | ||
383 | } | ||
384 | return do_msgrcv(first, uptr, second, fifth, third, | ||
385 | compat_do_msg_fill); | ||
367 | } | 386 | } |
368 | return do_msgrcv(first, uptr, second, msgtyp, third, | 387 | case MSGGET: |
369 | compat_do_msg_fill); | 388 | return sys_msgget(first, second); |
389 | case MSGCTL: | ||
390 | return compat_sys_msgctl(first, second, compat_ptr(ptr)); | ||
391 | |||
392 | case SHMAT: { | ||
393 | int err; | ||
394 | unsigned long raddr; | ||
395 | |||
396 | if (version == 1) | ||
397 | return -EINVAL; | ||
398 | err = do_shmat(first, compat_ptr(ptr), second, &raddr, | ||
399 | COMPAT_SHMLBA); | ||
400 | if (err < 0) | ||
401 | return err; | ||
402 | return put_user(raddr, (compat_ulong_t *)compat_ptr(third)); | ||
403 | } | ||
404 | case SHMDT: | ||
405 | return sys_shmdt(compat_ptr(ptr)); | ||
406 | case SHMGET: | ||
407 | return sys_shmget(first, (unsigned)second, third); | ||
408 | case SHMCTL: | ||
409 | return compat_sys_shmctl(first, second, compat_ptr(ptr)); | ||
410 | } | ||
411 | |||
412 | return -ENOSYS; | ||
370 | } | 413 | } |
371 | #else | 414 | #endif |
372 | long compat_sys_semctl(int semid, int semnum, int cmd, int arg) | 415 | |
416 | COMPAT_SYSCALL_DEFINE4(semctl, int, semid, int, semnum, int, cmd, int, arg) | ||
373 | { | 417 | { |
374 | return do_compat_semctl(semid, semnum, cmd, arg); | 418 | return do_compat_semctl(semid, semnum, cmd, arg); |
375 | } | 419 | } |
376 | 420 | ||
377 | long compat_sys_msgsnd(int msqid, struct compat_msgbuf __user *msgp, | 421 | COMPAT_SYSCALL_DEFINE4(msgsnd, int, msqid, compat_uptr_t, msgp, |
378 | compat_ssize_t msgsz, int msgflg) | 422 | compat_ssize_t, msgsz, int, msgflg) |
379 | { | 423 | { |
424 | struct compat_msgbuf __user *up = compat_ptr(msgp); | ||
380 | compat_long_t mtype; | 425 | compat_long_t mtype; |
381 | 426 | ||
382 | if (get_user(mtype, &msgp->mtype)) | 427 | if (get_user(mtype, &up->mtype)) |
383 | return -EFAULT; | 428 | return -EFAULT; |
384 | return do_msgsnd(msqid, mtype, msgp->mtext, (ssize_t)msgsz, msgflg); | 429 | return do_msgsnd(msqid, mtype, up->mtext, (ssize_t)msgsz, msgflg); |
385 | } | 430 | } |
386 | 431 | ||
387 | long compat_sys_msgrcv(int msqid, struct compat_msgbuf __user *msgp, | 432 | COMPAT_SYSCALL_DEFINE5(msgrcv, int, msqid, compat_uptr_t, msgp, |
388 | compat_ssize_t msgsz, long msgtyp, int msgflg) | 433 | compat_ssize_t, msgsz, long, msgtyp, int, msgflg) |
389 | { | 434 | { |
390 | return do_msgrcv(msqid, msgp, (ssize_t)msgsz, msgtyp, msgflg, | 435 | return do_msgrcv(msqid, compat_ptr(msgp), (ssize_t)msgsz, msgtyp, |
391 | compat_do_msg_fill); | 436 | msgflg, compat_do_msg_fill); |
392 | } | 437 | } |
393 | #endif | ||
394 | 438 | ||
395 | static inline int get_compat_msqid64(struct msqid64_ds *m64, | 439 | static inline int get_compat_msqid64(struct msqid64_ds *m64, |
396 | struct compat_msqid64_ds __user *up64) | 440 | struct compat_msqid64_ds __user *up64) |
@@ -508,28 +552,7 @@ long compat_sys_msgctl(int first, int second, void __user *uptr) | |||
508 | return err; | 552 | return err; |
509 | } | 553 | } |
510 | 554 | ||
511 | #ifndef COMPAT_SHMLBA | 555 | COMPAT_SYSCALL_DEFINE3(shmat, int, shmid, compat_uptr_t, shmaddr, int, shmflg) |
512 | #define COMPAT_SHMLBA SHMLBA | ||
513 | #endif | ||
514 | |||
515 | #ifdef CONFIG_ARCH_WANT_OLD_COMPAT_IPC | ||
516 | long compat_sys_shmat(int first, int second, compat_uptr_t third, int version, | ||
517 | void __user *uptr) | ||
518 | { | ||
519 | int err; | ||
520 | unsigned long raddr; | ||
521 | compat_ulong_t __user *uaddr; | ||
522 | |||
523 | if (version == 1) | ||
524 | return -EINVAL; | ||
525 | err = do_shmat(first, uptr, second, &raddr, COMPAT_SHMLBA); | ||
526 | if (err < 0) | ||
527 | return err; | ||
528 | uaddr = compat_ptr(third); | ||
529 | return put_user(raddr, uaddr); | ||
530 | } | ||
531 | #else | ||
532 | long compat_sys_shmat(int shmid, compat_uptr_t shmaddr, int shmflg) | ||
533 | { | 556 | { |
534 | unsigned long ret; | 557 | unsigned long ret; |
535 | long err; | 558 | long err; |
@@ -540,7 +563,6 @@ long compat_sys_shmat(int shmid, compat_uptr_t shmaddr, int shmflg) | |||
540 | force_successful_syscall_return(); | 563 | force_successful_syscall_return(); |
541 | return (long)ret; | 564 | return (long)ret; |
542 | } | 565 | } |
543 | #endif | ||
544 | 566 | ||
545 | static inline int get_compat_shmid64_ds(struct shmid64_ds *s64, | 567 | static inline int get_compat_shmid64_ds(struct shmid64_ds *s64, |
546 | struct compat_shmid64_ds __user *up64) | 568 | struct compat_shmid64_ds __user *up64) |
@@ -799,7 +799,7 @@ static unsigned long copy_semid_to_user(void __user *buf, struct semid64_ds *in, | |||
799 | } | 799 | } |
800 | 800 | ||
801 | static int semctl_nolock(struct ipc_namespace *ns, int semid, | 801 | static int semctl_nolock(struct ipc_namespace *ns, int semid, |
802 | int cmd, int version, union semun arg) | 802 | int cmd, int version, void __user *p) |
803 | { | 803 | { |
804 | int err; | 804 | int err; |
805 | struct sem_array *sma; | 805 | struct sem_array *sma; |
@@ -834,7 +834,7 @@ static int semctl_nolock(struct ipc_namespace *ns, int semid, | |||
834 | } | 834 | } |
835 | max_id = ipc_get_maxid(&sem_ids(ns)); | 835 | max_id = ipc_get_maxid(&sem_ids(ns)); |
836 | up_read(&sem_ids(ns).rw_mutex); | 836 | up_read(&sem_ids(ns).rw_mutex); |
837 | if (copy_to_user (arg.__buf, &seminfo, sizeof(struct seminfo))) | 837 | if (copy_to_user(p, &seminfo, sizeof(struct seminfo))) |
838 | return -EFAULT; | 838 | return -EFAULT; |
839 | return (max_id < 0) ? 0: max_id; | 839 | return (max_id < 0) ? 0: max_id; |
840 | } | 840 | } |
@@ -871,7 +871,7 @@ static int semctl_nolock(struct ipc_namespace *ns, int semid, | |||
871 | tbuf.sem_ctime = sma->sem_ctime; | 871 | tbuf.sem_ctime = sma->sem_ctime; |
872 | tbuf.sem_nsems = sma->sem_nsems; | 872 | tbuf.sem_nsems = sma->sem_nsems; |
873 | sem_unlock(sma); | 873 | sem_unlock(sma); |
874 | if (copy_semid_to_user (arg.buf, &tbuf, version)) | 874 | if (copy_semid_to_user(p, &tbuf, version)) |
875 | return -EFAULT; | 875 | return -EFAULT; |
876 | return id; | 876 | return id; |
877 | } | 877 | } |
@@ -883,8 +883,67 @@ out_unlock: | |||
883 | return err; | 883 | return err; |
884 | } | 884 | } |
885 | 885 | ||
886 | static int semctl_setval(struct ipc_namespace *ns, int semid, int semnum, | ||
887 | unsigned long arg) | ||
888 | { | ||
889 | struct sem_undo *un; | ||
890 | struct sem_array *sma; | ||
891 | struct sem* curr; | ||
892 | int err; | ||
893 | int nsems; | ||
894 | struct list_head tasks; | ||
895 | int val; | ||
896 | #if defined(CONFIG_64BIT) && defined(__BIG_ENDIAN) | ||
897 | /* big-endian 64bit */ | ||
898 | val = arg >> 32; | ||
899 | #else | ||
900 | /* 32bit or little-endian 64bit */ | ||
901 | val = arg; | ||
902 | #endif | ||
903 | |||
904 | sma = sem_lock_check(ns, semid); | ||
905 | if (IS_ERR(sma)) | ||
906 | return PTR_ERR(sma); | ||
907 | |||
908 | INIT_LIST_HEAD(&tasks); | ||
909 | nsems = sma->sem_nsems; | ||
910 | |||
911 | err = -EACCES; | ||
912 | if (ipcperms(ns, &sma->sem_perm, S_IWUGO)) | ||
913 | goto out_unlock; | ||
914 | |||
915 | err = security_sem_semctl(sma, SETVAL); | ||
916 | if (err) | ||
917 | goto out_unlock; | ||
918 | |||
919 | err = -EINVAL; | ||
920 | if(semnum < 0 || semnum >= nsems) | ||
921 | goto out_unlock; | ||
922 | |||
923 | curr = &sma->sem_base[semnum]; | ||
924 | |||
925 | err = -ERANGE; | ||
926 | if (val > SEMVMX || val < 0) | ||
927 | goto out_unlock; | ||
928 | |||
929 | assert_spin_locked(&sma->sem_perm.lock); | ||
930 | list_for_each_entry(un, &sma->list_id, list_id) | ||
931 | un->semadj[semnum] = 0; | ||
932 | |||
933 | curr->semval = val; | ||
934 | curr->sempid = task_tgid_vnr(current); | ||
935 | sma->sem_ctime = get_seconds(); | ||
936 | /* maybe some queued-up processes were waiting for this */ | ||
937 | do_smart_update(sma, NULL, 0, 0, &tasks); | ||
938 | err = 0; | ||
939 | out_unlock: | ||
940 | sem_unlock(sma); | ||
941 | wake_up_sem_queue_do(&tasks); | ||
942 | return err; | ||
943 | } | ||
944 | |||
886 | static int semctl_main(struct ipc_namespace *ns, int semid, int semnum, | 945 | static int semctl_main(struct ipc_namespace *ns, int semid, int semnum, |
887 | int cmd, int version, union semun arg) | 946 | int cmd, void __user *p) |
888 | { | 947 | { |
889 | struct sem_array *sma; | 948 | struct sem_array *sma; |
890 | struct sem* curr; | 949 | struct sem* curr; |
@@ -903,7 +962,7 @@ static int semctl_main(struct ipc_namespace *ns, int semid, int semnum, | |||
903 | 962 | ||
904 | err = -EACCES; | 963 | err = -EACCES; |
905 | if (ipcperms(ns, &sma->sem_perm, | 964 | if (ipcperms(ns, &sma->sem_perm, |
906 | (cmd == SETVAL || cmd == SETALL) ? S_IWUGO : S_IRUGO)) | 965 | cmd == SETALL ? S_IWUGO : S_IRUGO)) |
907 | goto out_unlock; | 966 | goto out_unlock; |
908 | 967 | ||
909 | err = security_sem_semctl(sma, cmd); | 968 | err = security_sem_semctl(sma, cmd); |
@@ -914,7 +973,7 @@ static int semctl_main(struct ipc_namespace *ns, int semid, int semnum, | |||
914 | switch (cmd) { | 973 | switch (cmd) { |
915 | case GETALL: | 974 | case GETALL: |
916 | { | 975 | { |
917 | ushort __user *array = arg.array; | 976 | ushort __user *array = p; |
918 | int i; | 977 | int i; |
919 | 978 | ||
920 | if(nsems > SEMMSL_FAST) { | 979 | if(nsems > SEMMSL_FAST) { |
@@ -957,7 +1016,7 @@ static int semctl_main(struct ipc_namespace *ns, int semid, int semnum, | |||
957 | } | 1016 | } |
958 | } | 1017 | } |
959 | 1018 | ||
960 | if (copy_from_user (sem_io, arg.array, nsems*sizeof(ushort))) { | 1019 | if (copy_from_user (sem_io, p, nsems*sizeof(ushort))) { |
961 | sem_putref(sma); | 1020 | sem_putref(sma); |
962 | err = -EFAULT; | 1021 | err = -EFAULT; |
963 | goto out_free; | 1022 | goto out_free; |
@@ -991,7 +1050,7 @@ static int semctl_main(struct ipc_namespace *ns, int semid, int semnum, | |||
991 | err = 0; | 1050 | err = 0; |
992 | goto out_unlock; | 1051 | goto out_unlock; |
993 | } | 1052 | } |
994 | /* GETVAL, GETPID, GETNCTN, GETZCNT, SETVAL: fall-through */ | 1053 | /* GETVAL, GETPID, GETNCTN, GETZCNT: fall-through */ |
995 | } | 1054 | } |
996 | err = -EINVAL; | 1055 | err = -EINVAL; |
997 | if(semnum < 0 || semnum >= nsems) | 1056 | if(semnum < 0 || semnum >= nsems) |
@@ -1012,27 +1071,6 @@ static int semctl_main(struct ipc_namespace *ns, int semid, int semnum, | |||
1012 | case GETZCNT: | 1071 | case GETZCNT: |
1013 | err = count_semzcnt(sma,semnum); | 1072 | err = count_semzcnt(sma,semnum); |
1014 | goto out_unlock; | 1073 | goto out_unlock; |
1015 | case SETVAL: | ||
1016 | { | ||
1017 | int val = arg.val; | ||
1018 | struct sem_undo *un; | ||
1019 | |||
1020 | err = -ERANGE; | ||
1021 | if (val > SEMVMX || val < 0) | ||
1022 | goto out_unlock; | ||
1023 | |||
1024 | assert_spin_locked(&sma->sem_perm.lock); | ||
1025 | list_for_each_entry(un, &sma->list_id, list_id) | ||
1026 | un->semadj[semnum] = 0; | ||
1027 | |||
1028 | curr->semval = val; | ||
1029 | curr->sempid = task_tgid_vnr(current); | ||
1030 | sma->sem_ctime = get_seconds(); | ||
1031 | /* maybe some queued-up processes were waiting for this */ | ||
1032 | do_smart_update(sma, NULL, 0, 0, &tasks); | ||
1033 | err = 0; | ||
1034 | goto out_unlock; | ||
1035 | } | ||
1036 | } | 1074 | } |
1037 | out_unlock: | 1075 | out_unlock: |
1038 | sem_unlock(sma); | 1076 | sem_unlock(sma); |
@@ -1076,7 +1114,7 @@ copy_semid_from_user(struct semid64_ds *out, void __user *buf, int version) | |||
1076 | * NOTE: no locks must be held, the rw_mutex is taken inside this function. | 1114 | * NOTE: no locks must be held, the rw_mutex is taken inside this function. |
1077 | */ | 1115 | */ |
1078 | static int semctl_down(struct ipc_namespace *ns, int semid, | 1116 | static int semctl_down(struct ipc_namespace *ns, int semid, |
1079 | int cmd, int version, union semun arg) | 1117 | int cmd, int version, void __user *p) |
1080 | { | 1118 | { |
1081 | struct sem_array *sma; | 1119 | struct sem_array *sma; |
1082 | int err; | 1120 | int err; |
@@ -1084,7 +1122,7 @@ static int semctl_down(struct ipc_namespace *ns, int semid, | |||
1084 | struct kern_ipc_perm *ipcp; | 1122 | struct kern_ipc_perm *ipcp; |
1085 | 1123 | ||
1086 | if(cmd == IPC_SET) { | 1124 | if(cmd == IPC_SET) { |
1087 | if (copy_semid_from_user(&semid64, arg.buf, version)) | 1125 | if (copy_semid_from_user(&semid64, p, version)) |
1088 | return -EFAULT; | 1126 | return -EFAULT; |
1089 | } | 1127 | } |
1090 | 1128 | ||
@@ -1120,11 +1158,11 @@ out_up: | |||
1120 | return err; | 1158 | return err; |
1121 | } | 1159 | } |
1122 | 1160 | ||
1123 | SYSCALL_DEFINE(semctl)(int semid, int semnum, int cmd, union semun arg) | 1161 | SYSCALL_DEFINE4(semctl, int, semid, int, semnum, int, cmd, unsigned long, arg) |
1124 | { | 1162 | { |
1125 | int err = -EINVAL; | ||
1126 | int version; | 1163 | int version; |
1127 | struct ipc_namespace *ns; | 1164 | struct ipc_namespace *ns; |
1165 | void __user *p = (void __user *)arg; | ||
1128 | 1166 | ||
1129 | if (semid < 0) | 1167 | if (semid < 0) |
1130 | return -EINVAL; | 1168 | return -EINVAL; |
@@ -1137,32 +1175,23 @@ SYSCALL_DEFINE(semctl)(int semid, int semnum, int cmd, union semun arg) | |||
1137 | case SEM_INFO: | 1175 | case SEM_INFO: |
1138 | case IPC_STAT: | 1176 | case IPC_STAT: |
1139 | case SEM_STAT: | 1177 | case SEM_STAT: |
1140 | err = semctl_nolock(ns, semid, cmd, version, arg); | 1178 | return semctl_nolock(ns, semid, cmd, version, p); |
1141 | return err; | ||
1142 | case GETALL: | 1179 | case GETALL: |
1143 | case GETVAL: | 1180 | case GETVAL: |
1144 | case GETPID: | 1181 | case GETPID: |
1145 | case GETNCNT: | 1182 | case GETNCNT: |
1146 | case GETZCNT: | 1183 | case GETZCNT: |
1147 | case SETVAL: | ||
1148 | case SETALL: | 1184 | case SETALL: |
1149 | err = semctl_main(ns,semid,semnum,cmd,version,arg); | 1185 | return semctl_main(ns, semid, semnum, cmd, p); |
1150 | return err; | 1186 | case SETVAL: |
1187 | return semctl_setval(ns, semid, semnum, arg); | ||
1151 | case IPC_RMID: | 1188 | case IPC_RMID: |
1152 | case IPC_SET: | 1189 | case IPC_SET: |
1153 | err = semctl_down(ns, semid, cmd, version, arg); | 1190 | return semctl_down(ns, semid, cmd, version, p); |
1154 | return err; | ||
1155 | default: | 1191 | default: |
1156 | return -EINVAL; | 1192 | return -EINVAL; |
1157 | } | 1193 | } |
1158 | } | 1194 | } |
1159 | #ifdef CONFIG_HAVE_SYSCALL_WRAPPERS | ||
1160 | asmlinkage long SyS_semctl(int semid, int semnum, int cmd, union semun arg) | ||
1161 | { | ||
1162 | return SYSC_semctl((int) semid, (int) semnum, (int) cmd, arg); | ||
1163 | } | ||
1164 | SYSCALL_ALIAS(sys_semctl, SyS_semctl); | ||
1165 | #endif | ||
1166 | 1195 | ||
1167 | /* If the task doesn't already have a undo_list, then allocate one | 1196 | /* If the task doesn't already have a undo_list, then allocate one |
1168 | * here. We guarantee there is only one thread using this undo list, | 1197 | * here. We guarantee there is only one thread using this undo list, |
diff --git a/ipc/syscall.c b/ipc/syscall.c index 0d1e32ce048e..52429489cde0 100644 --- a/ipc/syscall.c +++ b/ipc/syscall.c | |||
@@ -33,12 +33,12 @@ SYSCALL_DEFINE6(ipc, unsigned int, call, int, first, unsigned long, second, | |||
33 | case SEMGET: | 33 | case SEMGET: |
34 | return sys_semget(first, second, third); | 34 | return sys_semget(first, second, third); |
35 | case SEMCTL: { | 35 | case SEMCTL: { |
36 | union semun fourth; | 36 | unsigned long arg; |
37 | if (!ptr) | 37 | if (!ptr) |
38 | return -EINVAL; | 38 | return -EINVAL; |
39 | if (get_user(fourth.__pad, (void __user * __user *) ptr)) | 39 | if (get_user(arg, (unsigned long __user *) ptr)) |
40 | return -EFAULT; | 40 | return -EFAULT; |
41 | return sys_semctl(first, second, third, fourth); | 41 | return sys_semctl(first, second, third, arg); |
42 | } | 42 | } |
43 | 43 | ||
44 | case MSGSND: | 44 | case MSGSND: |