@@ -1520,34 +1520,19 @@ static int parse_insn(struct comedi_device *dev, struct comedi_insn *insn,
1520
1520
#define MIN_SAMPLES 16
1521
1521
#define MAX_SAMPLES 65536
1522
1522
static int do_insnlist_ioctl (struct comedi_device * dev ,
1523
- struct comedi_insnlist __user * arg , void * file )
1523
+ struct comedi_insn * insns ,
1524
+ unsigned int n_insns ,
1525
+ void * file )
1524
1526
{
1525
- struct comedi_insnlist insnlist ;
1526
- struct comedi_insn * insns = NULL ;
1527
1527
unsigned int * data = NULL ;
1528
1528
unsigned int max_n_data_required = MIN_SAMPLES ;
1529
1529
int i = 0 ;
1530
1530
int ret = 0 ;
1531
1531
1532
1532
lockdep_assert_held (& dev -> mutex );
1533
- if (copy_from_user (& insnlist , arg , sizeof (insnlist )))
1534
- return - EFAULT ;
1535
-
1536
- insns = kcalloc (insnlist .n_insns , sizeof (* insns ), GFP_KERNEL );
1537
- if (!insns ) {
1538
- ret = - ENOMEM ;
1539
- goto error ;
1540
- }
1541
-
1542
- if (copy_from_user (insns , insnlist .insns ,
1543
- sizeof (* insns ) * insnlist .n_insns )) {
1544
- dev_dbg (dev -> class_dev , "copy_from_user failed\n" );
1545
- ret = - EFAULT ;
1546
- goto error ;
1547
- }
1548
1533
1549
1534
/* Determine maximum memory needed for all instructions. */
1550
- for (i = 0 ; i < insnlist . n_insns ; ++ i ) {
1535
+ for (i = 0 ; i < n_insns ; ++ i ) {
1551
1536
if (insns [i ].n > MAX_SAMPLES ) {
1552
1537
dev_dbg (dev -> class_dev ,
1553
1538
"number of samples too large\n" );
@@ -1565,7 +1550,7 @@ static int do_insnlist_ioctl(struct comedi_device *dev,
1565
1550
goto error ;
1566
1551
}
1567
1552
1568
- for (i = 0 ; i < insnlist . n_insns ; ++ i ) {
1553
+ for (i = 0 ; i < n_insns ; ++ i ) {
1569
1554
if (insns [i ].insn & INSN_MASK_WRITE ) {
1570
1555
if (copy_from_user (data , insns [i ].data ,
1571
1556
insns [i ].n * sizeof (unsigned int ))) {
@@ -1592,7 +1577,6 @@ static int do_insnlist_ioctl(struct comedi_device *dev,
1592
1577
}
1593
1578
1594
1579
error :
1595
- kfree (insns );
1596
1580
kfree (data );
1597
1581
1598
1582
if (ret < 0 )
@@ -2236,11 +2220,30 @@ static long comedi_unlocked_ioctl(struct file *file, unsigned int cmd,
2236
2220
rc = do_cmdtest_ioctl (dev , (struct comedi_cmd __user * )arg ,
2237
2221
file );
2238
2222
break ;
2239
- case COMEDI_INSNLIST :
2240
- rc = do_insnlist_ioctl (dev ,
2241
- (struct comedi_insnlist __user * )arg ,
2242
- file );
2223
+ case COMEDI_INSNLIST : {
2224
+ struct comedi_insnlist insnlist ;
2225
+ struct comedi_insn * insns = NULL ;
2226
+
2227
+ if (copy_from_user (& insnlist , (void __user * )arg ,
2228
+ sizeof (insnlist ))) {
2229
+ rc = - EFAULT ;
2230
+ break ;
2231
+ }
2232
+ insns = kcalloc (insnlist .n_insns , sizeof (* insns ), GFP_KERNEL );
2233
+ if (!insns ) {
2234
+ rc = - ENOMEM ;
2235
+ break ;
2236
+ }
2237
+ if (copy_from_user (insns , insnlist .insns ,
2238
+ sizeof (* insns ) * insnlist .n_insns )) {
2239
+ rc = - EFAULT ;
2240
+ kfree (insns );
2241
+ break ;
2242
+ }
2243
+ rc = do_insnlist_ioctl (dev , insns , insnlist .n_insns , file );
2244
+ kfree (insns );
2243
2245
break ;
2246
+ }
2244
2247
case COMEDI_INSN : {
2245
2248
struct comedi_insn insn ;
2246
2249
if (copy_from_user (& insn , (void __user * )arg , sizeof (insn )))
@@ -3095,83 +3098,38 @@ static int get_compat_insn(struct comedi_insn *insn,
3095
3098
return 0 ;
3096
3099
}
3097
3100
3098
- /* Copy 32-bit insn structure to native insn structure. */
3099
- static int __get_compat_insn (struct comedi_insn __user * insn ,
3100
- struct comedi32_insn_struct __user * insn32 )
3101
- {
3102
- int err ;
3103
- union {
3104
- unsigned int uint ;
3105
- compat_uptr_t uptr ;
3106
- } temp ;
3107
-
3108
- /* Copy insn structure. Ignore the unused members. */
3109
- err = 0 ;
3110
- if (!access_ok (insn32 , sizeof (* insn32 )) ||
3111
- !access_ok (insn , sizeof (* insn )))
3112
- return - EFAULT ;
3113
-
3114
- err |= __get_user (temp .uint , & insn32 -> insn );
3115
- err |= __put_user (temp .uint , & insn -> insn );
3116
- err |= __get_user (temp .uint , & insn32 -> n );
3117
- err |= __put_user (temp .uint , & insn -> n );
3118
- err |= __get_user (temp .uptr , & insn32 -> data );
3119
- err |= __put_user (compat_ptr (temp .uptr ), & insn -> data );
3120
- err |= __get_user (temp .uint , & insn32 -> subdev );
3121
- err |= __put_user (temp .uint , & insn -> subdev );
3122
- err |= __get_user (temp .uint , & insn32 -> chanspec );
3123
- err |= __put_user (temp .uint , & insn -> chanspec );
3124
- return err ? - EFAULT : 0 ;
3125
- }
3126
-
3127
3101
/* Handle 32-bit COMEDI_INSNLIST ioctl. */
3128
3102
static int compat_insnlist (struct file * file , unsigned long arg )
3129
3103
{
3130
- struct combined_insnlist {
3131
- struct comedi_insnlist insnlist ;
3132
- struct comedi_insn insn [1 ];
3133
- } __user * s ;
3134
- struct comedi32_insnlist_struct __user * insnlist32 ;
3104
+ struct comedi_file * cfp = file -> private_data ;
3105
+ struct comedi_device * dev = cfp -> dev ;
3106
+ struct comedi32_insnlist_struct insnlist32 ;
3135
3107
struct comedi32_insn_struct __user * insn32 ;
3136
- compat_uptr_t uptr ;
3137
- unsigned int n_insns , n ;
3138
- int err , rc ;
3139
-
3140
- insnlist32 = compat_ptr (arg );
3141
-
3142
- /* Get 32-bit insnlist structure. */
3143
- if (!access_ok (insnlist32 , sizeof (* insnlist32 )))
3144
- return - EFAULT ;
3145
-
3146
- err = 0 ;
3147
- err |= __get_user (n_insns , & insnlist32 -> n_insns );
3148
- err |= __get_user (uptr , & insnlist32 -> insns );
3149
- insn32 = compat_ptr (uptr );
3150
- if (err )
3151
- return - EFAULT ;
3152
-
3153
- /* Allocate user memory to copy insnlist and insns into. */
3154
- s = compat_alloc_user_space (offsetof(struct combined_insnlist ,
3155
- insn [n_insns ]));
3108
+ struct comedi_insn * insns ;
3109
+ unsigned int n ;
3110
+ int rc ;
3156
3111
3157
- /* Set native insnlist structure. */
3158
- if (!access_ok (& s -> insnlist , sizeof (s -> insnlist )))
3112
+ if (copy_from_user (& insnlist32 , compat_ptr (arg ), sizeof (insnlist32 )))
3159
3113
return - EFAULT ;
3160
3114
3161
- err |= __put_user (n_insns , & s -> insnlist .n_insns );
3162
- err |= __put_user (& s -> insn [0 ], & s -> insnlist .insns );
3163
- if (err )
3164
- return - EFAULT ;
3115
+ insns = kcalloc (insnlist32 .n_insns , sizeof (* insns ), GFP_KERNEL );
3116
+ if (!insns )
3117
+ return - ENOMEM ;
3165
3118
3166
3119
/* Copy insn structures. */
3167
- for (n = 0 ; n < n_insns ; n ++ ) {
3168
- rc = __get_compat_insn (& s -> insn [n ], & insn32 [n ]);
3169
- if (rc )
3120
+ insn32 = compat_ptr (insnlist32 .insns );
3121
+ for (n = 0 ; n < insnlist32 .n_insns ; n ++ ) {
3122
+ rc = get_compat_insn (insns + n , insn32 + n );
3123
+ if (rc ) {
3124
+ kfree (insns );
3170
3125
return rc ;
3126
+ }
3171
3127
}
3172
3128
3173
- return comedi_unlocked_ioctl (file , COMEDI_INSNLIST ,
3174
- (unsigned long )& s -> insnlist );
3129
+ mutex_lock (& dev -> mutex );
3130
+ rc = do_insnlist_ioctl (dev , insns , insnlist32 .n_insns , file );
3131
+ mutex_unlock (& dev -> mutex );
3132
+ return rc ;
3175
3133
}
3176
3134
3177
3135
/* Handle 32-bit COMEDI_INSN ioctl. */
0 commit comments