Commit 56831a1a authored by Linus Torvalds's avatar Linus Torvalds

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
parents 6724cce8 ad8b15f0
Version 1.54
------------
Fix premature write failure on congested networks (we would give up
on EAGAIN from the socket too quickly on large writes).
Cifs_mkdir and cifs_create now respect the setgid bit on parent dir.
Fix endian problems in acl (mode from/to cifs acl) on bigendian
architectures.
Version 1.53
------------
DFS support added (Microsoft Distributed File System client support needed
......
......@@ -483,6 +483,7 @@ decode_negTokenInit(unsigned char *security_blob, int length,
asn1_open(&ctx, security_blob, length);
/* GSSAPI header */
if (asn1_header_decode(&ctx, &end, &cls, &con, &tag) == 0) {
cFYI(1, ("Error decoding negTokenInit header"));
return 0;
......@@ -490,153 +491,142 @@ decode_negTokenInit(unsigned char *security_blob, int length,
|| (tag != ASN1_EOC)) {
cFYI(1, ("cls = %d con = %d tag = %d", cls, con, tag));
return 0;
} else {
/* remember to free obj->oid */
rc = asn1_header_decode(&ctx, &end, &cls, &con, &tag);
if (rc) {
if ((tag == ASN1_OJI) && (con == ASN1_PRI)) {
rc = asn1_oid_decode(&ctx, end, &oid, &oidlen);
if (rc) {
rc = compare_oid(oid, oidlen,
SPNEGO_OID,
SPNEGO_OID_LEN);
kfree(oid);
}
} else
rc = 0;
}
}
if (!rc) {
cFYI(1, ("Error decoding negTokenInit header"));
return 0;
}
/* Check for SPNEGO OID -- remember to free obj->oid */
rc = asn1_header_decode(&ctx, &end, &cls, &con, &tag);
if (rc) {
if ((tag == ASN1_OJI) && (con == ASN1_PRI) &&
(cls == ASN1_UNI)) {
rc = asn1_oid_decode(&ctx, end, &oid, &oidlen);
if (rc) {
rc = compare_oid(oid, oidlen, SPNEGO_OID,
SPNEGO_OID_LEN);
kfree(oid);
}
} else
rc = 0;
}
if (asn1_header_decode(&ctx, &end, &cls, &con, &tag) == 0) {
cFYI(1, ("Error decoding negTokenInit"));
return 0;
} else if ((cls != ASN1_CTX) || (con != ASN1_CON)
|| (tag != ASN1_EOC)) {
cFYI(1,
("cls = %d con = %d tag = %d end = %p (%d) exit 0",
cls, con, tag, end, *end));
return 0;
}
/* SPNEGO OID not present or garbled -- bail out */
if (!rc) {
cFYI(1, ("Error decoding negTokenInit header"));
return 0;
}
if (asn1_header_decode(&ctx, &end, &cls, &con, &tag) == 0) {
cFYI(1, ("Error decoding negTokenInit"));
return 0;
} else if ((cls != ASN1_UNI) || (con != ASN1_CON)
|| (tag != ASN1_SEQ)) {
cFYI(1,
("cls = %d con = %d tag = %d end = %p (%d) exit 1",
cls, con, tag, end, *end));
return 0;
}
if (asn1_header_decode(&ctx, &end, &cls, &con, &tag) == 0) {
cFYI(1, ("Error decoding negTokenInit"));
return 0;
} else if ((cls != ASN1_CTX) || (con != ASN1_CON)
|| (tag != ASN1_EOC)) {
cFYI(1,
("cls = %d con = %d tag = %d end = %p (%d) exit 0",
cls, con, tag, end, *end));
return 0;
}
if (asn1_header_decode(&ctx, &end, &cls, &con, &tag) == 0) {
cFYI(1, ("Error decoding 2nd part of negTokenInit"));
return 0;
} else if ((cls != ASN1_CTX) || (con != ASN1_CON)
|| (tag != ASN1_EOC)) {
cFYI(1,
("cls = %d con = %d tag = %d end = %p (%d) exit 0",
cls, con, tag, end, *end));
return 0;
}
if (asn1_header_decode(&ctx, &end, &cls, &con, &tag) == 0) {
cFYI(1, ("Error decoding negTokenInit"));
return 0;
} else if ((cls != ASN1_UNI) || (con != ASN1_CON)
|| (tag != ASN1_SEQ)) {
cFYI(1,
("cls = %d con = %d tag = %d end = %p (%d) exit 1",
cls, con, tag, end, *end));
return 0;
}
if (asn1_header_decode
(&ctx, &sequence_end, &cls, &con, &tag) == 0) {
cFYI(1, ("Error decoding 2nd part of negTokenInit"));
return 0;
} else if ((cls != ASN1_UNI) || (con != ASN1_CON)
|| (tag != ASN1_SEQ)) {
cFYI(1,
("cls = %d con = %d tag = %d end = %p (%d) exit 1",
cls, con, tag, end, *end));
return 0;
}
if (asn1_header_decode(&ctx, &end, &cls, &con, &tag) == 0) {
cFYI(1, ("Error decoding 2nd part of negTokenInit"));
return 0;
} else if ((cls != ASN1_CTX) || (con != ASN1_CON)
|| (tag != ASN1_EOC)) {
cFYI(1,
("cls = %d con = %d tag = %d end = %p (%d) exit 0",
cls, con, tag, end, *end));
return 0;
}
while (!asn1_eoc_decode(&ctx, sequence_end)) {
rc = asn1_header_decode(&ctx, &end, &cls, &con, &tag);
if (!rc) {
cFYI(1,
("Error decoding negTokenInit hdr exit2"));
return 0;
}
if ((tag == ASN1_OJI) && (con == ASN1_PRI)) {
if (asn1_oid_decode(&ctx, end, &oid, &oidlen)) {
cFYI(1,
("OID len = %d oid = 0x%lx 0x%lx "
"0x%lx 0x%lx",
oidlen, *oid, *(oid + 1),
*(oid + 2), *(oid + 3)));
if (compare_oid(oid, oidlen,
MSKRB5_OID,
MSKRB5_OID_LEN))
use_kerberos = true;
else if (compare_oid(oid, oidlen,
KRB5_OID,
KRB5_OID_LEN))
use_kerberos = true;
else if (compare_oid(oid, oidlen,
NTLMSSP_OID,
NTLMSSP_OID_LEN))
use_ntlmssp = true;
kfree(oid);
}
} else {
cFYI(1, ("Should be an oid what is going on?"));
}
}
if (asn1_header_decode
(&ctx, &sequence_end, &cls, &con, &tag) == 0) {
cFYI(1, ("Error decoding 2nd part of negTokenInit"));
return 0;
} else if ((cls != ASN1_UNI) || (con != ASN1_CON)
|| (tag != ASN1_SEQ)) {
cFYI(1,
("cls = %d con = %d tag = %d end = %p (%d) exit 1",
cls, con, tag, end, *end));
return 0;
}
if (asn1_header_decode(&ctx, &end, &cls, &con, &tag) == 0) {
cFYI(1,
("Error decoding last part negTokenInit exit3"));
return 0;
} else if ((cls != ASN1_CTX) || (con != ASN1_CON)) {
/* tag = 3 indicating mechListMIC */
while (!asn1_eoc_decode(&ctx, sequence_end)) {
rc = asn1_header_decode(&ctx, &end, &cls, &con, &tag);
if (!rc) {
cFYI(1,
("Exit 4 cls = %d con = %d tag = %d end = %p (%d)",
cls, con, tag, end, *end));
("Error decoding negTokenInit hdr exit2"));
return 0;
}
if (asn1_header_decode(&ctx, &end, &cls, &con, &tag) == 0) {
cFYI(1,
("Error decoding last part negTokenInit exit5"));
return 0;
} else if ((cls != ASN1_UNI) || (con != ASN1_CON)
|| (tag != ASN1_SEQ)) {
cFYI(1, ("cls = %d con = %d tag = %d end = %p (%d)",
cls, con, tag, end, *end));
if ((tag == ASN1_OJI) && (con == ASN1_PRI)) {
if (asn1_oid_decode(&ctx, end, &oid, &oidlen)) {
cFYI(1, ("OID len = %d oid = 0x%lx 0x%lx "
"0x%lx 0x%lx", oidlen, *oid,
*(oid + 1), *(oid + 2), *(oid + 3)));
if (compare_oid(oid, oidlen, MSKRB5_OID,
MSKRB5_OID_LEN))
use_kerberos = true;
else if (compare_oid(oid, oidlen, KRB5_OID,
KRB5_OID_LEN))
use_kerberos = true;
else if (compare_oid(oid, oidlen, NTLMSSP_OID,
NTLMSSP_OID_LEN))
use_ntlmssp = true;
kfree(oid);
}
} else {
cFYI(1, ("Should be an oid what is going on?"));
}
}
if (asn1_header_decode(&ctx, &end, &cls, &con, &tag) == 0) {
cFYI(1,
("Error decoding last part negTokenInit exit 7"));
return 0;
} else if ((cls != ASN1_CTX) || (con != ASN1_CON)) {
cFYI(1,
("Exit 8 cls = %d con = %d tag = %d end = %p (%d)",
cls, con, tag, end, *end));
return 0;
}
if (asn1_header_decode(&ctx, &end, &cls, &con, &tag) == 0) {
cFYI(1,
("Error decoding last part negTokenInit exit9"));
return 0;
} else if ((cls != ASN1_UNI) || (con != ASN1_PRI)
|| (tag != ASN1_GENSTR)) {
cFYI(1,
("Exit10 cls = %d con = %d tag = %d end = %p (%d)",
cls, con, tag, end, *end));
return 0;
}
cFYI(1, ("Need to call asn1_octets_decode() function for %s",
ctx.pointer)); /* is this UTF-8 or ASCII? */
if (asn1_header_decode(&ctx, &end, &cls, &con, &tag) == 0) {
cFYI(1, ("Error decoding last part negTokenInit exit3"));
return 0;
} else if ((cls != ASN1_CTX) || (con != ASN1_CON)) {
/* tag = 3 indicating mechListMIC */
cFYI(1, ("Exit 4 cls = %d con = %d tag = %d end = %p (%d)",
cls, con, tag, end, *end));
return 0;
}
if (asn1_header_decode(&ctx, &end, &cls, &con, &tag) == 0) {
cFYI(1, ("Error decoding last part negTokenInit exit5"));
return 0;
} else if ((cls != ASN1_UNI) || (con != ASN1_CON)
|| (tag != ASN1_SEQ)) {
cFYI(1, ("cls = %d con = %d tag = %d end = %p (%d)",
cls, con, tag, end, *end));
}
if (asn1_header_decode(&ctx, &end, &cls, &con, &tag) == 0) {
cFYI(1, ("Error decoding last part negTokenInit exit 7"));
return 0;
} else if ((cls != ASN1_CTX) || (con != ASN1_CON)) {
cFYI(1, ("Exit 8 cls = %d con = %d tag = %d end = %p (%d)",
cls, con, tag, end, *end));
return 0;
}
if (asn1_header_decode(&ctx, &end, &cls, &con, &tag) == 0) {
cFYI(1, ("Error decoding last part negTokenInit exit9"));
return 0;
} else if ((cls != ASN1_UNI) || (con != ASN1_PRI)
|| (tag != ASN1_GENSTR)) {
cFYI(1, ("Exit10 cls = %d con = %d tag = %d end = %p (%d)",
cls, con, tag, end, *end));
return 0;
}
cFYI(1, ("Need to call asn1_octets_decode() function for %s",
ctx.pointer)); /* is this UTF-8 or ASCII? */
if (use_kerberos)
*secType = Kerberos;
......
......@@ -79,27 +79,25 @@ void cifs_dump_mids(struct TCP_Server_Info *server)
spin_lock(&GlobalMid_Lock);
list_for_each(tmp, &server->pending_mid_q) {
mid_entry = list_entry(tmp, struct mid_q_entry, qhead);
if (mid_entry) {
cERROR(1, ("State: %d Cmd: %d Pid: %d Tsk: %p Mid %d",
mid_entry->midState,
(int)mid_entry->command,
mid_entry->pid,
mid_entry->tsk,
mid_entry->mid));
cERROR(1, ("State: %d Cmd: %d Pid: %d Tsk: %p Mid %d",
mid_entry->midState,
(int)mid_entry->command,
mid_entry->pid,
mid_entry->tsk,
mid_entry->mid));
#ifdef CONFIG_CIFS_STATS2
cERROR(1, ("IsLarge: %d buf: %p time rcv: %ld now: %ld",
mid_entry->largeBuf,
mid_entry->resp_buf,
mid_entry->when_received,
jiffies));
cERROR(1, ("IsLarge: %d buf: %p time rcv: %ld now: %ld",
mid_entry->largeBuf,
mid_entry->resp_buf,
mid_entry->when_received,
jiffies));
#endif /* STATS2 */
cERROR(1, ("IsMult: %d IsEnd: %d", mid_entry->multiRsp,
mid_entry->multiEnd));
if (mid_entry->resp_buf) {
cifs_dump_detail(mid_entry->resp_buf);
cifs_dump_mem("existing buf: ",
mid_entry->resp_buf, 62);
}
cERROR(1, ("IsMult: %d IsEnd: %d", mid_entry->multiRsp,
mid_entry->multiEnd));
if (mid_entry->resp_buf) {
cifs_dump_detail(mid_entry->resp_buf);
cifs_dump_mem("existing buf: ",
mid_entry->resp_buf, 62);
}
}
spin_unlock(&GlobalMid_Lock);
......@@ -163,16 +161,13 @@ static int cifs_debug_data_proc_show(struct seq_file *m, void *v)
mid_entry = list_entry(tmp1, struct
mid_q_entry,
qhead);
if (mid_entry) {
seq_printf(m,
"State: %d com: %d pid:"
" %d tsk: %p mid %d\n",
mid_entry->midState,
(int)mid_entry->command,
mid_entry->pid,
mid_entry->tsk,
mid_entry->mid);
}
seq_printf(m, "State: %d com: %d pid:"
" %d tsk: %p mid %d\n",
mid_entry->midState,
(int)mid_entry->command,
mid_entry->pid,
mid_entry->tsk,
mid_entry->mid);
}
spin_unlock(&GlobalMid_Lock);
}
......
......@@ -66,8 +66,8 @@ struct key_type cifs_spnego_key_type = {
.describe = user_describe,
};
#define MAX_VER_STR_LEN 9 /* length of longest version string e.g.
strlen(";ver=0xFF") */
#define MAX_VER_STR_LEN 8 /* length of longest version string e.g.
strlen("ver=0xFF") */
#define MAX_MECH_STR_LEN 13 /* length of longest security mechanism name, eg
in future could have strlen(";sec=ntlmsspi") */
#define MAX_IPV6_ADDR_LEN 42 /* eg FEDC:BA98:7654:3210:FEDC:BA98:7654:3210/60 */
......@@ -81,11 +81,15 @@ cifs_get_spnego_key(struct cifsSesInfo *sesInfo)
struct key *spnego_key;
const char *hostname = server->hostname;
/* BB: come up with better scheme for determining length */
/* length of fields (with semicolons): ver=0xyz ipv4= ipaddress host=
hostname sec=mechanism uid=0x uid */
desc_len = MAX_VER_STR_LEN + 5 + MAX_IPV6_ADDR_LEN + 1 + 6 +
strlen(hostname) + MAX_MECH_STR_LEN + 8 + (sizeof(uid_t) * 2);
/* length of fields (with semicolons): ver=0xyz ip4=ipaddress
host=hostname sec=mechanism uid=0xFF user=username */
desc_len = MAX_VER_STR_LEN +
6 /* len of "host=" */ + strlen(hostname) +
5 /* len of ";ipv4=" */ + MAX_IPV6_ADDR_LEN +
MAX_MECH_STR_LEN +
7 /* len of ";uid=0x" */ + (sizeof(uid_t) * 2) +
6 /* len of ";user=" */ + strlen(sesInfo->userName) + 1;
spnego_key = ERR_PTR(-ENOMEM);
description = kzalloc(desc_len, GFP_KERNEL);
if (description == NULL)
......
......@@ -930,36 +930,34 @@ static int cifs_oplock_thread(void *dummyarg)
schedule_timeout(39*HZ);
} else {
oplock_item = list_entry(GlobalOplock_Q.next,
struct oplock_q_entry, qhead);
if (oplock_item) {
cFYI(1, ("found oplock item to write out"));
pTcon = oplock_item->tcon;
inode = oplock_item->pinode;
netfid = oplock_item->netfid;
spin_unlock(&GlobalMid_Lock);
DeleteOplockQEntry(oplock_item);
/* can not grab inode sem here since it would
struct oplock_q_entry, qhead);
cFYI(1, ("found oplock item to write out"));
pTcon = oplock_item->tcon;
inode = oplock_item->pinode;
netfid = oplock_item->netfid;
spin_unlock(&GlobalMid_Lock);
DeleteOplockQEntry(oplock_item);
/* can not grab inode sem here since it would
deadlock when oplock received on delete
since vfs_unlink holds the i_mutex across
the call */
/* mutex_lock(&inode->i_mutex);*/
if (S_ISREG(inode->i_mode)) {
rc =
filemap_fdatawrite(inode->i_mapping);
if (CIFS_I(inode)->clientCanCacheRead
== 0) {
waitrc = filemap_fdatawait(inode->i_mapping);
invalidate_remote_inode(inode);
}
if (rc == 0)
rc = waitrc;
} else
rc = 0;
/* mutex_unlock(&inode->i_mutex);*/
if (rc)
CIFS_I(inode)->write_behind_rc = rc;
cFYI(1, ("Oplock flush inode %p rc %d",
inode, rc));
/* mutex_lock(&inode->i_mutex);*/
if (S_ISREG(inode->i_mode)) {
rc = filemap_fdatawrite(inode->i_mapping);
if (CIFS_I(inode)->clientCanCacheRead == 0) {
waitrc = filemap_fdatawait(
inode->i_mapping);
invalidate_remote_inode(inode);
}
if (rc == 0)
rc = waitrc;
} else
rc = 0;
/* mutex_unlock(&inode->i_mutex);*/
if (rc)
CIFS_I(inode)->write_behind_rc = rc;
cFYI(1, ("Oplock flush inode %p rc %d",
inode, rc));
/* releasing stale oplock after recent reconnect
of smb session using a now incorrect file
......@@ -967,15 +965,13 @@ static int cifs_oplock_thread(void *dummyarg)
not bother sending an oplock release if session
to server still is disconnected since oplock
already released by the server in that case */
if (pTcon->tidStatus != CifsNeedReconnect) {
rc = CIFSSMBLock(0, pTcon, netfid,
0 /* len */ , 0 /* offset */, 0,
0, LOCKING_ANDX_OPLOCK_RELEASE,
false /* wait flag */);
cFYI(1, ("Oplock release rc = %d", rc));
}
} else
spin_unlock(&GlobalMid_Lock);
if (pTcon->tidStatus != CifsNeedReconnect) {
rc = CIFSSMBLock(0, pTcon, netfid,
0 /* len */ , 0 /* offset */, 0,
0, LOCKING_ANDX_OPLOCK_RELEASE,
false /* wait flag */);
cFYI(1, ("Oplock release rc = %d", rc));
}
set_current_state(TASK_INTERRUPTIBLE);
schedule_timeout(1); /* yield in case q were corrupt */
}
......@@ -1001,8 +997,7 @@ static int cifs_dnotify_thread(void *dummyarg)
list_for_each(tmp, &GlobalSMBSessionList) {
ses = list_entry(tmp, struct cifsSesInfo,
cifsSessionList);
if (ses && ses->server &&
atomic_read(&ses->server->inFlight))
if (ses->server && atomic_read(&ses->server->inFlight))
wake_up_all(&ses->server->response_q);
}
read_unlock(&GlobalSMBSeslock);
......
......@@ -101,5 +101,5 @@ extern long cifs_ioctl(struct file *filep, unsigned int cmd, unsigned long arg);
extern const struct export_operations cifs_export_ops;
#endif /* EXPERIMENTAL */
#define CIFS_VERSION "1.53"
#define CIFS_VERSION "1.54"
#endif /* _CIFSFS_H */
......@@ -262,7 +262,7 @@
*/
#define CIFS_NO_HANDLE 0xFFFF
#define NO_CHANGE_64 cpu_to_le64(0xFFFFFFFFFFFFFFFFULL)
#define NO_CHANGE_64 0xFFFFFFFFFFFFFFFFULL
#define NO_CHANGE_32 0xFFFFFFFFUL
/* IPC$ in ASCII */
......
......@@ -172,12 +172,13 @@ extern int CIFSSMBQFSUnixInfo(const int xid, struct cifsTconInfo *tcon);
extern int CIFSSMBQFSPosixInfo(const int xid, struct cifsTconInfo *tcon,
struct kstatfs *FSData);
extern int CIFSSMBSetTimes(const int xid, struct cifsTconInfo *tcon,
extern int CIFSSMBSetPathInfo(const int xid, struct cifsTconInfo *tcon,
const char *fileName, const FILE_BASIC_INFO *data,
const struct nls_table *nls_codepage,
int remap_special_chars);
extern int CIFSSMBSetFileTimes(const int xid, struct cifsTconInfo *tcon,
const FILE_BASIC_INFO *data, __u16 fid);
extern int CIFSSMBSetFileInfo(const int xid, struct cifsTconInfo *tcon,
const FILE_BASIC_INFO *data, __u16 fid,
__u32 pid_of_opener);
#if 0
extern int CIFSSMBSetAttrLegacy(int xid, struct cifsTconInfo *tcon,
char *fileName, __u16 dos_attributes,
......@@ -191,9 +192,20 @@ extern int CIFSSMBSetEOF(const int xid, struct cifsTconInfo *tcon,
extern int CIFSSMBSetFileSize(const int xid, struct cifsTconInfo *tcon,
__u64 size, __u16 fileHandle, __u32 opener_pid,
bool AllocSizeFlag);
extern int CIFSSMBUnixSetPerms(const int xid, struct cifsTconInfo *pTcon,
char *full_path, __u64 mode, __u64 uid,
__u64 gid, dev_t dev,
struct cifs_unix_set_info_args {
__u64 ctime;
__u64 atime;
__u64 mtime;
__u64 mode;
__u64 uid;
__u64 gid;
dev_t device;
};
extern int CIFSSMBUnixSetInfo(const int xid, struct cifsTconInfo *pTcon,
char *fileName,
const struct cifs_unix_set_info_args *args,
const struct nls_table *nls_codepage,
int remap_special_chars);
......
......@@ -128,8 +128,7 @@ static void mark_open_files_invalid(struct cifsTconInfo *pTcon)
write_lock(&GlobalSMBSeslock);
list_for_each_safe(tmp, tmp1, &pTcon->openFileList) {
open_file = list_entry(tmp, struct cifsFileInfo, tlist);
if (open_file)
open_file->invalidHandle = true;
open_file->invalidHandle = true;
}
write_unlock(&GlobalSMBSeslock);
/* BB Add call to invalidate_inodes(sb) for all superblocks mounted
......@@ -4816,8 +4815,8 @@ CIFSSMBSetFileSize(const int xid, struct cifsTconInfo *tcon, __u64 size,
time and resort to the original setpathinfo level which takes the ancient
DOS time format with 2 second granularity */
int
CIFSSMBSetFileTimes(const int xid, struct cifsTconInfo *tcon,
const FILE_BASIC_INFO *data, __u16 fid)
CIFSSMBSetFileInfo(const int xid, struct cifsTconInfo *tcon,
const FILE_BASIC_INFO *data, __u16 fid, __u32 pid_of_opener)
{
struct smb_com_transaction2_sfi_req *pSMB = NULL;
char *data_offset;
......@@ -4830,11 +4829,8 @@ CIFSSMBSetFileTimes(const int xid, struct cifsTconInfo *tcon,
if (rc)
return rc;
/* At this point there is no need to override the current pid
with the pid of the opener, but that could change if we someday
use an existing handle (rather than opening one on the fly) */
/* pSMB->hdr.Pid = cpu_to_le16((__u16)pid_of_opener);
pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid_of_opener >> 16));*/
pSMB->hdr.Pid = cpu_to_le16((__u16)pid_of_opener);
pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid_of_opener >> 16));
params = 6;
pSMB->MaxSetupCount = 0;
......@@ -4882,9 +4878,9 @@ CIFSSMBSetFileTimes(const int xid, struct cifsTconInfo *tcon,
int
CIFSSMBSetTimes(const int xid, struct cifsTconInfo *tcon, const char *fileName,
const FILE_BASIC_INFO *data,
const struct nls_table *nls_codepage, int remap)
CIFSSMBSetPathInfo(const int xid, struct cifsTconInfo *tcon,
const char *fileName, const FILE_BASIC_INFO *data,
const struct nls_table *nls_codepage, int remap)
{
TRANSACTION2_SPI_REQ *pSMB = NULL;
TRANSACTION2_SPI_RSP *pSMBr = NULL;
......@@ -5013,10 +5009,9 @@ CIFSSMBSetAttrLegacy(int xid, struct cifsTconInfo *tcon, char *fileName,
#endif /* temporarily unneeded SetAttr legacy function */
int
CIFSSMBUnixSetPerms(const int xid, struct cifsTconInfo *tcon,
char *fileName, __u64 mode, __u64 uid, __u64 gid,
dev_t device, const struct nls_table *nls_codepage,
int remap)
CIFSSMBUnixSetInfo(const int xid, struct cifsTconInfo *tcon, char *fileName,
const struct cifs_unix_set_info_args *args,
const struct nls_table *nls_codepage, int remap)
{
TRANSACTION2_SPI_REQ *pSMB = NULL;
TRANSACTION2_SPI_RSP *pSMBr = NULL;
......@@ -5025,6 +5020,7 @@ CIFSSMBUnixSetPerms(const int xid, struct cifsTconInfo *tcon,
int bytes_returned = 0;
FILE_UNIX_BASIC_INFO *data_offset;
__u16 params, param_offset, offset, count, byte_count;
__u64 mode = args->mode;
cFYI(1, ("In SetUID/GID/Mode"));
setPermsRetry:
......@@ -5080,16 +5076,16 @@ CIFSSMBUnixSetPerms(const int xid, struct cifsTconInfo *tcon,
set file size and do not want to truncate file size to zero
accidently as happened on one Samba server beta by putting
zero instead of -1 here */
data_offset->EndOfFile = NO_CHANGE_64;
data_offset->NumOfBytes = NO_CHANGE_64;
data_offset->LastStatusChange = NO_CHANGE_64;
data_offset->LastAccessTime = NO_CHANGE_64;
data_offset->LastModificationTime = NO_CHANGE_64;
data_offset->Uid = cpu_to_le64(uid);
data_offset->Gid = cpu_to_le64(gid);
data_offset->EndOfFile = cpu_to_le64(NO_CHANGE_64);
data_offset->NumOfBytes = cpu_to_le64(NO_CHANGE_64);
data_offset->LastStatusChange = cpu_to_le64(args->ctime);
data_offset->LastAccessTime = cpu_to_le64(args->atime);
data_offset->LastModificationTime = cpu_to_le64(args->mtime);
data_offset->Uid = cpu_to_le64(args->uid);
data_offset->Gid = cpu_to_le64(args->gid);
/* better to leave device as zero when it is */
data_offset->DevMajor = cpu_to_le64(MAJOR(device));
data_offset->DevMinor = cpu_to_le64(MINOR(device));
data_offset->DevMajor = cpu_to_le64(MAJOR(args->device));
data_offset->DevMinor = cpu_to_le64(MINOR(args->device));
data_offset->Permissions = cpu_to_le64(mode);
if (S_ISREG(mode))
......
......@@ -151,7 +151,7 @@ cifs_reconnect(struct TCP_Server_Info *server)
}
list_for_each(tmp, &GlobalTreeConnectionList) {
tcon = list_entry(tmp, struct cifsTconInfo, cifsConnectionList);
if ((tcon) && (tcon->ses) && (tcon->ses->server == server))
if ((tcon->ses) && (tcon->ses->server == server))
tcon->tidStatus = CifsNeedReconnect;
}
read_unlock(&GlobalSMBSeslock);
......@@ -173,14 +173,12 @@ cifs_reconnect(struct TCP_Server_Info *server)
mid_entry = list_entry(tmp, struct
mid_q_entry,
qhead);
if (mid_entry) {
if (mid_entry->midState == MID_REQUEST_SUBMITTED) {
if (mid_entry->midState == MID_REQUEST_SUBMITTED) {
/* Mark other intransit requests as needing
retry so we do not immediately mark the
session bad again (ie after we reconnect
below) as they timeout too */
mid_entry->midState = MID_RETRY_NEEDED;
}
mid_entry->midState = MID_RETRY_NEEDED;
}
}
spin_unlock(&GlobalMid_Lock);
......@@ -351,11 +349,9 @@ cifs_demultiplex_thread(struct TCP_Server_Info *server)
current->flags |= PF_MEMALLOC;
cFYI(1, ("Demultiplex PID: %d", task_pid_nr(current)));
write_lock(&GlobalSMBSeslock);
atomic_inc(&tcpSesAllocCount);
length = tcpSesAllocCount.counter;
write_unlock(&GlobalSMBSeslock);
if (length > 1)
length = atomic_inc_return(&tcpSesAllocCount);
if (length > 1)
mempool_resize(cifs_req_poolp, length + cifs_min_rcv,
GFP_KERNEL);
......@@ -745,14 +741,11 @@ cifs_demultiplex_thread(struct TCP_Server_Info *server)
coming home not much else we can do but free the memory */
}
write_lock(&GlobalSMBSeslock);
atomic_dec(&tcpSesAllocCount);
length = tcpSesAllocCount.counter;
/* last chance to mark ses pointers invalid
if there are any pointing to this (e.g
if a crazy root user tried to kill cifsd
kernel thread explicitly this might happen) */
write_lock(&GlobalSMBSeslock);
list_for_each(tmp, &GlobalSMBSessionList) {
ses = list_entry(tmp, struct cifsSesInfo,
cifsSessionList);
......@@ -763,6 +756,8 @@ cifs_demultiplex_thread(struct TCP_Server_Info *server)
kfree(server->hostname);
kfree(server);
length = atomic_dec_return(&tcpSesAllocCount);
if (length > 0)
mempool_resize(cifs_req_poolp, length + cifs_min_rcv,
GFP_KERNEL);
......@@ -3623,97 +3618,91 @@ int cifs_setup_session(unsigned int xid, struct cifsSesInfo *pSesInfo,
}
first_time = 1;
}
if (!rc) {
pSesInfo->flags = 0;
pSesInfo->capabilities = pSesInfo->server->capabilities;
if (linuxExtEnabled == 0)
pSesInfo->capabilities &= (~CAP_UNIX);
if (rc)
goto ss_err_exit;
pSesInfo->flags = 0;
pSesInfo->capabilities = pSesInfo->server->capabilities;
if (linuxExtEnabled == 0)
pSesInfo->capabilities &= (~CAP_UNIX);
/* pSesInfo->sequence_number = 0;*/
cFYI(1,
("Security Mode: 0x%x Capabilities: 0x%x TimeAdjust: %d",
pSesInfo->server->secMode,
pSesInfo->server->capabilities,
pSesInfo->server->timeAdj));
if (experimEnabled < 2)
rc = CIFS_SessSetup(xid, pSesInfo,
first_time, nls_info);
else if (extended_security
&& (pSesInfo->capabilities
& CAP_EXTENDED_SECURITY)
&& (pSesInfo->server->secType == NTLMSSP)) {
rc = -EOPNOTSUPP;
} else if (extended_security
&& (pSesInfo->capabilities & CAP_EXTENDED_SECURITY)
&& (pSesInfo->server->secType == RawNTLMSSP)) {
cFYI(1, ("NTLMSSP sesssetup"));
rc = CIFSNTLMSSPNegotiateSessSetup(xid,
pSesInfo,
&ntlmv2_flag,
nls_info);
if (!rc) {
if (ntlmv2_flag) {
char *v2_response;
cFYI(1, ("more secure NTLM ver2 hash"));
if (CalcNTLMv2_partial_mac_key(pSesInfo,
nls_info)) {
rc = -ENOMEM;
goto ss_err_exit;
} else
v2_response = kmalloc(16 + 64 /* blob */, GFP_KERNEL);
if (v2_response) {
CalcNTLMv2_response(pSesInfo,
v2_response);
/* if (first_time)
cifs_calculate_ntlmv2_mac_key(
pSesInfo->server->mac_signing_key,
response, ntlm_session_key,*/
kfree(v2_response);
cFYI(1, ("Security Mode: 0x%x Capabilities: 0x%x TimeAdjust: %d",
pSesInfo->server->secMode,
pSesInfo->server->capabilities,
pSesInfo->server->timeAdj));
if (experimEnabled < 2)
rc = CIFS_SessSetup(xid, pSesInfo, first_time, nls_info);
else if (extended_security
&& (pSesInfo->capabilities & CAP_EXTENDED_SECURITY)
&& (pSesInfo->server->secType == NTLMSSP)) {
rc = -EOPNOTSUPP;
} else if (extended_security
&& (pSesInfo->capabilities & CAP_EXTENDED_SECURITY)
&& (pSesInfo->server->secType == RawNTLMSSP)) {
cFYI(1, ("NTLMSSP sesssetup"));
rc = CIFSNTLMSSPNegotiateSessSetup(xid, pSesInfo, &ntlmv2_flag,
nls_info);
if (!rc) {
if (ntlmv2_flag) {
char *v2_response;
cFYI(1, ("more secure NTLM ver2 hash"));
if (CalcNTLMv2_partial_mac_key(pSesInfo,
nls_info)) {
rc = -ENOMEM;
goto ss_err_exit;
} else
v2_response = kmalloc(16 + 64 /* blob*/,
GFP_KERNEL);
if (v2_response) {
CalcNTLMv2_response(pSesInfo,
v2_response);
/* if (first_time)
cifs_calculate_ntlmv2_mac_key */
kfree(v2_response);
/* BB Put dummy sig in SessSetup PDU? */
} else {
rc = -ENOMEM;
goto ss_err_exit;
}
} else {
SMBNTencrypt(pSesInfo->password,
pSesInfo->server->cryptKey,
ntlm_session_key);
if (first_time)
cifs_calculate_mac_key(
&pSesInfo->server->mac_signing_key,
ntlm_session_key,
pSesInfo->password);
rc = -ENOMEM;
goto ss_err_exit;
}
} else {
SMBNTencrypt(pSesInfo->password,
pSesInfo->server->cryptKey,
ntlm_session_key);
if (first_time)
cifs_calculate_mac_key(
&pSesInfo->server->mac_signing_key,
ntlm_session_key,
pSesInfo->password);
}
/* for better security the weaker lanman hash not sent
in AuthSessSetup so we no longer calculate it */
rc = CIFSNTLMSSPAuthSessSetup(xid,
pSesInfo,
ntlm_session_key,
ntlmv2_flag,
nls_info);
}
} else { /* old style NTLM 0.12 session setup */
SMBNTencrypt(pSesInfo->password,
pSesInfo->server->cryptKey,
ntlm_session_key);
rc = CIFSNTLMSSPAuthSessSetup(xid, pSesInfo,
ntlm_session_key,
ntlmv2_flag,
nls_info);
}
} else { /* old style NTLM 0.12 session setup */
SMBNTencrypt(pSesInfo->password, pSesInfo->server->cryptKey,
ntlm_session_key);
if (first_time)
cifs_calculate_mac_key(
if (first_time)
cifs_calculate_mac_key(
&pSesInfo->server->mac_signing_key,
ntlm_session_key, pSesInfo->password);
rc = CIFSSessSetup(xid, pSesInfo,
ntlm_session_key, nls_info);
}
if (rc) {
cERROR(1, ("Send error in SessSetup = %d", rc));
} else {
cFYI(1, ("CIFS Session Established successfully"));
rc = CIFSSessSetup(xid, pSesInfo, ntlm_session_key, nls_info);
}
if (rc) {
cERROR(1, ("Send error in SessSetup = %d", rc));
} else {
cFYI(1, ("CIFS Session Established successfully"));
pSesInfo->status = CifsGood;
}
}
ss_err_exit:
return rc;
}
......
......@@ -226,23 +226,28 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode,
/* If Open reported that we actually created a file
then we now have to set the mode if possible */
if ((pTcon->unix_ext) && (oplock & CIFS_CREATE_ACTION)) {
struct cifs_unix_set_info_args args = {
.mode = mode,
.ctime = NO_CHANGE_64,
.atime = NO_CHANGE_64,
.mtime = NO_CHANGE_64,
.device = 0,
};
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID) {
CIFSSMBUnixSetPerms(xid, pTcon, full_path, mode,
(__u64)current->fsuid,
(__u64)current->fsgid,
0 /* dev */,
cifs_sb->local_nls,
cifs_sb->mnt_cifs_flags &
CIFS_MOUNT_MAP_SPECIAL_CHR);
args.uid = (__u64) current->fsuid;
if (inode->i_mode & S_ISGID)
args.gid = (__u64) inode->i_gid;
else
args.gid = (__u64) current->fsgid;
} else {
CIFSSMBUnixSetPerms(xid, pTcon, full_path, mode,
(__u64)-1,
(__u64)-1,
0 /* dev */,
cifs_sb->local_nls,
cifs_sb->mnt_cifs_flags &
CIFS_MOUNT_MAP_SPECIAL_CHR);
args.uid = NO_CHANGE_64;
args.gid = NO_CHANGE_64;
}
CIFSSMBUnixSetInfo(xid, pTcon, full_path, &args,
cifs_sb->local_nls,
cifs_sb->mnt_cifs_flags &
CIFS_MOUNT_MAP_SPECIAL_CHR);
} else {
/* BB implement mode setting via Windows security
descriptors e.g. */
......@@ -267,7 +272,12 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode,
(cifs_sb->mnt_cifs_flags &
CIFS_MOUNT_SET_UID)) {
newinode->i_uid = current->fsuid;
newinode->i_gid = current->fsgid;
if (inode->i_mode & S_ISGID)
newinode->i_gid =
inode->i_gid;
else
newinode->i_gid =
current->fsgid;
}
}
}
......@@ -357,21 +367,24 @@ int cifs_mknod(struct inode *inode, struct dentry *direntry, int mode,
if (full_path == NULL)
rc = -ENOMEM;
else if (pTcon->unix_ext) {
mode &= ~current->fs->umask;
struct cifs_unix_set_info_args args = {
.mode = mode & ~current->fs->umask,
.ctime = NO_CHANGE_64,
.atime = NO_CHANGE_64,
.mtime = NO_CHANGE_64,
.device = device_number,
};
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID) {
rc = CIFSSMBUnixSetPerms(xid, pTcon, full_path,
mode, (__u64)current->fsuid,
(__u64)current->fsgid,
device_number, cifs_sb->local_nls,
cifs_sb->mnt_cifs_flags &
CIFS_MOUNT_MAP_SPECIAL_CHR);
args.uid = (__u64) current->fsuid;
args.gid = (__u64) current->fsgid;
} else {
rc = CIFSSMBUnixSetPerms(xid, pTcon,
full_path, mode, (__u64)-1, (__u64)-1,
device_number, cifs_sb->local_nls,
cifs_sb->mnt_cifs_flags &
CIFS_MOUNT_MAP_SPECIAL_CHR);
args.uid = NO_CHANGE_64;
args.gid = NO_CHANGE_64;
}
rc = CIFSSMBUnixSetInfo(xid, pTcon, full_path,
&args, cifs_sb->local_nls,
cifs_sb->mnt_cifs_flags &
CIFS_MOUNT_MAP_SPECIAL_CHR);
if (!rc) {
rc = cifs_get_inode_info_unix(&newinode, full_path,
......
......@@ -310,18 +310,19 @@ int cifs_open(struct inode *inode, struct file *file)
/* time to set mode which we can not set earlier due to
problems creating new read-only files */
if (pTcon->unix_ext) {
CIFSSMBUnixSetPerms(xid, pTcon, full_path,
inode->i_mode,
(__u64)-1, (__u64)-1, 0 /* dev */,
struct cifs_unix_set_info_args args = {
.mode = inode->i_mode,
.uid = NO_CHANGE_64,
.gid = NO_CHANGE_64,
.ctime = NO_CHANGE_64,
.atime = NO_CHANGE_64,
.mtime = NO_CHANGE_64,
.device = 0,
};
CIFSSMBUnixSetInfo(xid, pTcon, full_path, &args,
cifs_sb->local_nls,
cifs_sb->mnt_cifs_flags &
CIFS_MOUNT_MAP_SPECIAL_CHR);
} else {
/* BB implement via Windows security descriptors eg
CIFSSMBWinSetPerms(xid, pTcon, full_path, mode,
-1, -1, local_nls);
in the meantime could set r/o dos attribute when
perms are eg: mode & 0222 == 0 */
}
}
......
This diff is collapsed.
......@@ -265,6 +265,7 @@ smb_send2(struct socket *ssocket, struct kvec *iov, int n_vec,
cFYI(1, ("Sending smb: total_len %d", total_len));
dump_smb(smb_buffer, len);
i = 0;
while (total_len) {
rc = kernel_sendmsg(ssocket, &smb_msg, &iov[first_vec],
n_vec - first_vec, total_len);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment