diff options
author | H Hartley Sweeten <hartleys@visionengravers.com> | 2012-09-19 17:26:53 -0700 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2012-09-21 09:26:20 -0700 |
commit | 1f5cc359158772304a92ee9c5682ca83416d2ba8 (patch) | |
tree | f140fca0c865fd86b9f0244e588068daa74838f4 /drivers/staging | |
parent | 94174847ea41b1c2a44d997f2850530fb33f41cd (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>
Diffstat (limited to 'drivers/staging')
-rw-r--r-- | drivers/staging/comedi/kcomedilib/kcomedilib_main.c | 14 |
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) } EXPORT_SYMBOL(comedi_close); -static int comedi_do_insn(struct comedi_device *dev, struct comedi_insn *insn) +static int comedi_do_insn(struct comedi_device *dev, + struct comedi_insn *insn, + unsigned int *data) { struct comedi_subdevice *s; int ret = 0; @@ -115,11 +117,11 @@ static int comedi_do_insn(struct comedi_device *dev, struct comedi_insn *insn) switch (insn->insn) { case INSN_BITS: - ret = s->insn_bits(dev, s, insn, insn->data); + ret = s->insn_bits(dev, s, insn, data); break; case INSN_CONFIG: /* XXX should check instruction length */ - ret = s->insn_config(dev, s, insn, insn->data); + ret = s->insn_config(dev, s, insn, data); break; default: ret = -EINVAL; @@ -140,11 +142,10 @@ int comedi_dio_config(struct comedi_device *dev, unsigned int subdev, memset(&insn, 0, sizeof(insn)); insn.insn = INSN_CONFIG; insn.n = 1; - insn.data = &io; insn.subdev = subdev; insn.chanspec = CR_PACK(chan, 0, 0); - return comedi_do_insn(dev, &insn); + return comedi_do_insn(dev, &insn, &io); } EXPORT_SYMBOL(comedi_dio_config); @@ -158,13 +159,12 @@ int comedi_dio_bitfield(struct comedi_device *dev, unsigned int subdev, memset(&insn, 0, sizeof(insn)); insn.insn = INSN_BITS; insn.n = 2; - insn.data = data; insn.subdev = subdev; data[0] = mask; data[1] = *bits; - ret = comedi_do_insn(dev, &insn); + ret = comedi_do_insn(dev, &insn, data); *bits = data[1]; |