1*1cdd5a26SSteve French // SPDX-License-Identifier: LGPL-2.1 2*1cdd5a26SSteve French /* 3*1cdd5a26SSteve French * 4*1cdd5a26SSteve French * Copyright (C) International Business Machines Corp., 2002,2008 5*1cdd5a26SSteve French * Author(s): Steve French (sfrench@us.ibm.com) 6*1cdd5a26SSteve French * Jeremy Allison (jra@samba.org) 2006. 7*1cdd5a26SSteve French * 8*1cdd5a26SSteve French */ 9*1cdd5a26SSteve French 10*1cdd5a26SSteve French #include <linux/fs.h> 11*1cdd5a26SSteve French #include <linux/list.h> 12*1cdd5a26SSteve French #include <linux/gfp.h> 13*1cdd5a26SSteve French #include <linux/wait.h> 14*1cdd5a26SSteve French #include <linux/net.h> 15*1cdd5a26SSteve French #include <linux/delay.h> 16*1cdd5a26SSteve French #include <linux/freezer.h> 17*1cdd5a26SSteve French #include <linux/tcp.h> 18*1cdd5a26SSteve French #include <linux/bvec.h> 19*1cdd5a26SSteve French #include <linux/highmem.h> 20*1cdd5a26SSteve French #include <linux/uaccess.h> 21*1cdd5a26SSteve French #include <linux/processor.h> 22*1cdd5a26SSteve French #include <linux/mempool.h> 23*1cdd5a26SSteve French #include <linux/sched/signal.h> 24*1cdd5a26SSteve French #include <linux/task_io_accounting_ops.h> 25*1cdd5a26SSteve French #include "cifspdu.h" 26*1cdd5a26SSteve French #include "cifsglob.h" 27*1cdd5a26SSteve French #include "cifsproto.h" 28*1cdd5a26SSteve French #include "cifs_debug.h" 29*1cdd5a26SSteve French #include "smb2proto.h" 30*1cdd5a26SSteve French #include "smbdirect.h" 31*1cdd5a26SSteve French #include "compress.h" 32*1cdd5a26SSteve French 33*1cdd5a26SSteve French /* Max number of iovectors we can use off the stack when sending requests. */ 34*1cdd5a26SSteve French #define CIFS_MAX_IOV_SIZE 8 35*1cdd5a26SSteve French 36*1cdd5a26SSteve French static struct mid_q_entry * 37*1cdd5a26SSteve French alloc_mid(const struct smb_hdr *smb_buffer, struct TCP_Server_Info *server) 38*1cdd5a26SSteve French { 39*1cdd5a26SSteve French struct mid_q_entry *temp; 40*1cdd5a26SSteve French 41*1cdd5a26SSteve French if (server == NULL) { 42*1cdd5a26SSteve French cifs_dbg(VFS, "%s: null TCP session\n", __func__); 43*1cdd5a26SSteve French return NULL; 44*1cdd5a26SSteve French } 45*1cdd5a26SSteve French 46*1cdd5a26SSteve French temp = mempool_alloc(cifs_mid_poolp, GFP_NOFS); 47*1cdd5a26SSteve French memset(temp, 0, sizeof(struct mid_q_entry)); 48*1cdd5a26SSteve French kref_init(&temp->refcount); 49*1cdd5a26SSteve French temp->mid = get_mid(smb_buffer); 50*1cdd5a26SSteve French temp->pid = current->pid; 51*1cdd5a26SSteve French temp->command = cpu_to_le16(smb_buffer->Command); 52*1cdd5a26SSteve French cifs_dbg(FYI, "For smb_command %d\n", smb_buffer->Command); 53*1cdd5a26SSteve French /* easier to use jiffies */ 54*1cdd5a26SSteve French /* when mid allocated can be before when sent */ 55*1cdd5a26SSteve French temp->when_alloc = jiffies; 56*1cdd5a26SSteve French temp->server = server; 57*1cdd5a26SSteve French 58*1cdd5a26SSteve French /* 59*1cdd5a26SSteve French * The default is for the mid to be synchronous, so the 60*1cdd5a26SSteve French * default callback just wakes up the current task. 61*1cdd5a26SSteve French */ 62*1cdd5a26SSteve French get_task_struct(current); 63*1cdd5a26SSteve French temp->creator = current; 64*1cdd5a26SSteve French temp->callback = cifs_wake_up_task; 65*1cdd5a26SSteve French temp->callback_data = current; 66*1cdd5a26SSteve French 67*1cdd5a26SSteve French atomic_inc(&mid_count); 68*1cdd5a26SSteve French temp->mid_state = MID_REQUEST_ALLOCATED; 69*1cdd5a26SSteve French return temp; 70*1cdd5a26SSteve French } 71*1cdd5a26SSteve French 72*1cdd5a26SSteve French int 73*1cdd5a26SSteve French smb_send(struct TCP_Server_Info *server, struct smb_hdr *smb_buffer, 74*1cdd5a26SSteve French unsigned int smb_buf_length) 75*1cdd5a26SSteve French { 76*1cdd5a26SSteve French struct kvec iov[2]; 77*1cdd5a26SSteve French struct smb_rqst rqst = { .rq_iov = iov, 78*1cdd5a26SSteve French .rq_nvec = 2 }; 79*1cdd5a26SSteve French 80*1cdd5a26SSteve French iov[0].iov_base = smb_buffer; 81*1cdd5a26SSteve French iov[0].iov_len = 4; 82*1cdd5a26SSteve French iov[1].iov_base = (char *)smb_buffer + 4; 83*1cdd5a26SSteve French iov[1].iov_len = smb_buf_length; 84*1cdd5a26SSteve French 85*1cdd5a26SSteve French return __smb_send_rqst(server, 1, &rqst); 86*1cdd5a26SSteve French } 87*1cdd5a26SSteve French 88*1cdd5a26SSteve French static int allocate_mid(struct cifs_ses *ses, struct smb_hdr *in_buf, 89*1cdd5a26SSteve French struct mid_q_entry **ppmidQ) 90*1cdd5a26SSteve French { 91*1cdd5a26SSteve French spin_lock(&ses->ses_lock); 92*1cdd5a26SSteve French if (ses->ses_status == SES_NEW) { 93*1cdd5a26SSteve French if ((in_buf->Command != SMB_COM_SESSION_SETUP_ANDX) && 94*1cdd5a26SSteve French (in_buf->Command != SMB_COM_NEGOTIATE)) { 95*1cdd5a26SSteve French spin_unlock(&ses->ses_lock); 96*1cdd5a26SSteve French return -EAGAIN; 97*1cdd5a26SSteve French } 98*1cdd5a26SSteve French /* else ok - we are setting up session */ 99*1cdd5a26SSteve French } 100*1cdd5a26SSteve French 101*1cdd5a26SSteve French if (ses->ses_status == SES_EXITING) { 102*1cdd5a26SSteve French /* check if SMB session is bad because we are setting it up */ 103*1cdd5a26SSteve French if (in_buf->Command != SMB_COM_LOGOFF_ANDX) { 104*1cdd5a26SSteve French spin_unlock(&ses->ses_lock); 105*1cdd5a26SSteve French return -EAGAIN; 106*1cdd5a26SSteve French } 107*1cdd5a26SSteve French /* else ok - we are shutting down session */ 108*1cdd5a26SSteve French } 109*1cdd5a26SSteve French spin_unlock(&ses->ses_lock); 110*1cdd5a26SSteve French 111*1cdd5a26SSteve French *ppmidQ = alloc_mid(in_buf, ses->server); 112*1cdd5a26SSteve French if (*ppmidQ == NULL) 113*1cdd5a26SSteve French return -ENOMEM; 114*1cdd5a26SSteve French spin_lock(&ses->server->mid_queue_lock); 115*1cdd5a26SSteve French list_add_tail(&(*ppmidQ)->qhead, &ses->server->pending_mid_q); 116*1cdd5a26SSteve French spin_unlock(&ses->server->mid_queue_lock); 117*1cdd5a26SSteve French return 0; 118*1cdd5a26SSteve French } 119*1cdd5a26SSteve French 120*1cdd5a26SSteve French struct mid_q_entry * 121*1cdd5a26SSteve French cifs_setup_async_request(struct TCP_Server_Info *server, struct smb_rqst *rqst) 122*1cdd5a26SSteve French { 123*1cdd5a26SSteve French int rc; 124*1cdd5a26SSteve French struct smb_hdr *hdr = (struct smb_hdr *)rqst->rq_iov[0].iov_base; 125*1cdd5a26SSteve French struct mid_q_entry *mid; 126*1cdd5a26SSteve French 127*1cdd5a26SSteve French if (rqst->rq_iov[0].iov_len != 4 || 128*1cdd5a26SSteve French rqst->rq_iov[0].iov_base + 4 != rqst->rq_iov[1].iov_base) 129*1cdd5a26SSteve French return ERR_PTR(-EIO); 130*1cdd5a26SSteve French 131*1cdd5a26SSteve French /* enable signing if server requires it */ 132*1cdd5a26SSteve French if (server->sign) 133*1cdd5a26SSteve French hdr->Flags2 |= SMBFLG2_SECURITY_SIGNATURE; 134*1cdd5a26SSteve French 135*1cdd5a26SSteve French mid = alloc_mid(hdr, server); 136*1cdd5a26SSteve French if (mid == NULL) 137*1cdd5a26SSteve French return ERR_PTR(-ENOMEM); 138*1cdd5a26SSteve French 139*1cdd5a26SSteve French rc = cifs_sign_rqst(rqst, server, &mid->sequence_number); 140*1cdd5a26SSteve French if (rc) { 141*1cdd5a26SSteve French release_mid(mid); 142*1cdd5a26SSteve French return ERR_PTR(rc); 143*1cdd5a26SSteve French } 144*1cdd5a26SSteve French 145*1cdd5a26SSteve French return mid; 146*1cdd5a26SSteve French } 147*1cdd5a26SSteve French 148*1cdd5a26SSteve French /* 149*1cdd5a26SSteve French * 150*1cdd5a26SSteve French * Send an SMB Request. No response info (other than return code) 151*1cdd5a26SSteve French * needs to be parsed. 152*1cdd5a26SSteve French * 153*1cdd5a26SSteve French * flags indicate the type of request buffer and how long to wait 154*1cdd5a26SSteve French * and whether to log NT STATUS code (error) before mapping it to POSIX error 155*1cdd5a26SSteve French * 156*1cdd5a26SSteve French */ 157*1cdd5a26SSteve French int 158*1cdd5a26SSteve French SendReceiveNoRsp(const unsigned int xid, struct cifs_ses *ses, 159*1cdd5a26SSteve French char *in_buf, int flags) 160*1cdd5a26SSteve French { 161*1cdd5a26SSteve French int rc; 162*1cdd5a26SSteve French struct kvec iov[1]; 163*1cdd5a26SSteve French struct kvec rsp_iov; 164*1cdd5a26SSteve French int resp_buf_type; 165*1cdd5a26SSteve French 166*1cdd5a26SSteve French iov[0].iov_base = in_buf; 167*1cdd5a26SSteve French iov[0].iov_len = get_rfc1002_length(in_buf) + 4; 168*1cdd5a26SSteve French flags |= CIFS_NO_RSP_BUF; 169*1cdd5a26SSteve French rc = SendReceive2(xid, ses, iov, 1, &resp_buf_type, flags, &rsp_iov); 170*1cdd5a26SSteve French cifs_dbg(NOISY, "SendRcvNoRsp flags %d rc %d\n", flags, rc); 171*1cdd5a26SSteve French 172*1cdd5a26SSteve French return rc; 173*1cdd5a26SSteve French } 174*1cdd5a26SSteve French 175*1cdd5a26SSteve French int 176*1cdd5a26SSteve French cifs_check_receive(struct mid_q_entry *mid, struct TCP_Server_Info *server, 177*1cdd5a26SSteve French bool log_error) 178*1cdd5a26SSteve French { 179*1cdd5a26SSteve French unsigned int len = get_rfc1002_length(mid->resp_buf) + 4; 180*1cdd5a26SSteve French 181*1cdd5a26SSteve French dump_smb(mid->resp_buf, min_t(u32, 92, len)); 182*1cdd5a26SSteve French 183*1cdd5a26SSteve French /* convert the length into a more usable form */ 184*1cdd5a26SSteve French if (server->sign) { 185*1cdd5a26SSteve French struct kvec iov[2]; 186*1cdd5a26SSteve French int rc = 0; 187*1cdd5a26SSteve French struct smb_rqst rqst = { .rq_iov = iov, 188*1cdd5a26SSteve French .rq_nvec = 2 }; 189*1cdd5a26SSteve French 190*1cdd5a26SSteve French iov[0].iov_base = mid->resp_buf; 191*1cdd5a26SSteve French iov[0].iov_len = 4; 192*1cdd5a26SSteve French iov[1].iov_base = (char *)mid->resp_buf + 4; 193*1cdd5a26SSteve French iov[1].iov_len = len - 4; 194*1cdd5a26SSteve French /* FIXME: add code to kill session */ 195*1cdd5a26SSteve French rc = cifs_verify_signature(&rqst, server, 196*1cdd5a26SSteve French mid->sequence_number); 197*1cdd5a26SSteve French if (rc) 198*1cdd5a26SSteve French cifs_server_dbg(VFS, "SMB signature verification returned error = %d\n", 199*1cdd5a26SSteve French rc); 200*1cdd5a26SSteve French } 201*1cdd5a26SSteve French 202*1cdd5a26SSteve French /* BB special case reconnect tid and uid here? */ 203*1cdd5a26SSteve French return map_and_check_smb_error(mid, log_error); 204*1cdd5a26SSteve French } 205*1cdd5a26SSteve French 206*1cdd5a26SSteve French struct mid_q_entry * 207*1cdd5a26SSteve French cifs_setup_request(struct cifs_ses *ses, struct TCP_Server_Info *ignored, 208*1cdd5a26SSteve French struct smb_rqst *rqst) 209*1cdd5a26SSteve French { 210*1cdd5a26SSteve French int rc; 211*1cdd5a26SSteve French struct smb_hdr *hdr = (struct smb_hdr *)rqst->rq_iov[0].iov_base; 212*1cdd5a26SSteve French struct mid_q_entry *mid; 213*1cdd5a26SSteve French 214*1cdd5a26SSteve French if (rqst->rq_iov[0].iov_len != 4 || 215*1cdd5a26SSteve French rqst->rq_iov[0].iov_base + 4 != rqst->rq_iov[1].iov_base) 216*1cdd5a26SSteve French return ERR_PTR(-EIO); 217*1cdd5a26SSteve French 218*1cdd5a26SSteve French rc = allocate_mid(ses, hdr, &mid); 219*1cdd5a26SSteve French if (rc) 220*1cdd5a26SSteve French return ERR_PTR(rc); 221*1cdd5a26SSteve French rc = cifs_sign_rqst(rqst, ses->server, &mid->sequence_number); 222*1cdd5a26SSteve French if (rc) { 223*1cdd5a26SSteve French delete_mid(mid); 224*1cdd5a26SSteve French return ERR_PTR(rc); 225*1cdd5a26SSteve French } 226*1cdd5a26SSteve French return mid; 227*1cdd5a26SSteve French } 228*1cdd5a26SSteve French 229*1cdd5a26SSteve French int 230*1cdd5a26SSteve French SendReceive2(const unsigned int xid, struct cifs_ses *ses, 231*1cdd5a26SSteve French struct kvec *iov, int n_vec, int *resp_buf_type /* ret */, 232*1cdd5a26SSteve French const int flags, struct kvec *resp_iov) 233*1cdd5a26SSteve French { 234*1cdd5a26SSteve French struct smb_rqst rqst; 235*1cdd5a26SSteve French struct kvec s_iov[CIFS_MAX_IOV_SIZE], *new_iov; 236*1cdd5a26SSteve French int rc; 237*1cdd5a26SSteve French 238*1cdd5a26SSteve French if (n_vec + 1 > CIFS_MAX_IOV_SIZE) { 239*1cdd5a26SSteve French new_iov = kmalloc_array(n_vec + 1, sizeof(struct kvec), 240*1cdd5a26SSteve French GFP_KERNEL); 241*1cdd5a26SSteve French if (!new_iov) { 242*1cdd5a26SSteve French /* otherwise cifs_send_recv below sets resp_buf_type */ 243*1cdd5a26SSteve French *resp_buf_type = CIFS_NO_BUFFER; 244*1cdd5a26SSteve French return -ENOMEM; 245*1cdd5a26SSteve French } 246*1cdd5a26SSteve French } else 247*1cdd5a26SSteve French new_iov = s_iov; 248*1cdd5a26SSteve French 249*1cdd5a26SSteve French /* 1st iov is a RFC1001 length followed by the rest of the packet */ 250*1cdd5a26SSteve French memcpy(new_iov + 1, iov, (sizeof(struct kvec) * n_vec)); 251*1cdd5a26SSteve French 252*1cdd5a26SSteve French new_iov[0].iov_base = new_iov[1].iov_base; 253*1cdd5a26SSteve French new_iov[0].iov_len = 4; 254*1cdd5a26SSteve French new_iov[1].iov_base += 4; 255*1cdd5a26SSteve French new_iov[1].iov_len -= 4; 256*1cdd5a26SSteve French 257*1cdd5a26SSteve French memset(&rqst, 0, sizeof(struct smb_rqst)); 258*1cdd5a26SSteve French rqst.rq_iov = new_iov; 259*1cdd5a26SSteve French rqst.rq_nvec = n_vec + 1; 260*1cdd5a26SSteve French 261*1cdd5a26SSteve French rc = cifs_send_recv(xid, ses, ses->server, 262*1cdd5a26SSteve French &rqst, resp_buf_type, flags, resp_iov); 263*1cdd5a26SSteve French if (n_vec + 1 > CIFS_MAX_IOV_SIZE) 264*1cdd5a26SSteve French kfree(new_iov); 265*1cdd5a26SSteve French return rc; 266*1cdd5a26SSteve French } 267*1cdd5a26SSteve French 268*1cdd5a26SSteve French int 269*1cdd5a26SSteve French SendReceive(const unsigned int xid, struct cifs_ses *ses, 270*1cdd5a26SSteve French struct smb_hdr *in_buf, struct smb_hdr *out_buf, 271*1cdd5a26SSteve French int *pbytes_returned, const int flags) 272*1cdd5a26SSteve French { 273*1cdd5a26SSteve French int rc = 0; 274*1cdd5a26SSteve French struct mid_q_entry *midQ; 275*1cdd5a26SSteve French unsigned int len = be32_to_cpu(in_buf->smb_buf_length); 276*1cdd5a26SSteve French struct kvec iov = { .iov_base = in_buf, .iov_len = len }; 277*1cdd5a26SSteve French struct smb_rqst rqst = { .rq_iov = &iov, .rq_nvec = 1 }; 278*1cdd5a26SSteve French struct cifs_credits credits = { .value = 1, .instance = 0 }; 279*1cdd5a26SSteve French struct TCP_Server_Info *server; 280*1cdd5a26SSteve French 281*1cdd5a26SSteve French if (ses == NULL) { 282*1cdd5a26SSteve French cifs_dbg(VFS, "Null smb session\n"); 283*1cdd5a26SSteve French return -EIO; 284*1cdd5a26SSteve French } 285*1cdd5a26SSteve French server = ses->server; 286*1cdd5a26SSteve French if (server == NULL) { 287*1cdd5a26SSteve French cifs_dbg(VFS, "Null tcp session\n"); 288*1cdd5a26SSteve French return -EIO; 289*1cdd5a26SSteve French } 290*1cdd5a26SSteve French 291*1cdd5a26SSteve French spin_lock(&server->srv_lock); 292*1cdd5a26SSteve French if (server->tcpStatus == CifsExiting) { 293*1cdd5a26SSteve French spin_unlock(&server->srv_lock); 294*1cdd5a26SSteve French return -ENOENT; 295*1cdd5a26SSteve French } 296*1cdd5a26SSteve French spin_unlock(&server->srv_lock); 297*1cdd5a26SSteve French 298*1cdd5a26SSteve French /* Ensure that we do not send more than 50 overlapping requests 299*1cdd5a26SSteve French to the same server. We may make this configurable later or 300*1cdd5a26SSteve French use ses->maxReq */ 301*1cdd5a26SSteve French 302*1cdd5a26SSteve French if (len > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE - 4) { 303*1cdd5a26SSteve French cifs_server_dbg(VFS, "Invalid length, greater than maximum frame, %d\n", 304*1cdd5a26SSteve French len); 305*1cdd5a26SSteve French return -EIO; 306*1cdd5a26SSteve French } 307*1cdd5a26SSteve French 308*1cdd5a26SSteve French rc = wait_for_free_request(server, flags, &credits.instance); 309*1cdd5a26SSteve French if (rc) 310*1cdd5a26SSteve French return rc; 311*1cdd5a26SSteve French 312*1cdd5a26SSteve French /* make sure that we sign in the same order that we send on this socket 313*1cdd5a26SSteve French and avoid races inside tcp sendmsg code that could cause corruption 314*1cdd5a26SSteve French of smb data */ 315*1cdd5a26SSteve French 316*1cdd5a26SSteve French cifs_server_lock(server); 317*1cdd5a26SSteve French 318*1cdd5a26SSteve French rc = allocate_mid(ses, in_buf, &midQ); 319*1cdd5a26SSteve French if (rc) { 320*1cdd5a26SSteve French cifs_server_unlock(server); 321*1cdd5a26SSteve French /* Update # of requests on wire to server */ 322*1cdd5a26SSteve French add_credits(server, &credits, 0); 323*1cdd5a26SSteve French return rc; 324*1cdd5a26SSteve French } 325*1cdd5a26SSteve French 326*1cdd5a26SSteve French rc = cifs_sign_smb(in_buf, server, &midQ->sequence_number); 327*1cdd5a26SSteve French if (rc) { 328*1cdd5a26SSteve French cifs_server_unlock(server); 329*1cdd5a26SSteve French goto out; 330*1cdd5a26SSteve French } 331*1cdd5a26SSteve French 332*1cdd5a26SSteve French midQ->mid_state = MID_REQUEST_SUBMITTED; 333*1cdd5a26SSteve French 334*1cdd5a26SSteve French rc = smb_send(server, in_buf, len); 335*1cdd5a26SSteve French cifs_save_when_sent(midQ); 336*1cdd5a26SSteve French 337*1cdd5a26SSteve French if (rc < 0) 338*1cdd5a26SSteve French server->sequence_number -= 2; 339*1cdd5a26SSteve French 340*1cdd5a26SSteve French cifs_server_unlock(server); 341*1cdd5a26SSteve French 342*1cdd5a26SSteve French if (rc < 0) 343*1cdd5a26SSteve French goto out; 344*1cdd5a26SSteve French 345*1cdd5a26SSteve French rc = wait_for_response(server, midQ); 346*1cdd5a26SSteve French if (rc != 0) { 347*1cdd5a26SSteve French send_cancel(server, &rqst, midQ); 348*1cdd5a26SSteve French spin_lock(&server->mid_queue_lock); 349*1cdd5a26SSteve French if (midQ->mid_state == MID_REQUEST_SUBMITTED || 350*1cdd5a26SSteve French midQ->mid_state == MID_RESPONSE_RECEIVED) { 351*1cdd5a26SSteve French /* no longer considered to be "in-flight" */ 352*1cdd5a26SSteve French midQ->callback = release_mid; 353*1cdd5a26SSteve French spin_unlock(&server->mid_queue_lock); 354*1cdd5a26SSteve French add_credits(server, &credits, 0); 355*1cdd5a26SSteve French return rc; 356*1cdd5a26SSteve French } 357*1cdd5a26SSteve French spin_unlock(&server->mid_queue_lock); 358*1cdd5a26SSteve French } 359*1cdd5a26SSteve French 360*1cdd5a26SSteve French rc = cifs_sync_mid_result(midQ, server); 361*1cdd5a26SSteve French if (rc != 0) { 362*1cdd5a26SSteve French add_credits(server, &credits, 0); 363*1cdd5a26SSteve French return rc; 364*1cdd5a26SSteve French } 365*1cdd5a26SSteve French 366*1cdd5a26SSteve French if (!midQ->resp_buf || !out_buf || 367*1cdd5a26SSteve French midQ->mid_state != MID_RESPONSE_READY) { 368*1cdd5a26SSteve French rc = -EIO; 369*1cdd5a26SSteve French cifs_server_dbg(VFS, "Bad MID state?\n"); 370*1cdd5a26SSteve French goto out; 371*1cdd5a26SSteve French } 372*1cdd5a26SSteve French 373*1cdd5a26SSteve French *pbytes_returned = get_rfc1002_length(midQ->resp_buf); 374*1cdd5a26SSteve French memcpy(out_buf, midQ->resp_buf, *pbytes_returned + 4); 375*1cdd5a26SSteve French rc = cifs_check_receive(midQ, server, 0); 376*1cdd5a26SSteve French out: 377*1cdd5a26SSteve French delete_mid(midQ); 378*1cdd5a26SSteve French add_credits(server, &credits, 0); 379*1cdd5a26SSteve French 380*1cdd5a26SSteve French return rc; 381*1cdd5a26SSteve French } 382*1cdd5a26SSteve French 383*1cdd5a26SSteve French /* We send a LOCKINGX_CANCEL_LOCK to cause the Windows 384*1cdd5a26SSteve French blocking lock to return. */ 385*1cdd5a26SSteve French 386*1cdd5a26SSteve French static int 387*1cdd5a26SSteve French send_lock_cancel(const unsigned int xid, struct cifs_tcon *tcon, 388*1cdd5a26SSteve French struct smb_hdr *in_buf, 389*1cdd5a26SSteve French struct smb_hdr *out_buf) 390*1cdd5a26SSteve French { 391*1cdd5a26SSteve French int bytes_returned; 392*1cdd5a26SSteve French struct cifs_ses *ses = tcon->ses; 393*1cdd5a26SSteve French LOCK_REQ *pSMB = (LOCK_REQ *)in_buf; 394*1cdd5a26SSteve French 395*1cdd5a26SSteve French /* We just modify the current in_buf to change 396*1cdd5a26SSteve French the type of lock from LOCKING_ANDX_SHARED_LOCK 397*1cdd5a26SSteve French or LOCKING_ANDX_EXCLUSIVE_LOCK to 398*1cdd5a26SSteve French LOCKING_ANDX_CANCEL_LOCK. */ 399*1cdd5a26SSteve French 400*1cdd5a26SSteve French pSMB->LockType = LOCKING_ANDX_CANCEL_LOCK|LOCKING_ANDX_LARGE_FILES; 401*1cdd5a26SSteve French pSMB->Timeout = 0; 402*1cdd5a26SSteve French pSMB->hdr.Mid = get_next_mid(ses->server); 403*1cdd5a26SSteve French 404*1cdd5a26SSteve French return SendReceive(xid, ses, in_buf, out_buf, 405*1cdd5a26SSteve French &bytes_returned, 0); 406*1cdd5a26SSteve French } 407*1cdd5a26SSteve French 408*1cdd5a26SSteve French int 409*1cdd5a26SSteve French SendReceiveBlockingLock(const unsigned int xid, struct cifs_tcon *tcon, 410*1cdd5a26SSteve French struct smb_hdr *in_buf, struct smb_hdr *out_buf, 411*1cdd5a26SSteve French int *pbytes_returned) 412*1cdd5a26SSteve French { 413*1cdd5a26SSteve French int rc = 0; 414*1cdd5a26SSteve French int rstart = 0; 415*1cdd5a26SSteve French struct mid_q_entry *midQ; 416*1cdd5a26SSteve French struct cifs_ses *ses; 417*1cdd5a26SSteve French unsigned int len = be32_to_cpu(in_buf->smb_buf_length); 418*1cdd5a26SSteve French struct kvec iov = { .iov_base = in_buf, .iov_len = len }; 419*1cdd5a26SSteve French struct smb_rqst rqst = { .rq_iov = &iov, .rq_nvec = 1 }; 420*1cdd5a26SSteve French unsigned int instance; 421*1cdd5a26SSteve French struct TCP_Server_Info *server; 422*1cdd5a26SSteve French 423*1cdd5a26SSteve French if (tcon == NULL || tcon->ses == NULL) { 424*1cdd5a26SSteve French cifs_dbg(VFS, "Null smb session\n"); 425*1cdd5a26SSteve French return -EIO; 426*1cdd5a26SSteve French } 427*1cdd5a26SSteve French ses = tcon->ses; 428*1cdd5a26SSteve French server = ses->server; 429*1cdd5a26SSteve French 430*1cdd5a26SSteve French if (server == NULL) { 431*1cdd5a26SSteve French cifs_dbg(VFS, "Null tcp session\n"); 432*1cdd5a26SSteve French return -EIO; 433*1cdd5a26SSteve French } 434*1cdd5a26SSteve French 435*1cdd5a26SSteve French spin_lock(&server->srv_lock); 436*1cdd5a26SSteve French if (server->tcpStatus == CifsExiting) { 437*1cdd5a26SSteve French spin_unlock(&server->srv_lock); 438*1cdd5a26SSteve French return -ENOENT; 439*1cdd5a26SSteve French } 440*1cdd5a26SSteve French spin_unlock(&server->srv_lock); 441*1cdd5a26SSteve French 442*1cdd5a26SSteve French /* Ensure that we do not send more than 50 overlapping requests 443*1cdd5a26SSteve French to the same server. We may make this configurable later or 444*1cdd5a26SSteve French use ses->maxReq */ 445*1cdd5a26SSteve French 446*1cdd5a26SSteve French if (len > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE - 4) { 447*1cdd5a26SSteve French cifs_tcon_dbg(VFS, "Invalid length, greater than maximum frame, %d\n", 448*1cdd5a26SSteve French len); 449*1cdd5a26SSteve French return -EIO; 450*1cdd5a26SSteve French } 451*1cdd5a26SSteve French 452*1cdd5a26SSteve French rc = wait_for_free_request(server, CIFS_BLOCKING_OP, &instance); 453*1cdd5a26SSteve French if (rc) 454*1cdd5a26SSteve French return rc; 455*1cdd5a26SSteve French 456*1cdd5a26SSteve French /* make sure that we sign in the same order that we send on this socket 457*1cdd5a26SSteve French and avoid races inside tcp sendmsg code that could cause corruption 458*1cdd5a26SSteve French of smb data */ 459*1cdd5a26SSteve French 460*1cdd5a26SSteve French cifs_server_lock(server); 461*1cdd5a26SSteve French 462*1cdd5a26SSteve French rc = allocate_mid(ses, in_buf, &midQ); 463*1cdd5a26SSteve French if (rc) { 464*1cdd5a26SSteve French cifs_server_unlock(server); 465*1cdd5a26SSteve French return rc; 466*1cdd5a26SSteve French } 467*1cdd5a26SSteve French 468*1cdd5a26SSteve French rc = cifs_sign_smb(in_buf, server, &midQ->sequence_number); 469*1cdd5a26SSteve French if (rc) { 470*1cdd5a26SSteve French delete_mid(midQ); 471*1cdd5a26SSteve French cifs_server_unlock(server); 472*1cdd5a26SSteve French return rc; 473*1cdd5a26SSteve French } 474*1cdd5a26SSteve French 475*1cdd5a26SSteve French midQ->mid_state = MID_REQUEST_SUBMITTED; 476*1cdd5a26SSteve French rc = smb_send(server, in_buf, len); 477*1cdd5a26SSteve French cifs_save_when_sent(midQ); 478*1cdd5a26SSteve French 479*1cdd5a26SSteve French if (rc < 0) 480*1cdd5a26SSteve French server->sequence_number -= 2; 481*1cdd5a26SSteve French 482*1cdd5a26SSteve French cifs_server_unlock(server); 483*1cdd5a26SSteve French 484*1cdd5a26SSteve French if (rc < 0) { 485*1cdd5a26SSteve French delete_mid(midQ); 486*1cdd5a26SSteve French return rc; 487*1cdd5a26SSteve French } 488*1cdd5a26SSteve French 489*1cdd5a26SSteve French /* Wait for a reply - allow signals to interrupt. */ 490*1cdd5a26SSteve French rc = wait_event_interruptible(server->response_q, 491*1cdd5a26SSteve French (!(midQ->mid_state == MID_REQUEST_SUBMITTED || 492*1cdd5a26SSteve French midQ->mid_state == MID_RESPONSE_RECEIVED)) || 493*1cdd5a26SSteve French ((server->tcpStatus != CifsGood) && 494*1cdd5a26SSteve French (server->tcpStatus != CifsNew))); 495*1cdd5a26SSteve French 496*1cdd5a26SSteve French /* Were we interrupted by a signal ? */ 497*1cdd5a26SSteve French spin_lock(&server->srv_lock); 498*1cdd5a26SSteve French if ((rc == -ERESTARTSYS) && 499*1cdd5a26SSteve French (midQ->mid_state == MID_REQUEST_SUBMITTED || 500*1cdd5a26SSteve French midQ->mid_state == MID_RESPONSE_RECEIVED) && 501*1cdd5a26SSteve French ((server->tcpStatus == CifsGood) || 502*1cdd5a26SSteve French (server->tcpStatus == CifsNew))) { 503*1cdd5a26SSteve French spin_unlock(&server->srv_lock); 504*1cdd5a26SSteve French 505*1cdd5a26SSteve French if (in_buf->Command == SMB_COM_TRANSACTION2) { 506*1cdd5a26SSteve French /* POSIX lock. We send a NT_CANCEL SMB to cause the 507*1cdd5a26SSteve French blocking lock to return. */ 508*1cdd5a26SSteve French rc = send_cancel(server, &rqst, midQ); 509*1cdd5a26SSteve French if (rc) { 510*1cdd5a26SSteve French delete_mid(midQ); 511*1cdd5a26SSteve French return rc; 512*1cdd5a26SSteve French } 513*1cdd5a26SSteve French } else { 514*1cdd5a26SSteve French /* Windows lock. We send a LOCKINGX_CANCEL_LOCK 515*1cdd5a26SSteve French to cause the blocking lock to return. */ 516*1cdd5a26SSteve French 517*1cdd5a26SSteve French rc = send_lock_cancel(xid, tcon, in_buf, out_buf); 518*1cdd5a26SSteve French 519*1cdd5a26SSteve French /* If we get -ENOLCK back the lock may have 520*1cdd5a26SSteve French already been removed. Don't exit in this case. */ 521*1cdd5a26SSteve French if (rc && rc != -ENOLCK) { 522*1cdd5a26SSteve French delete_mid(midQ); 523*1cdd5a26SSteve French return rc; 524*1cdd5a26SSteve French } 525*1cdd5a26SSteve French } 526*1cdd5a26SSteve French 527*1cdd5a26SSteve French rc = wait_for_response(server, midQ); 528*1cdd5a26SSteve French if (rc) { 529*1cdd5a26SSteve French send_cancel(server, &rqst, midQ); 530*1cdd5a26SSteve French spin_lock(&server->mid_queue_lock); 531*1cdd5a26SSteve French if (midQ->mid_state == MID_REQUEST_SUBMITTED || 532*1cdd5a26SSteve French midQ->mid_state == MID_RESPONSE_RECEIVED) { 533*1cdd5a26SSteve French /* no longer considered to be "in-flight" */ 534*1cdd5a26SSteve French midQ->callback = release_mid; 535*1cdd5a26SSteve French spin_unlock(&server->mid_queue_lock); 536*1cdd5a26SSteve French return rc; 537*1cdd5a26SSteve French } 538*1cdd5a26SSteve French spin_unlock(&server->mid_queue_lock); 539*1cdd5a26SSteve French } 540*1cdd5a26SSteve French 541*1cdd5a26SSteve French /* We got the response - restart system call. */ 542*1cdd5a26SSteve French rstart = 1; 543*1cdd5a26SSteve French spin_lock(&server->srv_lock); 544*1cdd5a26SSteve French } 545*1cdd5a26SSteve French spin_unlock(&server->srv_lock); 546*1cdd5a26SSteve French 547*1cdd5a26SSteve French rc = cifs_sync_mid_result(midQ, server); 548*1cdd5a26SSteve French if (rc != 0) 549*1cdd5a26SSteve French return rc; 550*1cdd5a26SSteve French 551*1cdd5a26SSteve French /* rcvd frame is ok */ 552*1cdd5a26SSteve French if (out_buf == NULL || midQ->mid_state != MID_RESPONSE_READY) { 553*1cdd5a26SSteve French rc = -EIO; 554*1cdd5a26SSteve French cifs_tcon_dbg(VFS, "Bad MID state?\n"); 555*1cdd5a26SSteve French goto out; 556*1cdd5a26SSteve French } 557*1cdd5a26SSteve French 558*1cdd5a26SSteve French *pbytes_returned = get_rfc1002_length(midQ->resp_buf); 559*1cdd5a26SSteve French memcpy(out_buf, midQ->resp_buf, *pbytes_returned + 4); 560*1cdd5a26SSteve French rc = cifs_check_receive(midQ, server, 0); 561*1cdd5a26SSteve French out: 562*1cdd5a26SSteve French delete_mid(midQ); 563*1cdd5a26SSteve French if (rstart && rc == -EACCES) 564*1cdd5a26SSteve French return -ERESTARTSYS; 565*1cdd5a26SSteve French return rc; 566*1cdd5a26SSteve French } 567