提交 6faf9a54 编写于 作者: L Linus Torvalds

Merge git://git.kernel.org/pub/scm/linux/kernel/git/sfrench/cifs-2.6

* git://git.kernel.org/pub/scm/linux/kernel/git/sfrench/cifs-2.6:
  cifs: don't allow mmap'ed pages to be dirtied while under writeback (try #3)
  [CIFS] Warn on requesting default security (ntlm) on mount
  [CIFS] cifs: clarify the meaning of tcpStatus == CifsGood
  cifs: wrap received signature check in srv_mutex
  cifs: clean up various nits in unicode routines (try #2)
  cifs: clean up length checks in check2ndT2
  cifs: set ra_pages in backing_dev_info
  cifs: fix broken BCC check in is_valid_oplock_break
  cifs: always do is_path_accessible check in cifs_mount
  various endian fixes to cifs
  Elminate sparse __CHECK_ENDIAN__ warnings on port conversion
  Max share size is too small
  Allow user names longer than 32 bytes
  cifs: replace /proc/fs/cifs/Experimental with a module parm
  cifs: check for private_data before trying to put it
......@@ -685,22 +685,6 @@ LinuxExtensionsEnabled If set to one then the client will attempt to
support and want to map the uid and gid fields
to values supplied at mount (rather than the
actual values, then set this to zero. (default 1)
Experimental When set to 1 used to enable certain experimental
features (currently enables multipage writes
when signing is enabled, the multipage write
performance enhancement was disabled when
signing turned on in case buffer was modified
just before it was sent, also this flag will
be used to use the new experimental directory change
notification code). When set to 2 enables
an additional experimental feature, "raw ntlmssp"
session establishment support (which allows
specifying "sec=ntlmssp" on mount). The Linux cifs
module will use ntlmv2 authentication encapsulated
in "raw ntlmssp" (not using SPNEGO) when
"sec=ntlmssp" is specified on mount.
This support also requires building cifs with
the CONFIG_CIFS_EXPERIMENTAL configuration flag.
These experimental features and tracing can be enabled by changing flags in
/proc/fs/cifs (after the cifs module has been installed or built into the
......
......@@ -50,7 +50,7 @@ void cifs_fscache_unregister(void)
*/
struct cifs_server_key {
uint16_t family; /* address family */
uint16_t port; /* IP port */
__be16 port; /* IP port */
union {
struct in_addr ipv4_addr;
struct in6_addr ipv6_addr;
......
......@@ -423,7 +423,6 @@ static const struct file_operations cifs_lookup_cache_proc_fops;
static const struct file_operations traceSMB_proc_fops;
static const struct file_operations cifs_multiuser_mount_proc_fops;
static const struct file_operations cifs_security_flags_proc_fops;
static const struct file_operations cifs_experimental_proc_fops;
static const struct file_operations cifs_linux_ext_proc_fops;
void
......@@ -441,8 +440,6 @@ cifs_proc_init(void)
proc_create("cifsFYI", 0, proc_fs_cifs, &cifsFYI_proc_fops);
proc_create("traceSMB", 0, proc_fs_cifs, &traceSMB_proc_fops);
proc_create("OplockEnabled", 0, proc_fs_cifs, &cifs_oplock_proc_fops);
proc_create("Experimental", 0, proc_fs_cifs,
&cifs_experimental_proc_fops);
proc_create("LinuxExtensionsEnabled", 0, proc_fs_cifs,
&cifs_linux_ext_proc_fops);
proc_create("MultiuserMount", 0, proc_fs_cifs,
......@@ -469,7 +466,6 @@ cifs_proc_clean(void)
remove_proc_entry("OplockEnabled", proc_fs_cifs);
remove_proc_entry("SecurityFlags", proc_fs_cifs);
remove_proc_entry("LinuxExtensionsEnabled", proc_fs_cifs);
remove_proc_entry("Experimental", proc_fs_cifs);
remove_proc_entry("LookupCacheEnabled", proc_fs_cifs);
remove_proc_entry("fs/cifs", NULL);
}
......@@ -550,45 +546,6 @@ static const struct file_operations cifs_oplock_proc_fops = {
.write = cifs_oplock_proc_write,
};
static int cifs_experimental_proc_show(struct seq_file *m, void *v)
{
seq_printf(m, "%d\n", experimEnabled);
return 0;
}
static int cifs_experimental_proc_open(struct inode *inode, struct file *file)
{
return single_open(file, cifs_experimental_proc_show, NULL);
}
static ssize_t cifs_experimental_proc_write(struct file *file,
const char __user *buffer, size_t count, loff_t *ppos)
{
char c;
int rc;
rc = get_user(c, buffer);
if (rc)
return rc;
if (c == '0' || c == 'n' || c == 'N')
experimEnabled = 0;
else if (c == '1' || c == 'y' || c == 'Y')
experimEnabled = 1;
else if (c == '2')
experimEnabled = 2;
return count;
}
static const struct file_operations cifs_experimental_proc_fops = {
.owner = THIS_MODULE,
.open = cifs_experimental_proc_open,
.read = seq_read,
.llseek = seq_lseek,
.release = single_release,
.write = cifs_experimental_proc_write,
};
static int cifs_linux_ext_proc_show(struct seq_file *m, void *v)
{
seq_printf(m, "%d\n", linuxExtEnabled);
......
......@@ -113,7 +113,7 @@ cifs_get_spnego_key(struct cifsSesInfo *sesInfo)
MAX_MECH_STR_LEN +
UID_KEY_LEN + (sizeof(uid_t) * 2) +
CREDUID_KEY_LEN + (sizeof(uid_t) * 2) +
USER_KEY_LEN + strlen(sesInfo->userName) +
USER_KEY_LEN + strlen(sesInfo->user_name) +
PID_KEY_LEN + (sizeof(pid_t) * 2) + 1;
spnego_key = ERR_PTR(-ENOMEM);
......@@ -153,7 +153,7 @@ cifs_get_spnego_key(struct cifsSesInfo *sesInfo)
sprintf(dp, ";creduid=0x%x", sesInfo->cred_uid);
dp = description + strlen(description);
sprintf(dp, ";user=%s", sesInfo->userName);
sprintf(dp, ";user=%s", sesInfo->user_name);
dp = description + strlen(description);
sprintf(dp, ";pid=0x%x", current->pid);
......
......@@ -90,7 +90,7 @@ cifs_mapchar(char *target, const __u16 src_char, const struct nls_table *cp,
case UNI_COLON:
*target = ':';
break;
case UNI_ASTERIK:
case UNI_ASTERISK:
*target = '*';
break;
case UNI_QUESTION:
......@@ -264,40 +264,40 @@ cifs_strndup_from_ucs(const char *src, const int maxlen, const bool is_unicode,
* names are little endian 16 bit Unicode on the wire
*/
int
cifsConvertToUCS(__le16 *target, const char *source, int maxlen,
cifsConvertToUCS(__le16 *target, const char *source, int srclen,
const struct nls_table *cp, int mapChars)
{
int i, j, charlen;
int len_remaining = maxlen;
char src_char;
__u16 temp;
__le16 dst_char;
wchar_t tmp;
if (!mapChars)
return cifs_strtoUCS(target, source, PATH_MAX, cp);
for (i = 0, j = 0; i < maxlen; j++) {
for (i = 0, j = 0; i < srclen; j++) {
src_char = source[i];
switch (src_char) {
case 0:
put_unaligned_le16(0, &target[j]);
put_unaligned(0, &target[j]);
goto ctoUCS_out;
case ':':
temp = UNI_COLON;
dst_char = cpu_to_le16(UNI_COLON);
break;
case '*':
temp = UNI_ASTERIK;
dst_char = cpu_to_le16(UNI_ASTERISK);
break;
case '?':
temp = UNI_QUESTION;
dst_char = cpu_to_le16(UNI_QUESTION);
break;
case '<':
temp = UNI_LESSTHAN;
dst_char = cpu_to_le16(UNI_LESSTHAN);
break;
case '>':
temp = UNI_GRTRTHAN;
dst_char = cpu_to_le16(UNI_GRTRTHAN);
break;
case '|':
temp = UNI_PIPE;
dst_char = cpu_to_le16(UNI_PIPE);
break;
/*
* FIXME: We can not handle remapping backslash (UNI_SLASH)
......@@ -305,17 +305,17 @@ cifsConvertToUCS(__le16 *target, const char *source, int maxlen,
* as they use backslash as separator.
*/
default:
charlen = cp->char2uni(source+i, len_remaining,
&temp);
charlen = cp->char2uni(source + i, srclen - i, &tmp);
dst_char = cpu_to_le16(tmp);
/*
* if no match, use question mark, which at least in
* some cases serves as wild card
*/
if (charlen < 1) {
temp = 0x003f;
dst_char = cpu_to_le16(0x003f);
charlen = 1;
}
len_remaining -= charlen;
/*
* character may take more than one byte in the source
* string, but will take exactly two bytes in the
......@@ -324,9 +324,8 @@ cifsConvertToUCS(__le16 *target, const char *source, int maxlen,
i += charlen;
continue;
}
put_unaligned_le16(temp, &target[j]);
put_unaligned(dst_char, &target[j]);
i++; /* move to next char in source string */
len_remaining--;
}
ctoUCS_out:
......
......@@ -44,7 +44,7 @@
* reserved symbols (along with \ and /), otherwise illegal to store
* in filenames in NTFS
*/
#define UNI_ASTERIK (__u16) ('*' + 0xF000)
#define UNI_ASTERISK (__u16) ('*' + 0xF000)
#define UNI_QUESTION (__u16) ('?' + 0xF000)
#define UNI_COLON (__u16) (':' + 0xF000)
#define UNI_GRTRTHAN (__u16) ('>' + 0xF000)
......
......@@ -30,12 +30,13 @@
#include <linux/ctype.h>
#include <linux/random.h>
/* Calculate and return the CIFS signature based on the mac key and SMB PDU */
/* the 16 byte signature must be allocated by the caller */
/* Note we only use the 1st eight bytes */
/* Note that the smb header signature field on input contains the
sequence number before this function is called */
/*
* Calculate and return the CIFS signature based on the mac key and SMB PDU.
* The 16 byte signature must be allocated by the caller. Note we only use the
* 1st eight bytes and that the smb header signature field on input contains
* the sequence number before this function is called. Also, this function
* should be called with the server->srv_mutex held.
*/
static int cifs_calculate_signature(const struct smb_hdr *cifs_pdu,
struct TCP_Server_Info *server, char *signature)
{
......@@ -209,8 +210,10 @@ int cifs_verify_signature(struct smb_hdr *cifs_pdu,
cpu_to_le32(expected_sequence_number);
cifs_pdu->Signature.Sequence.Reserved = 0;
mutex_lock(&server->srv_mutex);
rc = cifs_calculate_signature(cifs_pdu, server,
what_we_think_sig_should_be);
mutex_unlock(&server->srv_mutex);
if (rc)
return rc;
......@@ -469,15 +472,15 @@ static int calc_ntlmv2_hash(struct cifsSesInfo *ses, char *ntlmv2_hash,
return rc;
}
/* convert ses->userName to unicode and uppercase */
len = strlen(ses->userName);
/* convert ses->user_name to unicode and uppercase */
len = strlen(ses->user_name);
user = kmalloc(2 + (len * 2), GFP_KERNEL);
if (user == NULL) {
cERROR(1, "calc_ntlmv2_hash: user mem alloc failure\n");
rc = -ENOMEM;
goto calc_exit_2;
}
len = cifs_strtoUCS((__le16 *)user, ses->userName, len, nls_cp);
len = cifs_strtoUCS((__le16 *)user, ses->user_name, len, nls_cp);
UniStrupr(user);
crypto_shash_update(&ses->server->secmech.sdeschmacmd5->shash,
......
......@@ -53,7 +53,6 @@ int cifsFYI = 0;
int cifsERROR = 1;
int traceSMB = 0;
unsigned int oplockEnabled = 1;
unsigned int experimEnabled = 0;
unsigned int linuxExtEnabled = 1;
unsigned int lookupCacheEnabled = 1;
unsigned int multiuser_mount = 0;
......@@ -127,6 +126,7 @@ cifs_read_super(struct super_block *sb, void *data,
kfree(cifs_sb);
return rc;
}
cifs_sb->bdi.ra_pages = default_backing_dev_info.ra_pages;
#ifdef CONFIG_CIFS_DFS_UPCALL
/* copy mount params to sb for use in submounts */
......@@ -409,8 +409,8 @@ cifs_show_options(struct seq_file *s, struct vfsmount *m)
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MULTIUSER)
seq_printf(s, ",multiuser");
else if (tcon->ses->userName)
seq_printf(s, ",username=%s", tcon->ses->userName);
else if (tcon->ses->user_name)
seq_printf(s, ",username=%s", tcon->ses->user_name);
if (tcon->ses->domainName)
seq_printf(s, ",domain=%s", tcon->ses->domainName);
......
......@@ -37,10 +37,9 @@
#define MAX_TREE_SIZE (2 + MAX_SERVER_SIZE + 1 + MAX_SHARE_SIZE + 1)
#define MAX_SERVER_SIZE 15
#define MAX_SHARE_SIZE 64 /* used to be 20, this should still be enough */
#define MAX_USERNAME_SIZE 32 /* 32 is to allow for 15 char names + null
termination then *2 for unicode versions */
#define MAX_PASSWORD_SIZE 512 /* max for windows seems to be 256 wide chars */
#define MAX_SHARE_SIZE 80
#define MAX_USERNAME_SIZE 256 /* reasonable maximum for current servers */
#define MAX_PASSWORD_SIZE 512 /* max for windows seems to be 256 wide chars */
#define CIFS_MIN_RCV_POOL 4
......@@ -92,7 +91,8 @@ enum statusEnum {
CifsNew = 0,
CifsGood,
CifsExiting,
CifsNeedReconnect
CifsNeedReconnect,
CifsNeedNegotiate
};
enum securityEnum {
......@@ -274,7 +274,7 @@ struct cifsSesInfo {
int capabilities;
char serverName[SERVER_NAME_LEN_WITH_NULL * 2]; /* BB make bigger for
TCP names - will ipv6 and sctp addresses fit? */
char userName[MAX_USERNAME_SIZE + 1];
char *user_name;
char *domainName;
char *password;
struct session_key auth_key;
......@@ -817,7 +817,6 @@ GLOBAL_EXTERN unsigned int multiuser_mount; /* if enabled allows new sessions
have the uid/password or Kerberos credential
or equivalent for current user */
GLOBAL_EXTERN unsigned int oplockEnabled;
GLOBAL_EXTERN unsigned int experimEnabled;
GLOBAL_EXTERN unsigned int lookupCacheEnabled;
GLOBAL_EXTERN unsigned int global_secflags; /* if on, session setup sent
with more secure ntlmssp2 challenge/resp */
......
......@@ -142,9 +142,9 @@ cifs_reconnect_tcon(struct cifsTconInfo *tcon, int smb_command)
*/
while (server->tcpStatus == CifsNeedReconnect) {
wait_event_interruptible_timeout(server->response_q,
(server->tcpStatus == CifsGood), 10 * HZ);
(server->tcpStatus != CifsNeedReconnect), 10 * HZ);
/* is TCP session is reestablished now ?*/
/* are we still trying to reconnect? */
if (server->tcpStatus != CifsNeedReconnect)
break;
......@@ -729,7 +729,7 @@ CIFSSMBEcho(struct TCP_Server_Info *server)
return rc;
/* set up echo request */
smb->hdr.Tid = cpu_to_le16(0xffff);
smb->hdr.Tid = 0xffff;
smb->hdr.WordCount = 1;
put_unaligned_le16(1, &smb->EchoCount);
put_bcc_le(1, &smb->hdr);
......@@ -1884,10 +1884,10 @@ CIFSSMBPosixLock(const int xid, struct cifsTconInfo *tcon,
__constant_cpu_to_le16(CIFS_WRLCK))
pLockData->fl_type = F_WRLCK;
pLockData->fl_start = parm_data->start;
pLockData->fl_end = parm_data->start +
parm_data->length - 1;
pLockData->fl_pid = parm_data->pid;
pLockData->fl_start = le64_to_cpu(parm_data->start);
pLockData->fl_end = pLockData->fl_start +
le64_to_cpu(parm_data->length) - 1;
pLockData->fl_pid = le32_to_cpu(parm_data->pid);
}
}
......
......@@ -199,8 +199,7 @@ cifs_reconnect(struct TCP_Server_Info *server)
}
spin_unlock(&GlobalMid_Lock);
while ((server->tcpStatus != CifsExiting) &&
(server->tcpStatus != CifsGood)) {
while (server->tcpStatus == CifsNeedReconnect) {
try_to_freeze();
/* we should try only the port we connected to before */
......@@ -212,7 +211,7 @@ cifs_reconnect(struct TCP_Server_Info *server)
atomic_inc(&tcpSesReconnectCount);
spin_lock(&GlobalMid_Lock);
if (server->tcpStatus != CifsExiting)
server->tcpStatus = CifsGood;
server->tcpStatus = CifsNeedNegotiate;
spin_unlock(&GlobalMid_Lock);
}
}
......@@ -248,24 +247,24 @@ static int check2ndT2(struct smb_hdr *pSMB, unsigned int maxBufSize)
total_data_size = get_unaligned_le16(&pSMBt->t2_rsp.TotalDataCount);
data_in_this_rsp = get_unaligned_le16(&pSMBt->t2_rsp.DataCount);
remaining = total_data_size - data_in_this_rsp;
if (remaining == 0)
if (total_data_size == data_in_this_rsp)
return 0;
else if (remaining < 0) {
else if (total_data_size < data_in_this_rsp) {
cFYI(1, "total data %d smaller than data in frame %d",
total_data_size, data_in_this_rsp);
return -EINVAL;
} else {
cFYI(1, "missing %d bytes from transact2, check next response",
remaining);
if (total_data_size > maxBufSize) {
cERROR(1, "TotalDataSize %d is over maximum buffer %d",
total_data_size, maxBufSize);
return -EINVAL;
}
return remaining;
}
remaining = total_data_size - data_in_this_rsp;
cFYI(1, "missing %d bytes from transact2, check next response",
remaining);
if (total_data_size > maxBufSize) {
cERROR(1, "TotalDataSize %d is over maximum buffer %d",
total_data_size, maxBufSize);
return -EINVAL;
}
return remaining;
}
static int coalesce_t2(struct smb_hdr *psecond, struct smb_hdr *pTargetSMB)
......@@ -421,7 +420,7 @@ cifs_demultiplex_thread(struct TCP_Server_Info *server)
pdu_length = 4; /* enough to get RFC1001 header */
incomplete_rcv:
if (echo_retries > 0 &&
if (echo_retries > 0 && server->tcpStatus == CifsGood &&
time_after(jiffies, server->lstrp +
(echo_retries * SMB_ECHO_INTERVAL))) {
cERROR(1, "Server %s has not responded in %d seconds. "
......@@ -881,7 +880,8 @@ cifs_parse_mount_options(char *options, const char *devname,
/* null user, ie anonymous, authentication */
vol->nullauth = 1;
}
if (strnlen(value, 200) < 200) {
if (strnlen(value, MAX_USERNAME_SIZE) <
MAX_USERNAME_SIZE) {
vol->username = value;
} else {
printk(KERN_WARNING "CIFS: username too long\n");
......@@ -1472,7 +1472,7 @@ srcip_matches(struct sockaddr *srcaddr, struct sockaddr *rhs)
static bool
match_port(struct TCP_Server_Info *server, struct sockaddr *addr)
{
unsigned short int port, *sport;
__be16 port, *sport;
switch (addr->sa_family) {
case AF_INET:
......@@ -1765,6 +1765,7 @@ cifs_get_tcp_session(struct smb_vol *volume_info)
module_put(THIS_MODULE);
goto out_err_crypto_release;
}
tcp_ses->tcpStatus = CifsNeedNegotiate;
/* thread spawned, put it on the list */
spin_lock(&cifs_tcp_ses_lock);
......@@ -1808,7 +1809,9 @@ cifs_find_smb_ses(struct TCP_Server_Info *server, struct smb_vol *vol)
break;
default:
/* anything else takes username/password */
if (strncmp(ses->userName, vol->username,
if (ses->user_name == NULL)
continue;
if (strncmp(ses->user_name, vol->username,
MAX_USERNAME_SIZE))
continue;
if (strlen(vol->username) != 0 &&
......@@ -1851,6 +1854,8 @@ cifs_put_smb_ses(struct cifsSesInfo *ses)
cifs_put_tcp_session(server);
}
static bool warned_on_ntlm; /* globals init to false automatically */
static struct cifsSesInfo *
cifs_get_smb_ses(struct TCP_Server_Info *server, struct smb_vol *volume_info)
{
......@@ -1906,9 +1911,11 @@ cifs_get_smb_ses(struct TCP_Server_Info *server, struct smb_vol *volume_info)
else
sprintf(ses->serverName, "%pI4", &addr->sin_addr);
if (volume_info->username)
strncpy(ses->userName, volume_info->username,
MAX_USERNAME_SIZE);
if (volume_info->username) {
ses->user_name = kstrdup(volume_info->username, GFP_KERNEL);
if (!ses->user_name)
goto get_ses_fail;
}
/* volume_info->password freed at unmount */
if (volume_info->password) {
......@@ -1923,6 +1930,15 @@ cifs_get_smb_ses(struct TCP_Server_Info *server, struct smb_vol *volume_info)
}
ses->cred_uid = volume_info->cred_uid;
ses->linux_uid = volume_info->linux_uid;
/* ntlmv2 is much stronger than ntlm security, and has been broadly
supported for many years, time to update default security mechanism */
if ((volume_info->secFlg == 0) && warned_on_ntlm == false) {
warned_on_ntlm = true;
cERROR(1, "default security mechanism requested. The default "
"security mechanism will be upgraded from ntlm to "
"ntlmv2 in kernel release 2.6.41");
}
ses->overrideSecFlg = volume_info->secFlg;
mutex_lock(&ses->session_mutex);
......@@ -2276,7 +2292,7 @@ static int
generic_ip_connect(struct TCP_Server_Info *server)
{
int rc = 0;
unsigned short int sport;
__be16 sport;
int slen, sfamily;
struct socket *socket = server->ssocket;
struct sockaddr *saddr;
......@@ -2361,7 +2377,7 @@ generic_ip_connect(struct TCP_Server_Info *server)
static int
ip_connect(struct TCP_Server_Info *server)
{
unsigned short int *sport;
__be16 *sport;
struct sockaddr_in6 *addr6 = (struct sockaddr_in6 *)&server->dstaddr;
struct sockaddr_in *addr = (struct sockaddr_in *)&server->dstaddr;
......@@ -2826,7 +2842,7 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
remote_path_check:
/* check if a whole path (including prepath) is not remote */
if (!rc && cifs_sb->prepathlen && tcon) {
if (!rc && tcon) {
/* build_path_to_root works only when we have a valid tcon */
full_path = cifs_build_path_to_root(cifs_sb, tcon);
if (full_path == NULL) {
......
......@@ -575,8 +575,10 @@ static int cifs_reopen_file(struct cifsFileInfo *pCifsFile, bool can_flush)
int cifs_close(struct inode *inode, struct file *file)
{
cifsFileInfo_put(file->private_data);
file->private_data = NULL;
if (file->private_data != NULL) {
cifsFileInfo_put(file->private_data);
file->private_data = NULL;
}
/* return code from the ->release op is always ignored */
return 0;
......@@ -970,6 +972,9 @@ static ssize_t cifs_write(struct cifsFileInfo *open_file,
total_written += bytes_written) {
rc = -EAGAIN;
while (rc == -EAGAIN) {
struct kvec iov[2];
unsigned int len;
if (open_file->invalidHandle) {
/* we could deadlock if we called
filemap_fdatawait from here so tell
......@@ -979,31 +984,14 @@ static ssize_t cifs_write(struct cifsFileInfo *open_file,
if (rc != 0)
break;
}
if (experimEnabled || (pTcon->ses->server &&
((pTcon->ses->server->secMode &
(SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
== 0))) {
struct kvec iov[2];
unsigned int len;
len = min((size_t)cifs_sb->wsize,
write_size - total_written);
/* iov[0] is reserved for smb header */
iov[1].iov_base = (char *)write_data +
total_written;
iov[1].iov_len = len;
rc = CIFSSMBWrite2(xid, pTcon,
open_file->netfid, len,
*poffset, &bytes_written,
iov, 1, 0);
} else
rc = CIFSSMBWrite(xid, pTcon,
open_file->netfid,
min_t(const int, cifs_sb->wsize,
write_size - total_written),
*poffset, &bytes_written,
write_data + total_written,
NULL, 0);
len = min((size_t)cifs_sb->wsize,
write_size - total_written);
/* iov[0] is reserved for smb header */
iov[1].iov_base = (char *)write_data + total_written;
iov[1].iov_len = len;
rc = CIFSSMBWrite2(xid, pTcon, open_file->netfid, len,
*poffset, &bytes_written, iov, 1, 0);
}
if (rc || (bytes_written == 0)) {
if (total_written)
......@@ -1240,12 +1228,6 @@ static int cifs_writepages(struct address_space *mapping,
}
tcon = tlink_tcon(open_file->tlink);
if (!experimEnabled && tcon->ses->server->secMode &
(SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED)) {
cifsFileInfo_put(open_file);
kfree(iov);
return generic_writepages(mapping, wbc);
}
cifsFileInfo_put(open_file);
xid = GetXid();
......@@ -1980,6 +1962,24 @@ static ssize_t cifs_read(struct file *file, char *read_data, size_t read_size,
return total_read;
}
/*
* If the page is mmap'ed into a process' page tables, then we need to make
* sure that it doesn't change while being written back.
*/
static int
cifs_page_mkwrite(struct vm_area_struct *vma, struct vm_fault *vmf)
{
struct page *page = vmf->page;
lock_page(page);
return VM_FAULT_LOCKED;
}
static struct vm_operations_struct cifs_file_vm_ops = {
.fault = filemap_fault,
.page_mkwrite = cifs_page_mkwrite,
};
int cifs_file_strict_mmap(struct file *file, struct vm_area_struct *vma)
{
int rc, xid;
......@@ -1991,6 +1991,8 @@ int cifs_file_strict_mmap(struct file *file, struct vm_area_struct *vma)
cifs_invalidate_mapping(inode);
rc = generic_file_mmap(file, vma);
if (rc == 0)
vma->vm_ops = &cifs_file_vm_ops;
FreeXid(xid);
return rc;
}
......@@ -2007,6 +2009,8 @@ int cifs_file_mmap(struct file *file, struct vm_area_struct *vma)
return rc;
}
rc = generic_file_mmap(file, vma);
if (rc == 0)
vma->vm_ops = &cifs_file_vm_ops;
FreeXid(xid);
return rc;
}
......
......@@ -239,7 +239,7 @@ CIFSQueryMFSymLink(const int xid, struct cifsTconInfo *tcon,
if (rc != 0)
return rc;
if (file_info.EndOfFile != CIFS_MF_SYMLINK_FILE_SIZE) {
if (file_info.EndOfFile != cpu_to_le64(CIFS_MF_SYMLINK_FILE_SIZE)) {
CIFSSMBClose(xid, tcon, netfid);
/* it's not a symlink */
return -EINVAL;
......@@ -316,7 +316,7 @@ CIFSCheckMFSymlink(struct cifs_fattr *fattr,
if (rc != 0)
goto out;
if (file_info.EndOfFile != CIFS_MF_SYMLINK_FILE_SIZE) {
if (file_info.EndOfFile != cpu_to_le64(CIFS_MF_SYMLINK_FILE_SIZE)) {
CIFSSMBClose(xid, pTcon, netfid);
/* it's not a symlink */
goto out;
......
......@@ -100,6 +100,7 @@ sesInfoFree(struct cifsSesInfo *buf_to_free)
memset(buf_to_free->password, 0, strlen(buf_to_free->password));
kfree(buf_to_free->password);
}
kfree(buf_to_free->user_name);
kfree(buf_to_free->domainName);
kfree(buf_to_free);
}
......@@ -520,7 +521,7 @@ is_valid_oplock_break(struct smb_hdr *buf, struct TCP_Server_Info *srv)
(struct smb_com_transaction_change_notify_rsp *)buf;
struct file_notify_information *pnotify;
__u32 data_offset = 0;
if (pSMBr->ByteCount > sizeof(struct file_notify_information)) {
if (get_bcc_le(buf) > sizeof(struct file_notify_information)) {
data_offset = le32_to_cpu(pSMBr->DataOffset);
pnotify = (struct file_notify_information *)
......
......@@ -219,12 +219,12 @@ static void unicode_ssetup_strings(char **pbcc_area, struct cifsSesInfo *ses,
bcc_ptr++;
} */
/* copy user */
if (ses->userName == NULL) {
if (ses->user_name == NULL) {
/* null user mount */
*bcc_ptr = 0;
*(bcc_ptr+1) = 0;
} else {
bytes_ret = cifs_strtoUCS((__le16 *) bcc_ptr, ses->userName,
bytes_ret = cifs_strtoUCS((__le16 *) bcc_ptr, ses->user_name,
MAX_USERNAME_SIZE, nls_cp);
}
bcc_ptr += 2 * bytes_ret;
......@@ -244,12 +244,11 @@ static void ascii_ssetup_strings(char **pbcc_area, struct cifsSesInfo *ses,
/* copy user */
/* BB what about null user mounts - check that we do this BB */
/* copy user */
if (ses->userName == NULL) {
/* BB what about null user mounts - check that we do this BB */
} else {
strncpy(bcc_ptr, ses->userName, MAX_USERNAME_SIZE);
}
bcc_ptr += strnlen(ses->userName, MAX_USERNAME_SIZE);
if (ses->user_name != NULL)
strncpy(bcc_ptr, ses->user_name, MAX_USERNAME_SIZE);
/* else null user mount */
bcc_ptr += strnlen(ses->user_name, MAX_USERNAME_SIZE);
*bcc_ptr = 0;
bcc_ptr++; /* account for null termination */
......@@ -405,8 +404,8 @@ static int decode_ntlmssp_challenge(char *bcc_ptr, int blob_len,
/* BB spec says that if AvId field of MsvAvTimestamp is populated then
we must set the MIC field of the AUTHENTICATE_MESSAGE */
ses->ntlmssp->server_flags = le32_to_cpu(pblob->NegotiateFlags);
tioffset = cpu_to_le16(pblob->TargetInfoArray.BufferOffset);
tilen = cpu_to_le16(pblob->TargetInfoArray.Length);
tioffset = le32_to_cpu(pblob->TargetInfoArray.BufferOffset);
tilen = le16_to_cpu(pblob->TargetInfoArray.Length);
if (tilen) {
ses->auth_key.response = kmalloc(tilen, GFP_KERNEL);
if (!ses->auth_key.response) {
......@@ -523,14 +522,14 @@ static int build_ntlmssp_auth_blob(unsigned char *pbuffer,
tmp += len;
}
if (ses->userName == NULL) {
if (ses->user_name == NULL) {
sec_blob->UserName.BufferOffset = cpu_to_le32(tmp - pbuffer);
sec_blob->UserName.Length = 0;
sec_blob->UserName.MaximumLength = 0;
tmp += 2;
} else {
int len;
len = cifs_strtoUCS((__le16 *)tmp, ses->userName,
len = cifs_strtoUCS((__le16 *)tmp, ses->user_name,
MAX_USERNAME_SIZE, nls_cp);
len *= 2; /* unicode is 2 bytes each */
sec_blob->UserName.BufferOffset = cpu_to_le32(tmp - pbuffer);
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册