aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorH Hartley Sweeten <hartleys@visionengravers.com>2012-09-19 20:26:53 -0400
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2012-09-21 12:26:20 -0400
commit1f5cc359158772304a92ee9c5682ca83416d2ba8 (patch)
treef140fca0c865fd86b9f0244e588068daa74838f4
parent94174847ea41b1c2a44d997f2850530fb33f41cd (diff)
staging: comedi: kcomedilib: fix a __user space access issue
The 'data' field in struct comedi_insn is an unsigned int __user *. The comedi core copies this data to kernel space before passing it on to a drivers insn_bits/insn_config method. kcomedilib provides an interface for external kernel modules to use the comedi drivers. This interface creates a comedi_insn that is then passed to the comedi drivers insn_bits/insn_config method. Unfortunately, kcomedilib is using the comedi_insn 'data' field directly which results in some sparse warnings: warning: incorrect type in argument 4 (different address spaces) expected unsigned int *<noident> got unsigned int [noderef] <asn:1>*data warning: incorrect type in assignment (different address spaces) expected unsigned int [noderef] <asn:1>*[addressable] [assigned] data got unsigned int *<noident> Fix this by passing the kernel data directly, as a separate parameter, instead of trying to put in into the comedi_insn 'data' field. This is how the comedi core handles the data from user space. Signed-off-by: H Hartley Sweeten <hsweeten@visionengravers.com> Cc: Ian Abbott <abbotti@mev.co.uk> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-rw-r--r--drivers/staging/comedi/kcomedilib/kcomedilib_main.c14
1 files changed, 7 insertions, 7 deletions
diff --git a/drivers/staging/comedi/kcomedilib/kcomedilib_main.c b/drivers/staging/comedi/kcomedilib/kcomedilib_main.c
index f96416d1d2f7..3f20ea55b8d0 100644
--- a/drivers/staging/comedi/kcomedilib/kcomedilib_main.c
+++ b/drivers/staging/comedi/kcomedilib/kcomedilib_main.c
@@ -80,7 +80,9 @@ int comedi_close(struct comedi_device *d)
80} 80}
81EXPORT_SYMBOL(comedi_close); 81EXPORT_SYMBOL(comedi_close);
82 82
83static int comedi_do_insn(struct comedi_device *dev, struct comedi_insn *insn) 83static int comedi_do_insn(struct comedi_device *dev,
84 struct comedi_insn *insn,
85 unsigned int *data)
84{ 86{
85 struct comedi_subdevice *s; 87 struct comedi_subdevice *s;
86 int ret = 0; 88 int ret = 0;
@@ -115,11 +117,11 @@ static int comedi_do_insn(struct comedi_device *dev, struct comedi_insn *insn)
115 117
116 switch (insn->insn) { 118 switch (insn->insn) {
117 case INSN_BITS: 119 case INSN_BITS:
118 ret = s->insn_bits(dev, s, insn, insn->data); 120 ret = s->insn_bits(dev, s, insn, data);
119 break; 121 break;
120 case INSN_CONFIG: 122 case INSN_CONFIG:
121 /* XXX should check instruction length */ 123 /* XXX should check instruction length */
122 ret = s->insn_config(dev, s, insn, insn->data); 124 ret = s->insn_config(dev, s, insn, data);
123 break; 125 break;
124 default: 126 default:
125 ret = -EINVAL; 127 ret = -EINVAL;
@@ -140,11 +142,10 @@ int comedi_dio_config(struct comedi_device *dev, unsigned int subdev,
140 memset(&insn, 0, sizeof(insn)); 142 memset(&insn, 0, sizeof(insn));
141 insn.insn = INSN_CONFIG; 143 insn.insn = INSN_CONFIG;
142 insn.n = 1; 144 insn.n = 1;
143 insn.data = &io;
144 insn.subdev = subdev; 145 insn.subdev = subdev;
145 insn.chanspec = CR_PACK(chan, 0, 0); 146 insn.chanspec = CR_PACK(chan, 0, 0);
146 147
147 return comedi_do_insn(dev, &insn); 148 return comedi_do_insn(dev, &insn, &io);
148} 149}
149EXPORT_SYMBOL(comedi_dio_config); 150EXPORT_SYMBOL(comedi_dio_config);
150 151
@@ -158,13 +159,12 @@ int comedi_dio_bitfield(struct comedi_device *dev, unsigned int subdev,
158 memset(&insn, 0, sizeof(insn)); 159 memset(&insn, 0, sizeof(insn));
159 insn.insn = INSN_BITS; 160 insn.insn = INSN_BITS;
160 insn.n = 2; 161 insn.n = 2;
161 insn.data = data;
162 insn.subdev = subdev; 162 insn.subdev = subdev;
163 163
164 data[0] = mask; 164 data[0] = mask;
165 data[1] = *bits; 165 data[1] = *bits;
166 166
167 ret = comedi_do_insn(dev, &insn); 167 ret = comedi_do_insn(dev, &insn, data);
168 168
169 *bits = data[1]; 169 *bits = data[1];
170 170