misc.c 24.1 KB
Newer Older
L
Linus Torvalds 已提交
1 2 3
/*
 *   fs/cifs/misc.c
 *
S
Steve French 已提交
4
 *   Copyright (C) International Business Machines  Corp., 2002,2008
L
Linus Torvalds 已提交
5 6 7 8 9 10 11 12 13 14 15 16 17 18
 *   Author(s): Steve French (sfrench@us.ibm.com)
 *
 *   This library is free software; you can redistribute it and/or modify
 *   it under the terms of the GNU Lesser General Public License as published
 *   by the Free Software Foundation; either version 2.1 of the License, or
 *   (at your option) any later version.
 *
 *   This library is distributed in the hope that it will be useful,
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
 *   the GNU Lesser General Public License for more details.
 *
 *   You should have received a copy of the GNU Lesser General Public License
 *   along with this library; if not, write to the Free Software
S
Steve French 已提交
19
 *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
L
Linus Torvalds 已提交
20 21 22 23 24
 */

#include <linux/slab.h>
#include <linux/ctype.h>
#include <linux/mempool.h>
25
#include <linux/vmalloc.h>
L
Linus Torvalds 已提交
26 27 28 29 30 31
#include "cifspdu.h"
#include "cifsglob.h"
#include "cifsproto.h"
#include "cifs_debug.h"
#include "smberr.h"
#include "nterr.h"
32
#include "cifs_unicode.h"
33
#include "smb2pdu.h"
L
Linus Torvalds 已提交
34 35 36 37

extern mempool_t *cifs_sm_req_poolp;
extern mempool_t *cifs_req_poolp;

S
Steve French 已提交
38 39 40 41
/* The xid serves as a useful identifier for each incoming vfs request,
   in a similar way to the mid which is useful to track each sent smb,
   and CurrentXid can also provide a running counter (although it
   will eventually wrap past zero) of the total vfs operations handled
L
Linus Torvalds 已提交
42 43 44
   since the cifs fs was mounted */

unsigned int
45
_get_xid(void)
L
Linus Torvalds 已提交
46 47 48 49 50
{
	unsigned int xid;

	spin_lock(&GlobalMid_Lock);
	GlobalTotalActiveXid++;
51 52

	/* keep high water mark for number of simultaneous ops in filesystem */
L
Linus Torvalds 已提交
53
	if (GlobalTotalActiveXid > GlobalMaxActiveXid)
54
		GlobalMaxActiveXid = GlobalTotalActiveXid;
S
Steve French 已提交
55
	if (GlobalTotalActiveXid > 65000)
56
		cifs_dbg(FYI, "warning: more than 65000 requests active\n");
L
Linus Torvalds 已提交
57 58 59 60 61 62
	xid = GlobalCurrentXid++;
	spin_unlock(&GlobalMid_Lock);
	return xid;
}

void
63
_free_xid(unsigned int xid)
L
Linus Torvalds 已提交
64 65
{
	spin_lock(&GlobalMid_Lock);
S
Steve French 已提交
66
	/* if (GlobalTotalActiveXid == 0)
L
Linus Torvalds 已提交
67 68 69 70 71
		BUG(); */
	GlobalTotalActiveXid--;
	spin_unlock(&GlobalMid_Lock);
}

72
struct cifs_ses *
L
Linus Torvalds 已提交
73 74
sesInfoAlloc(void)
{
75
	struct cifs_ses *ret_buf;
L
Linus Torvalds 已提交
76

77
	ret_buf = kzalloc(sizeof(struct cifs_ses), GFP_KERNEL);
L
Linus Torvalds 已提交
78 79 80
	if (ret_buf) {
		atomic_inc(&sesInfoAllocCount);
		ret_buf->status = CifsNew;
81 82
		++ret_buf->ses_count;
		INIT_LIST_HEAD(&ret_buf->smb_ses_list);
83
		INIT_LIST_HEAD(&ret_buf->tcon_list);
84
		mutex_init(&ret_buf->session_mutex);
L
Linus Torvalds 已提交
85 86 87 88 89
	}
	return ret_buf;
}

void
90
sesInfoFree(struct cifs_ses *buf_to_free)
L
Linus Torvalds 已提交
91 92
{
	if (buf_to_free == NULL) {
93
		cifs_dbg(FYI, "Null buffer passed to sesInfoFree\n");
L
Linus Torvalds 已提交
94 95 96 97
		return;
	}

	atomic_dec(&sesInfoAllocCount);
J
Jesper Juhl 已提交
98 99 100
	kfree(buf_to_free->serverOS);
	kfree(buf_to_free->serverDomain);
	kfree(buf_to_free->serverNOS);
101
	kzfree(buf_to_free->password);
102
	kfree(buf_to_free->user_name);
103
	kfree(buf_to_free->domainName);
104 105
	kzfree(buf_to_free->auth_key.response);
	kzfree(buf_to_free);
L
Linus Torvalds 已提交
106 107
}

