@@ -1741,30 +1741,24 @@ static int __comedi_get_user_chanlist(struct comedi_device *dev,
1741
1741
* possibly modified comedi_cmd structure (when -EAGAIN returned)
1742
1742
*/
1743
1743
static int do_cmd_ioctl (struct comedi_device * dev ,
1744
- struct comedi_cmd __user * arg , void * file )
1744
+ struct comedi_cmd * cmd , bool * copy , void * file )
1745
1745
{
1746
- struct comedi_cmd cmd ;
1747
1746
struct comedi_subdevice * s ;
1748
1747
struct comedi_async * async ;
1749
1748
unsigned int __user * user_chanlist ;
1750
1749
int ret ;
1751
1750
1752
1751
lockdep_assert_held (& dev -> mutex );
1753
1752
1754
- if (copy_from_user (& cmd , arg , sizeof (cmd ))) {
1755
- dev_dbg (dev -> class_dev , "bad cmd address\n" );
1756
- return - EFAULT ;
1757
- }
1758
-
1759
- /* get the user's cmd and do some simple validation */
1760
- ret = __comedi_get_user_cmd (dev , & cmd );
1753
+ /* do some simple cmd validation */
1754
+ ret = __comedi_get_user_cmd (dev , cmd );
1761
1755
if (ret )
1762
1756
return ret ;
1763
1757
1764
1758
/* save user's chanlist pointer so it can be restored later */
1765
- user_chanlist = (unsigned int __user * )cmd . chanlist ;
1759
+ user_chanlist = (unsigned int __user * )cmd -> chanlist ;
1766
1760
1767
- s = & dev -> subdevices [cmd . subdev ];
1761
+ s = & dev -> subdevices [cmd -> subdev ];
1768
1762
async = s -> async ;
1769
1763
1770
1764
/* are we locked? (ioctl lock) */
@@ -1780,13 +1774,13 @@ static int do_cmd_ioctl(struct comedi_device *dev,
1780
1774
}
1781
1775
1782
1776
/* make sure channel/gain list isn't too short */
1783
- if (cmd . chanlist_len < 1 ) {
1777
+ if (cmd -> chanlist_len < 1 ) {
1784
1778
dev_dbg (dev -> class_dev , "channel/gain list too short %u < 1\n" ,
1785
- cmd . chanlist_len );
1779
+ cmd -> chanlist_len );
1786
1780
return - EINVAL ;
1787
1781
}
1788
1782
1789
- async -> cmd = cmd ;
1783
+ async -> cmd = * cmd ;
1790
1784
async -> cmd .data = NULL ;
1791
1785
1792
1786
/* load channel/gain list */
@@ -1798,15 +1792,11 @@ static int do_cmd_ioctl(struct comedi_device *dev,
1798
1792
1799
1793
if (async -> cmd .flags & CMDF_BOGUS || ret ) {
1800
1794
dev_dbg (dev -> class_dev , "test returned %d\n" , ret );
1801
- cmd = async -> cmd ;
1795
+ * cmd = async -> cmd ;
1802
1796
/* restore chanlist pointer before copying back */
1803
- cmd .chanlist = (unsigned int __force * )user_chanlist ;
1804
- cmd .data = NULL ;
1805
- if (copy_to_user (arg , & cmd , sizeof (cmd ))) {
1806
- dev_dbg (dev -> class_dev , "fault writing cmd\n" );
1807
- ret = - EFAULT ;
1808
- goto cleanup ;
1809
- }
1797
+ cmd -> chanlist = (unsigned int __force * )user_chanlist ;
1798
+ cmd -> data = NULL ;
1799
+ * copy = true;
1810
1800
ret = - EAGAIN ;
1811
1801
goto cleanup ;
1812
1802
}
@@ -2207,9 +2197,19 @@ static long comedi_unlocked_ioctl(struct file *file, unsigned int cmd,
2207
2197
case COMEDI_CANCEL :
2208
2198
rc = do_cancel_ioctl (dev , arg , file );
2209
2199
break ;
2210
- case COMEDI_CMD :
2211
- rc = do_cmd_ioctl (dev , (struct comedi_cmd __user * )arg , file );
2200
+ case COMEDI_CMD : {
2201
+ struct comedi_cmd cmd ;
2202
+ bool copy = false;
2203
+
2204
+ if (copy_from_user (& cmd , (void __user * )arg , sizeof (cmd ))) {
2205
+ rc = - EFAULT ;
2206
+ break ;
2207
+ }
2208
+ rc = do_cmd_ioctl (dev , & cmd , & copy , file );
2209
+ if (copy && copy_to_user ((void __user * )arg , & cmd , sizeof (cmd )))
2210
+ rc = - EFAULT ;
2212
2211
break ;
2212
+ }
2213
2213
case COMEDI_CMDTEST : {
2214
2214
struct comedi_cmd cmd ;
2215
2215
bool copy = false;
0 commit comments