Skip to content

Commit f5778c3

Browse files
Ronnie SahlbergSteve French
authored andcommitted
SMB3: Allow SMB3 FSCTL queries to be sent to server from tools
For debugging purposes we often have to be able to query additional information only available via SMB3 FSCTL from the server from user space tools (e.g. like cifs-utils's smbinfo). See MS-FSCC and MS-SMB2 protocol specifications for more details. Signed-off-by: Ronnie Sahlberg <lsahlber@redhat.com> Signed-off-by: Steve French <stfrench@microsoft.com>
1 parent f169947 commit f5778c3

File tree

1 file changed

+46
-16
lines changed

1 file changed

+46
-16
lines changed

fs/cifs/smb2ops.c

Lines changed: 46 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1330,7 +1330,8 @@ smb2_ioctl_query_info(const unsigned int xid,
13301330
struct smb_query_info __user *pqi;
13311331
int rc = 0;
13321332
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;
13341335
void *buffer = NULL;
13351336
struct smb_rqst rqst[3];
13361337
int resp_buftype[3];
@@ -1340,6 +1341,7 @@ smb2_ioctl_query_info(const unsigned int xid,
13401341
u8 oplock = SMB2_OPLOCK_LEVEL_NONE;
13411342
struct cifs_fid fid;
13421343
struct kvec qi_iov[1];
1344+
struct kvec io_iov[SMB2_IOCTL_IOV_SIZE];
13431345
struct kvec close_iov[1];
13441346

13451347
memset(rqst, 0, sizeof(rqst));
@@ -1394,8 +1396,16 @@ smb2_ioctl_query_info(const unsigned int xid,
13941396
/* Can eventually relax perm check since server enforces too */
13951397
if (!capable(CAP_SYS_ADMIN))
13961398
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+
}
13991409
} else if (qi.flags == PASSTHRU_QUERY_INFO) {
14001410
memset(&qi_iov, 0, sizeof(qi_iov));
14011411
rqst[1].rq_iov = qi_iov;
@@ -1430,24 +1440,44 @@ smb2_ioctl_query_info(const unsigned int xid,
14301440
resp_buftype, rsp_iov);
14311441
if (rc)
14321442
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+
}
14451471
}
14461472

14471473
iqinf_exit:
14481474
kfree(buffer);
14491475
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+
14511481
SMB2_close_free(&rqst[2]);
14521482
free_rsp_buf(resp_buftype[0], rsp_iov[0].iov_base);
14531483
free_rsp_buf(resp_buftype[1], rsp_iov[1].iov_base);

0 commit comments

Comments
 (0)