diff options
Diffstat (limited to 'ipc')
-rw-r--r-- | ipc/ipc_sysctl.c | 46 | ||||
-rw-r--r-- | ipc/mqueue.c | 129 | ||||
-rw-r--r-- | ipc/msg.c | 12 | ||||
-rw-r--r-- | ipc/sem.c | 21 | ||||
-rw-r--r-- | ipc/shm.c | 47 | ||||
-rw-r--r-- | ipc/util.c | 18 |
6 files changed, 141 insertions, 132 deletions
diff --git a/ipc/ipc_sysctl.c b/ipc/ipc_sysctl.c index 0dfebc509426..4a7a12c95abe 100644 --- a/ipc/ipc_sysctl.c +++ b/ipc/ipc_sysctl.c | |||
@@ -26,29 +26,6 @@ static void *get_ipc(ctl_table *table) | |||
26 | return which; | 26 | return which; |
27 | } | 27 | } |
28 | 28 | ||
29 | /* | ||
30 | * Routine that is called when the file "auto_msgmni" has successfully been | ||
31 | * written. | ||
32 | * Two values are allowed: | ||
33 | * 0: unregister msgmni's callback routine from the ipc namespace notifier | ||
34 | * chain. This means that msgmni won't be recomputed anymore upon memory | ||
35 | * add/remove or ipc namespace creation/removal. | ||
36 | * 1: register back the callback routine. | ||
37 | */ | ||
38 | static void ipc_auto_callback(int val) | ||
39 | { | ||
40 | if (!val) | ||
41 | unregister_ipcns_notifier(current->nsproxy->ipc_ns); | ||
42 | else { | ||
43 | /* | ||
44 | * Re-enable automatic recomputing only if not already | ||
45 | * enabled. | ||
46 | */ | ||
47 | recompute_msgmni(current->nsproxy->ipc_ns); | ||
48 | cond_register_ipcns_notifier(current->nsproxy->ipc_ns); | ||
49 | } | ||
50 | } | ||
51 | |||
52 | #ifdef CONFIG_PROC_FS | 29 | #ifdef CONFIG_PROC_FS |
53 | static int proc_ipc_dointvec(ctl_table *table, int write, struct file *filp, | 30 | static int proc_ipc_dointvec(ctl_table *table, int write, struct file *filp, |
54 | void __user *buffer, size_t *lenp, loff_t *ppos) | 31 | void __user *buffer, size_t *lenp, loff_t *ppos) |
@@ -94,6 +71,29 @@ static int proc_ipc_doulongvec_minmax(ctl_table *table, int write, | |||
94 | lenp, ppos); | 71 | lenp, ppos); |
95 | } | 72 | } |
96 | 73 | ||
74 | /* | ||
75 | * Routine that is called when the file "auto_msgmni" has successfully been | ||
76 | * written. | ||
77 | * Two values are allowed: | ||
78 | * 0: unregister msgmni's callback routine from the ipc namespace notifier | ||
79 | * chain. This means that msgmni won't be recomputed anymore upon memory | ||
80 | * add/remove or ipc namespace creation/removal. | ||
81 | * 1: register back the callback routine. | ||
82 | */ | ||
83 | static void ipc_auto_callback(int val) | ||
84 | { | ||
85 | if (!val) | ||
86 | unregister_ipcns_notifier(current->nsproxy->ipc_ns); | ||
87 | else { | ||
88 | /* | ||
89 | * Re-enable automatic recomputing only if not already | ||
90 | * enabled. | ||
91 | */ | ||
92 | recompute_msgmni(current->nsproxy->ipc_ns); | ||
93 | cond_register_ipcns_notifier(current->nsproxy->ipc_ns); | ||
94 | } | ||
95 | } | ||
96 | |||
97 | static int proc_ipcauto_dointvec_minmax(ctl_table *table, int write, | 97 | static int proc_ipcauto_dointvec_minmax(ctl_table *table, int write, |
98 | struct file *filp, void __user *buffer, size_t *lenp, loff_t *ppos) | 98 | struct file *filp, void __user *buffer, size_t *lenp, loff_t *ppos) |
99 | { | 99 | { |
diff --git a/ipc/mqueue.c b/ipc/mqueue.c index d9393f8e4c3e..54b4077fed79 100644 --- a/ipc/mqueue.c +++ b/ipc/mqueue.c | |||
@@ -120,7 +120,6 @@ static struct inode *mqueue_get_inode(struct super_block *sb, int mode, | |||
120 | inode->i_mode = mode; | 120 | inode->i_mode = mode; |
121 | inode->i_uid = current_fsuid(); | 121 | inode->i_uid = current_fsuid(); |
122 | inode->i_gid = current_fsgid(); | 122 | inode->i_gid = current_fsgid(); |
123 | inode->i_blocks = 0; | ||
124 | inode->i_mtime = inode->i_ctime = inode->i_atime = | 123 | inode->i_mtime = inode->i_ctime = inode->i_atime = |
125 | CURRENT_TIME; | 124 | CURRENT_TIME; |
126 | 125 | ||
@@ -506,7 +505,8 @@ static void __do_notify(struct mqueue_inode_info *info) | |||
506 | sig_i.si_errno = 0; | 505 | sig_i.si_errno = 0; |
507 | sig_i.si_code = SI_MESGQ; | 506 | sig_i.si_code = SI_MESGQ; |
508 | sig_i.si_value = info->notify.sigev_value; | 507 | sig_i.si_value = info->notify.sigev_value; |
509 | sig_i.si_pid = task_tgid_vnr(current); | 508 | sig_i.si_pid = task_tgid_nr_ns(current, |
509 | ns_of_pid(info->notify_owner)); | ||
510 | sig_i.si_uid = current_uid(); | 510 | sig_i.si_uid = current_uid(); |
511 | 511 | ||
512 | kill_pid_info(info->notify.sigev_signo, | 512 | kill_pid_info(info->notify.sigev_signo, |
@@ -524,31 +524,27 @@ static void __do_notify(struct mqueue_inode_info *info) | |||
524 | wake_up(&info->wait_q); | 524 | wake_up(&info->wait_q); |
525 | } | 525 | } |
526 | 526 | ||
527 | static long prepare_timeout(const struct timespec __user *u_arg) | 527 | static long prepare_timeout(struct timespec *p) |
528 | { | 528 | { |
529 | struct timespec ts, nowts; | 529 | struct timespec nowts; |
530 | long timeout; | 530 | long timeout; |
531 | 531 | ||
532 | if (u_arg) { | 532 | if (p) { |
533 | if (unlikely(copy_from_user(&ts, u_arg, | 533 | if (unlikely(p->tv_nsec < 0 || p->tv_sec < 0 |
534 | sizeof(struct timespec)))) | 534 | || p->tv_nsec >= NSEC_PER_SEC)) |
535 | return -EFAULT; | ||
536 | |||
537 | if (unlikely(ts.tv_nsec < 0 || ts.tv_sec < 0 | ||
538 | || ts.tv_nsec >= NSEC_PER_SEC)) | ||
539 | return -EINVAL; | 535 | return -EINVAL; |
540 | nowts = CURRENT_TIME; | 536 | nowts = CURRENT_TIME; |
541 | /* first subtract as jiffies can't be too big */ | 537 | /* first subtract as jiffies can't be too big */ |
542 | ts.tv_sec -= nowts.tv_sec; | 538 | p->tv_sec -= nowts.tv_sec; |
543 | if (ts.tv_nsec < nowts.tv_nsec) { | 539 | if (p->tv_nsec < nowts.tv_nsec) { |
544 | ts.tv_nsec += NSEC_PER_SEC; | 540 | p->tv_nsec += NSEC_PER_SEC; |
545 | ts.tv_sec--; | 541 | p->tv_sec--; |
546 | } | 542 | } |
547 | ts.tv_nsec -= nowts.tv_nsec; | 543 | p->tv_nsec -= nowts.tv_nsec; |
548 | if (ts.tv_sec < 0) | 544 | if (p->tv_sec < 0) |
549 | return 0; | 545 | return 0; |
550 | 546 | ||
551 | timeout = timespec_to_jiffies(&ts) + 1; | 547 | timeout = timespec_to_jiffies(p) + 1; |
552 | } else | 548 | } else |
553 | return MAX_SCHEDULE_TIMEOUT; | 549 | return MAX_SCHEDULE_TIMEOUT; |
554 | 550 | ||
@@ -592,22 +588,18 @@ static int mq_attr_ok(struct mq_attr *attr) | |||
592 | * Invoked when creating a new queue via sys_mq_open | 588 | * Invoked when creating a new queue via sys_mq_open |
593 | */ | 589 | */ |
594 | static struct file *do_create(struct dentry *dir, struct dentry *dentry, | 590 | static struct file *do_create(struct dentry *dir, struct dentry *dentry, |
595 | int oflag, mode_t mode, struct mq_attr __user *u_attr) | 591 | int oflag, mode_t mode, struct mq_attr *attr) |
596 | { | 592 | { |
597 | const struct cred *cred = current_cred(); | 593 | const struct cred *cred = current_cred(); |
598 | struct mq_attr attr; | ||
599 | struct file *result; | 594 | struct file *result; |
600 | int ret; | 595 | int ret; |
601 | 596 | ||
602 | if (u_attr) { | 597 | if (attr) { |
603 | ret = -EFAULT; | ||
604 | if (copy_from_user(&attr, u_attr, sizeof(attr))) | ||
605 | goto out; | ||
606 | ret = -EINVAL; | 598 | ret = -EINVAL; |
607 | if (!mq_attr_ok(&attr)) | 599 | if (!mq_attr_ok(attr)) |
608 | goto out; | 600 | goto out; |
609 | /* store for use during create */ | 601 | /* store for use during create */ |
610 | dentry->d_fsdata = &attr; | 602 | dentry->d_fsdata = attr; |
611 | } | 603 | } |
612 | 604 | ||
613 | mode &= ~current->fs->umask; | 605 | mode &= ~current->fs->umask; |
@@ -658,17 +650,19 @@ static struct file *do_open(struct dentry *dentry, int oflag) | |||
658 | return dentry_open(dentry, mqueue_mnt, oflag, cred); | 650 | return dentry_open(dentry, mqueue_mnt, oflag, cred); |
659 | } | 651 | } |
660 | 652 | ||
661 | asmlinkage long sys_mq_open(const char __user *u_name, int oflag, mode_t mode, | 653 | SYSCALL_DEFINE4(mq_open, const char __user *, u_name, int, oflag, mode_t, mode, |
662 | struct mq_attr __user *u_attr) | 654 | struct mq_attr __user *, u_attr) |
663 | { | 655 | { |
664 | struct dentry *dentry; | 656 | struct dentry *dentry; |
665 | struct file *filp; | 657 | struct file *filp; |
666 | char *name; | 658 | char *name; |
659 | struct mq_attr attr; | ||
667 | int fd, error; | 660 | int fd, error; |
668 | 661 | ||
669 | error = audit_mq_open(oflag, mode, u_attr); | 662 | if (u_attr && copy_from_user(&attr, u_attr, sizeof(struct mq_attr))) |
670 | if (error != 0) | 663 | return -EFAULT; |
671 | return error; | 664 | |
665 | audit_mq_open(oflag, mode, u_attr ? &attr : NULL); | ||
672 | 666 | ||
673 | if (IS_ERR(name = getname(u_name))) | 667 | if (IS_ERR(name = getname(u_name))) |
674 | return PTR_ERR(name); | 668 | return PTR_ERR(name); |
@@ -694,7 +688,8 @@ asmlinkage long sys_mq_open(const char __user *u_name, int oflag, mode_t mode, | |||
694 | filp = do_open(dentry, oflag); | 688 | filp = do_open(dentry, oflag); |
695 | } else { | 689 | } else { |
696 | filp = do_create(mqueue_mnt->mnt_root, dentry, | 690 | filp = do_create(mqueue_mnt->mnt_root, dentry, |
697 | oflag, mode, u_attr); | 691 | oflag, mode, |
692 | u_attr ? &attr : NULL); | ||
698 | } | 693 | } |
699 | } else { | 694 | } else { |
700 | error = -ENOENT; | 695 | error = -ENOENT; |
@@ -726,7 +721,7 @@ out_putname: | |||
726 | return fd; | 721 | return fd; |
727 | } | 722 | } |
728 | 723 | ||
729 | asmlinkage long sys_mq_unlink(const char __user *u_name) | 724 | SYSCALL_DEFINE1(mq_unlink, const char __user *, u_name) |
730 | { | 725 | { |
731 | int err; | 726 | int err; |
732 | char *name; | 727 | char *name; |
@@ -819,9 +814,9 @@ static inline void pipelined_receive(struct mqueue_inode_info *info) | |||
819 | sender->state = STATE_READY; | 814 | sender->state = STATE_READY; |
820 | } | 815 | } |
821 | 816 | ||
822 | asmlinkage long sys_mq_timedsend(mqd_t mqdes, const char __user *u_msg_ptr, | 817 | SYSCALL_DEFINE5(mq_timedsend, mqd_t, mqdes, const char __user *, u_msg_ptr, |
823 | size_t msg_len, unsigned int msg_prio, | 818 | size_t, msg_len, unsigned int, msg_prio, |
824 | const struct timespec __user *u_abs_timeout) | 819 | const struct timespec __user *, u_abs_timeout) |
825 | { | 820 | { |
826 | struct file *filp; | 821 | struct file *filp; |
827 | struct inode *inode; | 822 | struct inode *inode; |
@@ -829,17 +824,22 @@ asmlinkage long sys_mq_timedsend(mqd_t mqdes, const char __user *u_msg_ptr, | |||
829 | struct ext_wait_queue *receiver; | 824 | struct ext_wait_queue *receiver; |
830 | struct msg_msg *msg_ptr; | 825 | struct msg_msg *msg_ptr; |
831 | struct mqueue_inode_info *info; | 826 | struct mqueue_inode_info *info; |
827 | struct timespec ts, *p = NULL; | ||
832 | long timeout; | 828 | long timeout; |
833 | int ret; | 829 | int ret; |
834 | 830 | ||
835 | ret = audit_mq_timedsend(mqdes, msg_len, msg_prio, u_abs_timeout); | 831 | if (u_abs_timeout) { |
836 | if (ret != 0) | 832 | if (copy_from_user(&ts, u_abs_timeout, |
837 | return ret; | 833 | sizeof(struct timespec))) |
834 | return -EFAULT; | ||
835 | p = &ts; | ||
836 | } | ||
838 | 837 | ||
839 | if (unlikely(msg_prio >= (unsigned long) MQ_PRIO_MAX)) | 838 | if (unlikely(msg_prio >= (unsigned long) MQ_PRIO_MAX)) |
840 | return -EINVAL; | 839 | return -EINVAL; |
841 | 840 | ||
842 | timeout = prepare_timeout(u_abs_timeout); | 841 | audit_mq_sendrecv(mqdes, msg_len, msg_prio, p); |
842 | timeout = prepare_timeout(p); | ||
843 | 843 | ||
844 | ret = -EBADF; | 844 | ret = -EBADF; |
845 | filp = fget(mqdes); | 845 | filp = fget(mqdes); |
@@ -907,9 +907,9 @@ out: | |||
907 | return ret; | 907 | return ret; |
908 | } | 908 | } |
909 | 909 | ||
910 | asmlinkage ssize_t sys_mq_timedreceive(mqd_t mqdes, char __user *u_msg_ptr, | 910 | SYSCALL_DEFINE5(mq_timedreceive, mqd_t, mqdes, char __user *, u_msg_ptr, |
911 | size_t msg_len, unsigned int __user *u_msg_prio, | 911 | size_t, msg_len, unsigned int __user *, u_msg_prio, |
912 | const struct timespec __user *u_abs_timeout) | 912 | const struct timespec __user *, u_abs_timeout) |
913 | { | 913 | { |
914 | long timeout; | 914 | long timeout; |
915 | ssize_t ret; | 915 | ssize_t ret; |
@@ -918,12 +918,17 @@ asmlinkage ssize_t sys_mq_timedreceive(mqd_t mqdes, char __user *u_msg_ptr, | |||
918 | struct inode *inode; | 918 | struct inode *inode; |
919 | struct mqueue_inode_info *info; | 919 | struct mqueue_inode_info *info; |
920 | struct ext_wait_queue wait; | 920 | struct ext_wait_queue wait; |
921 | struct timespec ts, *p = NULL; | ||
921 | 922 | ||
922 | ret = audit_mq_timedreceive(mqdes, msg_len, u_msg_prio, u_abs_timeout); | 923 | if (u_abs_timeout) { |
923 | if (ret != 0) | 924 | if (copy_from_user(&ts, u_abs_timeout, |
924 | return ret; | 925 | sizeof(struct timespec))) |
926 | return -EFAULT; | ||
927 | p = &ts; | ||
928 | } | ||
925 | 929 | ||
926 | timeout = prepare_timeout(u_abs_timeout); | 930 | audit_mq_sendrecv(mqdes, msg_len, 0, p); |
931 | timeout = prepare_timeout(p); | ||
927 | 932 | ||
928 | ret = -EBADF; | 933 | ret = -EBADF; |
929 | filp = fget(mqdes); | 934 | filp = fget(mqdes); |
@@ -992,8 +997,8 @@ out: | |||
992 | * and he isn't currently owner of notification, will be silently discarded. | 997 | * and he isn't currently owner of notification, will be silently discarded. |
993 | * It isn't explicitly defined in the POSIX. | 998 | * It isn't explicitly defined in the POSIX. |
994 | */ | 999 | */ |
995 | asmlinkage long sys_mq_notify(mqd_t mqdes, | 1000 | SYSCALL_DEFINE2(mq_notify, mqd_t, mqdes, |
996 | const struct sigevent __user *u_notification) | 1001 | const struct sigevent __user *, u_notification) |
997 | { | 1002 | { |
998 | int ret; | 1003 | int ret; |
999 | struct file *filp; | 1004 | struct file *filp; |
@@ -1003,17 +1008,17 @@ asmlinkage long sys_mq_notify(mqd_t mqdes, | |||
1003 | struct mqueue_inode_info *info; | 1008 | struct mqueue_inode_info *info; |
1004 | struct sk_buff *nc; | 1009 | struct sk_buff *nc; |
1005 | 1010 | ||
1006 | ret = audit_mq_notify(mqdes, u_notification); | 1011 | if (u_notification) { |
1007 | if (ret != 0) | ||
1008 | return ret; | ||
1009 | |||
1010 | nc = NULL; | ||
1011 | sock = NULL; | ||
1012 | if (u_notification != NULL) { | ||
1013 | if (copy_from_user(¬ification, u_notification, | 1012 | if (copy_from_user(¬ification, u_notification, |
1014 | sizeof(struct sigevent))) | 1013 | sizeof(struct sigevent))) |
1015 | return -EFAULT; | 1014 | return -EFAULT; |
1015 | } | ||
1016 | 1016 | ||
1017 | audit_mq_notify(mqdes, u_notification ? ¬ification : NULL); | ||
1018 | |||
1019 | nc = NULL; | ||
1020 | sock = NULL; | ||
1021 | if (u_notification != NULL) { | ||
1017 | if (unlikely(notification.sigev_notify != SIGEV_NONE && | 1022 | if (unlikely(notification.sigev_notify != SIGEV_NONE && |
1018 | notification.sigev_notify != SIGEV_SIGNAL && | 1023 | notification.sigev_notify != SIGEV_SIGNAL && |
1019 | notification.sigev_notify != SIGEV_THREAD)) | 1024 | notification.sigev_notify != SIGEV_THREAD)) |
@@ -1118,9 +1123,9 @@ out: | |||
1118 | return ret; | 1123 | return ret; |
1119 | } | 1124 | } |
1120 | 1125 | ||
1121 | asmlinkage long sys_mq_getsetattr(mqd_t mqdes, | 1126 | SYSCALL_DEFINE3(mq_getsetattr, mqd_t, mqdes, |
1122 | const struct mq_attr __user *u_mqstat, | 1127 | const struct mq_attr __user *, u_mqstat, |
1123 | struct mq_attr __user *u_omqstat) | 1128 | struct mq_attr __user *, u_omqstat) |
1124 | { | 1129 | { |
1125 | int ret; | 1130 | int ret; |
1126 | struct mq_attr mqstat, omqstat; | 1131 | struct mq_attr mqstat, omqstat; |
@@ -1150,11 +1155,7 @@ asmlinkage long sys_mq_getsetattr(mqd_t mqdes, | |||
1150 | omqstat = info->attr; | 1155 | omqstat = info->attr; |
1151 | omqstat.mq_flags = filp->f_flags & O_NONBLOCK; | 1156 | omqstat.mq_flags = filp->f_flags & O_NONBLOCK; |
1152 | if (u_mqstat) { | 1157 | if (u_mqstat) { |
1153 | ret = audit_mq_getsetattr(mqdes, &mqstat); | 1158 | audit_mq_getsetattr(mqdes, &mqstat); |
1154 | if (ret != 0) { | ||
1155 | spin_unlock(&info->lock); | ||
1156 | goto out_fput; | ||
1157 | } | ||
1158 | if (mqstat.mq_flags & O_NONBLOCK) | 1159 | if (mqstat.mq_flags & O_NONBLOCK) |
1159 | filp->f_flags |= O_NONBLOCK; | 1160 | filp->f_flags |= O_NONBLOCK; |
1160 | else | 1161 | else |
@@ -309,7 +309,7 @@ static inline int msg_security(struct kern_ipc_perm *ipcp, int msgflg) | |||
309 | return security_msg_queue_associate(msq, msgflg); | 309 | return security_msg_queue_associate(msq, msgflg); |
310 | } | 310 | } |
311 | 311 | ||
312 | asmlinkage long sys_msgget(key_t key, int msgflg) | 312 | SYSCALL_DEFINE2(msgget, key_t, key, int, msgflg) |
313 | { | 313 | { |
314 | struct ipc_namespace *ns; | 314 | struct ipc_namespace *ns; |
315 | struct ipc_ops msg_ops; | 315 | struct ipc_ops msg_ops; |
@@ -466,7 +466,7 @@ out_up: | |||
466 | return err; | 466 | return err; |
467 | } | 467 | } |
468 | 468 | ||
469 | asmlinkage long sys_msgctl(int msqid, int cmd, struct msqid_ds __user *buf) | 469 | SYSCALL_DEFINE3(msgctl, int, msqid, int, cmd, struct msqid_ds __user *, buf) |
470 | { | 470 | { |
471 | struct msg_queue *msq; | 471 | struct msg_queue *msq; |
472 | int err, version; | 472 | int err, version; |
@@ -723,8 +723,8 @@ out_free: | |||
723 | return err; | 723 | return err; |
724 | } | 724 | } |
725 | 725 | ||
726 | asmlinkage long | 726 | SYSCALL_DEFINE4(msgsnd, int, msqid, struct msgbuf __user *, msgp, size_t, msgsz, |
727 | sys_msgsnd(int msqid, struct msgbuf __user *msgp, size_t msgsz, int msgflg) | 727 | int, msgflg) |
728 | { | 728 | { |
729 | long mtype; | 729 | long mtype; |
730 | 730 | ||
@@ -904,8 +904,8 @@ out_unlock: | |||
904 | return msgsz; | 904 | return msgsz; |
905 | } | 905 | } |
906 | 906 | ||
907 | asmlinkage long sys_msgrcv(int msqid, struct msgbuf __user *msgp, size_t msgsz, | 907 | SYSCALL_DEFINE5(msgrcv, int, msqid, struct msgbuf __user *, msgp, size_t, msgsz, |
908 | long msgtyp, int msgflg) | 908 | long, msgtyp, int, msgflg) |
909 | { | 909 | { |
910 | long err, mtype; | 910 | long err, mtype; |
911 | 911 | ||
@@ -58,7 +58,7 @@ | |||
58 | * SMP-threaded, sysctl's added | 58 | * SMP-threaded, sysctl's added |
59 | * (c) 1999 Manfred Spraul <manfred@colorfullife.com> | 59 | * (c) 1999 Manfred Spraul <manfred@colorfullife.com> |
60 | * Enforced range limit on SEM_UNDO | 60 | * Enforced range limit on SEM_UNDO |
61 | * (c) 2001 Red Hat Inc <alan@redhat.com> | 61 | * (c) 2001 Red Hat Inc |
62 | * Lockless wakeup | 62 | * Lockless wakeup |
63 | * (c) 2003 Manfred Spraul <manfred@colorfullife.com> | 63 | * (c) 2003 Manfred Spraul <manfred@colorfullife.com> |
64 | * | 64 | * |
@@ -308,7 +308,7 @@ static inline int sem_more_checks(struct kern_ipc_perm *ipcp, | |||
308 | return 0; | 308 | return 0; |
309 | } | 309 | } |
310 | 310 | ||
311 | asmlinkage long sys_semget(key_t key, int nsems, int semflg) | 311 | SYSCALL_DEFINE3(semget, key_t, key, int, nsems, int, semflg) |
312 | { | 312 | { |
313 | struct ipc_namespace *ns; | 313 | struct ipc_namespace *ns; |
314 | struct ipc_ops sem_ops; | 314 | struct ipc_ops sem_ops; |
@@ -887,7 +887,7 @@ out_up: | |||
887 | return err; | 887 | return err; |
888 | } | 888 | } |
889 | 889 | ||
890 | asmlinkage long sys_semctl (int semid, int semnum, int cmd, union semun arg) | 890 | SYSCALL_DEFINE(semctl)(int semid, int semnum, int cmd, union semun arg) |
891 | { | 891 | { |
892 | int err = -EINVAL; | 892 | int err = -EINVAL; |
893 | int version; | 893 | int version; |
@@ -923,6 +923,13 @@ asmlinkage long sys_semctl (int semid, int semnum, int cmd, union semun arg) | |||
923 | return -EINVAL; | 923 | return -EINVAL; |
924 | } | 924 | } |
925 | } | 925 | } |
926 | #ifdef CONFIG_HAVE_SYSCALL_WRAPPERS | ||
927 | asmlinkage long SyS_semctl(int semid, int semnum, int cmd, union semun arg) | ||
928 | { | ||
929 | return SYSC_semctl((int) semid, (int) semnum, (int) cmd, arg); | ||
930 | } | ||
931 | SYSCALL_ALIAS(sys_semctl, SyS_semctl); | ||
932 | #endif | ||
926 | 933 | ||
927 | /* If the task doesn't already have a undo_list, then allocate one | 934 | /* If the task doesn't already have a undo_list, then allocate one |
928 | * here. We guarantee there is only one thread using this undo list, | 935 | * here. We guarantee there is only one thread using this undo list, |
@@ -1048,8 +1055,8 @@ out: | |||
1048 | return un; | 1055 | return un; |
1049 | } | 1056 | } |
1050 | 1057 | ||
1051 | asmlinkage long sys_semtimedop(int semid, struct sembuf __user *tsops, | 1058 | SYSCALL_DEFINE4(semtimedop, int, semid, struct sembuf __user *, tsops, |
1052 | unsigned nsops, const struct timespec __user *timeout) | 1059 | unsigned, nsops, const struct timespec __user *, timeout) |
1053 | { | 1060 | { |
1054 | int error = -EINVAL; | 1061 | int error = -EINVAL; |
1055 | struct sem_array *sma; | 1062 | struct sem_array *sma; |
@@ -1216,7 +1223,6 @@ asmlinkage long sys_semtimedop(int semid, struct sembuf __user *tsops, | |||
1216 | if (timeout && jiffies_left == 0) | 1223 | if (timeout && jiffies_left == 0) |
1217 | error = -EAGAIN; | 1224 | error = -EAGAIN; |
1218 | list_del(&queue.list); | 1225 | list_del(&queue.list); |
1219 | goto out_unlock_free; | ||
1220 | 1226 | ||
1221 | out_unlock_free: | 1227 | out_unlock_free: |
1222 | sem_unlock(sma); | 1228 | sem_unlock(sma); |
@@ -1226,7 +1232,8 @@ out_free: | |||
1226 | return error; | 1232 | return error; |
1227 | } | 1233 | } |
1228 | 1234 | ||
1229 | asmlinkage long sys_semop (int semid, struct sembuf __user *tsops, unsigned nsops) | 1235 | SYSCALL_DEFINE3(semop, int, semid, struct sembuf __user *, tsops, |
1236 | unsigned, nsops) | ||
1230 | { | 1237 | { |
1231 | return sys_semtimedop(semid, tsops, nsops, NULL); | 1238 | return sys_semtimedop(semid, tsops, nsops, NULL); |
1232 | } | 1239 | } |
@@ -76,7 +76,7 @@ void shm_init_ns(struct ipc_namespace *ns) | |||
76 | ns->shm_ctlall = SHMALL; | 76 | ns->shm_ctlall = SHMALL; |
77 | ns->shm_ctlmni = SHMMNI; | 77 | ns->shm_ctlmni = SHMMNI; |
78 | ns->shm_tot = 0; | 78 | ns->shm_tot = 0; |
79 | ipc_init_ids(&ns->ids[IPC_SHM_IDS]); | 79 | ipc_init_ids(&shm_ids(ns)); |
80 | } | 80 | } |
81 | 81 | ||
82 | /* | 82 | /* |
@@ -369,14 +369,14 @@ static int newseg(struct ipc_namespace *ns, struct ipc_params *params) | |||
369 | file = hugetlb_file_setup(name, size); | 369 | file = hugetlb_file_setup(name, size); |
370 | shp->mlock_user = current_user(); | 370 | shp->mlock_user = current_user(); |
371 | } else { | 371 | } else { |
372 | int acctflag = VM_ACCOUNT; | 372 | int acctflag = 0; |
373 | /* | 373 | /* |
374 | * Do not allow no accounting for OVERCOMMIT_NEVER, even | 374 | * Do not allow no accounting for OVERCOMMIT_NEVER, even |
375 | * if it's asked for. | 375 | * if it's asked for. |
376 | */ | 376 | */ |
377 | if ((shmflg & SHM_NORESERVE) && | 377 | if ((shmflg & SHM_NORESERVE) && |
378 | sysctl_overcommit_memory != OVERCOMMIT_NEVER) | 378 | sysctl_overcommit_memory != OVERCOMMIT_NEVER) |
379 | acctflag = 0; | 379 | acctflag = VM_NORESERVE; |
380 | file = shmem_file_setup(name, size, acctflag); | 380 | file = shmem_file_setup(name, size, acctflag); |
381 | } | 381 | } |
382 | error = PTR_ERR(file); | 382 | error = PTR_ERR(file); |
@@ -442,7 +442,7 @@ static inline int shm_more_checks(struct kern_ipc_perm *ipcp, | |||
442 | return 0; | 442 | return 0; |
443 | } | 443 | } |
444 | 444 | ||
445 | asmlinkage long sys_shmget (key_t key, size_t size, int shmflg) | 445 | SYSCALL_DEFINE3(shmget, key_t, key, size_t, size, int, shmflg) |
446 | { | 446 | { |
447 | struct ipc_namespace *ns; | 447 | struct ipc_namespace *ns; |
448 | struct ipc_ops shm_ops; | 448 | struct ipc_ops shm_ops; |
@@ -567,11 +567,15 @@ static void shm_get_stat(struct ipc_namespace *ns, unsigned long *rss, | |||
567 | struct hstate *h = hstate_file(shp->shm_file); | 567 | struct hstate *h = hstate_file(shp->shm_file); |
568 | *rss += pages_per_huge_page(h) * mapping->nrpages; | 568 | *rss += pages_per_huge_page(h) * mapping->nrpages; |
569 | } else { | 569 | } else { |
570 | #ifdef CONFIG_SHMEM | ||
570 | struct shmem_inode_info *info = SHMEM_I(inode); | 571 | struct shmem_inode_info *info = SHMEM_I(inode); |
571 | spin_lock(&info->lock); | 572 | spin_lock(&info->lock); |
572 | *rss += inode->i_mapping->nrpages; | 573 | *rss += inode->i_mapping->nrpages; |
573 | *swp += info->swapped; | 574 | *swp += info->swapped; |
574 | spin_unlock(&info->lock); | 575 | spin_unlock(&info->lock); |
576 | #else | ||
577 | *rss += inode->i_mapping->nrpages; | ||
578 | #endif | ||
575 | } | 579 | } |
576 | 580 | ||
577 | total++; | 581 | total++; |
@@ -623,7 +627,7 @@ out_up: | |||
623 | return err; | 627 | return err; |
624 | } | 628 | } |
625 | 629 | ||
626 | asmlinkage long sys_shmctl(int shmid, int cmd, struct shmid_ds __user *buf) | 630 | SYSCALL_DEFINE3(shmctl, int, shmid, int, cmd, struct shmid_ds __user *, buf) |
627 | { | 631 | { |
628 | struct shmid_kernel *shp; | 632 | struct shmid_kernel *shp; |
629 | int err, version; | 633 | int err, version; |
@@ -646,7 +650,7 @@ asmlinkage long sys_shmctl(int shmid, int cmd, struct shmid_ds __user *buf) | |||
646 | if (err) | 650 | if (err) |
647 | return err; | 651 | return err; |
648 | 652 | ||
649 | memset(&shminfo,0,sizeof(shminfo)); | 653 | memset(&shminfo, 0, sizeof(shminfo)); |
650 | shminfo.shmmni = shminfo.shmseg = ns->shm_ctlmni; | 654 | shminfo.shmmni = shminfo.shmseg = ns->shm_ctlmni; |
651 | shminfo.shmmax = ns->shm_ctlmax; | 655 | shminfo.shmmax = ns->shm_ctlmax; |
652 | shminfo.shmall = ns->shm_ctlall; | 656 | shminfo.shmall = ns->shm_ctlall; |
@@ -671,7 +675,7 @@ asmlinkage long sys_shmctl(int shmid, int cmd, struct shmid_ds __user *buf) | |||
671 | if (err) | 675 | if (err) |
672 | return err; | 676 | return err; |
673 | 677 | ||
674 | memset(&shm_info,0,sizeof(shm_info)); | 678 | memset(&shm_info, 0, sizeof(shm_info)); |
675 | down_read(&shm_ids(ns).rw_mutex); | 679 | down_read(&shm_ids(ns).rw_mutex); |
676 | shm_info.used_ids = shm_ids(ns).in_use; | 680 | shm_info.used_ids = shm_ids(ns).in_use; |
677 | shm_get_stat (ns, &shm_info.shm_rss, &shm_info.shm_swp); | 681 | shm_get_stat (ns, &shm_info.shm_rss, &shm_info.shm_swp); |
@@ -680,7 +684,7 @@ asmlinkage long sys_shmctl(int shmid, int cmd, struct shmid_ds __user *buf) | |||
680 | shm_info.swap_successes = 0; | 684 | shm_info.swap_successes = 0; |
681 | err = ipc_get_maxid(&shm_ids(ns)); | 685 | err = ipc_get_maxid(&shm_ids(ns)); |
682 | up_read(&shm_ids(ns).rw_mutex); | 686 | up_read(&shm_ids(ns).rw_mutex); |
683 | if(copy_to_user (buf, &shm_info, sizeof(shm_info))) { | 687 | if (copy_to_user(buf, &shm_info, sizeof(shm_info))) { |
684 | err = -EFAULT; | 688 | err = -EFAULT; |
685 | goto out; | 689 | goto out; |
686 | } | 690 | } |
@@ -694,11 +698,6 @@ asmlinkage long sys_shmctl(int shmid, int cmd, struct shmid_ds __user *buf) | |||
694 | struct shmid64_ds tbuf; | 698 | struct shmid64_ds tbuf; |
695 | int result; | 699 | int result; |
696 | 700 | ||
697 | if (!buf) { | ||
698 | err = -EFAULT; | ||
699 | goto out; | ||
700 | } | ||
701 | |||
702 | if (cmd == SHM_STAT) { | 701 | if (cmd == SHM_STAT) { |
703 | shp = shm_lock(ns, shmid); | 702 | shp = shm_lock(ns, shmid); |
704 | if (IS_ERR(shp)) { | 703 | if (IS_ERR(shp)) { |
@@ -714,7 +713,7 @@ asmlinkage long sys_shmctl(int shmid, int cmd, struct shmid_ds __user *buf) | |||
714 | } | 713 | } |
715 | result = 0; | 714 | result = 0; |
716 | } | 715 | } |
717 | err=-EACCES; | 716 | err = -EACCES; |
718 | if (ipcperms (&shp->shm_perm, S_IRUGO)) | 717 | if (ipcperms (&shp->shm_perm, S_IRUGO)) |
719 | goto out_unlock; | 718 | goto out_unlock; |
720 | err = security_shm_shmctl(shp, cmd); | 719 | err = security_shm_shmctl(shp, cmd); |
@@ -749,9 +748,7 @@ asmlinkage long sys_shmctl(int shmid, int cmd, struct shmid_ds __user *buf) | |||
749 | goto out; | 748 | goto out; |
750 | } | 749 | } |
751 | 750 | ||
752 | err = audit_ipc_obj(&(shp->shm_perm)); | 751 | audit_ipc_obj(&(shp->shm_perm)); |
753 | if (err) | ||
754 | goto out_unlock; | ||
755 | 752 | ||
756 | if (!capable(CAP_IPC_LOCK)) { | 753 | if (!capable(CAP_IPC_LOCK)) { |
757 | uid_t euid = current_euid(); | 754 | uid_t euid = current_euid(); |
@@ -949,7 +946,7 @@ out_put_dentry: | |||
949 | goto out_nattch; | 946 | goto out_nattch; |
950 | } | 947 | } |
951 | 948 | ||
952 | asmlinkage long sys_shmat(int shmid, char __user *shmaddr, int shmflg) | 949 | SYSCALL_DEFINE3(shmat, int, shmid, char __user *, shmaddr, int, shmflg) |
953 | { | 950 | { |
954 | unsigned long ret; | 951 | unsigned long ret; |
955 | long err; | 952 | long err; |
@@ -965,7 +962,7 @@ asmlinkage long sys_shmat(int shmid, char __user *shmaddr, int shmflg) | |||
965 | * detach and kill segment if marked destroyed. | 962 | * detach and kill segment if marked destroyed. |
966 | * The work is done in shm_close. | 963 | * The work is done in shm_close. |
967 | */ | 964 | */ |
968 | asmlinkage long sys_shmdt(char __user *shmaddr) | 965 | SYSCALL_DEFINE1(shmdt, char __user *, shmaddr) |
969 | { | 966 | { |
970 | struct mm_struct *mm = current->mm; | 967 | struct mm_struct *mm = current->mm; |
971 | struct vm_area_struct *vma, *next; | 968 | struct vm_area_struct *vma, *next; |
@@ -1000,6 +997,7 @@ asmlinkage long sys_shmdt(char __user *shmaddr) | |||
1000 | */ | 997 | */ |
1001 | vma = find_vma(mm, addr); | 998 | vma = find_vma(mm, addr); |
1002 | 999 | ||
1000 | #ifdef CONFIG_MMU | ||
1003 | while (vma) { | 1001 | while (vma) { |
1004 | next = vma->vm_next; | 1002 | next = vma->vm_next; |
1005 | 1003 | ||
@@ -1044,6 +1042,17 @@ asmlinkage long sys_shmdt(char __user *shmaddr) | |||
1044 | vma = next; | 1042 | vma = next; |
1045 | } | 1043 | } |
1046 | 1044 | ||
1045 | #else /* CONFIG_MMU */ | ||
1046 | /* under NOMMU conditions, the exact address to be destroyed must be | ||
1047 | * given */ | ||
1048 | retval = -EINVAL; | ||
1049 | if (vma->vm_start == addr && vma->vm_ops == &shm_vm_ops) { | ||
1050 | do_munmap(mm, vma->vm_start, vma->vm_end - vma->vm_start); | ||
1051 | retval = 0; | ||
1052 | } | ||
1053 | |||
1054 | #endif | ||
1055 | |||
1047 | up_write(&mm->mmap_sem); | 1056 | up_write(&mm->mmap_sem); |
1048 | return retval; | 1057 | return retval; |
1049 | } | 1058 | } |
diff --git a/ipc/util.c b/ipc/util.c index 5a1808c774a2..7585a72e259b 100644 --- a/ipc/util.c +++ b/ipc/util.c | |||
@@ -624,10 +624,9 @@ void ipc_rcu_putref(void *ptr) | |||
624 | int ipcperms (struct kern_ipc_perm *ipcp, short flag) | 624 | int ipcperms (struct kern_ipc_perm *ipcp, short flag) |
625 | { /* flag will most probably be 0 or S_...UGO from <linux/stat.h> */ | 625 | { /* flag will most probably be 0 or S_...UGO from <linux/stat.h> */ |
626 | uid_t euid = current_euid(); | 626 | uid_t euid = current_euid(); |
627 | int requested_mode, granted_mode, err; | 627 | int requested_mode, granted_mode; |
628 | 628 | ||
629 | if (unlikely((err = audit_ipc_obj(ipcp)))) | 629 | audit_ipc_obj(ipcp); |
630 | return err; | ||
631 | requested_mode = (flag >> 6) | (flag >> 3) | flag; | 630 | requested_mode = (flag >> 6) | (flag >> 3) | flag; |
632 | granted_mode = ipcp->mode; | 631 | granted_mode = ipcp->mode; |
633 | if (euid == ipcp->cuid || | 632 | if (euid == ipcp->cuid || |
@@ -803,16 +802,10 @@ struct kern_ipc_perm *ipcctl_pre_down(struct ipc_ids *ids, int id, int cmd, | |||
803 | goto out_up; | 802 | goto out_up; |
804 | } | 803 | } |
805 | 804 | ||
806 | err = audit_ipc_obj(ipcp); | 805 | audit_ipc_obj(ipcp); |
807 | if (err) | 806 | if (cmd == IPC_SET) |
808 | goto out_unlock; | 807 | audit_ipc_set_perm(extra_perm, perm->uid, |
809 | |||
810 | if (cmd == IPC_SET) { | ||
811 | err = audit_ipc_set_perm(extra_perm, perm->uid, | ||
812 | perm->gid, perm->mode); | 808 | perm->gid, perm->mode); |
813 | if (err) | ||
814 | goto out_unlock; | ||
815 | } | ||
816 | 809 | ||
817 | euid = current_euid(); | 810 | euid = current_euid(); |
818 | if (euid == ipcp->cuid || | 811 | if (euid == ipcp->cuid || |
@@ -820,7 +813,6 @@ struct kern_ipc_perm *ipcctl_pre_down(struct ipc_ids *ids, int id, int cmd, | |||
820 | return ipcp; | 813 | return ipcp; |
821 | 814 | ||
822 | err = -EPERM; | 815 | err = -EPERM; |
823 | out_unlock: | ||
824 | ipc_unlock(ipcp); | 816 | ipc_unlock(ipcp); |
825 | out_up: | 817 | out_up: |
826 | up_write(&ids->rw_mutex); | 818 | up_write(&ids->rw_mutex); |