aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--ipc/util.c58
1 files changed, 45 insertions, 13 deletions
diff --git a/ipc/util.c b/ipc/util.c
index 0c97cb746160..115e9aac1366 100644
--- a/ipc/util.c
+++ b/ipc/util.c
@@ -738,14 +738,20 @@ int ipc_parse_version (int *cmd)
738#endif /* __ARCH_WANT_IPC_PARSE_VERSION */ 738#endif /* __ARCH_WANT_IPC_PARSE_VERSION */
739 739
740#ifdef CONFIG_PROC_FS 740#ifdef CONFIG_PROC_FS
741struct ipc_proc_iter {
742 struct ipc_namespace *ns;
743 struct ipc_proc_iface *iface;
744};
745
741static void *sysvipc_proc_next(struct seq_file *s, void *it, loff_t *pos) 746static void *sysvipc_proc_next(struct seq_file *s, void *it, loff_t *pos)
742{ 747{
743 struct ipc_proc_iface *iface = s->private; 748 struct ipc_proc_iter *iter = s->private;
749 struct ipc_proc_iface *iface = iter->iface;
744 struct kern_ipc_perm *ipc = it; 750 struct kern_ipc_perm *ipc = it;
745 loff_t p; 751 loff_t p;
746 struct ipc_ids *ids; 752 struct ipc_ids *ids;
747 753
748 ids = current->nsproxy->ipc_ns->ids[iface->ids]; 754 ids = iter->ns->ids[iface->ids];
749 755
750 /* If we had an ipc id locked before, unlock it */ 756 /* If we had an ipc id locked before, unlock it */
751 if (ipc && ipc != SEQ_START_TOKEN) 757 if (ipc && ipc != SEQ_START_TOKEN)
@@ -772,12 +778,13 @@ static void *sysvipc_proc_next(struct seq_file *s, void *it, loff_t *pos)
772 */ 778 */
773static void *sysvipc_proc_start(struct seq_file *s, loff_t *pos) 779static void *sysvipc_proc_start(struct seq_file *s, loff_t *pos)
774{ 780{
775 struct ipc_proc_iface *iface = s->private; 781 struct ipc_proc_iter *iter = s->private;
782 struct ipc_proc_iface *iface = iter->iface;
776 struct kern_ipc_perm *ipc; 783 struct kern_ipc_perm *ipc;
777 loff_t p; 784 loff_t p;
778 struct ipc_ids *ids; 785 struct ipc_ids *ids;
779 786
780 ids = current->nsproxy->ipc_ns->ids[iface->ids]; 787 ids = iter->ns->ids[iface->ids];
781 788
782 /* 789 /*
783 * Take the lock - this will be released by the corresponding 790 * Take the lock - this will be released by the corresponding
@@ -806,21 +813,23 @@ static void *sysvipc_proc_start(struct seq_file *s, loff_t *pos)
806static void sysvipc_proc_stop(struct seq_file *s, void *it) 813static void sysvipc_proc_stop(struct seq_file *s, void *it)
807{ 814{
808 struct kern_ipc_perm *ipc = it; 815 struct kern_ipc_perm *ipc = it;
809 struct ipc_proc_iface *iface = s->private; 816 struct ipc_proc_iter *iter = s->private;
817 struct ipc_proc_iface *iface = iter->iface;
810 struct ipc_ids *ids; 818 struct ipc_ids *ids;
811 819
812 /* If we had a locked segment, release it */ 820 /* If we had a locked segment, release it */
813 if (ipc && ipc != SEQ_START_TOKEN) 821 if (ipc && ipc != SEQ_START_TOKEN)
814 ipc_unlock(ipc); 822 ipc_unlock(ipc);
815 823
816 ids = current->nsproxy->ipc_ns->ids[iface->ids]; 824 ids = iter->ns->ids[iface->ids];
817 /* Release the lock we took in start() */ 825 /* Release the lock we took in start() */
818 mutex_unlock(&ids->mutex); 826 mutex_unlock(&ids->mutex);
819} 827}
820 828
821static int sysvipc_proc_show(struct seq_file *s, void *it) 829static int sysvipc_proc_show(struct seq_file *s, void *it)
822{ 830{
823 struct ipc_proc_iface *iface = s->private; 831 struct ipc_proc_iter *iter = s->private;
832 struct ipc_proc_iface *iface = iter->iface;
824 833
825 if (it == SEQ_START_TOKEN) 834 if (it == SEQ_START_TOKEN)
826 return seq_puts(s, iface->header); 835 return seq_puts(s, iface->header);
@@ -835,22 +844,45 @@ static struct seq_operations sysvipc_proc_seqops = {
835 .show = sysvipc_proc_show, 844 .show = sysvipc_proc_show,
836}; 845};
837 846
838static int sysvipc_proc_open(struct inode *inode, struct file *file) { 847static int sysvipc_proc_open(struct inode *inode, struct file *file)
848{
839 int ret; 849 int ret;
840 struct seq_file *seq; 850 struct seq_file *seq;
851 struct ipc_proc_iter *iter;
852
853 ret = -ENOMEM;
854 iter = kmalloc(sizeof(*iter), GFP_KERNEL);
855 if (!iter)
856 goto out;
841 857
842 ret = seq_open(file, &sysvipc_proc_seqops); 858 ret = seq_open(file, &sysvipc_proc_seqops);
843 if (!ret) { 859 if (ret)
844 seq = file->private_data; 860 goto out_kfree;
845 seq->private = PDE(inode)->data; 861
846 } 862 seq = file->private_data;
863 seq->private = iter;
864
865 iter->iface = PDE(inode)->data;
866 iter->ns = get_ipc_ns(current->nsproxy->ipc_ns);
867out:
847 return ret; 868 return ret;
869out_kfree:
870 kfree(iter);
871 goto out;
872}
873
874static int sysvipc_proc_release(struct inode *inode, struct file *file)
875{
876 struct seq_file *seq = file->private_data;
877 struct ipc_proc_iter *iter = seq->private;
878 put_ipc_ns(iter->ns);
879 return seq_release_private(inode, file);
848} 880}
849 881
850static struct file_operations sysvipc_proc_fops = { 882static struct file_operations sysvipc_proc_fops = {
851 .open = sysvipc_proc_open, 883 .open = sysvipc_proc_open,
852 .read = seq_read, 884 .read = seq_read,
853 .llseek = seq_lseek, 885 .llseek = seq_lseek,
854 .release = seq_release, 886 .release = sysvipc_proc_release,
855}; 887};
856#endif /* CONFIG_PROC_FS */ 888#endif /* CONFIG_PROC_FS */