Loading fs/cifs/smb2pdu.c +76 −57 Original line number Diff line number Diff line Loading @@ -2468,65 +2468,46 @@ SMB2_open(const unsigned int xid, struct cifs_open_parms *oparms, __le16 *path, return rc; } /* * SMB2 IOCTL is used for both IOCTLs and FSCTLs */ int SMB2_ioctl(const unsigned int xid, struct cifs_tcon *tcon, u64 persistent_fid, u64 volatile_fid, u32 opcode, bool is_fsctl, char *in_data, u32 indatalen, char **out_data, u32 *plen /* returned data len */) SMB2_ioctl_init(struct cifs_tcon *tcon, struct smb_rqst *rqst, u64 persistent_fid, u64 volatile_fid, u32 opcode, bool is_fsctl, char *in_data, u32 indatalen) { struct smb_rqst rqst; struct smb2_ioctl_req *req; struct smb2_ioctl_rsp *rsp; struct cifs_ses *ses; struct kvec iov[2]; struct kvec rsp_iov; int resp_buftype; int n_iov; int rc = 0; int flags = 0; struct kvec *iov = rqst->rq_iov; unsigned int total_len; cifs_dbg(FYI, "SMB2 IOCTL\n"); if (out_data != NULL) *out_data = NULL; /* zero out returned data len, in case of error */ if (plen) *plen = 0; if (tcon) ses = tcon->ses; else return -EIO; if (!ses || !(ses->server)) return -EIO; int rc; rc = smb2_plain_req_init(SMB2_IOCTL, tcon, (void **) &req, &total_len); if (rc) return rc; if (smb3_encryption_required(tcon)) flags |= CIFS_TRANSFORM_REQ; req->CtlCode = cpu_to_le32(opcode); req->PersistentFileId = persistent_fid; req->VolatileFileId = volatile_fid; iov[0].iov_base = (char *)req; /* * If no input data, the size of ioctl struct in * protocol spec still includes a 1 byte data buffer, * but if input data passed to ioctl, we do not * want to double count this, so we do not send * the dummy one byte of data in iovec[0] if sending * input data (in iovec[1]). */ if (indatalen) { req->InputCount = cpu_to_le32(indatalen); /* do not set InputOffset if no input data */ req->InputOffset = cpu_to_le32(offsetof(struct smb2_ioctl_req, Buffer)); rqst->rq_nvec = 2; iov[0].iov_len = total_len - 1; iov[1].iov_base = in_data; iov[1].iov_len = indatalen; n_iov = 2; } else n_iov = 1; } else { rqst->rq_nvec = 1; iov[0].iov_len = total_len; } req->OutputOffset = 0; req->OutputCount = 0; /* MBZ */ Loading @@ -2548,33 +2529,70 @@ SMB2_ioctl(const unsigned int xid, struct cifs_tcon *tcon, u64 persistent_fid, else req->Flags = 0; iov[0].iov_base = (char *)req; /* validate negotiate request must be signed - see MS-SMB2 3.2.5.5 */ if (opcode == FSCTL_VALIDATE_NEGOTIATE_INFO) req->sync_hdr.Flags |= SMB2_FLAGS_SIGNED; return 0; } void SMB2_ioctl_free(struct smb_rqst *rqst) { if (rqst && rqst->rq_iov) cifs_small_buf_release(rqst->rq_iov[0].iov_base); /* request */ } /* * If no input data, the size of ioctl struct in * protocol spec still includes a 1 byte data buffer, * but if input data passed to ioctl, we do not * want to double count this, so we do not send * the dummy one byte of data in iovec[0] if sending * input data (in iovec[1]). * SMB2 IOCTL is used for both IOCTLs and FSCTLs */ int SMB2_ioctl(const unsigned int xid, struct cifs_tcon *tcon, u64 persistent_fid, u64 volatile_fid, u32 opcode, bool is_fsctl, char *in_data, u32 indatalen, char **out_data, u32 *plen /* returned data len */) { struct smb_rqst rqst; struct smb2_ioctl_rsp *rsp = NULL; struct cifs_ses *ses; struct kvec iov[2]; struct kvec rsp_iov = {NULL, 0}; int resp_buftype = CIFS_NO_BUFFER; int rc = 0; int flags = 0; if (indatalen) { iov[0].iov_len = total_len - 1; } else iov[0].iov_len = total_len; cifs_dbg(FYI, "SMB2 IOCTL\n"); /* validate negotiate request must be signed - see MS-SMB2 3.2.5.5 */ if (opcode == FSCTL_VALIDATE_NEGOTIATE_INFO) req->sync_hdr.Flags |= SMB2_FLAGS_SIGNED; if (out_data != NULL) *out_data = NULL; /* zero out returned data len, in case of error */ if (plen) *plen = 0; if (tcon) ses = tcon->ses; else return -EIO; if (!ses || !(ses->server)) return -EIO; if (smb3_encryption_required(tcon)) flags |= CIFS_TRANSFORM_REQ; memset(&rqst, 0, sizeof(struct smb_rqst)); memset(&iov, 0, sizeof(iov)); rqst.rq_iov = iov; rqst.rq_nvec = n_iov; rqst.rq_nvec = 2; rc = SMB2_ioctl_init(tcon, &rqst, persistent_fid, volatile_fid, opcode, is_fsctl, in_data, indatalen); if (rc) goto ioctl_exit; rc = cifs_send_recv(xid, ses, &rqst, &resp_buftype, flags, &rsp_iov); cifs_small_buf_release(req); rsp = (struct smb2_ioctl_rsp *)rsp_iov.iov_base; if (rc != 0) Loading Loading @@ -2624,6 +2642,7 @@ SMB2_ioctl(const unsigned int xid, struct cifs_tcon *tcon, u64 persistent_fid, } ioctl_exit: SMB2_ioctl_free(&rqst); free_rsp_buf(resp_buftype, rsp); return rc; } Loading fs/cifs/smb2proto.h +4 −0 Original line number Diff line number Diff line Loading @@ -144,6 +144,10 @@ extern int SMB2_ioctl(const unsigned int xid, struct cifs_tcon *tcon, u64 persistent_fid, u64 volatile_fid, u32 opcode, bool is_fsctl, char *in_data, u32 indatalen, char **out_data, u32 *plen /* returned data len */); extern int SMB2_ioctl_init(struct cifs_tcon *tcon, struct smb_rqst *rqst, u64 persistent_fid, u64 volatile_fid, u32 opcode, bool is_fsctl, char *in_data, u32 indatalen); extern void SMB2_ioctl_free(struct smb_rqst *rqst); extern int SMB2_close(const unsigned int xid, struct cifs_tcon *tcon, u64 persistent_file_id, u64 volatile_file_id); extern int SMB2_close_flags(const unsigned int xid, struct cifs_tcon *tcon, Loading Loading
fs/cifs/smb2pdu.c +76 −57 Original line number Diff line number Diff line Loading @@ -2468,65 +2468,46 @@ SMB2_open(const unsigned int xid, struct cifs_open_parms *oparms, __le16 *path, return rc; } /* * SMB2 IOCTL is used for both IOCTLs and FSCTLs */ int SMB2_ioctl(const unsigned int xid, struct cifs_tcon *tcon, u64 persistent_fid, u64 volatile_fid, u32 opcode, bool is_fsctl, char *in_data, u32 indatalen, char **out_data, u32 *plen /* returned data len */) SMB2_ioctl_init(struct cifs_tcon *tcon, struct smb_rqst *rqst, u64 persistent_fid, u64 volatile_fid, u32 opcode, bool is_fsctl, char *in_data, u32 indatalen) { struct smb_rqst rqst; struct smb2_ioctl_req *req; struct smb2_ioctl_rsp *rsp; struct cifs_ses *ses; struct kvec iov[2]; struct kvec rsp_iov; int resp_buftype; int n_iov; int rc = 0; int flags = 0; struct kvec *iov = rqst->rq_iov; unsigned int total_len; cifs_dbg(FYI, "SMB2 IOCTL\n"); if (out_data != NULL) *out_data = NULL; /* zero out returned data len, in case of error */ if (plen) *plen = 0; if (tcon) ses = tcon->ses; else return -EIO; if (!ses || !(ses->server)) return -EIO; int rc; rc = smb2_plain_req_init(SMB2_IOCTL, tcon, (void **) &req, &total_len); if (rc) return rc; if (smb3_encryption_required(tcon)) flags |= CIFS_TRANSFORM_REQ; req->CtlCode = cpu_to_le32(opcode); req->PersistentFileId = persistent_fid; req->VolatileFileId = volatile_fid; iov[0].iov_base = (char *)req; /* * If no input data, the size of ioctl struct in * protocol spec still includes a 1 byte data buffer, * but if input data passed to ioctl, we do not * want to double count this, so we do not send * the dummy one byte of data in iovec[0] if sending * input data (in iovec[1]). */ if (indatalen) { req->InputCount = cpu_to_le32(indatalen); /* do not set InputOffset if no input data */ req->InputOffset = cpu_to_le32(offsetof(struct smb2_ioctl_req, Buffer)); rqst->rq_nvec = 2; iov[0].iov_len = total_len - 1; iov[1].iov_base = in_data; iov[1].iov_len = indatalen; n_iov = 2; } else n_iov = 1; } else { rqst->rq_nvec = 1; iov[0].iov_len = total_len; } req->OutputOffset = 0; req->OutputCount = 0; /* MBZ */ Loading @@ -2548,33 +2529,70 @@ SMB2_ioctl(const unsigned int xid, struct cifs_tcon *tcon, u64 persistent_fid, else req->Flags = 0; iov[0].iov_base = (char *)req; /* validate negotiate request must be signed - see MS-SMB2 3.2.5.5 */ if (opcode == FSCTL_VALIDATE_NEGOTIATE_INFO) req->sync_hdr.Flags |= SMB2_FLAGS_SIGNED; return 0; } void SMB2_ioctl_free(struct smb_rqst *rqst) { if (rqst && rqst->rq_iov) cifs_small_buf_release(rqst->rq_iov[0].iov_base); /* request */ } /* * If no input data, the size of ioctl struct in * protocol spec still includes a 1 byte data buffer, * but if input data passed to ioctl, we do not * want to double count this, so we do not send * the dummy one byte of data in iovec[0] if sending * input data (in iovec[1]). * SMB2 IOCTL is used for both IOCTLs and FSCTLs */ int SMB2_ioctl(const unsigned int xid, struct cifs_tcon *tcon, u64 persistent_fid, u64 volatile_fid, u32 opcode, bool is_fsctl, char *in_data, u32 indatalen, char **out_data, u32 *plen /* returned data len */) { struct smb_rqst rqst; struct smb2_ioctl_rsp *rsp = NULL; struct cifs_ses *ses; struct kvec iov[2]; struct kvec rsp_iov = {NULL, 0}; int resp_buftype = CIFS_NO_BUFFER; int rc = 0; int flags = 0; if (indatalen) { iov[0].iov_len = total_len - 1; } else iov[0].iov_len = total_len; cifs_dbg(FYI, "SMB2 IOCTL\n"); /* validate negotiate request must be signed - see MS-SMB2 3.2.5.5 */ if (opcode == FSCTL_VALIDATE_NEGOTIATE_INFO) req->sync_hdr.Flags |= SMB2_FLAGS_SIGNED; if (out_data != NULL) *out_data = NULL; /* zero out returned data len, in case of error */ if (plen) *plen = 0; if (tcon) ses = tcon->ses; else return -EIO; if (!ses || !(ses->server)) return -EIO; if (smb3_encryption_required(tcon)) flags |= CIFS_TRANSFORM_REQ; memset(&rqst, 0, sizeof(struct smb_rqst)); memset(&iov, 0, sizeof(iov)); rqst.rq_iov = iov; rqst.rq_nvec = n_iov; rqst.rq_nvec = 2; rc = SMB2_ioctl_init(tcon, &rqst, persistent_fid, volatile_fid, opcode, is_fsctl, in_data, indatalen); if (rc) goto ioctl_exit; rc = cifs_send_recv(xid, ses, &rqst, &resp_buftype, flags, &rsp_iov); cifs_small_buf_release(req); rsp = (struct smb2_ioctl_rsp *)rsp_iov.iov_base; if (rc != 0) Loading Loading @@ -2624,6 +2642,7 @@ SMB2_ioctl(const unsigned int xid, struct cifs_tcon *tcon, u64 persistent_fid, } ioctl_exit: SMB2_ioctl_free(&rqst); free_rsp_buf(resp_buftype, rsp); return rc; } Loading
fs/cifs/smb2proto.h +4 −0 Original line number Diff line number Diff line Loading @@ -144,6 +144,10 @@ extern int SMB2_ioctl(const unsigned int xid, struct cifs_tcon *tcon, u64 persistent_fid, u64 volatile_fid, u32 opcode, bool is_fsctl, char *in_data, u32 indatalen, char **out_data, u32 *plen /* returned data len */); extern int SMB2_ioctl_init(struct cifs_tcon *tcon, struct smb_rqst *rqst, u64 persistent_fid, u64 volatile_fid, u32 opcode, bool is_fsctl, char *in_data, u32 indatalen); extern void SMB2_ioctl_free(struct smb_rqst *rqst); extern int SMB2_close(const unsigned int xid, struct cifs_tcon *tcon, u64 persistent_file_id, u64 volatile_file_id); extern int SMB2_close_flags(const unsigned int xid, struct cifs_tcon *tcon, Loading