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
This commit is contained in:
commit
6faf9a5415
15 changed files with 142 additions and 180 deletions
|
@ -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);
|
||||
|
|
Loading…
Reference in a new issue