108
struct cifs_tcon *
L
Linus Torvalds 已提交
109 110
tconInfoAlloc(void)
{
111 112
	struct cifs_tcon *ret_buf;
	ret_buf = kzalloc(sizeof(struct cifs_tcon), GFP_KERNEL);
L
Linus Torvalds 已提交
113 114 115
	if (ret_buf) {
		atomic_inc(&tconInfoAllocCount);
		ret_buf->tidStatus = CifsNew;
116
		++ret_buf->tc_count;
L
Linus Torvalds 已提交
117
		INIT_LIST_HEAD(&ret_buf->openFileList);
118
		INIT_LIST_HEAD(&ret_buf->tcon_list);
119
		spin_lock_init(&ret_buf->open_file_lock);
S
Steve French 已提交
120 121
		mutex_init(&ret_buf->prfid_mutex);
		ret_buf->prfid = kzalloc(sizeof(struct cifs_fid), GFP_KERNEL);
L
Linus Torvalds 已提交
122 123 124 125 126 127 128 129
#ifdef CONFIG_CIFS_STATS
		spin_lock_init(&ret_buf->stat_lock);
#endif
	}
	return ret_buf;
}

void
130
tconInfoFree(struct cifs_tcon *buf_to_free)
L
Linus Torvalds 已提交
131 132
{
	if (buf_to_free == NULL) {
133
		cifs_dbg(FYI, "Null buffer passed to tconInfoFree\n");
L
Linus Torvalds 已提交
134 135 136
		return;
	}
	atomic_dec(&tconInfoAllocCount);
J
Jesper Juhl 已提交
137
	kfree(buf_to_free->nativeFileSystem);
138
	kzfree(buf_to_free->password);
S
Steve French 已提交
139
	kfree(buf_to_free->prfid);
L
Linus Torvalds 已提交
140 141 142 143 144 145 146
	kfree(buf_to_free);
}

struct smb_hdr *
cifs_buf_get(void)
{
	struct smb_hdr *ret_buf = NULL;
147 148 149 150
	/*
	 * SMB2 header is bigger than CIFS one - no problems to clean some
	 * more bytes for CIFS.
	 */
151 152
	size_t buf_size = sizeof(struct smb2_hdr);

153 154 155 156 157 158
	/*
	 * We could use negotiated size instead of max_msgsize -
	 * but it may be more efficient to always alloc same size
	 * albeit slightly larger than necessary and maxbuffersize
	 * defaults to this and can not be bigger.
	 */
159
	ret_buf = mempool_alloc(cifs_req_poolp, GFP_NOFS);
L
Linus Torvalds 已提交
160 161 162

	/* clear the first few header bytes */
	/* for most paths, more is cleared in header_assemble */
163 164
	memset(ret_buf, 0, buf_size + 3);
	atomic_inc(&bufAllocCount);
165
#ifdef CONFIG_CIFS_STATS2
166
	atomic_inc(&totBufAllocCount);
167
#endif /* CONFIG_CIFS_STATS2 */
L
Linus Torvalds 已提交
168 169 170 171 172 173 174 175

	return ret_buf;
}

void
cifs_buf_release(void *buf_to_free)
{
	if (buf_to_free == NULL) {
176
		/* cifs_dbg(FYI, "Null buffer passed to cifs_buf_release\n");*/
L
Linus Torvalds 已提交
177 178
		return;
	}
S
Steve French 已提交
179
	mempool_free(buf_to_free, cifs_req_poolp);
L
Linus Torvalds 已提交
180 181 182 183 184 185 186 187 188 189

	atomic_dec(&bufAllocCount);
	return;
}

struct smb_hdr *
cifs_small_buf_get(void)
{
	struct smb_hdr *ret_buf = NULL;

S
Steve French 已提交
190 191 192
/* We could use negotiated size instead of max_msgsize -
   but it may be more efficient to always alloc same size
   albeit slightly larger than necessary and maxbuffersize
L
Linus Torvalds 已提交
193
   defaults to this and can not be bigger */
194
	ret_buf = mempool_alloc(cifs_sm_req_poolp, GFP_NOFS);
L
Linus Torvalds 已提交
195 196
	/* No need to clear memory here, cleared in header assemble */
	/*	memset(ret_buf, 0, sizeof(struct smb_hdr) + 27);*/
197
	atomic_inc(&smBufAllocCount);
198
#ifdef CONFIG_CIFS_STATS2
199
	atomic_inc(&totSmBufAllocCount);
200 201
#endif /* CONFIG_CIFS_STATS2 */

L
Linus Torvalds 已提交
202 203 204 205 206 207 208 209
	return ret_buf;
}

void
cifs_small_buf_release(void *buf_to_free)
{

	if (buf_to_free == NULL) {
210
		cifs_dbg(FYI, "Null buffer passed to cifs_small_buf_release\n");
L
Linus Torvalds 已提交
211 212
		return;
	}
S
Steve French 已提交
213
	mempool_free(buf_to_free, cifs_sm_req_poolp);
L
Linus Torvalds 已提交
214 215 216 217 218

	atomic_dec(&smBufAllocCount);
	return;
}

