diff options
-rw-r--r-- | fs/cifs/smb2pdu.c | 101 |
1 files changed, 50 insertions, 51 deletions
diff --git a/fs/cifs/smb2pdu.c b/fs/cifs/smb2pdu.c index 3c92678cb45b..641fe79708d0 100644 --- a/fs/cifs/smb2pdu.c +++ b/fs/cifs/smb2pdu.c @@ -1928,7 +1928,7 @@ int smb311_posix_mkdir(const unsigned int xid, struct inode *inode, { struct smb_rqst rqst; struct smb2_create_req *req; - struct smb2_create_rsp *rsp; + struct smb2_create_rsp *rsp = NULL; struct TCP_Server_Info *server; struct cifs_ses *ses = tcon->ses; struct kvec iov[3]; /* make sure at least one for each open context */ @@ -1943,27 +1943,31 @@ int smb311_posix_mkdir(const unsigned int xid, struct inode *inode, char *pc_buf = NULL; int flags = 0; unsigned int total_len; - __le16 *path = cifs_convert_path_to_utf16(full_path, cifs_sb); - - if (!path) - return -ENOMEM; + __le16 *utf16_path = NULL; cifs_dbg(FYI, "mkdir\n"); + /* resource #1: path allocation */ + utf16_path = cifs_convert_path_to_utf16(full_path, cifs_sb); + if (!utf16_path) + return -ENOMEM; + if (ses && (ses->server)) server = ses->server; - else - return -EIO; + else { + rc = -EIO; + goto err_free_path; + } + /* resource #2: request */ rc = smb2_plain_req_init(SMB2_CREATE, tcon, (void **) &req, &total_len); - if (rc) - return rc; + goto err_free_path; + if (smb3_encryption_required(tcon)) flags |= CIFS_TRANSFORM_REQ; - req->ImpersonationLevel = IL_IMPERSONATION; req->DesiredAccess = cpu_to_le32(FILE_WRITE_ATTRIBUTES); /* File attributes ignored on open (used in create though) */ @@ -1992,50 +1996,44 @@ int smb311_posix_mkdir(const unsigned int xid, struct inode *inode, req->sync_hdr.Flags |= SMB2_FLAGS_DFS_OPERATIONS; rc = alloc_path_with_tree_prefix(©_path, ©_size, &name_len, - tcon->treeName, path); - if (rc) { - cifs_small_buf_release(req); - return rc; - } + tcon->treeName, utf16_path); + if (rc) + goto err_free_req; + req->NameLength = cpu_to_le16(name_len * 2); uni_path_len = copy_size; - path = copy_path; + /* free before overwriting resource */ + kfree(utf16_path); + utf16_path = copy_path; } else { - uni_path_len = (2 * UniStrnlen((wchar_t *)path, PATH_MAX)) + 2; + uni_path_len = (2 * UniStrnlen((wchar_t *)utf16_path, PATH_MAX)) + 2; /* MUST set path len (NameLength) to 0 opening root of share */ req->NameLength = cpu_to_le16(uni_path_len - 2); if (uni_path_len % 8 != 0) { copy_size = roundup(uni_path_len, 8); copy_path = kzalloc(copy_size, GFP_KERNEL); if (!copy_path) { - cifs_small_buf_release(req); - return -ENOMEM; + rc = -ENOMEM; + goto err_free_req; } - memcpy((char *)copy_path, (const char *)path, + memcpy((char *)copy_path, (const char *)utf16_path, uni_path_len); uni_path_len = copy_size; - path = copy_path; + /* free before overwriting resource */ + kfree(utf16_path); + utf16_path = copy_path; } } iov[1].iov_len = uni_path_len; - iov[1].iov_base = path; + iov[1].iov_base = utf16_path; req->RequestedOplockLevel = SMB2_OPLOCK_LEVEL_NONE; if (tcon->posix_extensions) { - if (n_iov > 2) { - struct create_context *ccontext = - (struct create_context *)iov[n_iov-1].iov_base; - ccontext->Next = - cpu_to_le32(iov[n_iov-1].iov_len); - } - + /* resource #3: posix buf */ rc = add_posix_context(iov, &n_iov, mode); - if (rc) { - cifs_small_buf_release(req); - kfree(copy_path); - return rc; - } + if (rc) + goto err_free_req; pc_buf = iov[n_iov-1].iov_base; } @@ -2044,32 +2042,33 @@ int smb311_posix_mkdir(const unsigned int xid, struct inode *inode, rqst.rq_iov = iov; rqst.rq_nvec = n_iov; - rc = cifs_send_recv(xid, ses, &rqst, &resp_buftype, flags, - &rsp_iov); - - cifs_small_buf_release(req); - rsp = (struct smb2_create_rsp *)rsp_iov.iov_base; - - if (rc != 0) { + /* resource #4: response buffer */ + rc = cifs_send_recv(xid, ses, &rqst, &resp_buftype, flags, &rsp_iov); + if (rc) { cifs_stats_fail_inc(tcon, SMB2_CREATE_HE); trace_smb3_posix_mkdir_err(xid, tcon->tid, ses->Suid, - CREATE_NOT_FILE, FILE_WRITE_ATTRIBUTES, rc); - goto smb311_mkdir_exit; - } else - trace_smb3_posix_mkdir_done(xid, rsp->PersistentFileId, tcon->tid, - ses->Suid, CREATE_NOT_FILE, - FILE_WRITE_ATTRIBUTES); + CREATE_NOT_FILE, + FILE_WRITE_ATTRIBUTES, rc); + goto err_free_rsp_buf; + } + + rsp = (struct smb2_create_rsp *)rsp_iov.iov_base; + trace_smb3_posix_mkdir_done(xid, rsp->PersistentFileId, tcon->tid, + ses->Suid, CREATE_NOT_FILE, + FILE_WRITE_ATTRIBUTES); SMB2_close(xid, tcon, rsp->PersistentFileId, rsp->VolatileFileId); /* Eventually save off posix specific response info and timestaps */ -smb311_mkdir_exit: - kfree(copy_path); - kfree(pc_buf); +err_free_rsp_buf: free_rsp_buf(resp_buftype, rsp); + kfree(pc_buf); +err_free_req: + cifs_small_buf_release(req); +err_free_path: + kfree(utf16_path); return rc; - } #endif /* SMB311 */ |