Changeset 988 for vendor/current/source3/smbd/files.c
- Timestamp:
- Nov 24, 2016, 1:14:11 PM (9 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
vendor/current/source3/smbd/files.c
r919 r988 25 25 #include "lib/util/bitmap.h" 26 26 27 #define VALID_FNUM(fnum) (((fnum) >= 0) && ((fnum) < real_max_open_files))28 29 27 #define FILE_HANDLE_OFFSET 0x1000 30 28 31 /**************************************************************************** 32 Return a unique number identifying this fsp over the life of this pid, 33 and try to make it as globally unique as possible. 34 See bug #8995 for the details. 35 ****************************************************************************/ 36 37 static unsigned long get_gen_count(struct smbd_server_connection *sconn) 38 { 39 /* 40 * While fsp->fh->gen_id is 'unsigned long' currently 41 * (which might by 8 bytes), 42 * there's some oplock code which truncates it to 43 * uint32_t(using IVAL()). 44 */ 45 if (sconn->file_gen_counter == 0) { 46 sconn->file_gen_counter = generate_random(); 47 } 48 sconn->file_gen_counter += 1; 49 if (sconn->file_gen_counter >= UINT32_MAX) { 50 sconn->file_gen_counter = 0; 51 } 52 if (sconn->file_gen_counter == 0) { 53 sconn->file_gen_counter += 1; 54 } 55 return sconn->file_gen_counter; 56 } 57 58 /**************************************************************************** 59 Find first available file slot. 60 ****************************************************************************/ 61 62 NTSTATUS file_new(struct smb_request *req, connection_struct *conn, 63 files_struct **result) 64 { 29 /** 30 * create new fsp to be used for file_new or a durable handle reconnect 31 */ 32 NTSTATUS fsp_new(struct connection_struct *conn, TALLOC_CTX *mem_ctx, 33 files_struct **result) 34 { 35 NTSTATUS status = NT_STATUS_NO_MEMORY; 36 files_struct *fsp = NULL; 65 37 struct smbd_server_connection *sconn = conn->sconn; 66 int i; 67 files_struct *fsp; 68 NTSTATUS status; 69 70 /* we want to give out file handles differently on each new 71 connection because of a common bug in MS clients where they try to 72 reuse a file descriptor from an earlier smb connection. This code 73 increases the chance that the errant client will get an error rather 74 than causing corruption */ 75 if (sconn->first_file == 0) { 76 sconn->first_file = (sys_getpid() ^ (int)time(NULL)); 77 sconn->first_file %= sconn->real_max_open_files; 78 } 79 80 /* TODO: Port the id-tree implementation from Samba4 */ 81 82 i = bitmap_find(sconn->file_bmap, sconn->first_file); 83 if (i == -1) { 84 DEBUG(0,("ERROR! Out of file structures\n")); 85 /* TODO: We have to unconditionally return a DOS error here, 86 * W2k3 even returns ERRDOS/ERRnofids for ntcreate&x with 87 * NTSTATUS negotiated */ 88 return NT_STATUS_TOO_MANY_OPENED_FILES; 89 } 90 91 /* 92 * Make a child of the connection_struct as an fsp can't exist 93 * independent of a connection. 94 */ 95 fsp = talloc_zero(conn, struct files_struct); 96 if (!fsp) { 97 return NT_STATUS_NO_MEMORY; 38 39 fsp = talloc_zero(mem_ctx, struct files_struct); 40 if (fsp == NULL) { 41 goto fail; 98 42 } 99 43 … … 103 47 * across multiple fsps. 104 48 */ 105 fsp->fh = talloc_zero(conn, struct fd_handle); 106 if (!fsp->fh) { 107 TALLOC_FREE(fsp); 108 return NT_STATUS_NO_MEMORY; 49 fsp->fh = talloc_zero(mem_ctx, struct fd_handle); 50 if (fsp->fh == NULL) { 51 goto fail; 109 52 } 110 53 … … 112 55 fsp->fh->fd = -1; 113 56 57 fsp->fnum = FNUM_FIELD_INVALID; 114 58 fsp->conn = conn; 115 fsp->fh->gen_id = get_gen_count(sconn); 59 60 DLIST_ADD(sconn->files, fsp); 61 sconn->num_files += 1; 62 63 conn->num_files_open++; 64 65 *result = fsp; 66 return NT_STATUS_OK; 67 68 fail: 69 if (fsp != NULL) { 70 TALLOC_FREE(fsp->fh); 71 } 72 TALLOC_FREE(fsp); 73 74 return status; 75 } 76 77 /**************************************************************************** 78 Find first available file slot. 79 ****************************************************************************/ 80 81 NTSTATUS file_new(struct smb_request *req, connection_struct *conn, 82 files_struct **result) 83 { 84 struct smbd_server_connection *sconn = conn->sconn; 85 files_struct *fsp; 86 NTSTATUS status; 87 88 status = fsp_new(conn, conn, &fsp); 89 if (!NT_STATUS_IS_OK(status)) { 90 return status; 91 } 92 116 93 GetTimeOfDay(&fsp->open_time); 117 94 118 sconn->first_file = (i+1) % (sconn->real_max_open_files); 119 120 bitmap_set(sconn->file_bmap, i); 121 sconn->files_used += 1; 122 123 fsp->fnum = i + FILE_HANDLE_OFFSET; 124 SMB_ASSERT(fsp->fnum < 65536); 95 if (req) { 96 struct smbXsrv_connection *xconn = req->xconn; 97 struct smbXsrv_open *op = NULL; 98 NTTIME now = timeval_to_nttime(&fsp->open_time); 99 100 status = smbXsrv_open_create(xconn, 101 conn->session_info, 102 now, &op); 103 if (!NT_STATUS_IS_OK(status)) { 104 file_free(NULL, fsp); 105 return status; 106 } 107 fsp->op = op; 108 op->compat = fsp; 109 fsp->fnum = op->local_id; 110 fsp->fh->gen_id = smbXsrv_open_hash(op); 111 } else { 112 DEBUG(10, ("%s: req==NULL, INTERNAL_OPEN_ONLY, smbXsrv_open " 113 "allocated\n", __func__)); 114 } 125 115 126 116 /* … … 129 119 * be safe until an audit can be done. 130 120 */ 131 status = create_synthetic_smb_fname(fsp, "", NULL, NULL, 132 &fsp->fsp_name); 133 if (!NT_STATUS_IS_OK(status)) { 134 TALLOC_FREE(fsp); 135 TALLOC_FREE(fsp->fh); 136 } 137 138 DLIST_ADD(sconn->files, fsp); 139 140 DEBUG(5,("allocated file structure %d, fnum = %d (%d used)\n", 141 i, fsp->fnum, sconn->files_used)); 121 fsp->fsp_name = synthetic_smb_fname(fsp, "", NULL, NULL); 122 if (fsp->fsp_name == NULL) { 123 file_free(NULL, fsp); 124 return NT_STATUS_NO_MEMORY; 125 } 126 127 DEBUG(5,("allocated file structure %s (%u used)\n", 128 fsp_fnum_dbg(fsp), (unsigned int)sconn->num_files)); 142 129 143 130 if (req != NULL) { 131 fsp->mid = req->mid; 144 132 req->chain_fsp = fsp; 145 133 } … … 152 140 ZERO_STRUCT(sconn->fsp_fi_cache); 153 141 154 conn->num_files_open++;155 156 142 *result = fsp; 157 143 return NT_STATUS_OK; … … 168 154 for (fsp=conn->sconn->files; fsp; fsp=next) { 169 155 next = fsp->next; 170 if (fsp->conn == conn) { 171 close_file(NULL, fsp, SHUTDOWN_CLOSE); 172 } 156 if (fsp->conn != conn) { 157 continue; 158 } 159 if (fsp->op != NULL && fsp->op->global->durable) { 160 /* 161 * A tree disconnect closes a durable handle 162 */ 163 fsp->op->global->durable = false; 164 } 165 close_file(NULL, fsp, SHUTDOWN_CLOSE); 173 166 } 174 167 } … … 178 171 ****************************************************************************/ 179 172 180 void file_close_pid(struct smbd_server_connection *sconn, uint16 smbpid,181 int vuid)173 void file_close_pid(struct smbd_server_connection *sconn, uint16_t smbpid, 174 uint64_t vuid) 182 175 { 183 176 files_struct *fsp, *next; … … 195 188 ****************************************************************************/ 196 189 197 bool file_init(struct smbd_server_connection *sconn) 198 { 199 int request_max_open_files = lp_max_open_files(); 190 static int files_max_open_fds; 191 192 bool file_init_global(void) 193 { 194 int request_max = lp_max_open_files(); 200 195 int real_lim; 196 int real_max; 197 198 if (files_max_open_fds != 0) { 199 return true; 200 } 201 201 202 202 /* … … 205 205 * fd's we need such as log files etc... 206 206 */ 207 real_lim = set_maxfiles(request_max_open_files + MAX_OPEN_FUDGEFACTOR); 208 209 sconn->real_max_open_files = real_lim - MAX_OPEN_FUDGEFACTOR; 210 211 if (sconn->real_max_open_files + FILE_HANDLE_OFFSET + MAX_OPEN_PIPES 212 > 65536) 213 sconn->real_max_open_files = 214 65536 - FILE_HANDLE_OFFSET - MAX_OPEN_PIPES; 215 216 if(sconn->real_max_open_files != request_max_open_files) { 217 DEBUG(1, ("file_init: Information only: requested %d " 207 real_lim = set_maxfiles(request_max + MAX_OPEN_FUDGEFACTOR); 208 209 real_max = real_lim - MAX_OPEN_FUDGEFACTOR; 210 211 if (real_max + FILE_HANDLE_OFFSET + MAX_OPEN_PIPES > 65536) { 212 real_max = 65536 - FILE_HANDLE_OFFSET - MAX_OPEN_PIPES; 213 } 214 215 if (real_max != request_max) { 216 DEBUG(1, ("file_init_global: Information only: requested %d " 218 217 "open files, %d are available.\n", 219 request_max_open_files, sconn->real_max_open_files)); 220 } 221 222 SMB_ASSERT(sconn->real_max_open_files > 100); 223 224 sconn->file_bmap = bitmap_talloc(sconn, sconn->real_max_open_files); 225 226 if (!sconn->file_bmap) { 218 request_max, real_max)); 219 } 220 221 SMB_ASSERT(real_max > 100); 222 223 files_max_open_fds = real_max; 224 return true; 225 } 226 227 bool file_init(struct smbd_server_connection *sconn) 228 { 229 bool ok; 230 231 ok = file_init_global(); 232 if (!ok) { 227 233 return false; 228 234 } 235 236 sconn->real_max_open_files = files_max_open_fds; 237 229 238 return true; 230 239 } … … 234 243 ****************************************************************************/ 235 244 236 void file_close_user(struct smbd_server_connection *sconn, int vuid)245 void file_close_user(struct smbd_server_connection *sconn, uint64_t vuid) 237 246 { 238 247 files_struct *fsp, *next; … … 313 322 /* Paranoia check. */ 314 323 if ((fsp->fh->fd == -1) && 315 (fsp->oplock_type != NO_OPLOCK )&&316 (fsp->oplock_type != FAKE_LEVEL_II_OPLOCK)) {324 (fsp->oplock_type != NO_OPLOCK && 325 fsp->oplock_type != LEASE_OPLOCK)) { 317 326 DEBUG(0,("file_find_dif: file %s file_id = " 318 327 "%s, gen = %u oplock_type = %u is a " … … 379 388 } 380 389 390 struct files_struct *file_find_one_fsp_from_lease_key( 391 struct smbd_server_connection *sconn, 392 const struct smb2_lease_key *lease_key) 393 { 394 struct files_struct *fsp; 395 396 for (fsp = sconn->files; fsp; fsp=fsp->next) { 397 if ((fsp->lease != NULL) && 398 (fsp->lease->lease.lease_key.data[0] == 399 lease_key->data[0]) && 400 (fsp->lease->lease.lease_key.data[1] == 401 lease_key->data[1])) { 402 return fsp; 403 } 404 } 405 return NULL; 406 } 407 381 408 /**************************************************************************** 382 409 Find any fsp open with a pathname below that of an already open path. … … 448 475 ****************************************************************************/ 449 476 450 void f ile_free(struct smb_request *req,files_struct *fsp)477 void fsp_free(files_struct *fsp) 451 478 { 452 479 struct smbd_server_connection *sconn = fsp->conn->sconn; 453 480 454 481 DLIST_REMOVE(sconn->files, fsp); 482 SMB_ASSERT(sconn->num_files > 0); 483 sconn->num_files--; 455 484 456 485 TALLOC_FREE(fsp->fake_file_handle); … … 462 491 } 463 492 493 if (fsp->lease != NULL) { 494 if (fsp->lease->ref_count == 1) { 495 TALLOC_FREE(fsp->lease); 496 } else { 497 fsp->lease->ref_count--; 498 } 499 } 500 501 fsp->conn->num_files_open--; 502 503 /* this is paranoia, just in case someone tries to reuse the 504 information */ 505 ZERO_STRUCTP(fsp); 506 507 /* fsp->fsp_name is a talloc child and is free'd automatically. */ 508 TALLOC_FREE(fsp); 509 } 510 511 void file_free(struct smb_request *req, files_struct *fsp) 512 { 513 struct smbd_server_connection *sconn = fsp->conn->sconn; 514 uint64_t fnum = fsp->fnum; 515 464 516 if (fsp->notify) { 465 if (fsp->is_directory) { 466 notify_remove_onelevel(fsp->conn->notify_ctx, 467 &fsp->file_id, fsp); 468 } 469 notify_remove(fsp->conn->notify_ctx, fsp); 517 struct notify_context *notify_ctx = 518 fsp->conn->sconn->notify_ctx; 519 notify_remove(notify_ctx, fsp); 470 520 TALLOC_FREE(fsp->notify); 471 521 } 472 473 /* Ensure this event will never fire. */474 TALLOC_FREE(fsp->oplock_timeout);475 522 476 523 /* Ensure this event will never fire. */ 477 524 TALLOC_FREE(fsp->update_write_time_event); 478 525 479 bitmap_clear(sconn->file_bmap, fsp->fnum - FILE_HANDLE_OFFSET); 480 sconn->files_used--; 481 482 DEBUG(5,("freed files structure %d (%d used)\n", 483 fsp->fnum, sconn->files_used)); 484 485 fsp->conn->num_files_open--; 526 if (fsp->op != NULL) { 527 fsp->op->compat = NULL; 528 } 529 TALLOC_FREE(fsp->op); 486 530 487 531 if ((req != NULL) && (fsp == req->chain_fsp)) { … … 503 547 504 548 /* Drop all remaining extensions. */ 505 while (fsp->vfs_extension) { 506 vfs_remove_fsp_extension(fsp->vfs_extension->owner, fsp); 507 } 508 509 /* this is paranoia, just in case someone tries to reuse the 510 information */ 511 ZERO_STRUCTP(fsp); 512 513 /* fsp->fsp_name is a talloc child and is free'd automatically. */ 514 TALLOC_FREE(fsp); 515 } 516 517 /**************************************************************************** 518 Get an fsp from a 16 bit fnum. 519 ****************************************************************************/ 520 521 static struct files_struct *file_fnum(struct smbd_server_connection *sconn, 522 uint16 fnum) 523 { 524 files_struct *fsp; 525 int count=0; 526 527 for (fsp=sconn->files; fsp; fsp=fsp->next, count++) { 528 if (fsp->fnum == fnum) { 529 if (count > 10) { 530 DLIST_PROMOTE(sconn->files, fsp); 531 } 532 return fsp; 533 } 534 } 535 return NULL; 549 vfs_remove_all_fsp_extensions(fsp); 550 551 fsp_free(fsp); 552 553 DEBUG(5,("freed files structure %llu (%u used)\n", 554 (unsigned long long)fnum, (unsigned int)sconn->num_files)); 536 555 } 537 556 … … 540 559 ****************************************************************************/ 541 560 542 files_struct *file_fsp(struct smb_request *req, uint16 fid) 543 { 561 files_struct *file_fsp(struct smb_request *req, uint16_t fid) 562 { 563 struct smbXsrv_open *op; 564 NTSTATUS status; 565 NTTIME now = 0; 544 566 files_struct *fsp; 545 567 … … 558 580 559 581 if (req->chain_fsp != NULL) { 582 if (req->chain_fsp->deferred_close) { 583 return NULL; 584 } 560 585 return req->chain_fsp; 561 586 } 562 587 563 fsp = file_fnum(req->sconn, fid); 564 if (fsp != NULL) { 565 req->chain_fsp = fsp; 566 } 588 if (req->xconn == NULL) { 589 return NULL; 590 } 591 592 now = timeval_to_nttime(&req->request_time); 593 594 status = smb1srv_open_lookup(req->xconn, 595 fid, now, &op); 596 if (!NT_STATUS_IS_OK(status)) { 597 return NULL; 598 } 599 600 fsp = op->compat; 601 if (fsp == NULL) { 602 return NULL; 603 } 604 605 if (fsp->deferred_close) { 606 return NULL; 607 } 608 609 req->chain_fsp = fsp; 567 610 return fsp; 568 611 } 569 612 570 uint64_t fsp_persistent_id(const struct files_struct *fsp) 571 { 572 uint64_t persistent_id; 573 574 /* 575 * This calculates a number that is most likely 576 * globally unique. In future we will have a database 577 * to make it completely unique. 578 * 579 * 32-bit random gen_id 580 * 16-bit truncated open_time 581 * 16-bit fnum (valatile_id) 582 */ 583 persistent_id = fsp->fh->gen_id & UINT32_MAX; 584 persistent_id <<= 16; 585 persistent_id &= 0x0000FFFFFFFF0000LLU; 586 persistent_id |= fsp->open_time.tv_usec & UINT16_MAX; 587 persistent_id <<= 16; 588 persistent_id &= 0xFFFFFFFFFFFF0000LLU; 589 persistent_id |= fsp->fnum & UINT16_MAX; 590 591 return persistent_id; 613 struct files_struct *file_fsp_get(struct smbd_smb2_request *smb2req, 614 uint64_t persistent_id, 615 uint64_t volatile_id) 616 { 617 struct smbXsrv_open *op; 618 NTSTATUS status; 619 NTTIME now = 0; 620 struct files_struct *fsp; 621 622 now = timeval_to_nttime(&smb2req->request_time); 623 624 status = smb2srv_open_lookup(smb2req->xconn, 625 persistent_id, volatile_id, 626 now, &op); 627 if (!NT_STATUS_IS_OK(status)) { 628 return NULL; 629 } 630 631 fsp = op->compat; 632 if (fsp == NULL) { 633 return NULL; 634 } 635 636 if (smb2req->tcon == NULL) { 637 return NULL; 638 } 639 640 if (smb2req->tcon->compat != fsp->conn) { 641 return NULL; 642 } 643 644 if (smb2req->session == NULL) { 645 return NULL; 646 } 647 648 if (smb2req->session->compat == NULL) { 649 return NULL; 650 } 651 652 if (smb2req->session->compat->vuid != fsp->vuid) { 653 return NULL; 654 } 655 656 if (fsp->deferred_close) { 657 return NULL; 658 } 659 660 return fsp; 592 661 } 593 662 … … 597 666 { 598 667 struct files_struct *fsp; 599 uint64_t fsp_persistent;600 668 601 669 if (smb2req->compat_chain_fsp != NULL) { 670 if (smb2req->compat_chain_fsp->deferred_close) { 671 return NULL; 672 } 602 673 return smb2req->compat_chain_fsp; 603 674 } 604 675 605 if (volatile_id > UINT16_MAX) { 606 return NULL; 607 } 608 609 fsp = file_fnum(smb2req->sconn, (uint16_t)volatile_id); 676 fsp = file_fsp_get(smb2req, persistent_id, volatile_id); 610 677 if (fsp == NULL) { 611 return NULL;612 }613 fsp_persistent = fsp_persistent_id(fsp);614 615 if (persistent_id != fsp_persistent) {616 return NULL;617 }618 619 if (smb2req->tcon == NULL) {620 return NULL;621 }622 623 if (smb2req->tcon->compat_conn != fsp->conn) {624 return NULL;625 }626 627 if (smb2req->session == NULL) {628 return NULL;629 }630 631 if (smb2req->session->vuid != fsp->vuid) {632 678 return NULL; 633 679 } … … 642 688 643 689 NTSTATUS dup_file_fsp(struct smb_request *req, files_struct *from, 644 uint32 access_mask, uint32 share_access, 645 uint32 create_options, files_struct *to) 646 { 690 uint32_t access_mask, uint32_t share_access, 691 uint32_t create_options, files_struct *to) 692 { 693 /* this can never happen for print files */ 694 SMB_ASSERT(from->print_file == NULL); 695 647 696 TALLOC_FREE(to->fh); 648 697 … … 652 701 to->file_id = from->file_id; 653 702 to->initial_allocation_size = from->initial_allocation_size; 654 to->mode = from->mode;655 703 to->file_pid = from->file_pid; 656 704 to->vuid = from->vuid; … … 660 708 to->oplock_type = from->oplock_type; 661 709 to->can_lock = from->can_lock; 662 to->can_read = (access_mask & (FILE_READ_DATA)) ? True : False; 663 if (!CAN_WRITE(from->conn)) { 664 to->can_write = False; 665 } else { 666 to->can_write = (access_mask & (FILE_WRITE_DATA | FILE_APPEND_DATA)) ? True : False; 667 } 710 to->can_read = ((access_mask & FILE_READ_DATA) != 0); 711 to->can_write = 712 CAN_WRITE(from->conn) && 713 ((access_mask & (FILE_WRITE_DATA | FILE_APPEND_DATA)) != 0); 668 714 to->modified = from->modified; 669 715 to->is_directory = from->is_directory; 670 716 to->aio_write_behind = from->aio_write_behind; 671 717 672 if (from->print_file) {673 to->print_file = talloc(to, struct print_file_data);674 if (!to->print_file) return NT_STATUS_NO_MEMORY;675 to->print_file->rap_jobid = from->print_file->rap_jobid;676 } else {677 to->print_file = NULL;678 }679 680 718 return fsp_set_smb_fname(to, from->fsp_name); 681 719 } … … 688 726 const char *name, uint32_t *p_name_hash) 689 727 { 728 char tmpbuf[PATH_MAX]; 729 char *fullpath, *to_free; 730 ssize_t len; 690 731 TDB_DATA key; 691 char *fullpath = NULL;692 732 693 733 /* Set the hash of the full pathname. */ 694 fullpath = talloc_asprintf(talloc_tos(), 695 "%s/%s", 696 conn->connectpath, 697 name); 698 if (!fullpath) { 734 735 len = full_path_tos(conn->connectpath, name, tmpbuf, sizeof(tmpbuf), 736 &fullpath, &to_free); 737 if (len == -1) { 699 738 return NT_STATUS_NO_MEMORY; 700 739 } 701 key = string_term_tdb_data(fullpath);740 key = (TDB_DATA) { .dptr = (uint8_t *)fullpath, .dsize = len+1 }; 702 741 *p_name_hash = tdb_jenkins_hash(&key); 703 742 704 743 DEBUG(10,("file_name_hash: %s hash 0x%x\n", 705 fullpath,744 fullpath, 706 745 (unsigned int)*p_name_hash )); 707 746 708 TALLOC_FREE( fullpath);747 TALLOC_FREE(to_free); 709 748 return NT_STATUS_OK; 710 749 } … … 716 755 const struct smb_filename *smb_fname_in) 717 756 { 718 NTSTATUS status;719 757 struct smb_filename *smb_fname_new; 720 758 721 s tatus = copy_smb_filename(fsp, smb_fname_in, &smb_fname_new);722 if ( !NT_STATUS_IS_OK(status)) {723 return status;759 smb_fname_new = cp_smb_filename(fsp, smb_fname_in); 760 if (smb_fname_new == NULL) { 761 return NT_STATUS_NO_MEMORY; 724 762 } 725 763 … … 731 769 &fsp->name_hash); 732 770 } 771 772 const struct GUID *fsp_client_guid(const files_struct *fsp) 773 { 774 return &fsp->conn->sconn->client->connections->smb2.client.guid; 775 } 776 777 uint32_t fsp_lease_type(struct files_struct *fsp) 778 { 779 if (fsp->oplock_type == LEASE_OPLOCK) { 780 return fsp->lease->lease.lease_state; 781 } 782 return map_oplock_to_lease_type(fsp->oplock_type); 783 }
Note:
See TracChangeset
for help on using the changeset viewer.