219 220 221 222 223 224 225 226 227
void
free_rsp_buf(int resp_buftype, void *rsp)
{
	if (resp_buftype == CIFS_SMALL_BUFFER)
		cifs_small_buf_release(rsp);
	else if (resp_buftype == CIFS_LARGE_BUFFER)
		cifs_buf_release(rsp);
}

228 229
/* NB: MID can not be set if treeCon not passed in, in that
   case it is responsbility of caller to set the mid */
L
Linus Torvalds 已提交
230 231
void
header_assemble(struct smb_hdr *buffer, char smb_command /* command */ ,
232
		const struct cifs_tcon *treeCon, int word_count
L
Linus Torvalds 已提交
233 234 235 236
		/* length of fixed section (word count) in two byte units  */)
{
	char *temp = (char *) buffer;

S
Steve French 已提交
237
	memset(temp, 0, 256); /* bigger than MAX_CIFS_HDR_SIZE */
L
Linus Torvalds 已提交
238

239
	buffer->smb_buf_length = cpu_to_be32(
S
Steve French 已提交
240
	    (2 * word_count) + sizeof(struct smb_hdr) -
L
Linus Torvalds 已提交
241
	    4 /*  RFC 1001 length field does not count */  +
242
	    2 /* for bcc field itself */) ;
L
Linus Torvalds 已提交
243 244 245 246 247 248 249 250 251 252 253 254 255 256 257

	buffer->Protocol[0] = 0xFF;
	buffer->Protocol[1] = 'S';
	buffer->Protocol[2] = 'M';
	buffer->Protocol[3] = 'B';
	buffer->Command = smb_command;
	buffer->Flags = 0x00;	/* case sensitive */
	buffer->Flags2 = SMBFLG2_KNOWS_LONG_NAMES;
	buffer->Pid = cpu_to_le16((__u16)current->tgid);
	buffer->PidHigh = cpu_to_le16((__u16)(current->tgid >> 16));
	if (treeCon) {
		buffer->Tid = treeCon->tid;
		if (treeCon->ses) {
			if (treeCon->ses->capabilities & CAP_UNICODE)
				buffer->Flags2 |= SMBFLG2_UNICODE;
S
Steve French 已提交
258
			if (treeCon->ses->capabilities & CAP_STATUS32)
L
Linus Torvalds 已提交
259
				buffer->Flags2 |= SMBFLG2_ERR_STATUS;
S
Steve French 已提交
260

261 262
			/* Uid is not converted */
			buffer->Uid = treeCon->ses->Suid;
263
			buffer->Mid = get_next_mid(treeCon->ses->server);
L
Linus Torvalds 已提交
264 265 266
		}
		if (treeCon->Flags & SMB_SHARE_IS_IN_DFS)
			buffer->Flags2 |= SMBFLG2_DFS;
267 268
		if (treeCon->nocase)
			buffer->Flags  |= SMBFLG_CASELESS;
S
Steve French 已提交
269
		if ((treeCon->ses) && (treeCon->ses->server))
270
			if (treeCon->ses->server->sign)
L
Linus Torvalds 已提交
271 272 273 274 275 276 277 278
				buffer->Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
	}

/*  endian conversion of flags is now done just before sending */
	buffer->WordCount = (char) word_count;
	return;
}

279
static int
280
check_smb_hdr(struct smb_hdr *smb)
L
Linus Torvalds 已提交
281
{
282 283
	/* does it have the right SMB "signature" ? */
	if (*(__le32 *) smb->Protocol != cpu_to_le32(0x424d53ff)) {
284 285
		cifs_dbg(VFS, "Bad protocol string signature header 0x%x\n",
			 *(unsigned int *)smb->Protocol);
286 287 288 289 290 291 292 293 294 295 296
		return 1;
	}

	/* if it's a response then accept */
	if (smb->Flags & SMBFLG_RESPONSE)
		return 0;

	/* only one valid case where server sends us request */
	if (smb->Command == SMB_COM_LOCKING_ANDX)
		return 0;

297 298
	cifs_dbg(VFS, "Server sent request, not response. mid=%u\n",
		 get_mid(smb));
L
Linus Torvalds 已提交
299 300 301 302
	return 1;
}

