at v3.5 568 lines 16 kB view raw
1/* 2 * fs/cifs/misc.c 3 * 4 * Copyright (C) International Business Machines Corp., 2002,2008 5 * Author(s): Steve French (sfrench@us.ibm.com) 6 * 7 * This library is free software; you can redistribute it and/or modify 8 * it under the terms of the GNU Lesser General Public License as published 9 * by the Free Software Foundation; either version 2.1 of the License, or 10 * (at your option) any later version. 11 * 12 * This library is distributed in the hope that it will be useful, 13 * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See 15 * the GNU Lesser General Public License for more details. 16 * 17 * You should have received a copy of the GNU Lesser General Public License 18 * along with this library; if not, write to the Free Software 19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 20 */ 21 22#include <linux/slab.h> 23#include <linux/ctype.h> 24#include <linux/mempool.h> 25#include "cifspdu.h" 26#include "cifsglob.h" 27#include "cifsproto.h" 28#include "cifs_debug.h" 29#include "smberr.h" 30#include "nterr.h" 31#include "cifs_unicode.h" 32 33extern mempool_t *cifs_sm_req_poolp; 34extern mempool_t *cifs_req_poolp; 35 36/* The xid serves as a useful identifier for each incoming vfs request, 37 in a similar way to the mid which is useful to track each sent smb, 38 and CurrentXid can also provide a running counter (although it 39 will eventually wrap past zero) of the total vfs operations handled 40 since the cifs fs was mounted */ 41 42unsigned int 43_GetXid(void) 44{ 45 unsigned int xid; 46 47 spin_lock(&GlobalMid_Lock); 48 GlobalTotalActiveXid++; 49 50 /* keep high water mark for number of simultaneous ops in filesystem */ 51 if (GlobalTotalActiveXid > GlobalMaxActiveXid) 52 GlobalMaxActiveXid = GlobalTotalActiveXid; 53 if (GlobalTotalActiveXid > 65000) 54 cFYI(1, "warning: more than 65000 requests active"); 55 xid = GlobalCurrentXid++; 56 spin_unlock(&GlobalMid_Lock); 57 return xid; 58} 59 60void 61_FreeXid(unsigned int xid) 62{ 63 spin_lock(&GlobalMid_Lock); 64 /* if (GlobalTotalActiveXid == 0) 65 BUG(); */ 66 GlobalTotalActiveXid--; 67 spin_unlock(&GlobalMid_Lock); 68} 69 70struct cifs_ses * 71sesInfoAlloc(void) 72{ 73 struct cifs_ses *ret_buf; 74 75 ret_buf = kzalloc(sizeof(struct cifs_ses), GFP_KERNEL); 76 if (ret_buf) { 77 atomic_inc(&sesInfoAllocCount); 78 ret_buf->status = CifsNew; 79 ++ret_buf->ses_count; 80 INIT_LIST_HEAD(&ret_buf->smb_ses_list); 81 INIT_LIST_HEAD(&ret_buf->tcon_list); 82 mutex_init(&ret_buf->session_mutex); 83 } 84 return ret_buf; 85} 86 87void 88sesInfoFree(struct cifs_ses *buf_to_free) 89{ 90 if (buf_to_free == NULL) { 91 cFYI(1, "Null buffer passed to sesInfoFree"); 92 return; 93 } 94 95 atomic_dec(&sesInfoAllocCount); 96 kfree(buf_to_free->serverOS); 97 kfree(buf_to_free->serverDomain); 98 kfree(buf_to_free->serverNOS); 99 if (buf_to_free->password) { 100 memset(buf_to_free->password, 0, strlen(buf_to_free->password)); 101 kfree(buf_to_free->password); 102 } 103 kfree(buf_to_free->user_name); 104 kfree(buf_to_free->domainName); 105 kfree(buf_to_free); 106} 107 108struct cifs_tcon * 109tconInfoAlloc(void) 110{ 111 struct cifs_tcon *ret_buf; 112 ret_buf = kzalloc(sizeof(struct cifs_tcon), GFP_KERNEL); 113 if (ret_buf) { 114 atomic_inc(&tconInfoAllocCount); 115 ret_buf->tidStatus = CifsNew; 116 ++ret_buf->tc_count; 117 INIT_LIST_HEAD(&ret_buf->openFileList); 118 INIT_LIST_HEAD(&ret_buf->tcon_list); 119#ifdef CONFIG_CIFS_STATS 120 spin_lock_init(&ret_buf->stat_lock); 121#endif 122 } 123 return ret_buf; 124} 125 126void 127tconInfoFree(struct cifs_tcon *buf_to_free) 128{ 129 if (buf_to_free == NULL) { 130 cFYI(1, "Null buffer passed to tconInfoFree"); 131 return; 132 } 133 atomic_dec(&tconInfoAllocCount); 134 kfree(buf_to_free->nativeFileSystem); 135 if (buf_to_free->password) { 136 memset(buf_to_free->password, 0, strlen(buf_to_free->password)); 137 kfree(buf_to_free->password); 138 } 139 kfree(buf_to_free); 140} 141 142struct smb_hdr * 143cifs_buf_get(void) 144{ 145 struct smb_hdr *ret_buf = NULL; 146 147/* We could use negotiated size instead of max_msgsize - 148 but it may be more efficient to always alloc same size 149 albeit slightly larger than necessary and maxbuffersize 150 defaults to this and can not be bigger */ 151 ret_buf = mempool_alloc(cifs_req_poolp, GFP_NOFS); 152 153 /* clear the first few header bytes */ 154 /* for most paths, more is cleared in header_assemble */ 155 if (ret_buf) { 156 memset(ret_buf, 0, sizeof(struct smb_hdr) + 3); 157 atomic_inc(&bufAllocCount); 158#ifdef CONFIG_CIFS_STATS2 159 atomic_inc(&totBufAllocCount); 160#endif /* CONFIG_CIFS_STATS2 */ 161 } 162 163 return ret_buf; 164} 165 166void 167cifs_buf_release(void *buf_to_free) 168{ 169 if (buf_to_free == NULL) { 170 /* cFYI(1, "Null buffer passed to cifs_buf_release");*/ 171 return; 172 } 173 mempool_free(buf_to_free, cifs_req_poolp); 174 175 atomic_dec(&bufAllocCount); 176 return; 177} 178 179struct smb_hdr * 180cifs_small_buf_get(void) 181{ 182 struct smb_hdr *ret_buf = NULL; 183 184/* We could use negotiated size instead of max_msgsize - 185 but it may be more efficient to always alloc same size 186 albeit slightly larger than necessary and maxbuffersize 187 defaults to this and can not be bigger */ 188 ret_buf = mempool_alloc(cifs_sm_req_poolp, GFP_NOFS); 189 if (ret_buf) { 190 /* No need to clear memory here, cleared in header assemble */ 191 /* memset(ret_buf, 0, sizeof(struct smb_hdr) + 27);*/ 192 atomic_inc(&smBufAllocCount); 193#ifdef CONFIG_CIFS_STATS2 194 atomic_inc(&totSmBufAllocCount); 195#endif /* CONFIG_CIFS_STATS2 */ 196 197 } 198 return ret_buf; 199} 200 201void 202cifs_small_buf_release(void *buf_to_free) 203{ 204 205 if (buf_to_free == NULL) { 206 cFYI(1, "Null buffer passed to cifs_small_buf_release"); 207 return; 208 } 209 mempool_free(buf_to_free, cifs_sm_req_poolp); 210 211 atomic_dec(&smBufAllocCount); 212 return; 213} 214 215/* NB: MID can not be set if treeCon not passed in, in that 216 case it is responsbility of caller to set the mid */ 217void 218header_assemble(struct smb_hdr *buffer, char smb_command /* command */ , 219 const struct cifs_tcon *treeCon, int word_count 220 /* length of fixed section (word count) in two byte units */) 221{ 222 char *temp = (char *) buffer; 223 224 memset(temp, 0, 256); /* bigger than MAX_CIFS_HDR_SIZE */ 225 226 buffer->smb_buf_length = cpu_to_be32( 227 (2 * word_count) + sizeof(struct smb_hdr) - 228 4 /* RFC 1001 length field does not count */ + 229 2 /* for bcc field itself */) ; 230 231 buffer->Protocol[0] = 0xFF; 232 buffer->Protocol[1] = 'S'; 233 buffer->Protocol[2] = 'M'; 234 buffer->Protocol[3] = 'B'; 235 buffer->Command = smb_command; 236 buffer->Flags = 0x00; /* case sensitive */ 237 buffer->Flags2 = SMBFLG2_KNOWS_LONG_NAMES; 238 buffer->Pid = cpu_to_le16((__u16)current->tgid); 239 buffer->PidHigh = cpu_to_le16((__u16)(current->tgid >> 16)); 240 if (treeCon) { 241 buffer->Tid = treeCon->tid; 242 if (treeCon->ses) { 243 if (treeCon->ses->capabilities & CAP_UNICODE) 244 buffer->Flags2 |= SMBFLG2_UNICODE; 245 if (treeCon->ses->capabilities & CAP_STATUS32) 246 buffer->Flags2 |= SMBFLG2_ERR_STATUS; 247 248 /* Uid is not converted */ 249 buffer->Uid = treeCon->ses->Suid; 250 buffer->Mid = get_next_mid(treeCon->ses->server); 251 } 252 if (treeCon->Flags & SMB_SHARE_IS_IN_DFS) 253 buffer->Flags2 |= SMBFLG2_DFS; 254 if (treeCon->nocase) 255 buffer->Flags |= SMBFLG_CASELESS; 256 if ((treeCon->ses) && (treeCon->ses->server)) 257 if (treeCon->ses->server->sec_mode & 258 (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED)) 259 buffer->Flags2 |= SMBFLG2_SECURITY_SIGNATURE; 260 } 261 262/* endian conversion of flags is now done just before sending */ 263 buffer->WordCount = (char) word_count; 264 return; 265} 266 267static int 268check_smb_hdr(struct smb_hdr *smb, __u16 mid) 269{ 270 /* does it have the right SMB "signature" ? */ 271 if (*(__le32 *) smb->Protocol != cpu_to_le32(0x424d53ff)) { 272 cERROR(1, "Bad protocol string signature header 0x%x", 273 *(unsigned int *)smb->Protocol); 274 return 1; 275 } 276 277 /* Make sure that message ids match */ 278 if (mid != smb->Mid) { 279 cERROR(1, "Mids do not match. received=%u expected=%u", 280 smb->Mid, mid); 281 return 1; 282 } 283 284 /* if it's a response then accept */ 285 if (smb->Flags & SMBFLG_RESPONSE) 286 return 0; 287 288 /* only one valid case where server sends us request */ 289 if (smb->Command == SMB_COM_LOCKING_ANDX) 290 return 0; 291 292 cERROR(1, "Server sent request, not response. mid=%u", smb->Mid); 293 return 1; 294} 295 296int 297checkSMB(char *buf, unsigned int total_read) 298{ 299 struct smb_hdr *smb = (struct smb_hdr *)buf; 300 __u16 mid = smb->Mid; 301 __u32 rfclen = be32_to_cpu(smb->smb_buf_length); 302 __u32 clc_len; /* calculated length */ 303 cFYI(0, "checkSMB Length: 0x%x, smb_buf_length: 0x%x", 304 total_read, rfclen); 305 306 /* is this frame too small to even get to a BCC? */ 307 if (total_read < 2 + sizeof(struct smb_hdr)) { 308 if ((total_read >= sizeof(struct smb_hdr) - 1) 309 && (smb->Status.CifsError != 0)) { 310 /* it's an error return */ 311 smb->WordCount = 0; 312 /* some error cases do not return wct and bcc */ 313 return 0; 314 } else if ((total_read == sizeof(struct smb_hdr) + 1) && 315 (smb->WordCount == 0)) { 316 char *tmp = (char *)smb; 317 /* Need to work around a bug in two servers here */ 318 /* First, check if the part of bcc they sent was zero */ 319 if (tmp[sizeof(struct smb_hdr)] == 0) { 320 /* some servers return only half of bcc 321 * on simple responses (wct, bcc both zero) 322 * in particular have seen this on 323 * ulogoffX and FindClose. This leaves 324 * one byte of bcc potentially unitialized 325 */ 326 /* zero rest of bcc */ 327 tmp[sizeof(struct smb_hdr)+1] = 0; 328 return 0; 329 } 330 cERROR(1, "rcvd invalid byte count (bcc)"); 331 } else { 332 cERROR(1, "Length less than smb header size"); 333 } 334 return -EIO; 335 } 336 337 /* otherwise, there is enough to get to the BCC */ 338 if (check_smb_hdr(smb, mid)) 339 return -EIO; 340 clc_len = smbCalcSize(smb); 341 342 if (4 + rfclen != total_read) { 343 cERROR(1, "Length read does not match RFC1001 length %d", 344 rfclen); 345 return -EIO; 346 } 347 348 if (4 + rfclen != clc_len) { 349 /* check if bcc wrapped around for large read responses */ 350 if ((rfclen > 64 * 1024) && (rfclen > clc_len)) { 351 /* check if lengths match mod 64K */ 352 if (((4 + rfclen) & 0xFFFF) == (clc_len & 0xFFFF)) 353 return 0; /* bcc wrapped */ 354 } 355 cFYI(1, "Calculated size %u vs length %u mismatch for mid=%u", 356 clc_len, 4 + rfclen, smb->Mid); 357 358 if (4 + rfclen < clc_len) { 359 cERROR(1, "RFC1001 size %u smaller than SMB for mid=%u", 360 rfclen, smb->Mid); 361 return -EIO; 362 } else if (rfclen > clc_len + 512) { 363 /* 364 * Some servers (Windows XP in particular) send more 365 * data than the lengths in the SMB packet would 366 * indicate on certain calls (byte range locks and 367 * trans2 find first calls in particular). While the 368 * client can handle such a frame by ignoring the 369 * trailing data, we choose limit the amount of extra 370 * data to 512 bytes. 371 */ 372 cERROR(1, "RFC1001 size %u more than 512 bytes larger " 373 "than SMB for mid=%u", rfclen, smb->Mid); 374 return -EIO; 375 } 376 } 377 return 0; 378} 379 380bool 381is_valid_oplock_break(char *buffer, struct TCP_Server_Info *srv) 382{ 383 struct smb_hdr *buf = (struct smb_hdr *)buffer; 384 struct smb_com_lock_req *pSMB = (struct smb_com_lock_req *)buf; 385 struct list_head *tmp, *tmp1, *tmp2; 386 struct cifs_ses *ses; 387 struct cifs_tcon *tcon; 388 struct cifsInodeInfo *pCifsInode; 389 struct cifsFileInfo *netfile; 390 391 cFYI(1, "Checking for oplock break or dnotify response"); 392 if ((pSMB->hdr.Command == SMB_COM_NT_TRANSACT) && 393 (pSMB->hdr.Flags & SMBFLG_RESPONSE)) { 394 struct smb_com_transaction_change_notify_rsp *pSMBr = 395 (struct smb_com_transaction_change_notify_rsp *)buf; 396 struct file_notify_information *pnotify; 397 __u32 data_offset = 0; 398 if (get_bcc(buf) > sizeof(struct file_notify_information)) { 399 data_offset = le32_to_cpu(pSMBr->DataOffset); 400 401 pnotify = (struct file_notify_information *) 402 ((char *)&pSMBr->hdr.Protocol + data_offset); 403 cFYI(1, "dnotify on %s Action: 0x%x", 404 pnotify->FileName, pnotify->Action); 405 /* cifs_dump_mem("Rcvd notify Data: ",buf, 406 sizeof(struct smb_hdr)+60); */ 407 return true; 408 } 409 if (pSMBr->hdr.Status.CifsError) { 410 cFYI(1, "notify err 0x%d", 411 pSMBr->hdr.Status.CifsError); 412 return true; 413 } 414 return false; 415 } 416 if (pSMB->hdr.Command != SMB_COM_LOCKING_ANDX) 417 return false; 418 if (pSMB->hdr.Flags & SMBFLG_RESPONSE) { 419 /* no sense logging error on invalid handle on oplock 420 break - harmless race between close request and oplock 421 break response is expected from time to time writing out 422 large dirty files cached on the client */ 423 if ((NT_STATUS_INVALID_HANDLE) == 424 le32_to_cpu(pSMB->hdr.Status.CifsError)) { 425 cFYI(1, "invalid handle on oplock break"); 426 return true; 427 } else if (ERRbadfid == 428 le16_to_cpu(pSMB->hdr.Status.DosError.Error)) { 429 return true; 430 } else { 431 return false; /* on valid oplock brk we get "request" */ 432 } 433 } 434 if (pSMB->hdr.WordCount != 8) 435 return false; 436 437 cFYI(1, "oplock type 0x%d level 0x%d", 438 pSMB->LockType, pSMB->OplockLevel); 439 if (!(pSMB->LockType & LOCKING_ANDX_OPLOCK_RELEASE)) 440 return false; 441 442 /* look up tcon based on tid & uid */ 443 spin_lock(&cifs_tcp_ses_lock); 444 list_for_each(tmp, &srv->smb_ses_list) { 445 ses = list_entry(tmp, struct cifs_ses, smb_ses_list); 446 list_for_each(tmp1, &ses->tcon_list) { 447 tcon = list_entry(tmp1, struct cifs_tcon, tcon_list); 448 if (tcon->tid != buf->Tid) 449 continue; 450 451 cifs_stats_inc(&tcon->num_oplock_brks); 452 spin_lock(&cifs_file_list_lock); 453 list_for_each(tmp2, &tcon->openFileList) { 454 netfile = list_entry(tmp2, struct cifsFileInfo, 455 tlist); 456 if (pSMB->Fid != netfile->netfid) 457 continue; 458 459 cFYI(1, "file id match, oplock break"); 460 pCifsInode = CIFS_I(netfile->dentry->d_inode); 461 462 cifs_set_oplock_level(pCifsInode, 463 pSMB->OplockLevel ? OPLOCK_READ : 0); 464 queue_work(cifsiod_wq, 465 &netfile->oplock_break); 466 netfile->oplock_break_cancelled = false; 467 468 spin_unlock(&cifs_file_list_lock); 469 spin_unlock(&cifs_tcp_ses_lock); 470 return true; 471 } 472 spin_unlock(&cifs_file_list_lock); 473 spin_unlock(&cifs_tcp_ses_lock); 474 cFYI(1, "No matching file for oplock break"); 475 return true; 476 } 477 } 478 spin_unlock(&cifs_tcp_ses_lock); 479 cFYI(1, "Can not process oplock break for non-existent connection"); 480 return true; 481} 482 483void 484dump_smb(void *buf, int smb_buf_length) 485{ 486 int i, j; 487 char debug_line[17]; 488 unsigned char *buffer = buf; 489 490 if (traceSMB == 0) 491 return; 492 493 for (i = 0, j = 0; i < smb_buf_length; i++, j++) { 494 if (i % 8 == 0) { 495 /* have reached the beginning of line */ 496 printk(KERN_DEBUG "| "); 497 j = 0; 498 } 499 printk("%0#4x ", buffer[i]); 500 debug_line[2 * j] = ' '; 501 if (isprint(buffer[i])) 502 debug_line[1 + (2 * j)] = buffer[i]; 503 else 504 debug_line[1 + (2 * j)] = '_'; 505 506 if (i % 8 == 7) { 507 /* reached end of line, time to print ascii */ 508 debug_line[16] = 0; 509 printk(" | %s\n", debug_line); 510 } 511 } 512 for (; j < 8; j++) { 513 printk(" "); 514 debug_line[2 * j] = ' '; 515 debug_line[1 + (2 * j)] = ' '; 516 } 517 printk(" | %s\n", debug_line); 518 return; 519} 520 521void 522cifs_autodisable_serverino(struct cifs_sb_info *cifs_sb) 523{ 524 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM) { 525 cifs_sb->mnt_cifs_flags &= ~CIFS_MOUNT_SERVER_INUM; 526 cERROR(1, "Autodisabling the use of server inode numbers on " 527 "%s. This server doesn't seem to support them " 528 "properly. Hardlinks will not be recognized on this " 529 "mount. Consider mounting with the \"noserverino\" " 530 "option to silence this message.", 531 cifs_sb_master_tcon(cifs_sb)->treeName); 532 } 533} 534 535void cifs_set_oplock_level(struct cifsInodeInfo *cinode, __u32 oplock) 536{ 537 oplock &= 0xF; 538 539 if (oplock == OPLOCK_EXCLUSIVE) { 540 cinode->clientCanCacheAll = true; 541 cinode->clientCanCacheRead = true; 542 cFYI(1, "Exclusive Oplock granted on inode %p", 543 &cinode->vfs_inode); 544 } else if (oplock == OPLOCK_READ) { 545 cinode->clientCanCacheAll = false; 546 cinode->clientCanCacheRead = true; 547 cFYI(1, "Level II Oplock granted on inode %p", 548 &cinode->vfs_inode); 549 } else { 550 cinode->clientCanCacheAll = false; 551 cinode->clientCanCacheRead = false; 552 } 553} 554 555bool 556backup_cred(struct cifs_sb_info *cifs_sb) 557{ 558 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_BACKUPUID) { 559 if (cifs_sb->mnt_backupuid == current_fsuid()) 560 return true; 561 } 562 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_BACKUPGID) { 563 if (in_group_p(cifs_sb->mnt_backupgid)) 564 return true; 565 } 566 567 return false; 568}