@@ -1330,7 +1330,8 @@ smb2_ioctl_query_info(const unsigned int xid,
1330
1330
struct smb_query_info __user * pqi ;
1331
1331
int rc = 0 ;
1332
1332
int flags = 0 ;
1333
- struct smb2_query_info_rsp * rsp = NULL ;
1333
+ struct smb2_query_info_rsp * qi_rsp = NULL ;
1334
+ struct smb2_ioctl_rsp * io_rsp = NULL ;
1334
1335
void * buffer = NULL ;
1335
1336
struct smb_rqst rqst [3 ];
1336
1337
int resp_buftype [3 ];
@@ -1340,6 +1341,7 @@ smb2_ioctl_query_info(const unsigned int xid,
1340
1341
u8 oplock = SMB2_OPLOCK_LEVEL_NONE ;
1341
1342
struct cifs_fid fid ;
1342
1343
struct kvec qi_iov [1 ];
1344
+ struct kvec io_iov [SMB2_IOCTL_IOV_SIZE ];
1343
1345
struct kvec close_iov [1 ];
1344
1346
1345
1347
memset (rqst , 0 , sizeof (rqst ));
@@ -1394,8 +1396,16 @@ smb2_ioctl_query_info(const unsigned int xid,
1394
1396
/* Can eventually relax perm check since server enforces too */
1395
1397
if (!capable (CAP_SYS_ADMIN ))
1396
1398
rc = - EPERM ;
1397
- else /* TBD: Add code to compound FSCTL */
1398
- rc = - EOPNOTSUPP ;
1399
+ else {
1400
+ memset (& io_iov , 0 , sizeof (io_iov ));
1401
+ rqst [1 ].rq_iov = io_iov ;
1402
+ rqst [1 ].rq_nvec = SMB2_IOCTL_IOV_SIZE ;
1403
+
1404
+ rc = SMB2_ioctl_init (tcon , & rqst [1 ],
1405
+ COMPOUND_FID , COMPOUND_FID ,
1406
+ qi .info_type , true, NULL ,
1407
+ 0 );
1408
+ }
1399
1409
} else if (qi .flags == PASSTHRU_QUERY_INFO ) {
1400
1410
memset (& qi_iov , 0 , sizeof (qi_iov ));
1401
1411
rqst [1 ].rq_iov = qi_iov ;
@@ -1430,24 +1440,44 @@ smb2_ioctl_query_info(const unsigned int xid,
1430
1440
resp_buftype , rsp_iov );
1431
1441
if (rc )
1432
1442
goto iqinf_exit ;
1433
- pqi = (struct smb_query_info __user * )arg ;
1434
- rsp = (struct smb2_query_info_rsp * )rsp_iov [1 ].iov_base ;
1435
- if (le32_to_cpu (rsp -> OutputBufferLength ) < qi .input_buffer_length )
1436
- qi .input_buffer_length = le32_to_cpu (rsp -> OutputBufferLength );
1437
- if (copy_to_user (& pqi -> input_buffer_length , & qi .input_buffer_length ,
1438
- sizeof (qi .input_buffer_length ))) {
1439
- rc = - EFAULT ;
1440
- goto iqinf_exit ;
1441
- }
1442
- if (copy_to_user (pqi + 1 , rsp -> Buffer , qi .input_buffer_length )) {
1443
- rc = - EFAULT ;
1444
- goto iqinf_exit ;
1443
+ if (qi .flags & PASSTHRU_FSCTL ) {
1444
+ pqi = (struct smb_query_info __user * )arg ;
1445
+ io_rsp = (struct smb2_ioctl_rsp * )rsp_iov [1 ].iov_base ;
1446
+ if (le32_to_cpu (io_rsp -> OutputCount ) < qi .input_buffer_length )
1447
+ qi .input_buffer_length = le32_to_cpu (io_rsp -> OutputCount );
1448
+ if (copy_to_user (& pqi -> input_buffer_length , & qi .input_buffer_length ,
1449
+ sizeof (qi .input_buffer_length ))) {
1450
+ rc = - EFAULT ;
1451
+ goto iqinf_exit ;
1452
+ }
1453
+ if (copy_to_user (pqi + 1 , & io_rsp [1 ], qi .input_buffer_length )) {
1454
+ rc = - EFAULT ;
1455
+ goto iqinf_exit ;
1456
+ }
1457
+ } else {
1458
+ pqi = (struct smb_query_info __user * )arg ;
1459
+ qi_rsp = (struct smb2_query_info_rsp * )rsp_iov [1 ].iov_base ;
1460
+ if (le32_to_cpu (qi_rsp -> OutputBufferLength ) < qi .input_buffer_length )
1461
+ qi .input_buffer_length = le32_to_cpu (qi_rsp -> OutputBufferLength );
1462
+ if (copy_to_user (& pqi -> input_buffer_length , & qi .input_buffer_length ,
1463
+ sizeof (qi .input_buffer_length ))) {
1464
+ rc = - EFAULT ;
1465
+ goto iqinf_exit ;
1466
+ }
1467
+ if (copy_to_user (pqi + 1 , qi_rsp -> Buffer , qi .input_buffer_length )) {
1468
+ rc = - EFAULT ;
1469
+ goto iqinf_exit ;
1470
+ }
1445
1471
}
1446
1472
1447
1473
iqinf_exit :
1448
1474
kfree (buffer );
1449
1475
SMB2_open_free (& rqst [0 ]);
1450
- SMB2_query_info_free (& rqst [1 ]);
1476
+ if (qi .flags & PASSTHRU_FSCTL )
1477
+ SMB2_ioctl_free (& rqst [1 ]);
1478
+ else
1479
+ SMB2_query_info_free (& rqst [1 ]);
1480
+
1451
1481
SMB2_close_free (& rqst [2 ]);
1452
1482
free_rsp_buf (resp_buftype [0 ], rsp_iov [0 ].iov_base );
1453
1483
free_rsp_buf (resp_buftype [1 ], rsp_iov [1 ].iov_base );
0 commit comments