int
303
checkSMB(char *buf, unsigned int total_read, struct TCP_Server_Info *server)
L
Linus Torvalds 已提交
304
{
305
	struct smb_hdr *smb = (struct smb_hdr *)buf;
J
Jeff Layton 已提交
306
	__u32 rfclen = be32_to_cpu(smb->smb_buf_length);
307
	__u32 clc_len;  /* calculated length */
308 309
	cifs_dbg(FYI, "checkSMB Length: 0x%x, smb_buf_length: 0x%x\n",
		 total_read, rfclen);
310

J
Jeff Layton 已提交
311 312 313
	/* is this frame too small to even get to a BCC? */
	if (total_read < 2 + sizeof(struct smb_hdr)) {
		if ((total_read >= sizeof(struct smb_hdr) - 1)
L
Linus Torvalds 已提交
314
			    && (smb->Status.CifsError != 0)) {
J
Jeff Layton 已提交
315
			/* it's an error return */
316 317 318
			smb->WordCount = 0;
			/* some error cases do not return wct and bcc */
			return 0;
J
Jeff Layton 已提交
319
		} else if ((total_read == sizeof(struct smb_hdr) + 1) &&
320
				(smb->WordCount == 0)) {
S
Steve French 已提交
321
			char *tmp = (char *)smb;
322 323 324 325 326 327 328 329 330 331 332
			/* Need to work around a bug in two servers here */
			/* First, check if the part of bcc they sent was zero */
			if (tmp[sizeof(struct smb_hdr)] == 0) {
				/* some servers return only half of bcc
				 * on simple responses (wct, bcc both zero)
				 * in particular have seen this on
				 * ulogoffX and FindClose. This leaves
				 * one byte of bcc potentially unitialized
				 */
				/* zero rest of bcc */
				tmp[sizeof(struct smb_hdr)+1] = 0;
333
				return 0;
L
Linus Torvalds 已提交
334
			}
335
			cifs_dbg(VFS, "rcvd invalid byte count (bcc)\n");
336
		} else {
337
			cifs_dbg(VFS, "Length less than smb header size\n");
L
Linus Torvalds 已提交
338
		}
J
Jeff Layton 已提交
339
		return -EIO;
L
Linus Torvalds 已提交
340 341
	}

J
Jeff Layton 已提交
342
	/* otherwise, there is enough to get to the BCC */
343
	if (check_smb_hdr(smb))
J
Jeff Layton 已提交
344
		return -EIO;
345
	clc_len = smbCalcSize(smb);
346

J
Jeff Layton 已提交
347
	if (4 + rfclen != total_read) {
348 349
		cifs_dbg(VFS, "Length read does not match RFC1001 length %d\n",
			 rfclen);
J
Jeff Layton 已提交
350
		return -EIO;
351 352
	}

J
Jeff Layton 已提交
353
	if (4 + rfclen != clc_len) {
354
		__u16 mid = get_mid(smb);
355
		/* check if bcc wrapped around for large read responses */
J
Jeff Layton 已提交
356
		if ((rfclen > 64 * 1024) && (rfclen > clc_len)) {
357
			/* check if lengths match mod 64K */
J
Jeff Layton 已提交
358
			if (((4 + rfclen) & 0xFFFF) == (clc_len & 0xFFFF))
S
Steve French 已提交
359
				return 0; /* bcc wrapped */
360
		}
361
		cifs_dbg(FYI, "Calculated size %u vs length %u mismatch for mid=%u\n",
362
			 clc_len, 4 + rfclen, mid);
363

J
Jeff Layton 已提交
364
		if (4 + rfclen < clc_len) {
365
			cifs_dbg(VFS, "RFC1001 size %u smaller than SMB for mid=%u\n",
366
				 rfclen, mid);
J
Jeff Layton 已提交
367 368
			return -EIO;
		} else if (rfclen > clc_len + 512) {
369 370 371 372 373 374 375 376 377
			/*
			 * Some servers (Windows XP in particular) send more
			 * data than the lengths in the SMB packet would
			 * indicate on certain calls (byte range locks and
			 * trans2 find first calls in particular). While the
			 * client can handle such a frame by ignoring the
			 * trailing data, we choose limit the amount of extra
			 * data to 512 bytes.
			 */
378
			cifs_dbg(VFS, "RFC1001 size %u more than 512 bytes larger than SMB for mid=%u\n",
379
				 rfclen, mid);
J
Jeff Layton 已提交
380
			return -EIO;
381
		}
L
Linus Torvalds 已提交
382
	}
383
	return 0;
L
Linus Torvalds 已提交
384
}
385 386

