From 95bc359f98a077a5cfc34feb0a333d11a4124b1c Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Tue, 18 Sep 2012 11:43:52 -0700 Subject: [PATCH] staging: comedi: comedi_fops: cast the cmd->chanlist to the correct address space Rename 'chanlist_saver' to 'user_chanlist' to avoid confusion that it's actually a __user *. The chanlist pointer in comedi_cmd is still a user space pointer when the comedi_cmd is copied with copy_from_user() in do_cmd_ioctl() and do_cmdtest_ioctl(). This pointer needs to be cast when it is saved in user_chanlist in order to preserve its address space. The copy_from_user() call to copy the chanlist to the kernel space comedi_command requires the second parameter to be a __user pointer. Use the correctly cast user_chanlist instead of cmd->chanlist. Before the comedi_cmd is copied back to user space, the saved user_chanlist pointer is restored. Cast the user_chanlist again so that the address space matches the comedi_cmd. Signed-off-by: H Hartley Sweeten Cc: Ian Abbott Acked-by: Dan Carpenter Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/comedi_fops.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/drivers/staging/comedi/comedi_fops.c b/drivers/staging/comedi/comedi_fops.c index df627c8223d5..626fa723f199 100644 --- a/drivers/staging/comedi/comedi_fops.c +++ b/drivers/staging/comedi/comedi_fops.c @@ -1137,14 +1137,14 @@ static int do_cmd_ioctl(struct comedi_device *dev, struct comedi_subdevice *s; struct comedi_async *async; int ret = 0; - unsigned int __user *chanlist_saver = NULL; + unsigned int __user *user_chanlist; if (copy_from_user(&cmd, arg, sizeof(struct comedi_cmd))) { DPRINTK("bad cmd address\n"); return -EFAULT; } /* save user's chanlist pointer so it can be restored later */ - chanlist_saver = cmd.chanlist; + user_chanlist = (unsigned int __user *)cmd.chanlist; if (cmd.subdev >= dev->n_subdevices) { DPRINTK("%d no such subdevice\n", cmd.subdev); @@ -1206,7 +1206,7 @@ static int do_cmd_ioctl(struct comedi_device *dev, goto cleanup; } - if (copy_from_user(async->cmd.chanlist, cmd.chanlist, + if (copy_from_user(async->cmd.chanlist, user_chanlist, async->cmd.chanlist_len * sizeof(int))) { DPRINTK("fault reading chanlist\n"); ret = -EFAULT; @@ -1228,7 +1228,7 @@ static int do_cmd_ioctl(struct comedi_device *dev, DPRINTK("test returned %d\n", ret); cmd = async->cmd; /* restore chanlist pointer before copying back */ - cmd.chanlist = chanlist_saver; + cmd.chanlist = (unsigned int __force *)user_chanlist; cmd.data = NULL; if (copy_to_user(arg, &cmd, sizeof(struct comedi_cmd))) { DPRINTK("fault writing cmd\n"); @@ -1287,14 +1287,14 @@ static int do_cmdtest_ioctl(struct comedi_device *dev, struct comedi_subdevice *s; int ret = 0; unsigned int *chanlist = NULL; - unsigned int __user *chanlist_saver = NULL; + unsigned int __user *user_chanlist; if (copy_from_user(&cmd, arg, sizeof(struct comedi_cmd))) { DPRINTK("bad cmd address\n"); return -EFAULT; } /* save user's chanlist pointer so it can be restored later */ - chanlist_saver = cmd.chanlist; + user_chanlist = (unsigned int __user *)cmd.chanlist; if (cmd.subdev >= dev->n_subdevices) { DPRINTK("%d no such subdevice\n", cmd.subdev); @@ -1331,7 +1331,7 @@ static int do_cmdtest_ioctl(struct comedi_device *dev, goto cleanup; } - if (copy_from_user(chanlist, cmd.chanlist, + if (copy_from_user(chanlist, user_chanlist, cmd.chanlist_len * sizeof(int))) { DPRINTK("fault reading chanlist\n"); ret = -EFAULT; @@ -1351,7 +1351,7 @@ static int do_cmdtest_ioctl(struct comedi_device *dev, ret = s->do_cmdtest(dev, s, &cmd); /* restore chanlist pointer before copying back */ - cmd.chanlist = chanlist_saver; + cmd.chanlist = (unsigned int __force *)user_chanlist; if (copy_to_user(arg, &cmd, sizeof(struct comedi_cmd))) { DPRINTK("bad cmd address\n"); -- 2.34.1