@@ -254,6 +254,10 @@ static irqreturn_t do_hpsa_intr_intx(int irq, void *dev_id);
254254static irqreturn_t do_hpsa_intr_msi (int irq , void * dev_id );
255255static int hpsa_ioctl (struct scsi_device * dev , unsigned int cmd ,
256256 void __user * arg );
257+ static int hpsa_passthru_ioctl (struct ctlr_info * h ,
258+ IOCTL_Command_struct * iocommand );
259+ static int hpsa_big_passthru_ioctl (struct ctlr_info * h ,
260+ BIG_IOCTL_Command_struct * ioc );
257261
258262#ifdef CONFIG_COMPAT
259263static int hpsa_compat_ioctl (struct scsi_device * dev , unsigned int cmd ,
@@ -6217,75 +6221,63 @@ static void cmd_free(struct ctlr_info *h, struct CommandList *c)
62176221static int hpsa_ioctl32_passthru (struct scsi_device * dev , unsigned int cmd ,
62186222 void __user * arg )
62196223{
6220- IOCTL32_Command_struct __user * arg32 =
6221- ( IOCTL32_Command_struct __user * ) arg ;
6224+ struct ctlr_info * h = sdev_to_hba ( dev );
6225+ IOCTL32_Command_struct __user * arg32 = arg ;
62226226 IOCTL_Command_struct arg64 ;
6223- IOCTL_Command_struct __user * p = compat_alloc_user_space (sizeof (arg64 ));
62246227 int err ;
62256228 u32 cp ;
62266229
6227- memset (& arg64 , 0 , sizeof (arg64 ));
6228- err = 0 ;
6229- err |= copy_from_user (& arg64 .LUN_info , & arg32 -> LUN_info ,
6230- sizeof (arg64 .LUN_info ));
6231- err |= copy_from_user (& arg64 .Request , & arg32 -> Request ,
6232- sizeof (arg64 .Request ));
6233- err |= copy_from_user (& arg64 .error_info , & arg32 -> error_info ,
6234- sizeof (arg64 .error_info ));
6235- err |= get_user (arg64 .buf_size , & arg32 -> buf_size );
6236- err |= get_user (cp , & arg32 -> buf );
6237- arg64 .buf = compat_ptr (cp );
6238- err |= copy_to_user (p , & arg64 , sizeof (arg64 ));
6230+ if (!arg )
6231+ return - EINVAL ;
62396232
6240- if (err )
6233+ memset (& arg64 , 0 , sizeof (arg64 ));
6234+ if (copy_from_user (& arg64 , arg32 , offsetof(IOCTL_Command_struct , buf )))
6235+ return - EFAULT ;
6236+ if (get_user (cp , & arg32 -> buf ))
62416237 return - EFAULT ;
6238+ arg64 .buf = compat_ptr (cp );
62426239
6243- err = hpsa_ioctl (dev , CCISS_PASSTHRU , p );
6240+ if (atomic_dec_if_positive (& h -> passthru_cmds_avail ) < 0 )
6241+ return - EAGAIN ;
6242+ err = hpsa_passthru_ioctl (h , & arg64 );
6243+ atomic_inc (& h -> passthru_cmds_avail );
62446244 if (err )
62456245 return err ;
6246- err |= copy_in_user (& arg32 -> error_info , & p -> error_info ,
6247- sizeof (arg32 -> error_info ));
6248- if (err )
6246+ if (copy_to_user (& arg32 -> error_info , & arg64 .error_info ,
6247+ sizeof (arg32 -> error_info )))
62496248 return - EFAULT ;
6250- return err ;
6249+ return 0 ;
62516250}
62526251
62536252static int hpsa_ioctl32_big_passthru (struct scsi_device * dev ,
62546253 unsigned int cmd , void __user * arg )
62556254{
6256- BIG_IOCTL32_Command_struct __user * arg32 =
6257- ( BIG_IOCTL32_Command_struct __user * ) arg ;
6255+ struct ctlr_info * h = sdev_to_hba ( dev );
6256+ BIG_IOCTL32_Command_struct __user * arg32 = arg ;
62586257 BIG_IOCTL_Command_struct arg64 ;
6259- BIG_IOCTL_Command_struct __user * p =
6260- compat_alloc_user_space (sizeof (arg64 ));
62616258 int err ;
62626259 u32 cp ;
62636260
6261+ if (!arg )
6262+ return - EINVAL ;
62646263 memset (& arg64 , 0 , sizeof (arg64 ));
6265- err = 0 ;
6266- err |= copy_from_user (& arg64 .LUN_info , & arg32 -> LUN_info ,
6267- sizeof (arg64 .LUN_info ));
6268- err |= copy_from_user (& arg64 .Request , & arg32 -> Request ,
6269- sizeof (arg64 .Request ));
6270- err |= copy_from_user (& arg64 .error_info , & arg32 -> error_info ,
6271- sizeof (arg64 .error_info ));
6272- err |= get_user (arg64 .buf_size , & arg32 -> buf_size );
6273- err |= get_user (arg64 .malloc_size , & arg32 -> malloc_size );
6274- err |= get_user (cp , & arg32 -> buf );
6275- arg64 .buf = compat_ptr (cp );
6276- err |= copy_to_user (p , & arg64 , sizeof (arg64 ));
6277-
6278- if (err )
6264+ if (copy_from_user (& arg64 , arg32 ,
6265+ offsetof(BIG_IOCTL32_Command_struct , buf )))
6266+ return - EFAULT ;
6267+ if (get_user (cp , & arg32 -> buf ))
62796268 return - EFAULT ;
6269+ arg64 .buf = compat_ptr (cp );
62806270
6281- err = hpsa_ioctl (dev , CCISS_BIG_PASSTHRU , p );
6271+ if (atomic_dec_if_positive (& h -> passthru_cmds_avail ) < 0 )
6272+ return - EAGAIN ;
6273+ err = hpsa_big_passthru_ioctl (h , & arg64 );
6274+ atomic_inc (& h -> passthru_cmds_avail );
62826275 if (err )
62836276 return err ;
6284- err |= copy_in_user (& arg32 -> error_info , & p -> error_info ,
6285- sizeof (arg32 -> error_info ));
6286- if (err )
6277+ if (copy_to_user (& arg32 -> error_info , & arg64 .error_info ,
6278+ sizeof (arg32 -> error_info )))
62876279 return - EFAULT ;
6288- return err ;
6280+ return 0 ;
62896281}
62906282
62916283static int hpsa_compat_ioctl (struct scsi_device * dev , unsigned int cmd ,
@@ -6358,37 +6350,33 @@ static int hpsa_getdrivver_ioctl(struct ctlr_info *h, void __user *argp)
63586350 return 0 ;
63596351}
63606352
6361- static int hpsa_passthru_ioctl (struct ctlr_info * h , void __user * argp )
6353+ static int hpsa_passthru_ioctl (struct ctlr_info * h ,
6354+ IOCTL_Command_struct * iocommand )
63626355{
6363- IOCTL_Command_struct iocommand ;
63646356 struct CommandList * c ;
63656357 char * buff = NULL ;
63666358 u64 temp64 ;
63676359 int rc = 0 ;
63686360
6369- if (!argp )
6370- return - EINVAL ;
63716361 if (!capable (CAP_SYS_RAWIO ))
63726362 return - EPERM ;
6373- if (copy_from_user (& iocommand , argp , sizeof (iocommand )))
6374- return - EFAULT ;
6375- if ((iocommand .buf_size < 1 ) &&
6376- (iocommand .Request .Type .Direction != XFER_NONE )) {
6363+ if ((iocommand -> buf_size < 1 ) &&
6364+ (iocommand -> Request .Type .Direction != XFER_NONE )) {
63776365 return - EINVAL ;
63786366 }
6379- if (iocommand . buf_size > 0 ) {
6380- buff = kmalloc (iocommand . buf_size , GFP_KERNEL );
6367+ if (iocommand -> buf_size > 0 ) {
6368+ buff = kmalloc (iocommand -> buf_size , GFP_KERNEL );
63816369 if (buff == NULL )
63826370 return - ENOMEM ;
6383- if (iocommand . Request .Type .Direction & XFER_WRITE ) {
6371+ if (iocommand -> Request .Type .Direction & XFER_WRITE ) {
63846372 /* Copy the data into the buffer we created */
6385- if (copy_from_user (buff , iocommand . buf ,
6386- iocommand . buf_size )) {
6373+ if (copy_from_user (buff , iocommand -> buf ,
6374+ iocommand -> buf_size )) {
63876375 rc = - EFAULT ;
63886376 goto out_kfree ;
63896377 }
63906378 } else {
6391- memset (buff , 0 , iocommand . buf_size );
6379+ memset (buff , 0 , iocommand -> buf_size );
63926380 }
63936381 }
63946382 c = cmd_alloc (h );
@@ -6398,36 +6386,36 @@ static int hpsa_passthru_ioctl(struct ctlr_info *h, void __user *argp)
63986386 c -> scsi_cmd = SCSI_CMD_BUSY ;
63996387 /* Fill in Command Header */
64006388 c -> Header .ReplyQueue = 0 ; /* unused in simple mode */
6401- if (iocommand . buf_size > 0 ) { /* buffer to fill */
6389+ if (iocommand -> buf_size > 0 ) { /* buffer to fill */
64026390 c -> Header .SGList = 1 ;
64036391 c -> Header .SGTotal = cpu_to_le16 (1 );
64046392 } else { /* no buffers to fill */
64056393 c -> Header .SGList = 0 ;
64066394 c -> Header .SGTotal = cpu_to_le16 (0 );
64076395 }
6408- memcpy (& c -> Header .LUN , & iocommand . LUN_info , sizeof (c -> Header .LUN ));
6396+ memcpy (& c -> Header .LUN , & iocommand -> LUN_info , sizeof (c -> Header .LUN ));
64096397
64106398 /* Fill in Request block */
6411- memcpy (& c -> Request , & iocommand . Request ,
6399+ memcpy (& c -> Request , & iocommand -> Request ,
64126400 sizeof (c -> Request ));
64136401
64146402 /* Fill in the scatter gather information */
6415- if (iocommand . buf_size > 0 ) {
6403+ if (iocommand -> buf_size > 0 ) {
64166404 temp64 = dma_map_single (& h -> pdev -> dev , buff ,
6417- iocommand . buf_size , DMA_BIDIRECTIONAL );
6405+ iocommand -> buf_size , DMA_BIDIRECTIONAL );
64186406 if (dma_mapping_error (& h -> pdev -> dev , (dma_addr_t ) temp64 )) {
64196407 c -> SG [0 ].Addr = cpu_to_le64 (0 );
64206408 c -> SG [0 ].Len = cpu_to_le32 (0 );
64216409 rc = - ENOMEM ;
64226410 goto out ;
64236411 }
64246412 c -> SG [0 ].Addr = cpu_to_le64 (temp64 );
6425- c -> SG [0 ].Len = cpu_to_le32 (iocommand . buf_size );
6413+ c -> SG [0 ].Len = cpu_to_le32 (iocommand -> buf_size );
64266414 c -> SG [0 ].Ext = cpu_to_le32 (HPSA_SG_LAST ); /* not chaining */
64276415 }
64286416 rc = hpsa_scsi_do_simple_cmd (h , c , DEFAULT_REPLY_QUEUE ,
64296417 NO_TIMEOUT );
6430- if (iocommand . buf_size > 0 )
6418+ if (iocommand -> buf_size > 0 )
64316419 hpsa_pci_unmap (h -> pdev , c , 1 , DMA_BIDIRECTIONAL );
64326420 check_ioctl_unit_attention (h , c );
64336421 if (rc ) {
@@ -6436,16 +6424,12 @@ static int hpsa_passthru_ioctl(struct ctlr_info *h, void __user *argp)
64366424 }
64376425
64386426 /* Copy the error information out */
6439- memcpy (& iocommand .error_info , c -> err_info ,
6440- sizeof (iocommand .error_info ));
6441- if (copy_to_user (argp , & iocommand , sizeof (iocommand ))) {
6442- rc = - EFAULT ;
6443- goto out ;
6444- }
6445- if ((iocommand .Request .Type .Direction & XFER_READ ) &&
6446- iocommand .buf_size > 0 ) {
6427+ memcpy (& iocommand -> error_info , c -> err_info ,
6428+ sizeof (iocommand -> error_info ));
6429+ if ((iocommand -> Request .Type .Direction & XFER_READ ) &&
6430+ iocommand -> buf_size > 0 ) {
64476431 /* Copy the data out of the buffer we created */
6448- if (copy_to_user (iocommand . buf , buff , iocommand . buf_size )) {
6432+ if (copy_to_user (iocommand -> buf , buff , iocommand -> buf_size )) {
64496433 rc = - EFAULT ;
64506434 goto out ;
64516435 }
@@ -6457,9 +6441,9 @@ static int hpsa_passthru_ioctl(struct ctlr_info *h, void __user *argp)
64576441 return rc ;
64586442}
64596443
6460- static int hpsa_big_passthru_ioctl (struct ctlr_info * h , void __user * argp )
6444+ static int hpsa_big_passthru_ioctl (struct ctlr_info * h ,
6445+ BIG_IOCTL_Command_struct * ioc )
64616446{
6462- BIG_IOCTL_Command_struct * ioc ;
64636447 struct CommandList * c ;
64646448 unsigned char * * buff = NULL ;
64656449 int * buff_size = NULL ;
@@ -6470,29 +6454,17 @@ static int hpsa_big_passthru_ioctl(struct ctlr_info *h, void __user *argp)
64706454 u32 sz ;
64716455 BYTE __user * data_ptr ;
64726456
6473- if (!argp )
6474- return - EINVAL ;
64756457 if (!capable (CAP_SYS_RAWIO ))
64766458 return - EPERM ;
6477- ioc = vmemdup_user (argp , sizeof (* ioc ));
6478- if (IS_ERR (ioc )) {
6479- status = PTR_ERR (ioc );
6480- goto cleanup1 ;
6481- }
6459+
64826460 if ((ioc -> buf_size < 1 ) &&
6483- (ioc -> Request .Type .Direction != XFER_NONE )) {
6484- status = - EINVAL ;
6485- goto cleanup1 ;
6486- }
6461+ (ioc -> Request .Type .Direction != XFER_NONE ))
6462+ return - EINVAL ;
64876463 /* Check kmalloc limits using all SGs */
6488- if (ioc -> malloc_size > MAX_KMALLOC_SIZE ) {
6489- status = - EINVAL ;
6490- goto cleanup1 ;
6491- }
6492- if (ioc -> buf_size > ioc -> malloc_size * SG_ENTRIES_IN_CMD ) {
6493- status = - EINVAL ;
6494- goto cleanup1 ;
6495- }
6464+ if (ioc -> malloc_size > MAX_KMALLOC_SIZE )
6465+ return - EINVAL ;
6466+ if (ioc -> buf_size > ioc -> malloc_size * SG_ENTRIES_IN_CMD )
6467+ return - EINVAL ;
64966468 buff = kcalloc (SG_ENTRIES_IN_CMD , sizeof (char * ), GFP_KERNEL );
64976469 if (!buff ) {
64986470 status = - ENOMEM ;
@@ -6565,10 +6537,6 @@ static int hpsa_big_passthru_ioctl(struct ctlr_info *h, void __user *argp)
65656537
65666538 /* Copy the error information out */
65676539 memcpy (& ioc -> error_info , c -> err_info , sizeof (ioc -> error_info ));
6568- if (copy_to_user (argp , ioc , sizeof (* ioc ))) {
6569- status = - EFAULT ;
6570- goto cleanup0 ;
6571- }
65726540 if ((ioc -> Request .Type .Direction & XFER_READ ) && ioc -> buf_size > 0 ) {
65736541 int i ;
65746542
@@ -6594,7 +6562,6 @@ static int hpsa_big_passthru_ioctl(struct ctlr_info *h, void __user *argp)
65946562 kfree (buff );
65956563 }
65966564 kfree (buff_size );
6597- kvfree (ioc );
65986565 return status ;
65996566}
66006567
@@ -6610,14 +6577,11 @@ static void check_ioctl_unit_attention(struct ctlr_info *h,
66106577 * ioctl
66116578 */
66126579static int hpsa_ioctl (struct scsi_device * dev , unsigned int cmd ,
6613- void __user * arg )
6580+ void __user * argp )
66146581{
6615- struct ctlr_info * h ;
6616- void __user * argp = (void __user * )arg ;
6582+ struct ctlr_info * h = sdev_to_hba (dev );
66176583 int rc ;
66186584
6619- h = sdev_to_hba (dev );
6620-
66216585 switch (cmd ) {
66226586 case CCISS_DEREGDISK :
66236587 case CCISS_REGNEWDISK :
@@ -6628,18 +6592,35 @@ static int hpsa_ioctl(struct scsi_device *dev, unsigned int cmd,
66286592 return hpsa_getpciinfo_ioctl (h , argp );
66296593 case CCISS_GETDRIVVER :
66306594 return hpsa_getdrivver_ioctl (h , argp );
6631- case CCISS_PASSTHRU :
6595+ case CCISS_PASSTHRU : {
6596+ IOCTL_Command_struct iocommand ;
6597+
6598+ if (!argp )
6599+ return - EINVAL ;
6600+ if (copy_from_user (& iocommand , argp , sizeof (iocommand )))
6601+ return - EFAULT ;
66326602 if (atomic_dec_if_positive (& h -> passthru_cmds_avail ) < 0 )
66336603 return - EAGAIN ;
6634- rc = hpsa_passthru_ioctl (h , argp );
6604+ rc = hpsa_passthru_ioctl (h , & iocommand );
66356605 atomic_inc (& h -> passthru_cmds_avail );
6606+ if (!rc && copy_to_user (argp , & iocommand , sizeof (iocommand )))
6607+ rc = - EFAULT ;
66366608 return rc ;
6637- case CCISS_BIG_PASSTHRU :
6609+ }
6610+ case CCISS_BIG_PASSTHRU : {
6611+ BIG_IOCTL_Command_struct ioc ;
6612+ if (!argp )
6613+ return - EINVAL ;
6614+ if (copy_from_user (& ioc , argp , sizeof (ioc )))
6615+ return - EFAULT ;
66386616 if (atomic_dec_if_positive (& h -> passthru_cmds_avail ) < 0 )
66396617 return - EAGAIN ;
6640- rc = hpsa_big_passthru_ioctl (h , argp );
6618+ rc = hpsa_big_passthru_ioctl (h , & ioc );
66416619 atomic_inc (& h -> passthru_cmds_avail );
6620+ if (!rc && copy_to_user (argp , & ioc , sizeof (ioc )))
6621+ rc = - EFAULT ;
66426622 return rc ;
6623+ }
66436624 default :
66446625 return - ENOTTY ;
66456626 }
0 commit comments