bool
387
is_valid_oplock_break(char *buffer, struct TCP_Server_Info *srv)
S
Steve French 已提交
388
{
389
	struct smb_hdr *buf = (struct smb_hdr *)buffer;
S
Steve French 已提交
390
	struct smb_com_lock_req *pSMB = (struct smb_com_lock_req *)buf;
391
	struct list_head *tmp, *tmp1, *tmp2;
392 393
	struct cifs_ses *ses;
	struct cifs_tcon *tcon;
394
	struct cifsInodeInfo *pCifsInode;
L
Linus Torvalds 已提交
395 396
	struct cifsFileInfo *netfile;

397
	cifs_dbg(FYI, "Checking for oplock break or dnotify response\n");
S
Steve French 已提交
398
	if ((pSMB->hdr.Command == SMB_COM_NT_TRANSACT) &&
L
Linus Torvalds 已提交
399
	   (pSMB->hdr.Flags & SMBFLG_RESPONSE)) {
S
Steve French 已提交
400
		struct smb_com_transaction_change_notify_rsp *pSMBr =
L
Linus Torvalds 已提交
401
			(struct smb_com_transaction_change_notify_rsp *)buf;
S
Steve French 已提交
402
		struct file_notify_information *pnotify;
L
Linus Torvalds 已提交
403
		__u32 data_offset = 0;
404
		if (get_bcc(buf) > sizeof(struct file_notify_information)) {
L
Linus Torvalds 已提交
405 406
			data_offset = le32_to_cpu(pSMBr->DataOffset);

407 408
			pnotify = (struct file_notify_information *)
				((char *)&pSMBr->hdr.Protocol + data_offset);
409
			cifs_dbg(FYI, "dnotify on %s Action: 0x%x\n",
410
				 pnotify->FileName, pnotify->Action);
S
Steve French 已提交
411
			/*   cifs_dump_mem("Rcvd notify Data: ",buf,
412
				sizeof(struct smb_hdr)+60); */
413
			return true;
L
Linus Torvalds 已提交
414
		}
S
Steve French 已提交
415
		if (pSMBr->hdr.Status.CifsError) {
416
			cifs_dbg(FYI, "notify err 0x%x\n",
417
				 pSMBr->hdr.Status.CifsError);
418
			return true;
L
Linus Torvalds 已提交
419
		}
420
		return false;
S
Steve French 已提交
421
	}
S
Steve French 已提交
422
	if (pSMB->hdr.Command != SMB_COM_LOCKING_ANDX)
423
		return false;
S
Steve French 已提交
424
	if (pSMB->hdr.Flags & SMBFLG_RESPONSE) {
L
Linus Torvalds 已提交
425 426 427 428
		/* no sense logging error on invalid handle on oplock
		   break - harmless race between close request and oplock
		   break response is expected from time to time writing out
		   large dirty files cached on the client */
S
Steve French 已提交
429 430
		if ((NT_STATUS_INVALID_HANDLE) ==
		   le32_to_cpu(pSMB->hdr.Status.CifsError)) {
431
			cifs_dbg(FYI, "invalid handle on oplock break\n");
432
			return true;
S
Steve French 已提交
433
		} else if (ERRbadfid ==
L
Linus Torvalds 已提交
434
		   le16_to_cpu(pSMB->hdr.Status.DosError.Error)) {
435
			return true;
L
Linus Torvalds 已提交
436
		} else {
437
			return false; /* on valid oplock brk we get "request" */
L
Linus Torvalds 已提交
438 439
		}
	}
S
Steve French 已提交
440
	if (pSMB->hdr.WordCount != 8)
441
		return false;
L
Linus Torvalds 已提交
442

443
	cifs_dbg(FYI, "oplock type 0x%x level 0x%x\n",
444
		 pSMB->LockType, pSMB->OplockLevel);
S
Steve French 已提交
445
	if (!(pSMB->LockType & LOCKING_ANDX_OPLOCK_RELEASE))
446
		return false;
L
Linus Torvalds 已提交
447 448

	/* look up tcon based on tid & uid */
449
	spin_lock(&cifs_tcp_ses_lock);
450
	list_for_each(tmp, &srv->smb_ses_list) {
451
		ses = list_entry(tmp, struct cifs_ses, smb_ses_list);
452
		list_for_each(tmp1, &ses->tcon_list) {
453
			tcon = list_entry(tmp1, struct cifs_tcon, tcon_list);
454 455 456
			if (tcon->tid != buf->Tid)
				continue;

457
			cifs_stats_inc(&tcon->stats.cifs_stats.num_oplock_brks);
458
			spin_lock(&tcon->open_file_lock);
459 460
			list_for_each(tmp2, &tcon->openFileList) {
				netfile = list_entry(tmp2, struct cifsFileInfo,
461
						     tlist);
462
				if (pSMB->Fid != netfile->fid.netfid)
463 464
					continue;

465
				cifs_dbg(FYI, "file id match, oplock break\n");
466
				pCifsInode = CIFS_I(d_inode(netfile->dentry));
467

468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483
				set_bit(CIFS_INODE_PENDING_OPLOCK_BREAK,
					&pCifsInode->flags);

				/*
				 * Set flag if the server downgrades the oplock
				 * to L2 else clear.
				 */
				if (pSMB->OplockLevel)
					set_bit(
					   CIFS_INODE_DOWNGRADE_OPLOCK_TO_L2,
					   &pCifsInode->flags);
				else
					clear_bit(
					   CIFS_INODE_DOWNGRADE_OPLOCK_TO_L2,
					   &pCifsInode->flags);

R
Rabin Vincent 已提交
484
				queue_work(cifsoplockd_wq,
485
					   &netfile->oplock_break);
486 487
				netfile->oplock_break_cancelled = false;

488
				spin_unlock(&tcon->open_file_lock);
489
				spin_unlock(&cifs_tcp_ses_lock);
490
				return true;
L
Linus Torvalds 已提交
491
			}
492
			spin_unlock(&tcon->open_file_lock);
493
			spin_unlock(&cifs_tcp_ses_lock);
494
			cifs_dbg(FYI, "No matching file for oplock break\n");
495
			return true;
L
Linus Torvalds 已提交
496 497
		}
	}
498
	spin_unlock(&cifs_tcp_ses_lock);
499
	cifs_dbg(FYI, "Can not process oplock break for non-existent connection\n");
500
	return true;
L
Linus Torvalds 已提交
501 502 503
}

