Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/sfrench/cifs-2.6

* 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/sfrench/cifs-2.6:
[CIFS] list entry can not return null
turn cifs_setattr into a multiplexor that calls the correct function
move file time and dos attribute setting logic into new function
spin off cifs_setattr with unix extensions to its own function
[CIFS] Code cleanup in old sessionsetup code
[CIFS] cifs_mkdir and cifs_create should respect the setgid bit on parent dir
Rename CIFSSMBSetFileTimes to CIFSSMBSetFileInfo and add PID arg
change CIFSSMBSetTimes to CIFSSMBSetPathInfo
[CIFS] fix trailing whitespace
bundle up Unix SET_PATH_INFO args into a struct and change name
Fix missing braces in cifs_revalidate()
remove locking around tcpSesAllocCount atomic variable
[CIFS] properly account for new user= field in SPNEGO upcall string allocation
[CIFS] remove level of indentation from decode_negTokenInit
[CIFS] cifs send2 not retrying enough in some cases on full socket
[CIFS] oid should also be checked against class in cifs asn

+665 -522
+8
fs/cifs/CHANGES
··· 1 + Version 1.54 2 + ------------ 3 + Fix premature write failure on congested networks (we would give up 4 + on EAGAIN from the socket too quickly on large writes). 5 + Cifs_mkdir and cifs_create now respect the setgid bit on parent dir. 6 + Fix endian problems in acl (mode from/to cifs acl) on bigendian 7 + architectures. 8 + 1 9 Version 1.53 2 10 ------------ 3 11 DFS support added (Microsoft Distributed File System client support needed
+136 -146
fs/cifs/asn1.c
··· 483 483 484 484 asn1_open(&ctx, security_blob, length); 485 485 486 + /* GSSAPI header */ 486 487 if (asn1_header_decode(&ctx, &end, &cls, &con, &tag) == 0) { 487 488 cFYI(1, ("Error decoding negTokenInit header")); 488 489 return 0; ··· 491 490 || (tag != ASN1_EOC)) { 492 491 cFYI(1, ("cls = %d con = %d tag = %d", cls, con, tag)); 493 492 return 0; 494 - } else { 495 - /* remember to free obj->oid */ 496 - rc = asn1_header_decode(&ctx, &end, &cls, &con, &tag); 497 - if (rc) { 498 - if ((tag == ASN1_OJI) && (con == ASN1_PRI)) { 499 - rc = asn1_oid_decode(&ctx, end, &oid, &oidlen); 500 - if (rc) { 501 - rc = compare_oid(oid, oidlen, 502 - SPNEGO_OID, 503 - SPNEGO_OID_LEN); 504 - kfree(oid); 505 - } 506 - } else 507 - rc = 0; 508 - } 509 - 510 - if (!rc) { 511 - cFYI(1, ("Error decoding negTokenInit header")); 512 - return 0; 513 - } 514 - 515 - if (asn1_header_decode(&ctx, &end, &cls, &con, &tag) == 0) { 516 - cFYI(1, ("Error decoding negTokenInit")); 517 - return 0; 518 - } else if ((cls != ASN1_CTX) || (con != ASN1_CON) 519 - || (tag != ASN1_EOC)) { 520 - cFYI(1, 521 - ("cls = %d con = %d tag = %d end = %p (%d) exit 0", 522 - cls, con, tag, end, *end)); 523 - return 0; 524 - } 525 - 526 - if (asn1_header_decode(&ctx, &end, &cls, &con, &tag) == 0) { 527 - cFYI(1, ("Error decoding negTokenInit")); 528 - return 0; 529 - } else if ((cls != ASN1_UNI) || (con != ASN1_CON) 530 - || (tag != ASN1_SEQ)) { 531 - cFYI(1, 532 - ("cls = %d con = %d tag = %d end = %p (%d) exit 1", 533 - cls, con, tag, end, *end)); 534 - return 0; 535 - } 536 - 537 - if (asn1_header_decode(&ctx, &end, &cls, &con, &tag) == 0) { 538 - cFYI(1, ("Error decoding 2nd part of negTokenInit")); 539 - return 0; 540 - } else if ((cls != ASN1_CTX) || (con != ASN1_CON) 541 - || (tag != ASN1_EOC)) { 542 - cFYI(1, 543 - ("cls = %d con = %d tag = %d end = %p (%d) exit 0", 544 - cls, con, tag, end, *end)); 545 - return 0; 546 - } 547 - 548 - if (asn1_header_decode 549 - (&ctx, &sequence_end, &cls, &con, &tag) == 0) { 550 - cFYI(1, ("Error decoding 2nd part of negTokenInit")); 551 - return 0; 552 - } else if ((cls != ASN1_UNI) || (con != ASN1_CON) 553 - || (tag != ASN1_SEQ)) { 554 - cFYI(1, 555 - ("cls = %d con = %d tag = %d end = %p (%d) exit 1", 556 - cls, con, tag, end, *end)); 557 - return 0; 558 - } 559 - 560 - while (!asn1_eoc_decode(&ctx, sequence_end)) { 561 - rc = asn1_header_decode(&ctx, &end, &cls, &con, &tag); 562 - if (!rc) { 563 - cFYI(1, 564 - ("Error decoding negTokenInit hdr exit2")); 565 - return 0; 566 - } 567 - if ((tag == ASN1_OJI) && (con == ASN1_PRI)) { 568 - if (asn1_oid_decode(&ctx, end, &oid, &oidlen)) { 569 - 570 - cFYI(1, 571 - ("OID len = %d oid = 0x%lx 0x%lx " 572 - "0x%lx 0x%lx", 573 - oidlen, *oid, *(oid + 1), 574 - *(oid + 2), *(oid + 3))); 575 - 576 - if (compare_oid(oid, oidlen, 577 - MSKRB5_OID, 578 - MSKRB5_OID_LEN)) 579 - use_kerberos = true; 580 - else if (compare_oid(oid, oidlen, 581 - KRB5_OID, 582 - KRB5_OID_LEN)) 583 - use_kerberos = true; 584 - else if (compare_oid(oid, oidlen, 585 - NTLMSSP_OID, 586 - NTLMSSP_OID_LEN)) 587 - use_ntlmssp = true; 588 - 589 - kfree(oid); 590 - } 591 - } else { 592 - cFYI(1, ("Should be an oid what is going on?")); 593 - } 594 - } 595 - 596 - if (asn1_header_decode(&ctx, &end, &cls, &con, &tag) == 0) { 597 - cFYI(1, 598 - ("Error decoding last part negTokenInit exit3")); 599 - return 0; 600 - } else if ((cls != ASN1_CTX) || (con != ASN1_CON)) { 601 - /* tag = 3 indicating mechListMIC */ 602 - cFYI(1, 603 - ("Exit 4 cls = %d con = %d tag = %d end = %p (%d)", 604 - cls, con, tag, end, *end)); 605 - return 0; 606 - } 607 - if (asn1_header_decode(&ctx, &end, &cls, &con, &tag) == 0) { 608 - cFYI(1, 609 - ("Error decoding last part negTokenInit exit5")); 610 - return 0; 611 - } else if ((cls != ASN1_UNI) || (con != ASN1_CON) 612 - || (tag != ASN1_SEQ)) { 613 - cFYI(1, ("cls = %d con = %d tag = %d end = %p (%d)", 614 - cls, con, tag, end, *end)); 615 - } 616 - 617 - if (asn1_header_decode(&ctx, &end, &cls, &con, &tag) == 0) { 618 - cFYI(1, 619 - ("Error decoding last part negTokenInit exit 7")); 620 - return 0; 621 - } else if ((cls != ASN1_CTX) || (con != ASN1_CON)) { 622 - cFYI(1, 623 - ("Exit 8 cls = %d con = %d tag = %d end = %p (%d)", 624 - cls, con, tag, end, *end)); 625 - return 0; 626 - } 627 - if (asn1_header_decode(&ctx, &end, &cls, &con, &tag) == 0) { 628 - cFYI(1, 629 - ("Error decoding last part negTokenInit exit9")); 630 - return 0; 631 - } else if ((cls != ASN1_UNI) || (con != ASN1_PRI) 632 - || (tag != ASN1_GENSTR)) { 633 - cFYI(1, 634 - ("Exit10 cls = %d con = %d tag = %d end = %p (%d)", 635 - cls, con, tag, end, *end)); 636 - return 0; 637 - } 638 - cFYI(1, ("Need to call asn1_octets_decode() function for %s", 639 - ctx.pointer)); /* is this UTF-8 or ASCII? */ 640 493 } 494 + 495 + /* Check for SPNEGO OID -- remember to free obj->oid */ 496 + rc = asn1_header_decode(&ctx, &end, &cls, &con, &tag); 497 + if (rc) { 498 + if ((tag == ASN1_OJI) && (con == ASN1_PRI) && 499 + (cls == ASN1_UNI)) { 500 + rc = asn1_oid_decode(&ctx, end, &oid, &oidlen); 501 + if (rc) { 502 + rc = compare_oid(oid, oidlen, SPNEGO_OID, 503 + SPNEGO_OID_LEN); 504 + kfree(oid); 505 + } 506 + } else 507 + rc = 0; 508 + } 509 + 510 + /* SPNEGO OID not present or garbled -- bail out */ 511 + if (!rc) { 512 + cFYI(1, ("Error decoding negTokenInit header")); 513 + return 0; 514 + } 515 + 516 + if (asn1_header_decode(&ctx, &end, &cls, &con, &tag) == 0) { 517 + cFYI(1, ("Error decoding negTokenInit")); 518 + return 0; 519 + } else if ((cls != ASN1_CTX) || (con != ASN1_CON) 520 + || (tag != ASN1_EOC)) { 521 + cFYI(1, 522 + ("cls = %d con = %d tag = %d end = %p (%d) exit 0", 523 + cls, con, tag, end, *end)); 524 + return 0; 525 + } 526 + 527 + if (asn1_header_decode(&ctx, &end, &cls, &con, &tag) == 0) { 528 + cFYI(1, ("Error decoding negTokenInit")); 529 + return 0; 530 + } else if ((cls != ASN1_UNI) || (con != ASN1_CON) 531 + || (tag != ASN1_SEQ)) { 532 + cFYI(1, 533 + ("cls = %d con = %d tag = %d end = %p (%d) exit 1", 534 + cls, con, tag, end, *end)); 535 + return 0; 536 + } 537 + 538 + if (asn1_header_decode(&ctx, &end, &cls, &con, &tag) == 0) { 539 + cFYI(1, ("Error decoding 2nd part of negTokenInit")); 540 + return 0; 541 + } else if ((cls != ASN1_CTX) || (con != ASN1_CON) 542 + || (tag != ASN1_EOC)) { 543 + cFYI(1, 544 + ("cls = %d con = %d tag = %d end = %p (%d) exit 0", 545 + cls, con, tag, end, *end)); 546 + return 0; 547 + } 548 + 549 + if (asn1_header_decode 550 + (&ctx, &sequence_end, &cls, &con, &tag) == 0) { 551 + cFYI(1, ("Error decoding 2nd part of negTokenInit")); 552 + return 0; 553 + } else if ((cls != ASN1_UNI) || (con != ASN1_CON) 554 + || (tag != ASN1_SEQ)) { 555 + cFYI(1, 556 + ("cls = %d con = %d tag = %d end = %p (%d) exit 1", 557 + cls, con, tag, end, *end)); 558 + return 0; 559 + } 560 + 561 + while (!asn1_eoc_decode(&ctx, sequence_end)) { 562 + rc = asn1_header_decode(&ctx, &end, &cls, &con, &tag); 563 + if (!rc) { 564 + cFYI(1, 565 + ("Error decoding negTokenInit hdr exit2")); 566 + return 0; 567 + } 568 + if ((tag == ASN1_OJI) && (con == ASN1_PRI)) { 569 + if (asn1_oid_decode(&ctx, end, &oid, &oidlen)) { 570 + 571 + cFYI(1, ("OID len = %d oid = 0x%lx 0x%lx " 572 + "0x%lx 0x%lx", oidlen, *oid, 573 + *(oid + 1), *(oid + 2), *(oid + 3))); 574 + 575 + if (compare_oid(oid, oidlen, MSKRB5_OID, 576 + MSKRB5_OID_LEN)) 577 + use_kerberos = true; 578 + else if (compare_oid(oid, oidlen, KRB5_OID, 579 + KRB5_OID_LEN)) 580 + use_kerberos = true; 581 + else if (compare_oid(oid, oidlen, NTLMSSP_OID, 582 + NTLMSSP_OID_LEN)) 583 + use_ntlmssp = true; 584 + 585 + kfree(oid); 586 + } 587 + } else { 588 + cFYI(1, ("Should be an oid what is going on?")); 589 + } 590 + } 591 + 592 + if (asn1_header_decode(&ctx, &end, &cls, &con, &tag) == 0) { 593 + cFYI(1, ("Error decoding last part negTokenInit exit3")); 594 + return 0; 595 + } else if ((cls != ASN1_CTX) || (con != ASN1_CON)) { 596 + /* tag = 3 indicating mechListMIC */ 597 + cFYI(1, ("Exit 4 cls = %d con = %d tag = %d end = %p (%d)", 598 + cls, con, tag, end, *end)); 599 + return 0; 600 + } 601 + if (asn1_header_decode(&ctx, &end, &cls, &con, &tag) == 0) { 602 + cFYI(1, ("Error decoding last part negTokenInit exit5")); 603 + return 0; 604 + } else if ((cls != ASN1_UNI) || (con != ASN1_CON) 605 + || (tag != ASN1_SEQ)) { 606 + cFYI(1, ("cls = %d con = %d tag = %d end = %p (%d)", 607 + cls, con, tag, end, *end)); 608 + } 609 + 610 + if (asn1_header_decode(&ctx, &end, &cls, &con, &tag) == 0) { 611 + cFYI(1, ("Error decoding last part negTokenInit exit 7")); 612 + return 0; 613 + } else if ((cls != ASN1_CTX) || (con != ASN1_CON)) { 614 + cFYI(1, ("Exit 8 cls = %d con = %d tag = %d end = %p (%d)", 615 + cls, con, tag, end, *end)); 616 + return 0; 617 + } 618 + if (asn1_header_decode(&ctx, &end, &cls, &con, &tag) == 0) { 619 + cFYI(1, ("Error decoding last part negTokenInit exit9")); 620 + return 0; 621 + } else if ((cls != ASN1_UNI) || (con != ASN1_PRI) 622 + || (tag != ASN1_GENSTR)) { 623 + cFYI(1, ("Exit10 cls = %d con = %d tag = %d end = %p (%d)", 624 + cls, con, tag, end, *end)); 625 + return 0; 626 + } 627 + cFYI(1, ("Need to call asn1_octets_decode() function for %s", 628 + ctx.pointer)); /* is this UTF-8 or ASCII? */ 641 629 642 630 if (use_kerberos) 643 631 *secType = Kerberos;
+24 -29
fs/cifs/cifs_debug.c
··· 79 79 spin_lock(&GlobalMid_Lock); 80 80 list_for_each(tmp, &server->pending_mid_q) { 81 81 mid_entry = list_entry(tmp, struct mid_q_entry, qhead); 82 - if (mid_entry) { 83 - cERROR(1, ("State: %d Cmd: %d Pid: %d Tsk: %p Mid %d", 84 - mid_entry->midState, 85 - (int)mid_entry->command, 86 - mid_entry->pid, 87 - mid_entry->tsk, 88 - mid_entry->mid)); 82 + cERROR(1, ("State: %d Cmd: %d Pid: %d Tsk: %p Mid %d", 83 + mid_entry->midState, 84 + (int)mid_entry->command, 85 + mid_entry->pid, 86 + mid_entry->tsk, 87 + mid_entry->mid)); 89 88 #ifdef CONFIG_CIFS_STATS2 90 - cERROR(1, ("IsLarge: %d buf: %p time rcv: %ld now: %ld", 91 - mid_entry->largeBuf, 92 - mid_entry->resp_buf, 93 - mid_entry->when_received, 94 - jiffies)); 89 + cERROR(1, ("IsLarge: %d buf: %p time rcv: %ld now: %ld", 90 + mid_entry->largeBuf, 91 + mid_entry->resp_buf, 92 + mid_entry->when_received, 93 + jiffies)); 95 94 #endif /* STATS2 */ 96 - cERROR(1, ("IsMult: %d IsEnd: %d", mid_entry->multiRsp, 97 - mid_entry->multiEnd)); 98 - if (mid_entry->resp_buf) { 99 - cifs_dump_detail(mid_entry->resp_buf); 100 - cifs_dump_mem("existing buf: ", 101 - mid_entry->resp_buf, 62); 102 - } 95 + cERROR(1, ("IsMult: %d IsEnd: %d", mid_entry->multiRsp, 96 + mid_entry->multiEnd)); 97 + if (mid_entry->resp_buf) { 98 + cifs_dump_detail(mid_entry->resp_buf); 99 + cifs_dump_mem("existing buf: ", 100 + mid_entry->resp_buf, 62); 103 101 } 104 102 } 105 103 spin_unlock(&GlobalMid_Lock); ··· 161 163 mid_entry = list_entry(tmp1, struct 162 164 mid_q_entry, 163 165 qhead); 164 - if (mid_entry) { 165 - seq_printf(m, 166 - "State: %d com: %d pid:" 167 - " %d tsk: %p mid %d\n", 168 - mid_entry->midState, 169 - (int)mid_entry->command, 170 - mid_entry->pid, 171 - mid_entry->tsk, 172 - mid_entry->mid); 173 - } 166 + seq_printf(m, "State: %d com: %d pid:" 167 + " %d tsk: %p mid %d\n", 168 + mid_entry->midState, 169 + (int)mid_entry->command, 170 + mid_entry->pid, 171 + mid_entry->tsk, 172 + mid_entry->mid); 174 173 } 175 174 spin_unlock(&GlobalMid_Lock); 176 175 }
+11 -7
fs/cifs/cifs_spnego.c
··· 66 66 .describe = user_describe, 67 67 }; 68 68 69 - #define MAX_VER_STR_LEN 9 /* length of longest version string e.g. 70 - strlen(";ver=0xFF") */ 69 + #define MAX_VER_STR_LEN 8 /* length of longest version string e.g. 70 + strlen("ver=0xFF") */ 71 71 #define MAX_MECH_STR_LEN 13 /* length of longest security mechanism name, eg 72 72 in future could have strlen(";sec=ntlmsspi") */ 73 73 #define MAX_IPV6_ADDR_LEN 42 /* eg FEDC:BA98:7654:3210:FEDC:BA98:7654:3210/60 */ ··· 81 81 struct key *spnego_key; 82 82 const char *hostname = server->hostname; 83 83 84 - /* BB: come up with better scheme for determining length */ 85 - /* length of fields (with semicolons): ver=0xyz ipv4= ipaddress host= 86 - hostname sec=mechanism uid=0x uid */ 87 - desc_len = MAX_VER_STR_LEN + 5 + MAX_IPV6_ADDR_LEN + 1 + 6 + 88 - strlen(hostname) + MAX_MECH_STR_LEN + 8 + (sizeof(uid_t) * 2); 84 + /* length of fields (with semicolons): ver=0xyz ip4=ipaddress 85 + host=hostname sec=mechanism uid=0xFF user=username */ 86 + desc_len = MAX_VER_STR_LEN + 87 + 6 /* len of "host=" */ + strlen(hostname) + 88 + 5 /* len of ";ipv4=" */ + MAX_IPV6_ADDR_LEN + 89 + MAX_MECH_STR_LEN + 90 + 7 /* len of ";uid=0x" */ + (sizeof(uid_t) * 2) + 91 + 6 /* len of ";user=" */ + strlen(sesInfo->userName) + 1; 92 + 89 93 spnego_key = ERR_PTR(-ENOMEM); 90 94 description = kzalloc(desc_len, GFP_KERNEL); 91 95 if (description == NULL)
+33 -38
fs/cifs/cifsfs.c
··· 930 930 schedule_timeout(39*HZ); 931 931 } else { 932 932 oplock_item = list_entry(GlobalOplock_Q.next, 933 - struct oplock_q_entry, qhead); 934 - if (oplock_item) { 935 - cFYI(1, ("found oplock item to write out")); 936 - pTcon = oplock_item->tcon; 937 - inode = oplock_item->pinode; 938 - netfid = oplock_item->netfid; 939 - spin_unlock(&GlobalMid_Lock); 940 - DeleteOplockQEntry(oplock_item); 941 - /* can not grab inode sem here since it would 933 + struct oplock_q_entry, qhead); 934 + cFYI(1, ("found oplock item to write out")); 935 + pTcon = oplock_item->tcon; 936 + inode = oplock_item->pinode; 937 + netfid = oplock_item->netfid; 938 + spin_unlock(&GlobalMid_Lock); 939 + DeleteOplockQEntry(oplock_item); 940 + /* can not grab inode sem here since it would 942 941 deadlock when oplock received on delete 943 942 since vfs_unlink holds the i_mutex across 944 943 the call */ 945 - /* mutex_lock(&inode->i_mutex);*/ 946 - if (S_ISREG(inode->i_mode)) { 947 - rc = 948 - filemap_fdatawrite(inode->i_mapping); 949 - if (CIFS_I(inode)->clientCanCacheRead 950 - == 0) { 951 - waitrc = filemap_fdatawait(inode->i_mapping); 952 - invalidate_remote_inode(inode); 953 - } 954 - if (rc == 0) 955 - rc = waitrc; 956 - } else 957 - rc = 0; 958 - /* mutex_unlock(&inode->i_mutex);*/ 959 - if (rc) 960 - CIFS_I(inode)->write_behind_rc = rc; 961 - cFYI(1, ("Oplock flush inode %p rc %d", 962 - inode, rc)); 944 + /* mutex_lock(&inode->i_mutex);*/ 945 + if (S_ISREG(inode->i_mode)) { 946 + rc = filemap_fdatawrite(inode->i_mapping); 947 + if (CIFS_I(inode)->clientCanCacheRead == 0) { 948 + waitrc = filemap_fdatawait( 949 + inode->i_mapping); 950 + invalidate_remote_inode(inode); 951 + } 952 + if (rc == 0) 953 + rc = waitrc; 954 + } else 955 + rc = 0; 956 + /* mutex_unlock(&inode->i_mutex);*/ 957 + if (rc) 958 + CIFS_I(inode)->write_behind_rc = rc; 959 + cFYI(1, ("Oplock flush inode %p rc %d", 960 + inode, rc)); 963 961 964 962 /* releasing stale oplock after recent reconnect 965 963 of smb session using a now incorrect file ··· 965 967 not bother sending an oplock release if session 966 968 to server still is disconnected since oplock 967 969 already released by the server in that case */ 968 - if (pTcon->tidStatus != CifsNeedReconnect) { 969 - rc = CIFSSMBLock(0, pTcon, netfid, 970 - 0 /* len */ , 0 /* offset */, 0, 971 - 0, LOCKING_ANDX_OPLOCK_RELEASE, 972 - false /* wait flag */); 973 - cFYI(1, ("Oplock release rc = %d", rc)); 974 - } 975 - } else 976 - spin_unlock(&GlobalMid_Lock); 970 + if (pTcon->tidStatus != CifsNeedReconnect) { 971 + rc = CIFSSMBLock(0, pTcon, netfid, 972 + 0 /* len */ , 0 /* offset */, 0, 973 + 0, LOCKING_ANDX_OPLOCK_RELEASE, 974 + false /* wait flag */); 975 + cFYI(1, ("Oplock release rc = %d", rc)); 976 + } 977 977 set_current_state(TASK_INTERRUPTIBLE); 978 978 schedule_timeout(1); /* yield in case q were corrupt */ 979 979 } ··· 997 1001 list_for_each(tmp, &GlobalSMBSessionList) { 998 1002 ses = list_entry(tmp, struct cifsSesInfo, 999 1003 cifsSessionList); 1000 - if (ses && ses->server && 1001 - atomic_read(&ses->server->inFlight)) 1004 + if (ses->server && atomic_read(&ses->server->inFlight)) 1002 1005 wake_up_all(&ses->server->response_q); 1003 1006 } 1004 1007 read_unlock(&GlobalSMBSeslock);
+1 -1
fs/cifs/cifsfs.h
··· 101 101 extern const struct export_operations cifs_export_ops; 102 102 #endif /* EXPERIMENTAL */ 103 103 104 - #define CIFS_VERSION "1.53" 104 + #define CIFS_VERSION "1.54" 105 105 #endif /* _CIFSFS_H */
+1 -1
fs/cifs/cifspdu.h
··· 262 262 */ 263 263 #define CIFS_NO_HANDLE 0xFFFF 264 264 265 - #define NO_CHANGE_64 cpu_to_le64(0xFFFFFFFFFFFFFFFFULL) 265 + #define NO_CHANGE_64 0xFFFFFFFFFFFFFFFFULL 266 266 #define NO_CHANGE_32 0xFFFFFFFFUL 267 267 268 268 /* IPC$ in ASCII */
+18 -6
fs/cifs/cifsproto.h
··· 172 172 extern int CIFSSMBQFSPosixInfo(const int xid, struct cifsTconInfo *tcon, 173 173 struct kstatfs *FSData); 174 174 175 - extern int CIFSSMBSetTimes(const int xid, struct cifsTconInfo *tcon, 175 + extern int CIFSSMBSetPathInfo(const int xid, struct cifsTconInfo *tcon, 176 176 const char *fileName, const FILE_BASIC_INFO *data, 177 177 const struct nls_table *nls_codepage, 178 178 int remap_special_chars); 179 - extern int CIFSSMBSetFileTimes(const int xid, struct cifsTconInfo *tcon, 180 - const FILE_BASIC_INFO *data, __u16 fid); 179 + extern int CIFSSMBSetFileInfo(const int xid, struct cifsTconInfo *tcon, 180 + const FILE_BASIC_INFO *data, __u16 fid, 181 + __u32 pid_of_opener); 181 182 #if 0 182 183 extern int CIFSSMBSetAttrLegacy(int xid, struct cifsTconInfo *tcon, 183 184 char *fileName, __u16 dos_attributes, ··· 192 191 extern int CIFSSMBSetFileSize(const int xid, struct cifsTconInfo *tcon, 193 192 __u64 size, __u16 fileHandle, __u32 opener_pid, 194 193 bool AllocSizeFlag); 195 - extern int CIFSSMBUnixSetPerms(const int xid, struct cifsTconInfo *pTcon, 196 - char *full_path, __u64 mode, __u64 uid, 197 - __u64 gid, dev_t dev, 194 + 195 + struct cifs_unix_set_info_args { 196 + __u64 ctime; 197 + __u64 atime; 198 + __u64 mtime; 199 + __u64 mode; 200 + __u64 uid; 201 + __u64 gid; 202 + dev_t device; 203 + }; 204 + 205 + extern int CIFSSMBUnixSetInfo(const int xid, struct cifsTconInfo *pTcon, 206 + char *fileName, 207 + const struct cifs_unix_set_info_args *args, 198 208 const struct nls_table *nls_codepage, 199 209 int remap_special_chars); 200 210
+21 -25
fs/cifs/cifssmb.c
··· 128 128 write_lock(&GlobalSMBSeslock); 129 129 list_for_each_safe(tmp, tmp1, &pTcon->openFileList) { 130 130 open_file = list_entry(tmp, struct cifsFileInfo, tlist); 131 - if (open_file) 132 - open_file->invalidHandle = true; 131 + open_file->invalidHandle = true; 133 132 } 134 133 write_unlock(&GlobalSMBSeslock); 135 134 /* BB Add call to invalidate_inodes(sb) for all superblocks mounted ··· 4815 4816 time and resort to the original setpathinfo level which takes the ancient 4816 4817 DOS time format with 2 second granularity */ 4817 4818 int 4818 - CIFSSMBSetFileTimes(const int xid, struct cifsTconInfo *tcon, 4819 - const FILE_BASIC_INFO *data, __u16 fid) 4819 + CIFSSMBSetFileInfo(const int xid, struct cifsTconInfo *tcon, 4820 + const FILE_BASIC_INFO *data, __u16 fid, __u32 pid_of_opener) 4820 4821 { 4821 4822 struct smb_com_transaction2_sfi_req *pSMB = NULL; 4822 4823 char *data_offset; ··· 4829 4830 if (rc) 4830 4831 return rc; 4831 4832 4832 - /* At this point there is no need to override the current pid 4833 - with the pid of the opener, but that could change if we someday 4834 - use an existing handle (rather than opening one on the fly) */ 4835 - /* pSMB->hdr.Pid = cpu_to_le16((__u16)pid_of_opener); 4836 - pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid_of_opener >> 16));*/ 4833 + pSMB->hdr.Pid = cpu_to_le16((__u16)pid_of_opener); 4834 + pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid_of_opener >> 16)); 4837 4835 4838 4836 params = 6; 4839 4837 pSMB->MaxSetupCount = 0; ··· 4878 4882 4879 4883 4880 4884 int 4881 - CIFSSMBSetTimes(const int xid, struct cifsTconInfo *tcon, const char *fileName, 4882 - const FILE_BASIC_INFO *data, 4883 - const struct nls_table *nls_codepage, int remap) 4885 + CIFSSMBSetPathInfo(const int xid, struct cifsTconInfo *tcon, 4886 + const char *fileName, const FILE_BASIC_INFO *data, 4887 + const struct nls_table *nls_codepage, int remap) 4884 4888 { 4885 4889 TRANSACTION2_SPI_REQ *pSMB = NULL; 4886 4890 TRANSACTION2_SPI_RSP *pSMBr = NULL; ··· 5009 5013 #endif /* temporarily unneeded SetAttr legacy function */ 5010 5014 5011 5015 int 5012 - CIFSSMBUnixSetPerms(const int xid, struct cifsTconInfo *tcon, 5013 - char *fileName, __u64 mode, __u64 uid, __u64 gid, 5014 - dev_t device, const struct nls_table *nls_codepage, 5015 - int remap) 5016 + CIFSSMBUnixSetInfo(const int xid, struct cifsTconInfo *tcon, char *fileName, 5017 + const struct cifs_unix_set_info_args *args, 5018 + const struct nls_table *nls_codepage, int remap) 5016 5019 { 5017 5020 TRANSACTION2_SPI_REQ *pSMB = NULL; 5018 5021 TRANSACTION2_SPI_RSP *pSMBr = NULL; ··· 5020 5025 int bytes_returned = 0; 5021 5026 FILE_UNIX_BASIC_INFO *data_offset; 5022 5027 __u16 params, param_offset, offset, count, byte_count; 5028 + __u64 mode = args->mode; 5023 5029 5024 5030 cFYI(1, ("In SetUID/GID/Mode")); 5025 5031 setPermsRetry: ··· 5076 5080 set file size and do not want to truncate file size to zero 5077 5081 accidently as happened on one Samba server beta by putting 5078 5082 zero instead of -1 here */ 5079 - data_offset->EndOfFile = NO_CHANGE_64; 5080 - data_offset->NumOfBytes = NO_CHANGE_64; 5081 - data_offset->LastStatusChange = NO_CHANGE_64; 5082 - data_offset->LastAccessTime = NO_CHANGE_64; 5083 - data_offset->LastModificationTime = NO_CHANGE_64; 5084 - data_offset->Uid = cpu_to_le64(uid); 5085 - data_offset->Gid = cpu_to_le64(gid); 5083 + data_offset->EndOfFile = cpu_to_le64(NO_CHANGE_64); 5084 + data_offset->NumOfBytes = cpu_to_le64(NO_CHANGE_64); 5085 + data_offset->LastStatusChange = cpu_to_le64(args->ctime); 5086 + data_offset->LastAccessTime = cpu_to_le64(args->atime); 5087 + data_offset->LastModificationTime = cpu_to_le64(args->mtime); 5088 + data_offset->Uid = cpu_to_le64(args->uid); 5089 + data_offset->Gid = cpu_to_le64(args->gid); 5086 5090 /* better to leave device as zero when it is */ 5087 - data_offset->DevMajor = cpu_to_le64(MAJOR(device)); 5088 - data_offset->DevMinor = cpu_to_le64(MINOR(device)); 5091 + data_offset->DevMajor = cpu_to_le64(MAJOR(args->device)); 5092 + data_offset->DevMinor = cpu_to_le64(MINOR(args->device)); 5089 5093 data_offset->Permissions = cpu_to_le64(mode); 5090 5094 5091 5095 if (S_ISREG(mode))
+82 -93
fs/cifs/connect.c
··· 151 151 } 152 152 list_for_each(tmp, &GlobalTreeConnectionList) { 153 153 tcon = list_entry(tmp, struct cifsTconInfo, cifsConnectionList); 154 - if ((tcon) && (tcon->ses) && (tcon->ses->server == server)) 154 + if ((tcon->ses) && (tcon->ses->server == server)) 155 155 tcon->tidStatus = CifsNeedReconnect; 156 156 } 157 157 read_unlock(&GlobalSMBSeslock); ··· 173 173 mid_entry = list_entry(tmp, struct 174 174 mid_q_entry, 175 175 qhead); 176 - if (mid_entry) { 177 - if (mid_entry->midState == MID_REQUEST_SUBMITTED) { 176 + if (mid_entry->midState == MID_REQUEST_SUBMITTED) { 178 177 /* Mark other intransit requests as needing 179 178 retry so we do not immediately mark the 180 179 session bad again (ie after we reconnect 181 180 below) as they timeout too */ 182 - mid_entry->midState = MID_RETRY_NEEDED; 183 - } 181 + mid_entry->midState = MID_RETRY_NEEDED; 184 182 } 185 183 } 186 184 spin_unlock(&GlobalMid_Lock); ··· 349 351 350 352 current->flags |= PF_MEMALLOC; 351 353 cFYI(1, ("Demultiplex PID: %d", task_pid_nr(current))); 352 - write_lock(&GlobalSMBSeslock); 353 - atomic_inc(&tcpSesAllocCount); 354 - length = tcpSesAllocCount.counter; 355 - write_unlock(&GlobalSMBSeslock); 356 - if (length > 1) 354 + 355 + length = atomic_inc_return(&tcpSesAllocCount); 356 + if (length > 1) 357 357 mempool_resize(cifs_req_poolp, length + cifs_min_rcv, 358 358 GFP_KERNEL); 359 359 ··· 741 745 coming home not much else we can do but free the memory */ 742 746 } 743 747 744 - write_lock(&GlobalSMBSeslock); 745 - atomic_dec(&tcpSesAllocCount); 746 - length = tcpSesAllocCount.counter; 747 - 748 748 /* last chance to mark ses pointers invalid 749 749 if there are any pointing to this (e.g 750 750 if a crazy root user tried to kill cifsd 751 751 kernel thread explicitly this might happen) */ 752 + write_lock(&GlobalSMBSeslock); 752 753 list_for_each(tmp, &GlobalSMBSessionList) { 753 754 ses = list_entry(tmp, struct cifsSesInfo, 754 755 cifsSessionList); ··· 756 763 757 764 kfree(server->hostname); 758 765 kfree(server); 766 + 767 + length = atomic_dec_return(&tcpSesAllocCount); 759 768 if (length > 0) 760 769 mempool_resize(cifs_req_poolp, length + cifs_min_rcv, 761 770 GFP_KERNEL); ··· 3618 3623 } 3619 3624 first_time = 1; 3620 3625 } 3621 - if (!rc) { 3622 - pSesInfo->flags = 0; 3623 - pSesInfo->capabilities = pSesInfo->server->capabilities; 3624 - if (linuxExtEnabled == 0) 3625 - pSesInfo->capabilities &= (~CAP_UNIX); 3626 + 3627 + if (rc) 3628 + goto ss_err_exit; 3629 + 3630 + pSesInfo->flags = 0; 3631 + pSesInfo->capabilities = pSesInfo->server->capabilities; 3632 + if (linuxExtEnabled == 0) 3633 + pSesInfo->capabilities &= (~CAP_UNIX); 3626 3634 /* pSesInfo->sequence_number = 0;*/ 3627 - cFYI(1, 3628 - ("Security Mode: 0x%x Capabilities: 0x%x TimeAdjust: %d", 3629 - pSesInfo->server->secMode, 3630 - pSesInfo->server->capabilities, 3631 - pSesInfo->server->timeAdj)); 3632 - if (experimEnabled < 2) 3633 - rc = CIFS_SessSetup(xid, pSesInfo, 3634 - first_time, nls_info); 3635 - else if (extended_security 3636 - && (pSesInfo->capabilities 3637 - & CAP_EXTENDED_SECURITY) 3638 - && (pSesInfo->server->secType == NTLMSSP)) { 3639 - rc = -EOPNOTSUPP; 3640 - } else if (extended_security 3641 - && (pSesInfo->capabilities & CAP_EXTENDED_SECURITY) 3642 - && (pSesInfo->server->secType == RawNTLMSSP)) { 3643 - cFYI(1, ("NTLMSSP sesssetup")); 3644 - rc = CIFSNTLMSSPNegotiateSessSetup(xid, 3645 - pSesInfo, 3646 - &ntlmv2_flag, 3647 - nls_info); 3648 - if (!rc) { 3649 - if (ntlmv2_flag) { 3650 - char *v2_response; 3651 - cFYI(1, ("more secure NTLM ver2 hash")); 3652 - if (CalcNTLMv2_partial_mac_key(pSesInfo, 3653 - nls_info)) { 3654 - rc = -ENOMEM; 3655 - goto ss_err_exit; 3656 - } else 3657 - v2_response = kmalloc(16 + 64 /* blob */, GFP_KERNEL); 3658 - if (v2_response) { 3659 - CalcNTLMv2_response(pSesInfo, 3660 - v2_response); 3661 - /* if (first_time) 3662 - cifs_calculate_ntlmv2_mac_key( 3663 - pSesInfo->server->mac_signing_key, 3664 - response, ntlm_session_key,*/ 3665 - kfree(v2_response); 3635 + cFYI(1, ("Security Mode: 0x%x Capabilities: 0x%x TimeAdjust: %d", 3636 + pSesInfo->server->secMode, 3637 + pSesInfo->server->capabilities, 3638 + pSesInfo->server->timeAdj)); 3639 + if (experimEnabled < 2) 3640 + rc = CIFS_SessSetup(xid, pSesInfo, first_time, nls_info); 3641 + else if (extended_security 3642 + && (pSesInfo->capabilities & CAP_EXTENDED_SECURITY) 3643 + && (pSesInfo->server->secType == NTLMSSP)) { 3644 + rc = -EOPNOTSUPP; 3645 + } else if (extended_security 3646 + && (pSesInfo->capabilities & CAP_EXTENDED_SECURITY) 3647 + && (pSesInfo->server->secType == RawNTLMSSP)) { 3648 + cFYI(1, ("NTLMSSP sesssetup")); 3649 + rc = CIFSNTLMSSPNegotiateSessSetup(xid, pSesInfo, &ntlmv2_flag, 3650 + nls_info); 3651 + if (!rc) { 3652 + if (ntlmv2_flag) { 3653 + char *v2_response; 3654 + cFYI(1, ("more secure NTLM ver2 hash")); 3655 + if (CalcNTLMv2_partial_mac_key(pSesInfo, 3656 + nls_info)) { 3657 + rc = -ENOMEM; 3658 + goto ss_err_exit; 3659 + } else 3660 + v2_response = kmalloc(16 + 64 /* blob*/, 3661 + GFP_KERNEL); 3662 + if (v2_response) { 3663 + CalcNTLMv2_response(pSesInfo, 3664 + v2_response); 3665 + /* if (first_time) 3666 + cifs_calculate_ntlmv2_mac_key */ 3667 + kfree(v2_response); 3666 3668 /* BB Put dummy sig in SessSetup PDU? */ 3667 - } else { 3668 - rc = -ENOMEM; 3669 - goto ss_err_exit; 3670 - } 3671 - 3672 3669 } else { 3673 - SMBNTencrypt(pSesInfo->password, 3674 - pSesInfo->server->cryptKey, 3675 - ntlm_session_key); 3676 - 3677 - if (first_time) 3678 - cifs_calculate_mac_key( 3679 - &pSesInfo->server->mac_signing_key, 3680 - ntlm_session_key, 3681 - pSesInfo->password); 3670 + rc = -ENOMEM; 3671 + goto ss_err_exit; 3682 3672 } 3673 + 3674 + } else { 3675 + SMBNTencrypt(pSesInfo->password, 3676 + pSesInfo->server->cryptKey, 3677 + ntlm_session_key); 3678 + 3679 + if (first_time) 3680 + cifs_calculate_mac_key( 3681 + &pSesInfo->server->mac_signing_key, 3682 + ntlm_session_key, 3683 + pSesInfo->password); 3684 + } 3683 3685 /* for better security the weaker lanman hash not sent 3684 3686 in AuthSessSetup so we no longer calculate it */ 3685 3687 3686 - rc = CIFSNTLMSSPAuthSessSetup(xid, 3687 - pSesInfo, 3688 - ntlm_session_key, 3689 - ntlmv2_flag, 3690 - nls_info); 3691 - } 3692 - } else { /* old style NTLM 0.12 session setup */ 3693 - SMBNTencrypt(pSesInfo->password, 3694 - pSesInfo->server->cryptKey, 3695 - ntlm_session_key); 3688 + rc = CIFSNTLMSSPAuthSessSetup(xid, pSesInfo, 3689 + ntlm_session_key, 3690 + ntlmv2_flag, 3691 + nls_info); 3692 + } 3693 + } else { /* old style NTLM 0.12 session setup */ 3694 + SMBNTencrypt(pSesInfo->password, pSesInfo->server->cryptKey, 3695 + ntlm_session_key); 3696 3696 3697 - if (first_time) 3698 - cifs_calculate_mac_key( 3697 + if (first_time) 3698 + cifs_calculate_mac_key( 3699 3699 &pSesInfo->server->mac_signing_key, 3700 3700 ntlm_session_key, pSesInfo->password); 3701 3701 3702 - rc = CIFSSessSetup(xid, pSesInfo, 3703 - ntlm_session_key, nls_info); 3704 - } 3705 - if (rc) { 3706 - cERROR(1, ("Send error in SessSetup = %d", rc)); 3707 - } else { 3708 - cFYI(1, ("CIFS Session Established successfully")); 3709 - pSesInfo->status = CifsGood; 3710 - } 3702 + rc = CIFSSessSetup(xid, pSesInfo, ntlm_session_key, nls_info); 3711 3703 } 3704 + if (rc) { 3705 + cERROR(1, ("Send error in SessSetup = %d", rc)); 3706 + } else { 3707 + cFYI(1, ("CIFS Session Established successfully")); 3708 + pSesInfo->status = CifsGood; 3709 + } 3710 + 3712 3711 ss_err_exit: 3713 3712 return rc; 3714 3713 }
+40 -27
fs/cifs/dir.c
··· 226 226 /* If Open reported that we actually created a file 227 227 then we now have to set the mode if possible */ 228 228 if ((pTcon->unix_ext) && (oplock & CIFS_CREATE_ACTION)) { 229 + struct cifs_unix_set_info_args args = { 230 + .mode = mode, 231 + .ctime = NO_CHANGE_64, 232 + .atime = NO_CHANGE_64, 233 + .mtime = NO_CHANGE_64, 234 + .device = 0, 235 + }; 236 + 229 237 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID) { 230 - CIFSSMBUnixSetPerms(xid, pTcon, full_path, mode, 231 - (__u64)current->fsuid, 232 - (__u64)current->fsgid, 233 - 0 /* dev */, 234 - cifs_sb->local_nls, 235 - cifs_sb->mnt_cifs_flags & 236 - CIFS_MOUNT_MAP_SPECIAL_CHR); 238 + args.uid = (__u64) current->fsuid; 239 + if (inode->i_mode & S_ISGID) 240 + args.gid = (__u64) inode->i_gid; 241 + else 242 + args.gid = (__u64) current->fsgid; 237 243 } else { 238 - CIFSSMBUnixSetPerms(xid, pTcon, full_path, mode, 239 - (__u64)-1, 240 - (__u64)-1, 241 - 0 /* dev */, 242 - cifs_sb->local_nls, 243 - cifs_sb->mnt_cifs_flags & 244 - CIFS_MOUNT_MAP_SPECIAL_CHR); 244 + args.uid = NO_CHANGE_64; 245 + args.gid = NO_CHANGE_64; 245 246 } 247 + CIFSSMBUnixSetInfo(xid, pTcon, full_path, &args, 248 + cifs_sb->local_nls, 249 + cifs_sb->mnt_cifs_flags & 250 + CIFS_MOUNT_MAP_SPECIAL_CHR); 246 251 } else { 247 252 /* BB implement mode setting via Windows security 248 253 descriptors e.g. */ ··· 272 267 (cifs_sb->mnt_cifs_flags & 273 268 CIFS_MOUNT_SET_UID)) { 274 269 newinode->i_uid = current->fsuid; 275 - newinode->i_gid = current->fsgid; 270 + if (inode->i_mode & S_ISGID) 271 + newinode->i_gid = 272 + inode->i_gid; 273 + else 274 + newinode->i_gid = 275 + current->fsgid; 276 276 } 277 277 } 278 278 } ··· 367 357 if (full_path == NULL) 368 358 rc = -ENOMEM; 369 359 else if (pTcon->unix_ext) { 370 - mode &= ~current->fs->umask; 360 + struct cifs_unix_set_info_args args = { 361 + .mode = mode & ~current->fs->umask, 362 + .ctime = NO_CHANGE_64, 363 + .atime = NO_CHANGE_64, 364 + .mtime = NO_CHANGE_64, 365 + .device = device_number, 366 + }; 371 367 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID) { 372 - rc = CIFSSMBUnixSetPerms(xid, pTcon, full_path, 373 - mode, (__u64)current->fsuid, 374 - (__u64)current->fsgid, 375 - device_number, cifs_sb->local_nls, 376 - cifs_sb->mnt_cifs_flags & 377 - CIFS_MOUNT_MAP_SPECIAL_CHR); 368 + args.uid = (__u64) current->fsuid; 369 + args.gid = (__u64) current->fsgid; 378 370 } else { 379 - rc = CIFSSMBUnixSetPerms(xid, pTcon, 380 - full_path, mode, (__u64)-1, (__u64)-1, 381 - device_number, cifs_sb->local_nls, 382 - cifs_sb->mnt_cifs_flags & 383 - CIFS_MOUNT_MAP_SPECIAL_CHR); 371 + args.uid = NO_CHANGE_64; 372 + args.gid = NO_CHANGE_64; 384 373 } 374 + rc = CIFSSMBUnixSetInfo(xid, pTcon, full_path, 375 + &args, cifs_sb->local_nls, 376 + cifs_sb->mnt_cifs_flags & 377 + CIFS_MOUNT_MAP_SPECIAL_CHR); 385 378 386 379 if (!rc) { 387 380 rc = cifs_get_inode_info_unix(&newinode, full_path,
+10 -9
fs/cifs/file.c
··· 310 310 /* time to set mode which we can not set earlier due to 311 311 problems creating new read-only files */ 312 312 if (pTcon->unix_ext) { 313 - CIFSSMBUnixSetPerms(xid, pTcon, full_path, 314 - inode->i_mode, 315 - (__u64)-1, (__u64)-1, 0 /* dev */, 313 + struct cifs_unix_set_info_args args = { 314 + .mode = inode->i_mode, 315 + .uid = NO_CHANGE_64, 316 + .gid = NO_CHANGE_64, 317 + .ctime = NO_CHANGE_64, 318 + .atime = NO_CHANGE_64, 319 + .mtime = NO_CHANGE_64, 320 + .device = 0, 321 + }; 322 + CIFSSMBUnixSetInfo(xid, pTcon, full_path, &args, 316 323 cifs_sb->local_nls, 317 324 cifs_sb->mnt_cifs_flags & 318 325 CIFS_MOUNT_MAP_SPECIAL_CHR); 319 - } else { 320 - /* BB implement via Windows security descriptors eg 321 - CIFSSMBWinSetPerms(xid, pTcon, full_path, mode, 322 - -1, -1, local_nls); 323 - in the meantime could set r/o dos attribute when 324 - perms are eg: mode & 0222 == 0 */ 325 326 } 326 327 } 327 328
+279 -140
fs/cifs/inode.c
··· 737 737 /* ATTRS set to normal clears r/o bit */ 738 738 pinfo_buf->Attributes = cpu_to_le32(ATTR_NORMAL); 739 739 if (!(pTcon->ses->flags & CIFS_SES_NT4)) 740 - rc = CIFSSMBSetTimes(xid, pTcon, full_path, 740 + rc = CIFSSMBSetPathInfo(xid, pTcon, full_path, 741 741 pinfo_buf, 742 742 cifs_sb->local_nls, 743 743 cifs_sb->mnt_cifs_flags & ··· 767 767 cifs_sb->mnt_cifs_flags & 768 768 CIFS_MOUNT_MAP_SPECIAL_CHR); 769 769 if (rc == 0) { 770 - rc = CIFSSMBSetFileTimes(xid, pTcon, 771 - pinfo_buf, 772 - netfid); 770 + rc = CIFSSMBSetFileInfo(xid, pTcon, 771 + pinfo_buf, 772 + netfid, 773 + current->tgid); 773 774 CIFSSMBClose(xid, pTcon, netfid); 774 775 } 775 776 } ··· 985 984 * failed to get it from the server or was set bogus */ 986 985 if ((direntry->d_inode) && (direntry->d_inode->i_nlink < 2)) 987 986 direntry->d_inode->i_nlink = 2; 987 + 988 988 mode &= ~current->fs->umask; 989 + /* must turn on setgid bit if parent dir has it */ 990 + if (inode->i_mode & S_ISGID) 991 + mode |= S_ISGID; 992 + 989 993 if (pTcon->unix_ext) { 994 + struct cifs_unix_set_info_args args = { 995 + .mode = mode, 996 + .ctime = NO_CHANGE_64, 997 + .atime = NO_CHANGE_64, 998 + .mtime = NO_CHANGE_64, 999 + .device = 0, 1000 + }; 990 1001 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID) { 991 - CIFSSMBUnixSetPerms(xid, pTcon, full_path, 992 - mode, 993 - (__u64)current->fsuid, 994 - (__u64)current->fsgid, 995 - 0 /* dev_t */, 996 - cifs_sb->local_nls, 997 - cifs_sb->mnt_cifs_flags & 998 - CIFS_MOUNT_MAP_SPECIAL_CHR); 1002 + args.uid = (__u64)current->fsuid; 1003 + if (inode->i_mode & S_ISGID) 1004 + args.gid = (__u64)inode->i_gid; 1005 + else 1006 + args.gid = (__u64)current->fsgid; 999 1007 } else { 1000 - CIFSSMBUnixSetPerms(xid, pTcon, full_path, 1001 - mode, (__u64)-1, 1002 - (__u64)-1, 0 /* dev_t */, 1003 - cifs_sb->local_nls, 1004 - cifs_sb->mnt_cifs_flags & 1005 - CIFS_MOUNT_MAP_SPECIAL_CHR); 1008 + args.uid = NO_CHANGE_64; 1009 + args.gid = NO_CHANGE_64; 1006 1010 } 1011 + CIFSSMBUnixSetInfo(xid, pTcon, full_path, &args, 1012 + cifs_sb->local_nls, 1013 + cifs_sb->mnt_cifs_flags & 1014 + CIFS_MOUNT_MAP_SPECIAL_CHR); 1007 1015 } else { 1008 1016 if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_ACL) && 1009 1017 (mode & S_IWUGO) == 0) { 1010 1018 FILE_BASIC_INFO pInfo; 1011 1019 memset(&pInfo, 0, sizeof(pInfo)); 1012 1020 pInfo.Attributes = cpu_to_le32(ATTR_READONLY); 1013 - CIFSSMBSetTimes(xid, pTcon, full_path, 1021 + CIFSSMBSetPathInfo(xid, pTcon, full_path, 1014 1022 &pInfo, cifs_sb->local_nls, 1015 1023 cifs_sb->mnt_cifs_flags & 1016 1024 CIFS_MOUNT_MAP_SPECIAL_CHR); ··· 1034 1024 CIFS_MOUNT_SET_UID) { 1035 1025 direntry->d_inode->i_uid = 1036 1026 current->fsuid; 1037 - direntry->d_inode->i_gid = 1038 - current->fsgid; 1027 + if (inode->i_mode & S_ISGID) 1028 + direntry->d_inode->i_gid = 1029 + inode->i_gid; 1030 + else 1031 + direntry->d_inode->i_gid = 1032 + current->fsgid; 1039 1033 } 1040 1034 } 1041 1035 } ··· 1324 1310 /* if (S_ISDIR(direntry->d_inode->i_mode)) 1325 1311 shrink_dcache_parent(direntry); */ 1326 1312 if (S_ISREG(direntry->d_inode->i_mode)) { 1327 - if (direntry->d_inode->i_mapping) 1313 + if (direntry->d_inode->i_mapping) { 1328 1314 wbrc = filemap_fdatawait(direntry->d_inode->i_mapping); 1329 1315 if (wbrc) 1330 1316 CIFS_I(direntry->d_inode)->write_behind_rc = wbrc; 1317 + } 1331 1318 /* may eventually have to do this for open files too */ 1332 1319 if (list_empty(&(cifsInode->openFileList))) { 1333 1320 /* changed on server - flush read ahead pages */ ··· 1504 1489 return rc; 1505 1490 } 1506 1491 1507 - int cifs_setattr(struct dentry *direntry, struct iattr *attrs) 1492 + static int 1493 + cifs_set_file_info(struct inode *inode, struct iattr *attrs, int xid, 1494 + char *full_path, __u32 dosattr) 1495 + { 1496 + int rc; 1497 + int oplock = 0; 1498 + __u16 netfid; 1499 + __u32 netpid; 1500 + bool set_time = false; 1501 + struct cifsFileInfo *open_file; 1502 + struct cifsInodeInfo *cifsInode = CIFS_I(inode); 1503 + struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb); 1504 + struct cifsTconInfo *pTcon = cifs_sb->tcon; 1505 + FILE_BASIC_INFO info_buf; 1506 + 1507 + if (attrs->ia_valid & ATTR_ATIME) { 1508 + set_time = true; 1509 + info_buf.LastAccessTime = 1510 + cpu_to_le64(cifs_UnixTimeToNT(attrs->ia_atime)); 1511 + } else 1512 + info_buf.LastAccessTime = 0; 1513 + 1514 + if (attrs->ia_valid & ATTR_MTIME) { 1515 + set_time = true; 1516 + info_buf.LastWriteTime = 1517 + cpu_to_le64(cifs_UnixTimeToNT(attrs->ia_mtime)); 1518 + } else 1519 + info_buf.LastWriteTime = 0; 1520 + 1521 + /* 1522 + * Samba throws this field away, but windows may actually use it. 1523 + * Do not set ctime unless other time stamps are changed explicitly 1524 + * (i.e. by utimes()) since we would then have a mix of client and 1525 + * server times. 1526 + */ 1527 + if (set_time && (attrs->ia_valid & ATTR_CTIME)) { 1528 + cFYI(1, ("CIFS - CTIME changed")); 1529 + info_buf.ChangeTime = 1530 + cpu_to_le64(cifs_UnixTimeToNT(attrs->ia_ctime)); 1531 + } else 1532 + info_buf.ChangeTime = 0; 1533 + 1534 + info_buf.CreationTime = 0; /* don't change */ 1535 + info_buf.Attributes = cpu_to_le32(dosattr); 1536 + 1537 + /* 1538 + * If the file is already open for write, just use that fileid 1539 + */ 1540 + open_file = find_writable_file(cifsInode); 1541 + if (open_file) { 1542 + netfid = open_file->netfid; 1543 + netpid = open_file->pid; 1544 + goto set_via_filehandle; 1545 + } 1546 + 1547 + /* 1548 + * NT4 apparently returns success on this call, but it doesn't 1549 + * really work. 1550 + */ 1551 + if (!(pTcon->ses->flags & CIFS_SES_NT4)) { 1552 + rc = CIFSSMBSetPathInfo(xid, pTcon, full_path, 1553 + &info_buf, cifs_sb->local_nls, 1554 + cifs_sb->mnt_cifs_flags & 1555 + CIFS_MOUNT_MAP_SPECIAL_CHR); 1556 + if (rc != -EOPNOTSUPP && rc != -EINVAL) 1557 + goto out; 1558 + } 1559 + 1560 + cFYI(1, ("calling SetFileInfo since SetPathInfo for " 1561 + "times not supported by this server")); 1562 + rc = CIFSSMBOpen(xid, pTcon, full_path, FILE_OPEN, 1563 + SYNCHRONIZE | FILE_WRITE_ATTRIBUTES, 1564 + CREATE_NOT_DIR, &netfid, &oplock, 1565 + NULL, cifs_sb->local_nls, 1566 + cifs_sb->mnt_cifs_flags & 1567 + CIFS_MOUNT_MAP_SPECIAL_CHR); 1568 + 1569 + if (rc != 0) { 1570 + if (rc == -EIO) 1571 + rc = -EINVAL; 1572 + goto out; 1573 + } 1574 + 1575 + netpid = current->tgid; 1576 + 1577 + set_via_filehandle: 1578 + rc = CIFSSMBSetFileInfo(xid, pTcon, &info_buf, netfid, netpid); 1579 + if (open_file == NULL) 1580 + CIFSSMBClose(xid, pTcon, netfid); 1581 + else 1582 + atomic_dec(&open_file->wrtPending); 1583 + out: 1584 + return rc; 1585 + } 1586 + 1587 + static int 1588 + cifs_setattr_unix(struct dentry *direntry, struct iattr *attrs) 1589 + { 1590 + int rc; 1591 + int xid; 1592 + char *full_path = NULL; 1593 + struct inode *inode = direntry->d_inode; 1594 + struct cifsInodeInfo *cifsInode = CIFS_I(inode); 1595 + struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb); 1596 + struct cifsTconInfo *pTcon = cifs_sb->tcon; 1597 + struct cifs_unix_set_info_args *args = NULL; 1598 + 1599 + cFYI(1, ("setattr_unix on file %s attrs->ia_valid=0x%x", 1600 + direntry->d_name.name, attrs->ia_valid)); 1601 + 1602 + xid = GetXid(); 1603 + 1604 + if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_PERM) == 0) { 1605 + /* check if we have permission to change attrs */ 1606 + rc = inode_change_ok(inode, attrs); 1607 + if (rc < 0) 1608 + goto out; 1609 + else 1610 + rc = 0; 1611 + } 1612 + 1613 + full_path = build_path_from_dentry(direntry); 1614 + if (full_path == NULL) { 1615 + rc = -ENOMEM; 1616 + goto out; 1617 + } 1618 + 1619 + if ((attrs->ia_valid & ATTR_MTIME) || (attrs->ia_valid & ATTR_SIZE)) { 1620 + /* 1621 + Flush data before changing file size or changing the last 1622 + write time of the file on the server. If the 1623 + flush returns error, store it to report later and continue. 1624 + BB: This should be smarter. Why bother flushing pages that 1625 + will be truncated anyway? Also, should we error out here if 1626 + the flush returns error? 1627 + */ 1628 + rc = filemap_write_and_wait(inode->i_mapping); 1629 + if (rc != 0) { 1630 + cifsInode->write_behind_rc = rc; 1631 + rc = 0; 1632 + } 1633 + } 1634 + 1635 + if (attrs->ia_valid & ATTR_SIZE) { 1636 + rc = cifs_set_file_size(inode, attrs, xid, full_path); 1637 + if (rc != 0) 1638 + goto out; 1639 + } 1640 + 1641 + /* skip mode change if it's just for clearing setuid/setgid */ 1642 + if (attrs->ia_valid & (ATTR_KILL_SUID|ATTR_KILL_SGID)) 1643 + attrs->ia_valid &= ~ATTR_MODE; 1644 + 1645 + args = kmalloc(sizeof(*args), GFP_KERNEL); 1646 + if (args == NULL) { 1647 + rc = -ENOMEM; 1648 + goto out; 1649 + } 1650 + 1651 + /* set up the struct */ 1652 + if (attrs->ia_valid & ATTR_MODE) 1653 + args->mode = attrs->ia_mode; 1654 + else 1655 + args->mode = NO_CHANGE_64; 1656 + 1657 + if (attrs->ia_valid & ATTR_UID) 1658 + args->uid = attrs->ia_uid; 1659 + else 1660 + args->uid = NO_CHANGE_64; 1661 + 1662 + if (attrs->ia_valid & ATTR_GID) 1663 + args->gid = attrs->ia_gid; 1664 + else 1665 + args->gid = NO_CHANGE_64; 1666 + 1667 + if (attrs->ia_valid & ATTR_ATIME) 1668 + args->atime = cifs_UnixTimeToNT(attrs->ia_atime); 1669 + else 1670 + args->atime = NO_CHANGE_64; 1671 + 1672 + if (attrs->ia_valid & ATTR_MTIME) 1673 + args->mtime = cifs_UnixTimeToNT(attrs->ia_mtime); 1674 + else 1675 + args->mtime = NO_CHANGE_64; 1676 + 1677 + if (attrs->ia_valid & ATTR_CTIME) 1678 + args->ctime = cifs_UnixTimeToNT(attrs->ia_ctime); 1679 + else 1680 + args->ctime = NO_CHANGE_64; 1681 + 1682 + args->device = 0; 1683 + rc = CIFSSMBUnixSetInfo(xid, pTcon, full_path, args, 1684 + cifs_sb->local_nls, 1685 + cifs_sb->mnt_cifs_flags & 1686 + CIFS_MOUNT_MAP_SPECIAL_CHR); 1687 + 1688 + if (!rc) 1689 + rc = inode_setattr(inode, attrs); 1690 + out: 1691 + kfree(args); 1692 + kfree(full_path); 1693 + FreeXid(xid); 1694 + return rc; 1695 + } 1696 + 1697 + static int 1698 + cifs_setattr_nounix(struct dentry *direntry, struct iattr *attrs) 1508 1699 { 1509 1700 int xid; 1510 - struct cifs_sb_info *cifs_sb; 1511 - struct cifsTconInfo *pTcon; 1701 + struct inode *inode = direntry->d_inode; 1702 + struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb); 1703 + struct cifsInodeInfo *cifsInode = CIFS_I(inode); 1512 1704 char *full_path = NULL; 1513 1705 int rc = -EACCES; 1514 - FILE_BASIC_INFO time_buf; 1515 - bool set_time = false; 1516 - bool set_dosattr = false; 1517 - __u64 mode = 0xFFFFFFFFFFFFFFFFULL; 1518 - __u64 uid = 0xFFFFFFFFFFFFFFFFULL; 1519 - __u64 gid = 0xFFFFFFFFFFFFFFFFULL; 1520 - struct cifsInodeInfo *cifsInode; 1521 - struct inode *inode = direntry->d_inode; 1706 + __u32 dosattr = 0; 1707 + __u64 mode = NO_CHANGE_64; 1522 1708 1523 1709 xid = GetXid(); 1524 1710 1525 1711 cFYI(1, ("setattr on file %s attrs->iavalid 0x%x", 1526 1712 direntry->d_name.name, attrs->ia_valid)); 1527 - 1528 - cifs_sb = CIFS_SB(inode->i_sb); 1529 - pTcon = cifs_sb->tcon; 1530 1713 1531 1714 if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_PERM) == 0) { 1532 1715 /* check if we have permission to change attrs */ ··· 1741 1528 FreeXid(xid); 1742 1529 return -ENOMEM; 1743 1530 } 1744 - cifsInode = CIFS_I(inode); 1745 1531 1746 1532 if ((attrs->ia_valid & ATTR_MTIME) || (attrs->ia_valid & ATTR_SIZE)) { 1747 1533 /* ··· 1771 1559 * CIFSACL support + proper Windows to Unix idmapping, we may be 1772 1560 * able to support this in the future. 1773 1561 */ 1774 - if (!pTcon->unix_ext && 1775 - !(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID)) { 1562 + if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID)) 1776 1563 attrs->ia_valid &= ~(ATTR_UID | ATTR_GID); 1777 - } else { 1778 - if (attrs->ia_valid & ATTR_UID) { 1779 - cFYI(1, ("UID changed to %d", attrs->ia_uid)); 1780 - uid = attrs->ia_uid; 1781 - } 1782 - if (attrs->ia_valid & ATTR_GID) { 1783 - cFYI(1, ("GID changed to %d", attrs->ia_gid)); 1784 - gid = attrs->ia_gid; 1785 - } 1786 - } 1787 - 1788 - time_buf.Attributes = 0; 1789 1564 1790 1565 /* skip mode change if it's just for clearing setuid/setgid */ 1791 1566 if (attrs->ia_valid & (ATTR_KILL_SUID|ATTR_KILL_SGID)) ··· 1783 1584 mode = attrs->ia_mode; 1784 1585 } 1785 1586 1786 - if ((pTcon->unix_ext) 1787 - && (attrs->ia_valid & (ATTR_MODE | ATTR_GID | ATTR_UID))) 1788 - rc = CIFSSMBUnixSetPerms(xid, pTcon, full_path, mode, uid, gid, 1789 - 0 /* dev_t */, cifs_sb->local_nls, 1790 - cifs_sb->mnt_cifs_flags & 1791 - CIFS_MOUNT_MAP_SPECIAL_CHR); 1792 - else if (attrs->ia_valid & ATTR_MODE) { 1587 + if (attrs->ia_valid & ATTR_MODE) { 1793 1588 rc = 0; 1794 1589 #ifdef CONFIG_CIFS_EXPERIMENTAL 1795 1590 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_ACL) ··· 1792 1599 #endif 1793 1600 if (((mode & S_IWUGO) == 0) && 1794 1601 (cifsInode->cifsAttrs & ATTR_READONLY) == 0) { 1795 - set_dosattr = true; 1796 - time_buf.Attributes = cpu_to_le32(cifsInode->cifsAttrs | 1797 - ATTR_READONLY); 1602 + 1603 + dosattr = cifsInode->cifsAttrs | ATTR_READONLY; 1604 + 1798 1605 /* fix up mode if we're not using dynperm */ 1799 1606 if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DYNPERM) == 0) 1800 1607 attrs->ia_mode = inode->i_mode & ~S_IWUGO; 1801 1608 } else if ((mode & S_IWUGO) && 1802 1609 (cifsInode->cifsAttrs & ATTR_READONLY)) { 1803 - /* If file is readonly on server, we would 1804 - not be able to write to it - so if any write 1805 - bit is enabled for user or group or other we 1806 - need to at least try to remove r/o dos attr */ 1807 - set_dosattr = true; 1808 - time_buf.Attributes = cpu_to_le32(cifsInode->cifsAttrs & 1809 - (~ATTR_READONLY)); 1810 - /* Windows ignores set to zero */ 1811 - if (time_buf.Attributes == 0) 1812 - time_buf.Attributes |= cpu_to_le32(ATTR_NORMAL); 1610 + 1611 + dosattr = cifsInode->cifsAttrs & ~ATTR_READONLY; 1612 + /* Attributes of 0 are ignored */ 1613 + if (dosattr == 0) 1614 + dosattr |= ATTR_NORMAL; 1813 1615 1814 1616 /* reset local inode permissions to normal */ 1815 1617 if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DYNPERM)) { ··· 1822 1634 } 1823 1635 } 1824 1636 1825 - if (attrs->ia_valid & ATTR_ATIME) { 1826 - set_time = true; 1827 - time_buf.LastAccessTime = 1828 - cpu_to_le64(cifs_UnixTimeToNT(attrs->ia_atime)); 1829 - } else 1830 - time_buf.LastAccessTime = 0; 1637 + if (attrs->ia_valid & (ATTR_MTIME|ATTR_ATIME|ATTR_CTIME) || 1638 + ((attrs->ia_valid & ATTR_MODE) && dosattr)) { 1639 + rc = cifs_set_file_info(inode, attrs, xid, full_path, dosattr); 1640 + /* BB: check for rc = -EOPNOTSUPP and switch to legacy mode */ 1831 1641 1832 - if (attrs->ia_valid & ATTR_MTIME) { 1833 - set_time = true; 1834 - time_buf.LastWriteTime = 1835 - cpu_to_le64(cifs_UnixTimeToNT(attrs->ia_mtime)); 1836 - } else 1837 - time_buf.LastWriteTime = 0; 1838 - /* Do not set ctime explicitly unless other time 1839 - stamps are changed explicitly (i.e. by utime() 1840 - since we would then have a mix of client and 1841 - server times */ 1842 - 1843 - if (set_time && (attrs->ia_valid & ATTR_CTIME)) { 1844 - set_time = true; 1845 - /* Although Samba throws this field away 1846 - it may be useful to Windows - but we do 1847 - not want to set ctime unless some other 1848 - timestamp is changing */ 1849 - cFYI(1, ("CIFS - CTIME changed")); 1850 - time_buf.ChangeTime = 1851 - cpu_to_le64(cifs_UnixTimeToNT(attrs->ia_ctime)); 1852 - } else 1853 - time_buf.ChangeTime = 0; 1854 - 1855 - if (set_time || set_dosattr) { 1856 - time_buf.CreationTime = 0; /* do not change */ 1857 - /* In the future we should experiment - try setting timestamps 1858 - via Handle (SetFileInfo) instead of by path */ 1859 - if (!(pTcon->ses->flags & CIFS_SES_NT4)) 1860 - rc = CIFSSMBSetTimes(xid, pTcon, full_path, &time_buf, 1861 - cifs_sb->local_nls, 1862 - cifs_sb->mnt_cifs_flags & 1863 - CIFS_MOUNT_MAP_SPECIAL_CHR); 1864 - else 1865 - rc = -EOPNOTSUPP; 1866 - 1867 - if (rc == -EOPNOTSUPP) { 1868 - int oplock = 0; 1869 - __u16 netfid; 1870 - 1871 - cFYI(1, ("calling SetFileInfo since SetPathInfo for " 1872 - "times not supported by this server")); 1873 - /* BB we could scan to see if we already have it open 1874 - and pass in pid of opener to function */ 1875 - rc = CIFSSMBOpen(xid, pTcon, full_path, FILE_OPEN, 1876 - SYNCHRONIZE | FILE_WRITE_ATTRIBUTES, 1877 - CREATE_NOT_DIR, &netfid, &oplock, 1878 - NULL, cifs_sb->local_nls, 1879 - cifs_sb->mnt_cifs_flags & 1880 - CIFS_MOUNT_MAP_SPECIAL_CHR); 1881 - if (rc == 0) { 1882 - rc = CIFSSMBSetFileTimes(xid, pTcon, &time_buf, 1883 - netfid); 1884 - CIFSSMBClose(xid, pTcon, netfid); 1885 - } else { 1886 - /* BB For even older servers we could convert time_buf 1887 - into old DOS style which uses two second 1888 - granularity */ 1889 - 1890 - /* rc = CIFSSMBSetTimesLegacy(xid, pTcon, full_path, 1891 - &time_buf, cifs_sb->local_nls); */ 1892 - } 1893 - } 1894 1642 /* Even if error on time set, no sense failing the call if 1895 1643 the server would set the time to a reasonable value anyway, 1896 1644 and this check ensures that we are not being called from 1897 1645 sys_utimes in which case we ought to fail the call back to 1898 1646 the user when the server rejects the call */ 1899 1647 if ((rc) && (attrs->ia_valid & 1900 - (ATTR_MODE | ATTR_GID | ATTR_UID | ATTR_SIZE))) 1648 + (ATTR_MODE | ATTR_GID | ATTR_UID | ATTR_SIZE))) 1901 1649 rc = 0; 1902 1650 } 1903 1651 ··· 1845 1721 kfree(full_path); 1846 1722 FreeXid(xid); 1847 1723 return rc; 1724 + } 1725 + 1726 + int 1727 + cifs_setattr(struct dentry *direntry, struct iattr *attrs) 1728 + { 1729 + struct inode *inode = direntry->d_inode; 1730 + struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb); 1731 + struct cifsTconInfo *pTcon = cifs_sb->tcon; 1732 + 1733 + if (pTcon->unix_ext) 1734 + return cifs_setattr_unix(direntry, attrs); 1735 + 1736 + return cifs_setattr_nounix(direntry, attrs); 1737 + 1738 + /* BB: add cifs_setattr_legacy for really old servers */ 1848 1739 } 1849 1740 1850 1741 #if 0
+1
fs/cifs/transport.c
··· 265 265 cFYI(1, ("Sending smb: total_len %d", total_len)); 266 266 dump_smb(smb_buffer, len); 267 267 268 + i = 0; 268 269 while (total_len) { 269 270 rc = kernel_sendmsg(ssocket, &smb_msg, &iov[first_vec], 270 271 n_vec - first_vec, total_len);