aboutsummaryrefslogtreecommitdiffstats
path: root/ipc
diff options
context:
space:
mode:
authorIngo Molnar <mingo@elte.hu>2009-01-18 12:37:14 -0500
committerIngo Molnar <mingo@elte.hu>2009-01-18 12:37:14 -0500
commitb2b062b8163391c42b3219d466ca1ac9742b9c7b (patch)
treef3f920c09b8de694b1bc1d4b878cfd2b0b98c913 /ipc
parenta9de18eb761f7c1c860964b2e5addc1a35c7e861 (diff)
parent99937d6455cea95405ac681c86a857d0fcd530bd (diff)
Merge branch 'core/percpu' into stackprotector
Conflicts: arch/x86/include/asm/pda.h arch/x86/include/asm/system.h Also, moved include/asm-x86/stackprotector.h to arch/x86/include/asm. Signed-off-by: Ingo Molnar <mingo@elte.hu>
Diffstat (limited to 'ipc')
-rw-r--r--ipc/ipc_sysctl.c46
-rw-r--r--ipc/mqueue.c101
-rw-r--r--ipc/sem.c3
-rw-r--r--ipc/shm.c31
-rw-r--r--ipc/util.c18
5 files changed, 98 insertions, 101 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 */
38static 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
53static int proc_ipc_dointvec(ctl_table *table, int write, struct file *filp, 30static 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 */
83static 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
97static int proc_ipcauto_dointvec_minmax(ctl_table *table, int write, 97static 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..23fdb8492b8e 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
527static long prepare_timeout(const struct timespec __user *u_arg) 527static 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 */
594static struct file *do_create(struct dentry *dir, struct dentry *dentry, 590static 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;
@@ -664,11 +656,13 @@ asmlinkage long sys_mq_open(const char __user *u_name, int oflag, mode_t mode,
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;
@@ -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);
@@ -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);
@@ -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(&notification, u_notification, 1012 if (copy_from_user(&notification, 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 ? &notification : 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))
@@ -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
diff --git a/ipc/sem.c b/ipc/sem.c
index 082122469b17..c68cd3f8f0c9 100644
--- a/ipc/sem.c
+++ b/ipc/sem.c
@@ -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 *
@@ -1216,7 +1216,6 @@ asmlinkage long sys_semtimedop(int semid, struct sembuf __user *tsops,
1216 if (timeout && jiffies_left == 0) 1216 if (timeout && jiffies_left == 0)
1217 error = -EAGAIN; 1217 error = -EAGAIN;
1218 list_del(&queue.list); 1218 list_del(&queue.list);
1219 goto out_unlock_free;
1220 1219
1221out_unlock_free: 1220out_unlock_free:
1222 sem_unlock(sma); 1221 sem_unlock(sma);
diff --git a/ipc/shm.c b/ipc/shm.c
index 38a055758a9b..d0ab5527bf45 100644
--- a/ipc/shm.c
+++ b/ipc/shm.c
@@ -75,7 +75,7 @@ void shm_init_ns(struct ipc_namespace *ns)
75 ns->shm_ctlall = SHMALL; 75 ns->shm_ctlall = SHMALL;
76 ns->shm_ctlmni = SHMMNI; 76 ns->shm_ctlmni = SHMMNI;
77 ns->shm_tot = 0; 77 ns->shm_tot = 0;
78 ipc_init_ids(&ns->ids[IPC_SHM_IDS]); 78 ipc_init_ids(&shm_ids(ns));
79} 79}
80 80
81/* 81/*
@@ -644,7 +644,7 @@ asmlinkage long sys_shmctl(int shmid, int cmd, struct shmid_ds __user *buf)
644 if (err) 644 if (err)
645 return err; 645 return err;
646 646
647 memset(&shminfo,0,sizeof(shminfo)); 647 memset(&shminfo, 0, sizeof(shminfo));
648 shminfo.shmmni = shminfo.shmseg = ns->shm_ctlmni; 648 shminfo.shmmni = shminfo.shmseg = ns->shm_ctlmni;
649 shminfo.shmmax = ns->shm_ctlmax; 649 shminfo.shmmax = ns->shm_ctlmax;
650 shminfo.shmall = ns->shm_ctlall; 650 shminfo.shmall = ns->shm_ctlall;
@@ -669,7 +669,7 @@ asmlinkage long sys_shmctl(int shmid, int cmd, struct shmid_ds __user *buf)
669 if (err) 669 if (err)
670 return err; 670 return err;
671 671
672 memset(&shm_info,0,sizeof(shm_info)); 672 memset(&shm_info, 0, sizeof(shm_info));
673 down_read(&shm_ids(ns).rw_mutex); 673 down_read(&shm_ids(ns).rw_mutex);
674 shm_info.used_ids = shm_ids(ns).in_use; 674 shm_info.used_ids = shm_ids(ns).in_use;
675 shm_get_stat (ns, &shm_info.shm_rss, &shm_info.shm_swp); 675 shm_get_stat (ns, &shm_info.shm_rss, &shm_info.shm_swp);
@@ -678,7 +678,7 @@ asmlinkage long sys_shmctl(int shmid, int cmd, struct shmid_ds __user *buf)
678 shm_info.swap_successes = 0; 678 shm_info.swap_successes = 0;
679 err = ipc_get_maxid(&shm_ids(ns)); 679 err = ipc_get_maxid(&shm_ids(ns));
680 up_read(&shm_ids(ns).rw_mutex); 680 up_read(&shm_ids(ns).rw_mutex);
681 if(copy_to_user (buf, &shm_info, sizeof(shm_info))) { 681 if (copy_to_user(buf, &shm_info, sizeof(shm_info))) {
682 err = -EFAULT; 682 err = -EFAULT;
683 goto out; 683 goto out;
684 } 684 }
@@ -692,11 +692,6 @@ asmlinkage long sys_shmctl(int shmid, int cmd, struct shmid_ds __user *buf)
692 struct shmid64_ds tbuf; 692 struct shmid64_ds tbuf;
693 int result; 693 int result;
694 694
695 if (!buf) {
696 err = -EFAULT;
697 goto out;
698 }
699
700 if (cmd == SHM_STAT) { 695 if (cmd == SHM_STAT) {
701 shp = shm_lock(ns, shmid); 696 shp = shm_lock(ns, shmid);
702 if (IS_ERR(shp)) { 697 if (IS_ERR(shp)) {
@@ -712,7 +707,7 @@ asmlinkage long sys_shmctl(int shmid, int cmd, struct shmid_ds __user *buf)
712 } 707 }
713 result = 0; 708 result = 0;
714 } 709 }
715 err=-EACCES; 710 err = -EACCES;
716 if (ipcperms (&shp->shm_perm, S_IRUGO)) 711 if (ipcperms (&shp->shm_perm, S_IRUGO))
717 goto out_unlock; 712 goto out_unlock;
718 err = security_shm_shmctl(shp, cmd); 713 err = security_shm_shmctl(shp, cmd);
@@ -747,9 +742,7 @@ asmlinkage long sys_shmctl(int shmid, int cmd, struct shmid_ds __user *buf)
747 goto out; 742 goto out;
748 } 743 }
749 744
750 err = audit_ipc_obj(&(shp->shm_perm)); 745 audit_ipc_obj(&(shp->shm_perm));
751 if (err)
752 goto out_unlock;
753 746
754 if (!capable(CAP_IPC_LOCK)) { 747 if (!capable(CAP_IPC_LOCK)) {
755 uid_t euid = current_euid(); 748 uid_t euid = current_euid();
@@ -997,6 +990,7 @@ asmlinkage long sys_shmdt(char __user *shmaddr)
997 */ 990 */
998 vma = find_vma(mm, addr); 991 vma = find_vma(mm, addr);
999 992
993#ifdef CONFIG_MMU
1000 while (vma) { 994 while (vma) {
1001 next = vma->vm_next; 995 next = vma->vm_next;
1002 996
@@ -1041,6 +1035,17 @@ asmlinkage long sys_shmdt(char __user *shmaddr)
1041 vma = next; 1035 vma = next;
1042 } 1036 }
1043 1037
1038#else /* CONFIG_MMU */
1039 /* under NOMMU conditions, the exact address to be destroyed must be
1040 * given */
1041 retval = -EINVAL;
1042 if (vma->vm_start == addr && vma->vm_ops == &shm_vm_ops) {
1043 do_munmap(mm, vma->vm_start, vma->vm_end - vma->vm_start);
1044 retval = 0;
1045 }
1046
1047#endif
1048
1044 up_write(&mm->mmap_sem); 1049 up_write(&mm->mmap_sem);
1045 return retval; 1050 return retval;
1046} 1051}
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)
624int ipcperms (struct kern_ipc_perm *ipcp, short flag) 624int 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;
823out_unlock:
824 ipc_unlock(ipcp); 816 ipc_unlock(ipcp);
825out_up: 817out_up:
826 up_write(&ids->rw_mutex); 818 up_write(&ids->rw_mutex);