void
504
dump_smb(void *buf, int smb_buf_length)
L
Linus Torvalds 已提交
505 506 507 508
{
	if (traceSMB == 0)
		return;

509 510
	print_hex_dump(KERN_DEBUG, "", DUMP_PREFIX_NONE, 8, 2, buf,
		       smb_buf_length, true);
L
Linus Torvalds 已提交
511
}
512

513 514 515 516
void
cifs_autodisable_serverino(struct cifs_sb_info *cifs_sb)
{
	if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM) {
517
		cifs_sb->mnt_cifs_flags &= ~CIFS_MOUNT_SERVER_INUM;
518 519
		cifs_dbg(VFS, "Autodisabling the use of server inode numbers on %s. This server doesn't seem to support them properly. Hardlinks will not be recognized on this mount. Consider mounting with the \"noserverino\" option to silence this message.\n",
			 cifs_sb_master_tcon(cifs_sb)->treeName);
520 521
	}
}
P
Pavel Shilovsky 已提交
522

523
void cifs_set_oplock_level(struct cifsInodeInfo *cinode, __u32 oplock)
P
Pavel Shilovsky 已提交
524
{
525
	oplock &= 0xF;
P
Pavel Shilovsky 已提交
526

527
	if (oplock == OPLOCK_EXCLUSIVE) {
528
		cinode->oplock = CIFS_CACHE_WRITE_FLG | CIFS_CACHE_READ_FLG;
529 530
		cifs_dbg(FYI, "Exclusive Oplock granted on inode %p\n",
			 &cinode->vfs_inode);
531
	} else if (oplock == OPLOCK_READ) {
532
		cinode->oplock = CIFS_CACHE_READ_FLG;
533 534
		cifs_dbg(FYI, "Level II Oplock granted on inode %p\n",
			 &cinode->vfs_inode);
535 536
	} else
		cinode->oplock = 0;
P
Pavel Shilovsky 已提交
537
}
538

539 540 541 542 543 544 545 546 547 548
/*
 * We wait for oplock breaks to be processed before we attempt to perform
 * writes.
 */
int cifs_get_writer(struct cifsInodeInfo *cinode)
{
	int rc;

start:
	rc = wait_on_bit(&cinode->flags, CIFS_INODE_PENDING_OPLOCK_BREAK,
549
			 TASK_KILLABLE);
550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587
	if (rc)
		return rc;

	spin_lock(&cinode->writers_lock);
	if (!cinode->writers)
		set_bit(CIFS_INODE_PENDING_WRITERS, &cinode->flags);
	cinode->writers++;
	/* Check to see if we have started servicing an oplock break */
	if (test_bit(CIFS_INODE_PENDING_OPLOCK_BREAK, &cinode->flags)) {
		cinode->writers--;
		if (cinode->writers == 0) {
			clear_bit(CIFS_INODE_PENDING_WRITERS, &cinode->flags);
			wake_up_bit(&cinode->flags, CIFS_INODE_PENDING_WRITERS);
		}
		spin_unlock(&cinode->writers_lock);
		goto start;
	}
	spin_unlock(&cinode->writers_lock);
	return 0;
}

void cifs_put_writer(struct cifsInodeInfo *cinode)
{
	spin_lock(&cinode->writers_lock);
	cinode->writers--;
	if (cinode->writers == 0) {
		clear_bit(CIFS_INODE_PENDING_WRITERS, &cinode->flags);
		wake_up_bit(&cinode->flags, CIFS_INODE_PENDING_WRITERS);
	}
	spin_unlock(&cinode->writers_lock);
}

void cifs_done_oplock_break(struct cifsInodeInfo *cinode)
{
	clear_bit(CIFS_INODE_PENDING_OPLOCK_BREAK, &cinode->flags);
	wake_up_bit(&cinode->flags, CIFS_INODE_PENDING_OPLOCK_BREAK);
}

588 589 590 591
bool
backup_cred(struct cifs_sb_info *cifs_sb)
{
	if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_BACKUPUID) {
592
		if (uid_eq(cifs_sb->mnt_backupuid, current_fsuid()))
593 594 595 596 597 598 599 600 601
			return true;
	}
	if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_BACKUPGID) {
		if (in_group_p(cifs_sb->mnt_backupgid))
			return true;
	}

	return false;
}
602 603 604 605

void
cifs_del_pending_open(struct cifs_pending_open *open)
{
606
	spin_lock(&tlink_tcon(open->tlink)->open_file_lock);
607
	list_del(&open->olist);
608
	spin_unlock(&tlink_tcon(open->tlink)->open_file_lock);
609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625
}

