@@ -1615,22 +1615,19 @@ static int do_insnlist_ioctl(struct comedi_device *dev,
1615
1615
* data (for reads) to insn->data pointer
1616
1616
*/
1617
1617
static int do_insn_ioctl (struct comedi_device * dev ,
1618
- struct comedi_insn __user * arg , void * file )
1618
+ struct comedi_insn * insn , void * file )
1619
1619
{
1620
- struct comedi_insn insn ;
1621
1620
unsigned int * data = NULL ;
1622
1621
unsigned int n_data = MIN_SAMPLES ;
1623
1622
int ret = 0 ;
1624
1623
1625
1624
lockdep_assert_held (& dev -> mutex );
1626
- if (copy_from_user (& insn , arg , sizeof (insn )))
1627
- return - EFAULT ;
1628
1625
1629
- n_data = max (n_data , insn . n );
1626
+ n_data = max (n_data , insn -> n );
1630
1627
1631
1628
/* This is where the behavior of insn and insnlist deviate. */
1632
- if (insn . n > MAX_SAMPLES ) {
1633
- insn . n = MAX_SAMPLES ;
1629
+ if (insn -> n > MAX_SAMPLES ) {
1630
+ insn -> n = MAX_SAMPLES ;
1634
1631
n_data = MAX_SAMPLES ;
1635
1632
}
1636
1633
@@ -1640,26 +1637,26 @@ static int do_insn_ioctl(struct comedi_device *dev,
1640
1637
goto error ;
1641
1638
}
1642
1639
1643
- if (insn . insn & INSN_MASK_WRITE ) {
1640
+ if (insn -> insn & INSN_MASK_WRITE ) {
1644
1641
if (copy_from_user (data ,
1645
- insn . data ,
1646
- insn . n * sizeof (unsigned int ))) {
1642
+ insn -> data ,
1643
+ insn -> n * sizeof (unsigned int ))) {
1647
1644
ret = - EFAULT ;
1648
1645
goto error ;
1649
1646
}
1650
1647
}
1651
- ret = parse_insn (dev , & insn , data , file );
1648
+ ret = parse_insn (dev , insn , data , file );
1652
1649
if (ret < 0 )
1653
1650
goto error ;
1654
- if (insn . insn & INSN_MASK_READ ) {
1655
- if (copy_to_user (insn . data ,
1651
+ if (insn -> insn & INSN_MASK_READ ) {
1652
+ if (copy_to_user (insn -> data ,
1656
1653
data ,
1657
- insn . n * sizeof (unsigned int ))) {
1654
+ insn -> n * sizeof (unsigned int ))) {
1658
1655
ret = - EFAULT ;
1659
1656
goto error ;
1660
1657
}
1661
1658
}
1662
- ret = insn . n ;
1659
+ ret = insn -> n ;
1663
1660
1664
1661
error :
1665
1662
kfree (data );
@@ -2244,10 +2241,14 @@ static long comedi_unlocked_ioctl(struct file *file, unsigned int cmd,
2244
2241
(struct comedi_insnlist __user * )arg ,
2245
2242
file );
2246
2243
break ;
2247
- case COMEDI_INSN :
2248
- rc = do_insn_ioctl (dev , (struct comedi_insn __user * )arg ,
2249
- file );
2244
+ case COMEDI_INSN : {
2245
+ struct comedi_insn insn ;
2246
+ if (copy_from_user (& insn , (void __user * )arg , sizeof (insn )))
2247
+ rc = - EFAULT ;
2248
+ else
2249
+ rc = do_insn_ioctl (dev , & insn , file );
2250
2250
break ;
2251
+ }
2251
2252
case COMEDI_POLL :
2252
2253
rc = do_poll_ioctl (dev , arg , file );
2253
2254
break ;
@@ -3077,7 +3078,25 @@ static int compat_cmdtest(struct file *file, unsigned long arg)
3077
3078
}
3078
3079
3079
3080
/* Copy 32-bit insn structure to native insn structure. */
3080
- static int get_compat_insn (struct comedi_insn __user * insn ,
3081
+ static int get_compat_insn (struct comedi_insn * insn ,
3082
+ struct comedi32_insn_struct __user * insn32 )
3083
+ {
3084
+ struct comedi32_insn_struct v32 ;
3085
+
3086
+ /* Copy insn structure. Ignore the unused members. */
3087
+ if (copy_from_user (& v32 , insn32 , sizeof (v32 )))
3088
+ return - EFAULT ;
3089
+ memset (insn , 0 , sizeof (* insn ));
3090
+ insn -> insn = v32 .insn ;
3091
+ insn -> n = v32 .n ;
3092
+ insn -> data = compat_ptr (v32 .data );
3093
+ insn -> subdev = v32 .subdev ;
3094
+ insn -> chanspec = v32 .chanspec ;
3095
+ return 0 ;
3096
+ }
3097
+
3098
+ /* Copy 32-bit insn structure to native insn structure. */
3099
+ static int __get_compat_insn (struct comedi_insn __user * insn ,
3081
3100
struct comedi32_insn_struct __user * insn32 )
3082
3101
{
3083
3102
int err ;
@@ -3146,7 +3165,7 @@ static int compat_insnlist(struct file *file, unsigned long arg)
3146
3165
3147
3166
/* Copy insn structures. */
3148
3167
for (n = 0 ; n < n_insns ; n ++ ) {
3149
- rc = get_compat_insn (& s -> insn [n ], & insn32 [n ]);
3168
+ rc = __get_compat_insn (& s -> insn [n ], & insn32 [n ]);
3150
3169
if (rc )
3151
3170
return rc ;
3152
3171
}
@@ -3158,18 +3177,19 @@ static int compat_insnlist(struct file *file, unsigned long arg)
3158
3177
/* Handle 32-bit COMEDI_INSN ioctl. */
3159
3178
static int compat_insn (struct file * file , unsigned long arg )
3160
3179
{
3161
- struct comedi_insn __user * insn ;
3162
- struct comedi32_insn_struct __user * insn32 ;
3180
+ struct comedi_file * cfp = file -> private_data ;
3181
+ struct comedi_device * dev = cfp -> dev ;
3182
+ struct comedi_insn insn ;
3163
3183
int rc ;
3164
3184
3165
- insn32 = compat_ptr (arg );
3166
- insn = compat_alloc_user_space (sizeof (* insn ));
3167
-
3168
- rc = get_compat_insn (insn , insn32 );
3185
+ rc = get_compat_insn (& insn , (void __user * )arg );
3169
3186
if (rc )
3170
3187
return rc ;
3171
3188
3172
- return comedi_unlocked_ioctl (file , COMEDI_INSN , (unsigned long )insn );
3189
+ mutex_lock (& dev -> mutex );
3190
+ rc = do_insn_ioctl (dev , & insn , file );
3191
+ mutex_unlock (& dev -> mutex );
3192
+ return rc ;
3173
3193
}
3174
3194
3175
3195
/*
0 commit comments