aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/cifs/smb2ops.c62
1 files changed, 46 insertions, 16 deletions
diff --git a/fs/cifs/smb2ops.c b/fs/cifs/smb2ops.c
index 1c8d3684bb8b..1022a3771e14 100644
--- a/fs/cifs/smb2ops.c
+++ b/fs/cifs/smb2ops.c
@@ -1330,7 +1330,8 @@ smb2_ioctl_query_info(const unsigned int xid,
1330 struct smb_query_info __user *pqi; 1330 struct smb_query_info __user *pqi;
1331 int rc = 0; 1331 int rc = 0;
1332 int flags = 0; 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 void *buffer = NULL; 1335 void *buffer = NULL;
1335 struct smb_rqst rqst[3]; 1336 struct smb_rqst rqst[3];
1336 int resp_buftype[3]; 1337 int resp_buftype[3];
@@ -1340,6 +1341,7 @@ smb2_ioctl_query_info(const unsigned int xid,
1340 u8 oplock = SMB2_OPLOCK_LEVEL_NONE; 1341 u8 oplock = SMB2_OPLOCK_LEVEL_NONE;
1341 struct cifs_fid fid; 1342 struct cifs_fid fid;
1342 struct kvec qi_iov[1]; 1343 struct kvec qi_iov[1];
1344 struct kvec io_iov[SMB2_IOCTL_IOV_SIZE];
1343 struct kvec close_iov[1]; 1345 struct kvec close_iov[1];
1344 1346
1345 memset(rqst, 0, sizeof(rqst)); 1347 memset(rqst, 0, sizeof(rqst));
@@ -1394,8 +1396,16 @@ smb2_ioctl_query_info(const unsigned int xid,
1394 /* Can eventually relax perm check since server enforces too */ 1396 /* Can eventually relax perm check since server enforces too */
1395 if (!capable(CAP_SYS_ADMIN)) 1397 if (!capable(CAP_SYS_ADMIN))
1396 rc = -EPERM; 1398 rc = -EPERM;
1397 else /* TBD: Add code to compound FSCTL */ 1399 else {
1398 rc = -EOPNOTSUPP; 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 } else if (qi.flags == PASSTHRU_QUERY_INFO) { 1409 } else if (qi.flags == PASSTHRU_QUERY_INFO) {
1400 memset(&qi_iov, 0, sizeof(qi_iov)); 1410 memset(&qi_iov, 0, sizeof(qi_iov));
1401 rqst[1].rq_iov = qi_iov; 1411 rqst[1].rq_iov = qi_iov;
@@ -1430,24 +1440,44 @@ smb2_ioctl_query_info(const unsigned int xid,
1430 resp_buftype, rsp_iov); 1440 resp_buftype, rsp_iov);
1431 if (rc) 1441 if (rc)
1432 goto iqinf_exit; 1442 goto iqinf_exit;
1433 pqi = (struct smb_query_info __user *)arg; 1443 if (qi.flags & PASSTHRU_FSCTL) {
1434 rsp = (struct smb2_query_info_rsp *)rsp_iov[1].iov_base; 1444 pqi = (struct smb_query_info __user *)arg;
1435 if (le32_to_cpu(rsp->OutputBufferLength) < qi.input_buffer_length) 1445 io_rsp = (struct smb2_ioctl_rsp *)rsp_iov[1].iov_base;
1436 qi.input_buffer_length = le32_to_cpu(rsp->OutputBufferLength); 1446 if (le32_to_cpu(io_rsp->OutputCount) < qi.input_buffer_length)
1437 if (copy_to_user(&pqi->input_buffer_length, &qi.input_buffer_length, 1447 qi.input_buffer_length = le32_to_cpu(io_rsp->OutputCount);
1438 sizeof(qi.input_buffer_length))) { 1448 if (copy_to_user(&pqi->input_buffer_length, &qi.input_buffer_length,
1439 rc = -EFAULT; 1449 sizeof(qi.input_buffer_length))) {
1440 goto iqinf_exit; 1450 rc = -EFAULT;
1441 } 1451 goto iqinf_exit;
1442 if (copy_to_user(pqi + 1, rsp->Buffer, qi.input_buffer_length)) { 1452 }
1443 rc = -EFAULT; 1453 if (copy_to_user(pqi + 1, &io_rsp[1], qi.input_buffer_length)) {
1444 goto iqinf_exit; 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 iqinf_exit: 1473 iqinf_exit:
1448 kfree(buffer); 1474 kfree(buffer);
1449 SMB2_open_free(&rqst[0]); 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 SMB2_close_free(&rqst[2]); 1481 SMB2_close_free(&rqst[2]);
1452 free_rsp_buf(resp_buftype[0], rsp_iov[0].iov_base); 1482 free_rsp_buf(resp_buftype[0], rsp_iov[0].iov_base);
1453 free_rsp_buf(resp_buftype[1], rsp_iov[1].iov_base); 1483 free_rsp_buf(resp_buftype[1], rsp_iov[1].iov_base);