void
cifs_add_pending_open_locked(struct cifs_fid *fid, struct tcon_link *tlink,
			     struct cifs_pending_open *open)
{
	memcpy(open->lease_key, fid->lease_key, SMB2_LEASE_KEY_SIZE);
	open->oplock = CIFS_OPLOCK_NO_CHANGE;
	open->tlink = tlink;
	fid->pending_open = open;
	list_add_tail(&open->olist, &tlink_tcon(tlink)->pending_opens);
}

void
cifs_add_pending_open(struct cifs_fid *fid, struct tcon_link *tlink,
		      struct cifs_pending_open *open)
{
626
	spin_lock(&tlink_tcon(tlink)->open_file_lock);
627
	cifs_add_pending_open_locked(fid, tlink, open);
628
	spin_unlock(&tlink_tcon(open->tlink)->open_file_lock);
629
}
630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734

/* parses DFS refferal V3 structure
 * caller is responsible for freeing target_nodes
 * returns:
 * - on success - 0
 * - on failure - errno
 */
int
parse_dfs_referrals(struct get_dfs_referral_rsp *rsp, u32 rsp_size,
		    unsigned int *num_of_nodes,
		    struct dfs_info3_param **target_nodes,
		    const struct nls_table *nls_codepage, int remap,
		    const char *searchName, bool is_unicode)
{
	int i, rc = 0;
	char *data_end;
	struct dfs_referral_level_3 *ref;

	*num_of_nodes = le16_to_cpu(rsp->NumberOfReferrals);

	if (*num_of_nodes < 1) {
		cifs_dbg(VFS, "num_referrals: must be at least > 0, but we get num_referrals = %d\n",
			 *num_of_nodes);
		rc = -EINVAL;
		goto parse_DFS_referrals_exit;
	}

	ref = (struct dfs_referral_level_3 *) &(rsp->referrals);
	if (ref->VersionNumber != cpu_to_le16(3)) {
		cifs_dbg(VFS, "Referrals of V%d version are not supported, should be V3\n",
			 le16_to_cpu(ref->VersionNumber));
		rc = -EINVAL;
		goto parse_DFS_referrals_exit;
	}

	/* get the upper boundary of the resp buffer */
	data_end = (char *)rsp + rsp_size;

	cifs_dbg(FYI, "num_referrals: %d dfs flags: 0x%x ...\n",
		 *num_of_nodes, le32_to_cpu(rsp->DFSFlags));

	*target_nodes = kcalloc(*num_of_nodes, sizeof(struct dfs_info3_param),
				GFP_KERNEL);
	if (*target_nodes == NULL) {
		rc = -ENOMEM;
		goto parse_DFS_referrals_exit;
	}

	/* collect necessary data from referrals */
	for (i = 0; i < *num_of_nodes; i++) {
		char *temp;
		int max_len;
		struct dfs_info3_param *node = (*target_nodes)+i;

		node->flags = le32_to_cpu(rsp->DFSFlags);
		if (is_unicode) {
			__le16 *tmp = kmalloc(strlen(searchName)*2 + 2,
						GFP_KERNEL);
			if (tmp == NULL) {
				rc = -ENOMEM;
				goto parse_DFS_referrals_exit;
			}
			cifsConvertToUTF16((__le16 *) tmp, searchName,
					   PATH_MAX, nls_codepage, remap);
			node->path_consumed = cifs_utf16_bytes(tmp,
					le16_to_cpu(rsp->PathConsumed),
					nls_codepage);
			kfree(tmp);
		} else
			node->path_consumed = le16_to_cpu(rsp->PathConsumed);

		node->server_type = le16_to_cpu(ref->ServerType);
		node->ref_flag = le16_to_cpu(ref->ReferralEntryFlags);

		/* copy DfsPath */
		temp = (char *)ref + le16_to_cpu(ref->DfsPathOffset);
		max_len = data_end - temp;
		node->path_name = cifs_strndup_from_utf16(temp, max_len,
						is_unicode, nls_codepage);
		if (!node->path_name) {
			rc = -ENOMEM;
			goto parse_DFS_referrals_exit;
		}

		/* copy link target UNC */
		temp = (char *)ref + le16_to_cpu(ref->NetworkAddressOffset);
		max_len = data_end - temp;
		node->node_name = cifs_strndup_from_utf16(temp, max_len,
						is_unicode, nls_codepage);
		if (!node->node_name) {
			rc = -ENOMEM;
			goto parse_DFS_referrals_exit;
		}

		ref++;
	}

parse_DFS_referrals_exit:
	if (rc) {
		free_dfs_info_array(*target_nodes, *num_of_nodes);
		*target_nodes = NULL;
		*num_of_nodes = 0;
	}
	return rc;
}
735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802

struct cifs_aio_ctx *
cifs_aio_ctx_alloc(void)
{
	struct cifs_aio_ctx *ctx;

	ctx = kzalloc(sizeof(struct cifs_aio_ctx), GFP_KERNEL);
	if (!ctx)
		return NULL;

	INIT_LIST_HEAD(&ctx->list);
	mutex_init(&ctx->aio_mutex);
	init_completion(&ctx->done);
	kref_init(&ctx->refcount);
	return ctx;
}

void
cifs_aio_ctx_release(struct kref *refcount)
{
	struct cifs_aio_ctx *ctx = container_of(refcount,
					struct cifs_aio_ctx, refcount);

	cifsFileInfo_put(ctx->cfile);
	kvfree(ctx->bv);
	kfree(ctx);
}

#define CIFS_AIO_KMALLOC_LIMIT (1024 * 1024)

int
setup_aio_ctx_iter(struct cifs_aio_ctx *ctx, struct iov_iter *iter, int rw)
{
	ssize_t rc;
	unsigned int cur_npages;
	unsigned int npages = 0;
	unsigned int i;
	size_t len;
	size_t count = iov_iter_count(iter);
	unsigned int saved_len;
	size_t start;
	unsigned int max_pages = iov_iter_npages(iter, INT_MAX);
	struct page **pages = NULL;
	struct bio_vec *bv = NULL;

	if (iter->type & ITER_KVEC) {
		memcpy(&ctx->iter, iter, sizeof(struct iov_iter));
		ctx->len = count;
		iov_iter_advance(iter, count);
		return 0;
	}

	if (max_pages * sizeof(struct bio_vec) <= CIFS_AIO_KMALLOC_LIMIT)
		bv = kmalloc_array(max_pages, sizeof(struct bio_vec),
				   GFP_KERNEL);

	if (!bv) {
		bv = vmalloc(max_pages * sizeof(struct bio_vec));
		if (!bv)
			return -ENOMEM;
	}

	if (max_pages * sizeof(struct page *) <= CIFS_AIO_KMALLOC_LIMIT)
		pages = kmalloc_array(max_pages, sizeof(struct page *),
				      GFP_KERNEL);

	if (!pages) {
		pages = vmalloc(max_pages * sizeof(struct page *));
803
		if (!pages) {
804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853
			kvfree(bv);
			return -ENOMEM;
		}
	}

	saved_len = count;

	while (count && npages < max_pages) {
		rc = iov_iter_get_pages(iter, pages, count, max_pages, &start);
		if (rc < 0) {
			cifs_dbg(VFS, "couldn't get user pages (rc=%zd)\n", rc);
			break;
		}

		if (rc > count) {
			cifs_dbg(VFS, "get pages rc=%zd more than %zu\n", rc,
				 count);
			break;
		}

		iov_iter_advance(iter, rc);
		count -= rc;
		rc += start;
		cur_npages = DIV_ROUND_UP(rc, PAGE_SIZE);

		if (npages + cur_npages > max_pages) {
			cifs_dbg(VFS, "out of vec array capacity (%u vs %u)\n",
				 npages + cur_npages, max_pages);
			break;
		}

		for (i = 0; i < cur_npages; i++) {
			len = rc > PAGE_SIZE ? PAGE_SIZE : rc;
			bv[npages + i].bv_page = pages[i];
			bv[npages + i].bv_offset = start;
			bv[npages + i].bv_len = len - start;
			rc -= len;
			start = 0;
		}

		npages += cur_npages;
	}

	kvfree(pages);
	ctx->bv = bv;
	ctx->len = saved_len - count;
	ctx->npages = npages;
	iov_iter_bvec(&ctx->iter, ITER_BVEC | rw, ctx->bv, npages, ctx->len);
	return 0;
}
854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907

/**
 * cifs_alloc_hash - allocate hash and hash context together
 *
 * The caller has to make sure @sdesc is initialized to either NULL or
 * a valid context. Both can be freed via cifs_free_hash().
 */
int
cifs_alloc_hash(const char *name,
		struct crypto_shash **shash, struct sdesc **sdesc)
{
	int rc = 0;
	size_t size;

	if (*sdesc != NULL)
		return 0;

	*shash = crypto_alloc_shash(name, 0, 0);
	if (IS_ERR(*shash)) {
		cifs_dbg(VFS, "could not allocate crypto %s\n", name);
		rc = PTR_ERR(*shash);
		*shash = NULL;
		*sdesc = NULL;
		return rc;
	}

	size = sizeof(struct shash_desc) + crypto_shash_descsize(*shash);
	*sdesc = kmalloc(size, GFP_KERNEL);
	if (*sdesc == NULL) {
		cifs_dbg(VFS, "no memory left to allocate crypto %s\n", name);
		crypto_free_shash(*shash);
		*shash = NULL;
		return -ENOMEM;
	}

	(*sdesc)->shash.tfm = *shash;
	(*sdesc)->shash.flags = 0x0;
	return 0;
}

/**
 * cifs_free_hash - free hash and hash context together
 *
 * Freeing a NULL hash or context is safe.
 */
void
cifs_free_hash(struct crypto_shash **shash, struct sdesc **sdesc)
{
	kfree(*sdesc);
	*sdesc = NULL;
	if (*shash)
		crypto_free_shash(*shash);
	*shash = NULL;
}