Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
E
etercifs
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
etersoft
etercifs
Commits
0688d963
Commit
0688d963
authored
Jan 30, 2018
by
Vitaly Lipatov
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
update 4.4 up to v4.4.113
parent
ac75de6b
Hide whitespace changes
Inline
Side-by-side
Showing
30 changed files
with
758 additions
and
239 deletions
+758
-239
cifs_debug.c
sources/4.4/cifs_debug.c
+15
-42
cifs_debug.h
sources/4.4/cifs_debug.h
+1
-1
cifs_fs_sb.h
sources/4.4/cifs_fs_sb.h
+4
-0
cifs_unicode.c
sources/4.4/cifs_unicode.c
+35
-4
cifs_unicode.h
sources/4.4/cifs_unicode.h
+3
-0
cifsencrypt.c
sources/4.4/cifsencrypt.c
+10
-6
cifsfs.c
sources/4.4/cifsfs.c
+17
-6
cifsglob.h
sources/4.4/cifsglob.h
+33
-18
cifsproto.h
sources/4.4/cifsproto.h
+3
-0
cifssmb.c
sources/4.4/cifssmb.c
+16
-2
connect.c
sources/4.4/connect.c
+125
-16
dir.c
sources/4.4/dir.c
+52
-11
file.c
sources/4.4/file.c
+49
-30
inode.c
sources/4.4/inode.c
+20
-2
ioctl.c
sources/4.4/ioctl.c
+2
-0
misc.c
sources/4.4/misc.c
+8
-7
ntlmssp.h
sources/4.4/ntlmssp.h
+1
-1
readdir.c
sources/4.4/readdir.c
+4
-3
sess.c
sources/4.4/sess.c
+42
-34
smb1ops.c
sources/4.4/smb1ops.c
+17
-2
smb2file.c
sources/4.4/smb2file.c
+1
-1
smb2glob.h
sources/4.4/smb2glob.h
+10
-0
smb2inode.c
sources/4.4/smb2inode.c
+6
-0
smb2misc.c
sources/4.4/smb2misc.c
+52
-8
smb2ops.c
sources/4.4/smb2ops.c
+57
-9
smb2pdu.c
sources/4.4/smb2pdu.c
+110
-27
smb2pdu.h
sources/4.4/smb2pdu.h
+3
-3
smb2proto.h
sources/4.4/smb2proto.h
+8
-0
smb2transport.c
sources/4.4/smb2transport.c
+52
-6
transport.c
sources/4.4/transport.c
+2
-0
No files found.
sources/4.4/cifs_debug.c
View file @
0688d963
...
...
@@ -152,6 +152,7 @@ static int cifs_debug_data_proc_show(struct seq_file *m, void *v)
list_for_each
(
tmp1
,
&
cifs_tcp_ses_list
)
{
server
=
list_entry
(
tmp1
,
struct
TCP_Server_Info
,
tcp_ses_list
);
seq_printf
(
m
,
"
\n
Number of credits: %d"
,
server
->
credits
);
i
++
;
list_for_each
(
tmp2
,
&
server
->
smb_ses_list
)
{
ses
=
list_entry
(
tmp2
,
struct
cifs_ses
,
...
...
@@ -255,7 +256,6 @@ static const struct file_operations cifs_debug_data_proc_fops = {
static
ssize_t
cifs_stats_proc_write
(
struct
file
*
file
,
const
char
__user
*
buffer
,
size_t
count
,
loff_t
*
ppos
)
{
char
c
;
bool
bv
;
int
rc
;
struct
list_head
*
tmp1
,
*
tmp2
,
*
tmp3
;
...
...
@@ -263,11 +263,8 @@ static ssize_t cifs_stats_proc_write(struct file *file,
struct
cifs_ses
*
ses
;
struct
cifs_tcon
*
tcon
;
rc
=
get_user
(
c
,
buffer
);
if
(
rc
)
return
rc
;
if
(
strtobool
(
&
c
,
&
bv
)
==
0
)
{
rc
=
kstrtobool_from_user
(
buffer
,
count
,
&
bv
);
if
(
rc
==
0
)
{
#ifdef CONFIG_CIFS_STATS2
atomic_set
(
&
totBufAllocCount
,
0
);
atomic_set
(
&
totSmBufAllocCount
,
0
);
...
...
@@ -290,6 +287,8 @@ static ssize_t cifs_stats_proc_write(struct file *file,
}
}
spin_unlock
(
&
cifs_tcp_ses_lock
);
}
else
{
return
rc
;
}
return
count
;
...
...
@@ -433,17 +432,17 @@ static int cifsFYI_proc_open(struct inode *inode, struct file *file)
static
ssize_t
cifsFYI_proc_write
(
struct
file
*
file
,
const
char
__user
*
buffer
,
size_t
count
,
loff_t
*
ppos
)
{
char
c
;
char
c
[
2
]
=
{
'\0'
}
;
bool
bv
;
int
rc
;
rc
=
get_user
(
c
,
buffer
);
rc
=
get_user
(
c
[
0
]
,
buffer
);
if
(
rc
)
return
rc
;
if
(
strtobool
(
&
c
,
&
bv
)
==
0
)
if
(
strtobool
(
c
,
&
bv
)
==
0
)
cifsFYI
=
bv
;
else
if
((
c
>
'1'
)
&&
(
c
<=
'9'
))
cifsFYI
=
(
int
)
(
c
-
'0'
);
/* see cifs_debug.h for meanings */
else
if
((
c
[
0
]
>
'1'
)
&&
(
c
[
0
]
<=
'9'
))
cifsFYI
=
(
int
)
(
c
[
0
]
-
'0'
);
/* see cifs_debug.h for meanings */
return
count
;
}
...
...
@@ -471,20 +470,12 @@ static int cifs_linux_ext_proc_open(struct inode *inode, struct file *file)
static
ssize_t
cifs_linux_ext_proc_write
(
struct
file
*
file
,
const
char
__user
*
buffer
,
size_t
count
,
loff_t
*
ppos
)
{
char
c
;
bool
bv
;
int
rc
;
rc
=
get_user
(
c
,
buffer
);
rc
=
kstrtobool_from_user
(
buffer
,
count
,
&
linuxExtEnabled
);
if
(
rc
)
return
rc
;
rc
=
strtobool
(
&
c
,
&
bv
);
if
(
rc
)
return
rc
;
linuxExtEnabled
=
bv
;
return
count
;
}
...
...
@@ -511,20 +502,12 @@ static int cifs_lookup_cache_proc_open(struct inode *inode, struct file *file)
static
ssize_t
cifs_lookup_cache_proc_write
(
struct
file
*
file
,
const
char
__user
*
buffer
,
size_t
count
,
loff_t
*
ppos
)
{
char
c
;
bool
bv
;
int
rc
;
rc
=
get_user
(
c
,
buffer
);
rc
=
kstrtobool_from_user
(
buffer
,
count
,
&
lookupCacheEnabled
);
if
(
rc
)
return
rc
;
rc
=
strtobool
(
&
c
,
&
bv
);
if
(
rc
)
return
rc
;
lookupCacheEnabled
=
bv
;
return
count
;
}
...
...
@@ -551,20 +534,12 @@ static int traceSMB_proc_open(struct inode *inode, struct file *file)
static
ssize_t
traceSMB_proc_write
(
struct
file
*
file
,
const
char
__user
*
buffer
,
size_t
count
,
loff_t
*
ppos
)
{
char
c
;
bool
bv
;
int
rc
;
rc
=
get_user
(
c
,
buffer
);
rc
=
kstrtobool_from_user
(
buffer
,
count
,
&
traceSMB
);
if
(
rc
)
return
rc
;
rc
=
strtobool
(
&
c
,
&
bv
);
if
(
rc
)
return
rc
;
traceSMB
=
bv
;
return
count
;
}
...
...
@@ -622,7 +597,6 @@ static ssize_t cifs_security_flags_proc_write(struct file *file,
int
rc
;
unsigned
int
flags
;
char
flags_string
[
12
];
char
c
;
bool
bv
;
if
((
count
<
1
)
||
(
count
>
11
))
...
...
@@ -635,11 +609,10 @@ static ssize_t cifs_security_flags_proc_write(struct file *file,
if
(
count
<
3
)
{
/* single char or single char followed by null */
c
=
flags_string
[
0
];
if
(
strtobool
(
&
c
,
&
bv
)
==
0
)
{
if
(
strtobool
(
flags_string
,
&
bv
)
==
0
)
{
global_secflags
=
bv
?
CIFSSEC_MAX
:
CIFSSEC_DEF
;
return
count
;
}
else
if
(
!
isdigit
(
c
))
{
}
else
if
(
!
isdigit
(
flags_string
[
0
]
))
{
cifs_dbg
(
VFS
,
"Invalid SecurityFlags: %s
\n
"
,
flags_string
);
return
-
EINVAL
;
...
...
sources/4.4/cifs_debug.h
View file @
0688d963
...
...
@@ -25,7 +25,7 @@
void
cifs_dump_mem
(
char
*
label
,
void
*
data
,
int
length
);
void
cifs_dump_detail
(
void
*
);
void
cifs_dump_mids
(
struct
TCP_Server_Info
*
);
extern
int
traceSMB
;
/* flag which enables the function below */
extern
bool
traceSMB
;
/* flag which enables the function below */
void
dump_smb
(
void
*
,
int
);
#define CIFS_INFO 0x01
#define CIFS_RC 0x02
...
...
sources/4.4/cifs_fs_sb.h
View file @
0688d963
...
...
@@ -46,6 +46,9 @@
#define CIFS_MOUNT_CIFS_BACKUPUID 0x200000
/* backup intent bit for a user */
#define CIFS_MOUNT_CIFS_BACKUPGID 0x400000
/* backup intent bit for a group */
#define CIFS_MOUNT_MAP_SFM_CHR 0x800000
/* SFM/MAC mapping for illegal chars */
#define CIFS_MOUNT_USE_PREFIX_PATH 0x1000000
/* make subpath with unaccessible
* root mountable
*/
struct
cifs_sb_info
{
struct
rb_root
tlink_tree
;
...
...
@@ -67,5 +70,6 @@ struct cifs_sb_info {
struct
backing_dev_info
bdi
;
struct
delayed_work
prune_tlinks
;
struct
rcu_head
rcu
;
char
*
prepath
;
};
#endif
/* _CIFS_FS_SB_H */
sources/4.4/cifs_unicode.c
View file @
0688d963
...
...
@@ -83,6 +83,9 @@ convert_sfm_char(const __u16 src_char, char *target)
case
SFM_COLON
:
*
target
=
':'
;
break
;
case
SFM_DOUBLEQUOTE
:
*
target
=
'"'
;
break
;
case
SFM_ASTERISK
:
*
target
=
'*'
;
break
;
...
...
@@ -101,6 +104,12 @@ convert_sfm_char(const __u16 src_char, char *target)
case
SFM_SLASH
:
*
target
=
'\\'
;
break
;
case
SFM_SPACE
:
*
target
=
' '
;
break
;
case
SFM_PERIOD
:
*
target
=
'.'
;
break
;
default:
return
false
;
}
...
...
@@ -404,7 +413,7 @@ static __le16 convert_to_sfu_char(char src_char)
return
dest_char
;
}
static
__le16
convert_to_sfm_char
(
char
src_char
)
static
__le16
convert_to_sfm_char
(
char
src_char
,
bool
end_of_string
)
{
__le16
dest_char
;
...
...
@@ -412,6 +421,9 @@ static __le16 convert_to_sfm_char(char src_char)
case
':'
:
dest_char
=
cpu_to_le16
(
SFM_COLON
);
break
;
case
'"'
:
dest_char
=
cpu_to_le16
(
SFM_DOUBLEQUOTE
);
break
;
case
'*'
:
dest_char
=
cpu_to_le16
(
SFM_ASTERISK
);
break
;
...
...
@@ -427,6 +439,18 @@ static __le16 convert_to_sfm_char(char src_char)
case
'|'
:
dest_char
=
cpu_to_le16
(
SFM_PIPE
);
break
;
case
'.'
:
if
(
end_of_string
)
dest_char
=
cpu_to_le16
(
SFM_PERIOD
);
else
dest_char
=
0
;
break
;
case
' '
:
if
(
end_of_string
)
dest_char
=
cpu_to_le16
(
SFM_SPACE
);
else
dest_char
=
0
;
break
;
default:
dest_char
=
0
;
}
...
...
@@ -469,9 +493,16 @@ cifsConvertToUTF16(__le16 *target, const char *source, int srclen,
/* see if we must remap this char */
if
(
map_chars
==
SFU_MAP_UNI_RSVD
)
dst_char
=
convert_to_sfu_char
(
src_char
);
else
if
(
map_chars
==
SFM_MAP_UNI_RSVD
)
dst_char
=
convert_to_sfm_char
(
src_char
);
else
else
if
(
map_chars
==
SFM_MAP_UNI_RSVD
)
{
bool
end_of_string
;
if
(
i
==
srclen
-
1
)
end_of_string
=
true
;
else
end_of_string
=
false
;
dst_char
=
convert_to_sfm_char
(
src_char
,
end_of_string
);
}
else
dst_char
=
0
;
/*
* FIXME: We can not handle remapping backslash (UNI_SLASH)
...
...
sources/4.4/cifs_unicode.h
View file @
0688d963
...
...
@@ -57,6 +57,7 @@
* not conflict (although almost does) with the mapping above.
*/
#define SFM_DOUBLEQUOTE ((__u16) 0xF020)
#define SFM_ASTERISK ((__u16) 0xF021)
#define SFM_QUESTION ((__u16) 0xF025)
#define SFM_COLON ((__u16) 0xF022)
...
...
@@ -64,6 +65,8 @@
#define SFM_LESSTHAN ((__u16) 0xF023)
#define SFM_PIPE ((__u16) 0xF027)
#define SFM_SLASH ((__u16) 0xF026)
#define SFM_SPACE ((__u16) 0xF028)
#define SFM_PERIOD ((__u16) 0xF029)
/*
* Mapping mechanism to use when one of the seven reserved characters is
...
...
sources/4.4/cifsencrypt.c
View file @
0688d963
...
...
@@ -731,24 +731,26 @@ setup_ntlmv2_rsp(struct cifs_ses *ses, const struct nls_table *nls_cp)
memcpy
(
ses
->
auth_key
.
response
+
baselen
,
tiblob
,
tilen
);
mutex_lock
(
&
ses
->
server
->
srv_mutex
);
rc
=
crypto_hmacmd5_alloc
(
ses
->
server
);
if
(
rc
)
{
cifs_dbg
(
VFS
,
"could not crypto alloc hmacmd5 rc %d
\n
"
,
rc
);
goto
setup_ntlmv2_rsp_ret
;
goto
unlock
;
}
/* calculate ntlmv2_hash */
rc
=
calc_ntlmv2_hash
(
ses
,
ntlmv2_hash
,
nls_cp
);
if
(
rc
)
{
cifs_dbg
(
VFS
,
"could not get v2 hash rc %d
\n
"
,
rc
);
goto
setup_ntlmv2_rsp_ret
;
goto
unlock
;
}
/* calculate first part of the client response (CR1) */
rc
=
CalcNTLMv2_response
(
ses
,
ntlmv2_hash
);
if
(
rc
)
{
cifs_dbg
(
VFS
,
"Could not calculate CR1 rc: %d
\n
"
,
rc
);
goto
setup_ntlmv2_rsp_ret
;
goto
unlock
;
}
/* now calculate the session key for NTLMv2 */
...
...
@@ -757,13 +759,13 @@ setup_ntlmv2_rsp(struct cifs_ses *ses, const struct nls_table *nls_cp)
if
(
rc
)
{
cifs_dbg
(
VFS
,
"%s: Could not set NTLMV2 Hash as a key
\n
"
,
__func__
);
goto
setup_ntlmv2_rsp_ret
;
goto
unlock
;
}
rc
=
crypto_shash_init
(
&
ses
->
server
->
secmech
.
sdeschmacmd5
->
shash
);
if
(
rc
)
{
cifs_dbg
(
VFS
,
"%s: Could not init hmacmd5
\n
"
,
__func__
);
goto
setup_ntlmv2_rsp_ret
;
goto
unlock
;
}
rc
=
crypto_shash_update
(
&
ses
->
server
->
secmech
.
sdeschmacmd5
->
shash
,
...
...
@@ -771,7 +773,7 @@ setup_ntlmv2_rsp(struct cifs_ses *ses, const struct nls_table *nls_cp)
CIFS_HMAC_MD5_HASH_SIZE
);
if
(
rc
)
{
cifs_dbg
(
VFS
,
"%s: Could not update with response
\n
"
,
__func__
);
goto
setup_ntlmv2_rsp_ret
;
goto
unlock
;
}
rc
=
crypto_shash_final
(
&
ses
->
server
->
secmech
.
sdeschmacmd5
->
shash
,
...
...
@@ -779,6 +781,8 @@ setup_ntlmv2_rsp(struct cifs_ses *ses, const struct nls_table *nls_cp)
if
(
rc
)
cifs_dbg
(
VFS
,
"%s: Could not generate md5 hash
\n
"
,
__func__
);
unlock:
mutex_unlock
(
&
ses
->
server
->
srv_mutex
);
setup_ntlmv2_rsp_ret:
kfree
(
tiblob
);
...
...
sources/4.4/cifsfs.c
View file @
0688d963
...
...
@@ -54,10 +54,10 @@
#endif
int
cifsFYI
=
0
;
int
traceSMB
=
0
;
bool
traceSMB
;
bool
enable_oplocks
=
true
;
unsigned
int
linuxExtEnabled
=
1
;
unsigned
int
lookupCacheEnabled
=
1
;
bool
linuxExtEnabled
=
true
;
bool
lookupCacheEnabled
=
true
;
unsigned
int
global_secflags
=
CIFSSEC_DEF
;
/* unsigned int ntlmv2_support = 0; */
unsigned
int
sign_CIFS_PDUs
=
1
;
...
...
@@ -268,7 +268,7 @@ cifs_alloc_inode(struct super_block *sb)
cifs_inode
->
createtime
=
0
;
cifs_inode
->
epoch
=
0
;
#ifdef CONFIG_CIFS_SMB2
ge
t_random_bytes
(
cifs_inode
->
lease_key
,
SMB2_LEASE_KEY_SIZE
);
ge
nerate_random_uuid
(
cifs_inode
->
lease_key
);
#endif
/*
* Can not set i_flags here - they get immediately overwritten to zero
...
...
@@ -689,6 +689,14 @@ cifs_do_mount(struct file_system_type *fs_type,
goto
out_cifs_sb
;
}
if
(
volume_info
->
prepath
)
{
cifs_sb
->
prepath
=
kstrdup
(
volume_info
->
prepath
,
GFP_KERNEL
);
if
(
cifs_sb
->
prepath
==
NULL
)
{
root
=
ERR_PTR
(
-
ENOMEM
);
goto
out_cifs_sb
;
}
}
cifs_setup_cifs_sb
(
volume_info
,
cifs_sb
);
rc
=
cifs_mount
(
cifs_sb
,
volume_info
);
...
...
@@ -727,7 +735,11 @@ cifs_do_mount(struct file_system_type *fs_type,
sb
->
s_flags
|=
MS_ACTIVE
;
}
root
=
cifs_get_root
(
volume_info
,
sb
);
if
(
cifs_sb
->
mnt_cifs_flags
&
CIFS_MOUNT_USE_PREFIX_PATH
)
root
=
dget
(
sb
->
s_root
);
else
root
=
cifs_get_root
(
volume_info
,
sb
);
if
(
IS_ERR
(
root
))
goto
out_super
;
...
...
@@ -1201,7 +1213,6 @@ init_cifs(void)
GlobalTotalActiveXid
=
0
;
GlobalMaxActiveXid
=
0
;
spin_lock_init
(
&
cifs_tcp_ses_lock
);
spin_lock_init
(
&
cifs_file_list_lock
);
spin_lock_init
(
&
GlobalMid_Lock
);
if
(
cifs_max_pending
<
2
)
{
...
...
sources/4.4/cifsglob.h
View file @
0688d963
...
...
@@ -227,6 +227,7 @@ struct smb_version_operations {
/* verify the message */
int
(
*
check_message
)(
char
*
,
unsigned
int
);
bool
(
*
is_oplock_break
)(
char
*
,
struct
TCP_Server_Info
*
);
int
(
*
handle_cancelled_mid
)(
char
*
,
struct
TCP_Server_Info
*
);
void
(
*
downgrade_oplock
)(
struct
TCP_Server_Info
*
,
struct
cifsInodeInfo
*
,
bool
);
/* process transaction2 response */
...
...
@@ -350,6 +351,8 @@ struct smb_version_operations {
unsigned
int
(
*
calc_smb_size
)(
void
*
);
/* check for STATUS_PENDING and process it in a positive case */
bool
(
*
is_status_pending
)(
char
*
,
struct
TCP_Server_Info
*
,
int
);
/* check for STATUS_NETWORK_SESSION_EXPIRED */
bool
(
*
is_session_expired
)(
char
*
);
/* send oplock break response */
int
(
*
oplock_response
)(
struct
cifs_tcon
*
,
struct
cifs_fid
*
,
struct
cifsInodeInfo
*
);
...
...
@@ -627,6 +630,8 @@ struct TCP_Server_Info {
#ifdef CONFIG_CIFS_SMB2
unsigned
int
max_read
;
unsigned
int
max_write
;
struct
delayed_work
reconnect
;
/* reconnect workqueue job */
struct
mutex
reconnect_mutex
;
/* prevent simultaneous reconnects */
#endif
/* CONFIG_CIFS_SMB2 */
};
...
...
@@ -826,7 +831,9 @@ cap_unix(struct cifs_ses *ses)
struct
cifs_tcon
{
struct
list_head
tcon_list
;
int
tc_count
;
struct
list_head
rlist
;
/* reconnect list */
struct
list_head
openFileList
;
spinlock_t
open_file_lock
;
/* protects list above */
struct
cifs_ses
*
ses
;
/* pointer to session associated with */
char
treeName
[
MAX_TREE_SIZE
+
1
];
/* UNC name of resource in ASCII */
char
*
nativeFileSystem
;
...
...
@@ -883,7 +890,7 @@ struct cifs_tcon {
#endif
/* CONFIG_CIFS_STATS2 */
__u64
bytes_read
;
__u64
bytes_written
;
spinlock_t
stat_lock
;
spinlock_t
stat_lock
;
/* protects the two fields above */
#endif
/* CONFIG_CIFS_STATS */
FILE_SYSTEM_DEVICE_INFO
fsDevInfo
;
FILE_SYSTEM_ATTRIBUTE_INFO
fsAttrInfo
;
/* ok if fs name truncated */
...
...
@@ -902,7 +909,6 @@ struct cifs_tcon {
bool
use_persistent
:
1
;
/* use persistent instead of durable handles */
#ifdef CONFIG_CIFS_SMB2
bool
print
:
1
;
/* set if connection to printer share */
bool
bad_network_name
:
1
;
/* set if ret status STATUS_BAD_NETWORK_NAME */
__le32
capabilities
;
__u32
share_flags
;
__u32
maximal_access
;
...
...
@@ -1035,8 +1041,10 @@ struct cifs_fid_locks {
};
struct
cifsFileInfo
{
/* following two lists are protected by tcon->open_file_lock */
struct
list_head
tlist
;
/* pointer to next fid owned by tcon */
struct
list_head
flist
;
/* next fid (file instance) for this inode */
/* lock list below protected by cifsi->lock_sem */
struct
cifs_fid_locks
*
llist
;
/* brlocks held by this fid */
kuid_t
uid
;
/* allows finding which FileInfo structure */
__u32
pid
;
/* process id who opened file */
...
...
@@ -1044,11 +1052,12 @@ struct cifsFileInfo {
/* BB add lock scope info here if needed */
;
/* lock scope id (0 if none) */
struct
dentry
*
dentry
;
unsigned
int
f_flags
;
struct
tcon_link
*
tlink
;
unsigned
int
f_flags
;
bool
invalidHandle
:
1
;
/* file closed via session abend */
bool
oplock_break_cancelled
:
1
;
int
count
;
/* refcount protected by cifs_file_list_lock */
int
count
;
spinlock_t
file_info_lock
;
/* protects four flag/count fields above */
struct
mutex
fh_mutex
;
/* prevents reopen race after dead ses*/
struct
cifs_search_info
srch_inf
;
struct
work_struct
oplock_break
;
/* work for oplock breaks */
...
...
@@ -1122,7 +1131,7 @@ struct cifs_writedata {
/*
* Take a reference on the file private data. Must be called with
* c
ifs_file_list
_lock held.
* c
file->file_info
_lock held.
*/
static
inline
void
cifsFileInfo_get_locked
(
struct
cifsFileInfo
*
cifs_file
)
...
...
@@ -1291,12 +1300,19 @@ struct mid_q_entry {
void
*
callback_data
;
/* general purpose pointer for callback */
void
*
resp_buf
;
/* pointer to received SMB header */
int
mid_state
;
/* wish this were enum but can not pass to wait_event */
unsigned
int
mid_flags
;
__le16
command
;
/* smb command code */
bool
large_buf
:
1
;
/* if valid response, is pointer to large buf */
bool
multiRsp
:
1
;
/* multiple trans2 responses for one request */
bool
multiEnd
:
1
;
/* both received */
};
struct
close_cancelled_open
{
struct
cifs_fid
fid
;
struct
cifs_tcon
*
tcon
;
struct
work_struct
work
;
};
/* Make code in transport.c a little cleaner by moving
update of optional stats into function below */
#ifdef CONFIG_CIFS_STATS2
...
...
@@ -1428,6 +1444,9 @@ static inline void free_dfs_info_array(struct dfs_info3_param *param,
#define MID_RESPONSE_MALFORMED 0x10
#define MID_SHUTDOWN 0x20
/* Flags */
#define MID_WAIT_CANCELLED 1
/* Cancelled while waiting for response */
/* Types of response buffer returned from SendReceive2 */
#define CIFS_NO_BUFFER 0
/* Response buffer not returned */
#define CIFS_SMALL_BUFFER 1
...
...
@@ -1516,8 +1535,10 @@ require use of the stronger protocol */
* GlobalMid_Lock protects:
* list operations on pending_mid_q and oplockQ
* updates to XID counters, multiplex id and SMB sequence numbers
* cifs_file_list_lock protects:
* list operations on tcp and SMB session lists and tCon lists
* tcp_ses_lock protects:
* list operations on tcp and SMB session lists
* tcon->open_file_lock protects the list of open files hanging off the tcon
* cfile->file_info_lock protects counters and fields in cifs file struct
* f_owner.lock protects certain per file struct operations
* mapping->page_lock protects certain per page operations
*
...
...
@@ -1549,18 +1570,12 @@ GLOBAL_EXTERN struct list_head cifs_tcp_ses_list;
* tcp session, and the list of tcon's per smb session. It also protects
* the reference counters for the server, smb session, and tcon. Finally,
* changes to the tcon->tidStatus should be done while holding this lock.
* generally the locks should be taken in order tcp_ses_lock before
* tcon->open_file_lock and that before file->file_info_lock since the
* structure order is cifs_socket-->cifs_ses-->cifs_tcon-->cifs_file
*/
GLOBAL_EXTERN
spinlock_t
cifs_tcp_ses_lock
;
/*
* This lock protects the cifs_file->llist and cifs_file->flist
* list operations, and updates to some flags (cifs_file->invalidHandle)
* It will be moved to either use the tcon->stat_lock or equivalent later.
* If cifs_tcp_ses_lock and the lock below are both needed to be held, then
* the cifs_tcp_ses_lock must be grabbed first and released last.
*/
GLOBAL_EXTERN
spinlock_t
cifs_file_list_lock
;
#ifdef CONFIG_CIFS_DNOTIFY_EXPERIMENTAL
/* unused temporarily */
/* Outstanding dir notify requests */
GLOBAL_EXTERN
struct
list_head
GlobalDnotifyReqList
;
...
...
@@ -1596,11 +1611,11 @@ GLOBAL_EXTERN atomic_t midCount;
/* Misc globals */
GLOBAL_EXTERN
bool
enable_oplocks
;
/* enable or disable oplocks */
GLOBAL_EXTERN
unsigned
int
lookupCacheEnabled
;
GLOBAL_EXTERN
bool
lookupCacheEnabled
;
GLOBAL_EXTERN
unsigned
int
global_secflags
;
/* if on, session setup sent
with more secure ntlmssp2 challenge/resp */
GLOBAL_EXTERN
unsigned
int
sign_CIFS_PDUs
;
/* enable smb packet signing */
GLOBAL_EXTERN
unsigned
int
linuxExtEnabled
;
/*enable Linux/Unix CIFS extensions*/
GLOBAL_EXTERN
bool
linuxExtEnabled
;
/*enable Linux/Unix CIFS extensions*/
GLOBAL_EXTERN
unsigned
int
CIFSMaxBufSize
;
/* max size not including hdr */
GLOBAL_EXTERN
unsigned
int
cifs_min_rcv
;
/* min size of big ntwrk buf pool */
GLOBAL_EXTERN
unsigned
int
cifs_min_small
;
/* min size of small buf pool */
...
...
sources/4.4/cifsproto.h
View file @
0688d963
...
...
@@ -205,6 +205,9 @@ extern void cifs_add_pending_open_locked(struct cifs_fid *fid,
struct
tcon_link
*
tlink
,
struct
cifs_pending_open
*
open
);
extern
void
cifs_del_pending_open
(
struct
cifs_pending_open
*
open
);
extern
void
cifs_put_tcp_session
(
struct
TCP_Server_Info
*
server
,
int
from_reconnect
);
extern
void
cifs_put_tcon
(
struct
cifs_tcon
*
tcon
);
#if IS_ENABLED(CONFIG_CIFS_DFS_UPCALL)
extern
void
cifs_dfs_release_automount_timer
(
void
);
...
...
sources/4.4/cifssmb.c
View file @
0688d963
...
...
@@ -98,13 +98,13 @@ cifs_mark_open_files_invalid(struct cifs_tcon *tcon)
struct
list_head
*
tmp1
;
/* list all files open on tree connection and mark them invalid */
spin_lock
(
&
cifs_file_list
_lock
);
spin_lock
(
&
tcon
->
open_file
_lock
);
list_for_each_safe
(
tmp
,
tmp1
,
&
tcon
->
openFileList
)
{
open_file
=
list_entry
(
tmp
,
struct
cifsFileInfo
,
tlist
);
open_file
->
invalidHandle
=
true
;
open_file
->
oplock_break_cancelled
=
true
;
}
spin_unlock
(
&
cifs_file_list
_lock
);
spin_unlock
(
&
tcon
->
open_file
_lock
);
/*
* BB Add call to invalidate_inodes(sb) for all superblocks mounted
* to this tcon.
...
...
@@ -717,6 +717,9 @@ CIFSSMBEcho(struct TCP_Server_Info *server)
if
(
rc
)
return
rc
;
if
(
server
->
capabilities
&
CAP_UNICODE
)
smb
->
hdr
.
Flags2
|=
SMBFLG2_UNICODE
;
/* set up echo request */
smb
->
hdr
.
Tid
=
0xffff
;
smb
->
hdr
.
WordCount
=
1
;
...
...
@@ -1431,6 +1434,8 @@ cifs_readv_discard(struct TCP_Server_Info *server, struct mid_q_entry *mid)
length
=
discard_remaining_data
(
server
);
dequeue_mid
(
mid
,
rdata
->
result
);
mid
->
resp_buf
=
server
->
smallbuf
;
server
->
smallbuf
=
NULL
;
return
length
;
}
...
...
@@ -1462,6 +1467,13 @@ cifs_readv_receive(struct TCP_Server_Info *server, struct mid_q_entry *mid)
return
length
;
server
->
total_read
+=
length
;
if
(
server
->
ops
->
is_session_expired
&&
server
->
ops
->
is_session_expired
(
buf
))
{
cifs_reconnect
(
server
);
wake_up
(
&
server
->
response_q
);
return
-
1
;
}
if
(
server
->
ops
->
is_status_pending
&&
server
->
ops
->
is_status_pending
(
buf
,
server
,
0
))
{
discard_remaining_data
(
server
);
...
...
@@ -1545,6 +1557,8 @@ cifs_readv_receive(struct TCP_Server_Info *server, struct mid_q_entry *mid)
return
cifs_readv_discard
(
server
,
mid
);
dequeue_mid
(
mid
,
false
);
mid
->
resp_buf
=
server
->
smallbuf
;
server
->
smallbuf
=
NULL
;
return
length
;
}
...
...
sources/4.4/connect.c
View file @
0688d963
...
...
@@ -52,6 +52,9 @@
#include "nterr.h"
#include "rfc1002pdu.h"
#include "fscache.h"
#ifdef CONFIG_CIFS_SMB2
#include "smb2proto.h"
#endif
#define CIFS_PORT 445
#define RFC1001_PORT 139
...
...
@@ -410,6 +413,9 @@ cifs_reconnect(struct TCP_Server_Info *server)
}
}
while
(
server
->
tcpStatus
==
CifsNeedReconnect
);
if
(
server
->
tcpStatus
==
CifsNeedNegotiate
)
mod_delayed_work
(
cifsiod_wq
,
&
server
->
echo
,
0
);
return
rc
;
}
...
...
@@ -419,16 +425,27 @@ cifs_echo_request(struct work_struct *work)
int
rc
;
struct
TCP_Server_Info
*
server
=
container_of
(
work
,
struct
TCP_Server_Info
,
echo
.
work
);
unsigned
long
echo_interval
;
/*
* If we need to renegotiate, set echo interval to zero to
* immediately call echo service where we can renegotiate.
*/
if
(
server
->
tcpStatus
==
CifsNeedNegotiate
)
echo_interval
=
0
;
else
echo_interval
=
SMB_ECHO_INTERVAL
;
/*
* We cannot send an echo if it is disabled or until the
* NEGOTIATE_PROTOCOL request is done, which is indicated by
* server->ops->need_neg() == true. Also, no need to ping if
* we got a response recently.
* We cannot send an echo if it is disabled.
* Also, no need to ping if we got a response recently.
*/
if
(
!
server
->
ops
->
need_neg
||
server
->
ops
->
need_neg
(
server
)
||
if
(
server
->
tcpStatus
==
CifsNeedReconnect
||
server
->
tcpStatus
==
CifsExiting
||
server
->
tcpStatus
==
CifsNew
||
(
server
->
ops
->
can_echo
&&
!
server
->
ops
->
can_echo
(
server
))
||
time_before
(
jiffies
,
server
->
lstrp
+
SMB_ECHO_INTERVAL
-
HZ
))
time_before
(
jiffies
,
server
->
lstrp
+
echo_interval
-
HZ
))
goto
requeue_echo
;
rc
=
server
->
ops
->
echo
?
server
->
ops
->
echo
(
server
)
:
-
ENOSYS
;
...
...
@@ -834,6 +851,13 @@ standard_receive3(struct TCP_Server_Info *server, struct mid_q_entry *mid)
cifs_dump_mem
(
"Bad SMB: "
,
buf
,
min_t
(
unsigned
int
,
server
->
total_read
,
48
));
if
(
server
->
ops
->
is_session_expired
&&
server
->
ops
->
is_session_expired
(
buf
))
{
cifs_reconnect
(
server
);
wake_up
(
&
server
->
response_q
);
return
-
1
;
}
if
(
server
->
ops
->
is_status_pending
&&
server
->
ops
->
is_status_pending
(
buf
,
server
,
length
))
return
-
1
;
...
...
@@ -920,10 +944,19 @@ cifs_demultiplex_thread(void *p)
server
->
lstrp
=
jiffies
;
if
(
mid_entry
!=
NULL
)
{
if
((
mid_entry
->
mid_flags
&
MID_WAIT_CANCELLED
)
&&
mid_entry
->
mid_state
==
MID_RESPONSE_RECEIVED
&&
server
->
ops
->
handle_cancelled_mid
)
server
->
ops
->
handle_cancelled_mid
(
mid_entry
->
resp_buf
,
server
);
if
(
!
mid_entry
->
multiRsp
||
mid_entry
->
multiEnd
)
mid_entry
->
callback
(
mid_entry
);
}
else
if
(
!
server
->
ops
->
is_oplock_break
||
!
server
->
ops
->
is_oplock_break
(
buf
,
server
))
{
}
else
if
(
server
->
ops
->
is_oplock_break
&&
server
->
ops
->
is_oplock_break
(
buf
,
server
))
{
cifs_dbg
(
FYI
,
"Received oplock break
\n
"
);
}
else
{
cifs_dbg
(
VFS
,
"No task to wake, unknown frame received! NumMids %d
\n
"
,
atomic_read
(
&
midCount
));
cifs_dump_mem
(
"Received Data is: "
,
buf
,
...
...
@@ -2116,8 +2149,8 @@ cifs_find_tcp_session(struct smb_vol *vol)
return
NULL
;
}
static
void
cifs_put_tcp_session
(
struct
TCP_Server_Info
*
server
)
void
cifs_put_tcp_session
(
struct
TCP_Server_Info
*
server
,
int
from_reconnect
)
{
struct
task_struct
*
task
;
...
...
@@ -2134,6 +2167,19 @@ cifs_put_tcp_session(struct TCP_Server_Info *server)
cancel_delayed_work_sync
(
&
server
->
echo
);
#ifdef CONFIG_CIFS_SMB2
if
(
from_reconnect
)
/*
* Avoid deadlock here: reconnect work calls
* cifs_put_tcp_session() at its end. Need to be sure
* that reconnect work does nothing with server pointer after
* that step.
*/
cancel_delayed_work
(
&
server
->
reconnect
);
else
cancel_delayed_work_sync
(
&
server
->
reconnect
);
#endif
spin_lock
(
&
GlobalMid_Lock
);
server
->
tcpStatus
=
CifsExiting
;
spin_unlock
(
&
GlobalMid_Lock
);
...
...
@@ -2198,12 +2244,16 @@ cifs_get_tcp_session(struct smb_vol *volume_info)
INIT_LIST_HEAD
(
&
tcp_ses
->
tcp_ses_list
);
INIT_LIST_HEAD
(
&
tcp_ses
->
smb_ses_list
);
INIT_DELAYED_WORK
(
&
tcp_ses
->
echo
,
cifs_echo_request
);
#ifdef CONFIG_CIFS_SMB2
INIT_DELAYED_WORK
(
&
tcp_ses
->
reconnect
,
smb2_reconnect_server
);
mutex_init
(
&
tcp_ses
->
reconnect_mutex
);
#endif
memcpy
(
&
tcp_ses
->
srcaddr
,
&
volume_info
->
srcaddr
,
sizeof
(
tcp_ses
->
srcaddr
));
memcpy
(
&
tcp_ses
->
dstaddr
,
&
volume_info
->
dstaddr
,
sizeof
(
tcp_ses
->
dstaddr
));
#ifdef CONFIG_CIFS_SMB2
ge
t_random_bytes
(
tcp_ses
->
client_guid
,
SMB2_CLIENT_GUID_SIZE
);
ge
nerate_random_uuid
(
tcp_ses
->
client_guid
);
#endif
/*
* at this point we are the only ones with the pointer
...
...
@@ -2350,7 +2400,7 @@ cifs_put_smb_ses(struct cifs_ses *ses)
spin_unlock
(
&
cifs_tcp_ses_lock
);
sesInfoFree
(
ses
);
cifs_put_tcp_session
(
server
);
cifs_put_tcp_session
(
server
,
0
);
}
#ifdef CONFIG_KEYS
...
...
@@ -2524,7 +2574,7 @@ cifs_get_smb_ses(struct TCP_Server_Info *server, struct smb_vol *volume_info)
mutex_unlock
(
&
ses
->
session_mutex
);
/* existing SMB ses has a server reference already */
cifs_put_tcp_session
(
server
);
cifs_put_tcp_session
(
server
,
0
);
free_xid
(
xid
);
return
ses
;
}
...
...
@@ -2614,7 +2664,7 @@ cifs_find_tcon(struct cifs_ses *ses, const char *unc)
return
NULL
;
}
static
void
void
cifs_put_tcon
(
struct
cifs_tcon
*
tcon
)
{
unsigned
int
xid
;
...
...
@@ -3520,6 +3570,44 @@ cifs_get_volume_info(char *mount_data, const char *devname)
return
volume_info
;
}
static
int
cifs_are_all_path_components_accessible
(
struct
TCP_Server_Info
*
server
,
unsigned
int
xid
,
struct
cifs_tcon
*
tcon
,
struct
cifs_sb_info
*
cifs_sb
,
char
*
full_path
)
{
int
rc
;
char
*
s
;
char
sep
,
tmp
;
sep
=
CIFS_DIR_SEP
(
cifs_sb
);
s
=
full_path
;
rc
=
server
->
ops
->
is_path_accessible
(
xid
,
tcon
,
cifs_sb
,
""
);
while
(
rc
==
0
)
{
/* skip separators */
while
(
*
s
==
sep
)
s
++
;
if
(
!*
s
)
break
;
/* next separator */
while
(
*
s
&&
*
s
!=
sep
)
s
++
;
/*
* temporarily null-terminate the path at the end of
* the current component
*/
tmp
=
*
s
;
*
s
=
0
;
rc
=
server
->
ops
->
is_path_accessible
(
xid
,
tcon
,
cifs_sb
,
full_path
);
*
s
=
tmp
;
}
return
rc
;
}
int
cifs_mount
(
struct
cifs_sb_info
*
cifs_sb
,
struct
smb_vol
*
volume_info
)
{
...
...
@@ -3657,6 +3745,18 @@ remote_path_check:
kfree
(
full_path
);
goto
mount_fail_check
;
}
if
(
rc
!=
-
EREMOTE
)
{
rc
=
cifs_are_all_path_components_accessible
(
server
,
xid
,
tcon
,
cifs_sb
,
full_path
);
if
(
rc
!=
0
)
{
cifs_dbg
(
VFS
,
"cannot query dirs between root and final path, "
"enabling CIFS_MOUNT_USE_PREFIX_PATH
\n
"
);
cifs_sb
->
mnt_cifs_flags
|=
CIFS_MOUNT_USE_PREFIX_PATH
;
rc
=
0
;
}
}
kfree
(
full_path
);
}
...
...
@@ -3720,7 +3820,7 @@ mount_fail_check:
else
if
(
ses
)
cifs_put_smb_ses
(
ses
);
else
cifs_put_tcp_session
(
server
);
cifs_put_tcp_session
(
server
,
0
);
bdi_destroy
(
&
cifs_sb
->
bdi
);
}
...
...
@@ -3926,6 +4026,7 @@ cifs_umount(struct cifs_sb_info *cifs_sb)
bdi_destroy
(
&
cifs_sb
->
bdi
);
kfree
(
cifs_sb
->
mountdata
);
kfree
(
cifs_sb
->
prepath
);
call_rcu
(
&
cifs_sb
->
rcu
,
delayed_free
);
}
...
...
@@ -3971,6 +4072,14 @@ cifs_setup_session(const unsigned int xid, struct cifs_ses *ses,
cifs_dbg
(
FYI
,
"Security Mode: 0x%x Capabilities: 0x%x TimeAdjust: %d
\n
"
,
server
->
sec_mode
,
server
->
capabilities
,
server
->
timeAdj
);
if
(
ses
->
auth_key
.
response
)
{
cifs_dbg
(
VFS
,
"Free previous auth_key.response = %p
\n
"
,
ses
->
auth_key
.
response
);
kfree
(
ses
->
auth_key
.
response
);
ses
->
auth_key
.
response
=
NULL
;
ses
->
auth_key
.
len
=
0
;
}
if
(
server
->
ops
->
sess_setup
)
rc
=
server
->
ops
->
sess_setup
(
xid
,
ses
,
nls_info
);
...
...
@@ -4030,7 +4139,7 @@ cifs_construct_tcon(struct cifs_sb_info *cifs_sb, kuid_t fsuid)
ses
=
cifs_get_smb_ses
(
master_tcon
->
ses
->
server
,
vol_info
);
if
(
IS_ERR
(
ses
))
{
tcon
=
(
struct
cifs_tcon
*
)
ses
;
cifs_put_tcp_session
(
master_tcon
->
ses
->
server
);
cifs_put_tcp_session
(
master_tcon
->
ses
->
server
,
0
);
goto
out
;
}
...
...
sources/4.4/dir.c
View file @
0688d963
...
...
@@ -84,6 +84,7 @@ build_path_from_dentry(struct dentry *direntry)
struct
dentry
*
temp
;
int
namelen
;
int
dfsplen
;
int
pplen
=
0
;
char
*
full_path
;
char
dirsep
;
struct
cifs_sb_info
*
cifs_sb
=
CIFS_SB
(
direntry
->
d_sb
);
...
...
@@ -95,8 +96,12 @@ build_path_from_dentry(struct dentry *direntry)
dfsplen
=
strnlen
(
tcon
->
treeName
,
MAX_TREE_SIZE
+
1
);
else
dfsplen
=
0
;
if
(
cifs_sb
->
mnt_cifs_flags
&
CIFS_MOUNT_USE_PREFIX_PATH
)
pplen
=
cifs_sb
->
prepath
?
strlen
(
cifs_sb
->
prepath
)
+
1
:
0
;
cifs_bp_rename_retry:
namelen
=
dfsplen
;
namelen
=
dfsplen
+
pplen
;
seq
=
read_seqbegin
(
&
rename_lock
);
rcu_read_lock
();
for
(
temp
=
direntry
;
!
IS_ROOT
(
temp
);)
{
...
...
@@ -137,7 +142,7 @@ cifs_bp_rename_retry:
}
}
rcu_read_unlock
();
if
(
namelen
!=
dfsplen
||
read_seqretry
(
&
rename_lock
,
seq
))
{
if
(
namelen
!=
dfsplen
+
pplen
||
read_seqretry
(
&
rename_lock
,
seq
))
{
cifs_dbg
(
FYI
,
"did not end path lookup where expected. namelen=%ddfsplen=%d
\n
"
,
namelen
,
dfsplen
);
/* presumably this is only possible if racing with a rename
...
...
@@ -153,6 +158,17 @@ cifs_bp_rename_retry:
those safely to '/' if any are found in the middle of the prepath */
/* BB test paths to Windows with '/' in the midst of prepath */
if
(
pplen
)
{
int
i
;
cifs_dbg
(
FYI
,
"using cifs_sb prepath <%s>
\n
"
,
cifs_sb
->
prepath
);
memcpy
(
full_path
+
dfsplen
+
1
,
cifs_sb
->
prepath
,
pplen
-
1
);
full_path
[
dfsplen
]
=
'\\'
;
for
(
i
=
0
;
i
<
pplen
-
1
;
i
++
)
if
(
full_path
[
dfsplen
+
1
+
i
]
==
'/'
)
full_path
[
dfsplen
+
1
+
i
]
=
CIFS_DIR_SEP
(
cifs_sb
);
}
if
(
dfsplen
)
{
strncpy
(
full_path
,
tcon
->
treeName
,
dfsplen
);
if
(
cifs_sb
->
mnt_cifs_flags
&
CIFS_MOUNT_POSIX_PATHS
)
{
...
...
@@ -167,15 +183,21 @@ cifs_bp_rename_retry:
}
/*
* Don't allow path components longer than the server max.
* Don't allow the separator character in a path component.
* The VFS will not allow "/", but "\" is allowed by posix.
*/
static
int
check_name
(
struct
dentry
*
direntry
)
check_name
(
struct
dentry
*
direntry
,
struct
cifs_tcon
*
tcon
)
{
struct
cifs_sb_info
*
cifs_sb
=
CIFS_SB
(
direntry
->
d_sb
);
int
i
;
if
(
unlikely
(
tcon
->
fsAttrInfo
.
MaxPathNameComponentLength
&&
direntry
->
d_name
.
len
>
le32_to_cpu
(
tcon
->
fsAttrInfo
.
MaxPathNameComponentLength
)))
return
-
ENAMETOOLONG
;
if
(
!
(
cifs_sb
->
mnt_cifs_flags
&
CIFS_MOUNT_POSIX_PATHS
))
{
for
(
i
=
0
;
i
<
direntry
->
d_name
.
len
;
i
++
)
{
if
(
direntry
->
d_name
.
name
[
i
]
==
'\\'
)
{
...
...
@@ -231,6 +253,13 @@ cifs_do_create(struct inode *inode, struct dentry *direntry, unsigned int xid,
goto
cifs_create_get_file_info
;
}
if
(
S_ISDIR
(
newinode
->
i_mode
))
{
CIFSSMBClose
(
xid
,
tcon
,
fid
->
netfid
);
iput
(
newinode
);
rc
=
-
EISDIR
;
goto
out
;
}
if
(
!
S_ISREG
(
newinode
->
i_mode
))
{
/*
* The server may allow us to open things like
...
...
@@ -404,10 +433,14 @@ cifs_create_set_dentry:
if
(
rc
!=
0
)
{
cifs_dbg
(
FYI
,
"Create worked, get_inode_info failed rc = %d
\n
"
,
rc
);
if
(
server
->
ops
->
close
)
server
->
ops
->
close
(
xid
,
tcon
,
fid
);
goto
out
;
goto
out_err
;
}
if
(
S_ISDIR
(
newinode
->
i_mode
))
{
rc
=
-
EISDIR
;
goto
out_err
;
}
d_drop
(
direntry
);
d_add
(
direntry
,
newinode
);
...
...
@@ -415,6 +448,13 @@ out:
kfree
(
buf
);
kfree
(
full_path
);
return
rc
;
out_err:
if
(
server
->
ops
->
close
)
server
->
ops
->
close
(
xid
,
tcon
,
fid
);
if
(
newinode
)
iput
(
newinode
);
goto
out
;
}
int
...
...
@@ -460,10 +500,6 @@ cifs_atomic_open(struct inode *inode, struct dentry *direntry,
return
finish_no_open
(
file
,
res
);
}
rc
=
check_name
(
direntry
);
if
(
rc
)
return
rc
;
xid
=
get_xid
();
cifs_dbg
(
FYI
,
"parent inode = 0x%p name is: %pd and dentry = 0x%p
\n
"
,
...
...
@@ -476,6 +512,11 @@ cifs_atomic_open(struct inode *inode, struct dentry *direntry,
}
tcon
=
tlink_tcon
(
tlink
);
rc
=
check_name
(
direntry
,
tcon
);
if
(
rc
)
goto
out
;
server
=
tcon
->
ses
->
server
;
if
(
server
->
ops
->
new_lease_key
)
...
...
@@ -736,7 +777,7 @@ cifs_lookup(struct inode *parent_dir_inode, struct dentry *direntry,
}
pTcon
=
tlink_tcon
(
tlink
);
rc
=
check_name
(
direntry
);
rc
=
check_name
(
direntry
,
pTcon
);
if
(
rc
)
goto
lookup_out
;
...
...
sources/4.4/file.c
View file @
0688d963
...
...
@@ -226,6 +226,13 @@ cifs_nt_open(char *full_path, struct inode *inode, struct cifs_sb_info *cifs_sb,
if
(
backup_cred
(
cifs_sb
))
create_options
|=
CREATE_OPEN_BACKUP_INTENT
;
/* O_SYNC also has bit for O_DSYNC so following check picks up either */
if
(
f_flags
&
O_SYNC
)
create_options
|=
CREATE_WRITE_THROUGH
;
if
(
f_flags
&
O_DIRECT
)
create_options
|=
CREATE_NO_BUFFER
;
oparms
.
tcon
=
tcon
;
oparms
.
cifs_sb
=
cifs_sb
;
oparms
.
desired_access
=
desired_access
;
...
...
@@ -308,6 +315,7 @@ cifs_new_fileinfo(struct cifs_fid *fid, struct file *file,
cfile
->
tlink
=
cifs_get_tlink
(
tlink
);
INIT_WORK
(
&
cfile
->
oplock_break
,
cifs_oplock_break
);
mutex_init
(
&
cfile
->
fh_mutex
);
spin_lock_init
(
&
cfile
->
file_info_lock
);
cifs_sb_active
(
inode
->
i_sb
);
...
...
@@ -320,7 +328,7 @@ cifs_new_fileinfo(struct cifs_fid *fid, struct file *file,
oplock
=
0
;
}
spin_lock
(
&
cifs_file_list
_lock
);
spin_lock
(
&
tcon
->
open_file
_lock
);
if
(
fid
->
pending_open
->
oplock
!=
CIFS_OPLOCK_NO_CHANGE
&&
oplock
)
oplock
=
fid
->
pending_open
->
oplock
;
list_del
(
&
fid
->
pending_open
->
olist
);
...
...
@@ -329,12 +337,13 @@ cifs_new_fileinfo(struct cifs_fid *fid, struct file *file,
server
->
ops
->
set_fid
(
cfile
,
fid
,
oplock
);
list_add
(
&
cfile
->
tlist
,
&
tcon
->
openFileList
);
/* if readable file instance put first in list*/
if
(
file
->
f_mode
&
FMODE_READ
)
list_add
(
&
cfile
->
flist
,
&
cinode
->
openFileList
);
else
list_add_tail
(
&
cfile
->
flist
,
&
cinode
->
openFileList
);
spin_unlock
(
&
cifs_file_list
_lock
);
spin_unlock
(
&
tcon
->
open_file
_lock
);
if
(
fid
->
purge_cache
)
cifs_zap_mapping
(
inode
);
...
...
@@ -346,16 +355,16 @@ cifs_new_fileinfo(struct cifs_fid *fid, struct file *file,
struct
cifsFileInfo
*
cifsFileInfo_get
(
struct
cifsFileInfo
*
cifs_file
)
{
spin_lock
(
&
cifs_file
_list
_lock
);
spin_lock
(
&
cifs_file
->
file_info
_lock
);
cifsFileInfo_get_locked
(
cifs_file
);
spin_unlock
(
&
cifs_file
_list
_lock
);
spin_unlock
(
&
cifs_file
->
file_info
_lock
);
return
cifs_file
;
}
/*
* Release a reference on the file private data. This may involve closing
* the filehandle out on the server. Must be called without holding
*
cifs_file_list
_lock.
*
tcon->open_file_lock and cifs_file->file_info
_lock.
*/
void
cifsFileInfo_put
(
struct
cifsFileInfo
*
cifs_file
)
{
...
...
@@ -370,11 +379,15 @@ void cifsFileInfo_put(struct cifsFileInfo *cifs_file)
struct
cifs_pending_open
open
;
bool
oplock_break_cancelled
;
spin_lock
(
&
cifs_file_list_lock
);
spin_lock
(
&
tcon
->
open_file_lock
);
spin_lock
(
&
cifs_file
->
file_info_lock
);
if
(
--
cifs_file
->
count
>
0
)
{
spin_unlock
(
&
cifs_file_list_lock
);
spin_unlock
(
&
cifs_file
->
file_info_lock
);
spin_unlock
(
&
tcon
->
open_file_lock
);
return
;
}
spin_unlock
(
&
cifs_file
->
file_info_lock
);
if
(
server
->
ops
->
get_lease_key
)
server
->
ops
->
get_lease_key
(
inode
,
&
fid
);
...
...
@@ -398,7 +411,8 @@ void cifsFileInfo_put(struct cifsFileInfo *cifs_file)
set_bit
(
CIFS_INO_INVALID_MAPPING
,
&
cifsi
->
flags
);
cifs_set_oplock_level
(
cifsi
,
0
);
}
spin_unlock
(
&
cifs_file_list_lock
);
spin_unlock
(
&
tcon
->
open_file_lock
);
oplock_break_cancelled
=
cancel_work_sync
(
&
cifs_file
->
oplock_break
);
...
...
@@ -780,10 +794,10 @@ int cifs_closedir(struct inode *inode, struct file *file)
server
=
tcon
->
ses
->
server
;
cifs_dbg
(
FYI
,
"Freeing private data in close dir
\n
"
);
spin_lock
(
&
c
ifs_file_list
_lock
);
spin_lock
(
&
c
file
->
file_info
_lock
);
if
(
server
->
ops
->
dir_needs_close
(
cfile
))
{
cfile
->
invalidHandle
=
true
;
spin_unlock
(
&
c
ifs_file_list
_lock
);
spin_unlock
(
&
c
file
->
file_info
_lock
);
if
(
server
->
ops
->
close_dir
)
rc
=
server
->
ops
->
close_dir
(
xid
,
tcon
,
&
cfile
->
fid
);
else
...
...
@@ -792,7 +806,7 @@ int cifs_closedir(struct inode *inode, struct file *file)
/* not much we can do if it fails anyway, ignore rc */
rc
=
0
;
}
else
spin_unlock
(
&
c
ifs_file_list
_lock
);
spin_unlock
(
&
c
file
->
file_info
_lock
);
buf
=
cfile
->
srch_inf
.
ntwrk_buf_start
;
if
(
buf
)
{
...
...
@@ -1728,12 +1742,13 @@ struct cifsFileInfo *find_readable_file(struct cifsInodeInfo *cifs_inode,
{
struct
cifsFileInfo
*
open_file
=
NULL
;
struct
cifs_sb_info
*
cifs_sb
=
CIFS_SB
(
cifs_inode
->
vfs_inode
.
i_sb
);
struct
cifs_tcon
*
tcon
=
cifs_sb_master_tcon
(
cifs_sb
);
/* only filter by fsuid on multiuser mounts */
if
(
!
(
cifs_sb
->
mnt_cifs_flags
&
CIFS_MOUNT_MULTIUSER
))
fsuid_only
=
false
;
spin_lock
(
&
cifs_file_list
_lock
);
spin_lock
(
&
tcon
->
open_file
_lock
);
/* we could simply get the first_list_entry since write-only entries
are always at the end of the list but since the first entry might
have a close pending, we go through the whole list */
...
...
@@ -1744,8 +1759,8 @@ struct cifsFileInfo *find_readable_file(struct cifsInodeInfo *cifs_inode,
if
(
!
open_file
->
invalidHandle
)
{
/* found a good file */
/* lock it so it will not be closed on us */
cifsFileInfo_get
_locked
(
open_file
);
spin_unlock
(
&
cifs_file_list
_lock
);
cifsFileInfo_get
(
open_file
);
spin_unlock
(
&
tcon
->
open_file
_lock
);
return
open_file
;
}
/* else might as well continue, and look for
another, or simply have the caller reopen it
...
...
@@ -1753,7 +1768,7 @@ struct cifsFileInfo *find_readable_file(struct cifsInodeInfo *cifs_inode,
}
else
/* write only file */
break
;
/* write only files are last so must be done */
}
spin_unlock
(
&
cifs_file_list
_lock
);
spin_unlock
(
&
tcon
->
open_file
_lock
);
return
NULL
;
}
...
...
@@ -1762,6 +1777,7 @@ struct cifsFileInfo *find_writable_file(struct cifsInodeInfo *cifs_inode,
{
struct
cifsFileInfo
*
open_file
,
*
inv_file
=
NULL
;
struct
cifs_sb_info
*
cifs_sb
;
struct
cifs_tcon
*
tcon
;
bool
any_available
=
false
;
int
rc
;
unsigned
int
refind
=
0
;
...
...
@@ -1777,15 +1793,16 @@ struct cifsFileInfo *find_writable_file(struct cifsInodeInfo *cifs_inode,
}
cifs_sb
=
CIFS_SB
(
cifs_inode
->
vfs_inode
.
i_sb
);
tcon
=
cifs_sb_master_tcon
(
cifs_sb
);
/* only filter by fsuid on multiuser mounts */
if
(
!
(
cifs_sb
->
mnt_cifs_flags
&
CIFS_MOUNT_MULTIUSER
))
fsuid_only
=
false
;
spin_lock
(
&
cifs_file_list
_lock
);
spin_lock
(
&
tcon
->
open_file
_lock
);
refind_writable:
if
(
refind
>
MAX_REOPEN_ATT
)
{
spin_unlock
(
&
cifs_file_list
_lock
);
spin_unlock
(
&
tcon
->
open_file
_lock
);
return
NULL
;
}
list_for_each_entry
(
open_file
,
&
cifs_inode
->
openFileList
,
flist
)
{
...
...
@@ -1796,8 +1813,8 @@ refind_writable:
if
(
OPEN_FMODE
(
open_file
->
f_flags
)
&
FMODE_WRITE
)
{
if
(
!
open_file
->
invalidHandle
)
{
/* found a good writable file */
cifsFileInfo_get
_locked
(
open_file
);
spin_unlock
(
&
cifs_file_list
_lock
);
cifsFileInfo_get
(
open_file
);
spin_unlock
(
&
tcon
->
open_file
_lock
);
return
open_file
;
}
else
{
if
(
!
inv_file
)
...
...
@@ -1813,24 +1830,24 @@ refind_writable:
if
(
inv_file
)
{
any_available
=
false
;
cifsFileInfo_get
_locked
(
inv_file
);
cifsFileInfo_get
(
inv_file
);
}
spin_unlock
(
&
cifs_file_list
_lock
);
spin_unlock
(
&
tcon
->
open_file
_lock
);
if
(
inv_file
)
{
rc
=
cifs_reopen_file
(
inv_file
,
false
);
if
(
!
rc
)
return
inv_file
;
else
{
spin_lock
(
&
cifs_file_list
_lock
);
spin_lock
(
&
tcon
->
open_file
_lock
);
list_move_tail
(
&
inv_file
->
flist
,
&
cifs_inode
->
openFileList
);
spin_unlock
(
&
cifs_file_list
_lock
);
spin_unlock
(
&
tcon
->
open_file
_lock
);
cifsFileInfo_put
(
inv_file
);
spin_lock
(
&
cifs_file_list_lock
);
++
refind
;
inv_file
=
NULL
;
spin_lock
(
&
tcon
->
open_file_lock
);
goto
refind_writable
;
}
}
...
...
@@ -2543,7 +2560,7 @@ cifs_write_from_iter(loff_t offset, size_t len, struct iov_iter *from,
wdata
->
credits
=
credits
;
if
(
!
wdata
->
cfile
->
invalidHandle
||
!
cifs_reopen_file
(
wdata
->
cfile
,
false
))
!
(
rc
=
cifs_reopen_file
(
wdata
->
cfile
,
false
)
))
rc
=
server
->
ops
->
async_writev
(
wdata
,
cifs_uncached_writedata_release
);
if
(
rc
)
{
...
...
@@ -2956,7 +2973,7 @@ cifs_send_async_read(loff_t offset, size_t len, struct cifsFileInfo *open_file,
rdata
->
credits
=
credits
;
if
(
!
rdata
->
cfile
->
invalidHandle
||
!
cifs_reopen_file
(
rdata
->
cfile
,
true
))
!
(
rc
=
cifs_reopen_file
(
rdata
->
cfile
,
true
)
))
rc
=
server
->
ops
->
async_readv
(
rdata
);
error:
if
(
rc
)
{
...
...
@@ -3542,7 +3559,7 @@ static int cifs_readpages(struct file *file, struct address_space *mapping,
}
if
(
!
rdata
->
cfile
->
invalidHandle
||
!
cifs_reopen_file
(
rdata
->
cfile
,
true
))
!
(
rc
=
cifs_reopen_file
(
rdata
->
cfile
,
true
)
))
rc
=
server
->
ops
->
async_readv
(
rdata
);
if
(
rc
)
{
add_credits_and_wake_if
(
server
,
rdata
->
credits
,
0
);
...
...
@@ -3640,15 +3657,17 @@ static int cifs_readpage(struct file *file, struct page *page)
static
int
is_inode_writable
(
struct
cifsInodeInfo
*
cifs_inode
)
{
struct
cifsFileInfo
*
open_file
;
struct
cifs_tcon
*
tcon
=
cifs_sb_master_tcon
(
CIFS_SB
(
cifs_inode
->
vfs_inode
.
i_sb
));
spin_lock
(
&
cifs_file_list
_lock
);
spin_lock
(
&
tcon
->
open_file
_lock
);
list_for_each_entry
(
open_file
,
&
cifs_inode
->
openFileList
,
flist
)
{
if
(
OPEN_FMODE
(
open_file
->
f_flags
)
&
FMODE_WRITE
)
{
spin_unlock
(
&
cifs_file_list
_lock
);
spin_unlock
(
&
tcon
->
open_file
_lock
);
return
1
;
}
}
spin_unlock
(
&
cifs_file_list
_lock
);
spin_unlock
(
&
tcon
->
open_file
_lock
);
return
0
;
}
...
...
sources/4.4/inode.c
View file @
0688d963
...
...
@@ -983,10 +983,26 @@ struct inode *cifs_root_iget(struct super_block *sb)
struct
inode
*
inode
=
NULL
;
long
rc
;
struct
cifs_tcon
*
tcon
=
cifs_sb_master_tcon
(
cifs_sb
);
char
*
path
=
NULL
;
int
len
;
if
((
cifs_sb
->
mnt_cifs_flags
&
CIFS_MOUNT_USE_PREFIX_PATH
)
&&
cifs_sb
->
prepath
)
{
len
=
strlen
(
cifs_sb
->
prepath
);
path
=
kzalloc
(
len
+
2
/* leading sep + null */
,
GFP_KERNEL
);
if
(
path
==
NULL
)
return
ERR_PTR
(
-
ENOMEM
);
path
[
0
]
=
'/'
;
memcpy
(
path
+
1
,
cifs_sb
->
prepath
,
len
);
}
else
{
path
=
kstrdup
(
""
,
GFP_KERNEL
);
if
(
path
==
NULL
)
return
ERR_PTR
(
-
ENOMEM
);
}
xid
=
get_xid
();
if
(
tcon
->
unix_ext
)
{
rc
=
cifs_get_inode_info_unix
(
&
inode
,
""
,
sb
,
xid
);
rc
=
cifs_get_inode_info_unix
(
&
inode
,
path
,
sb
,
xid
);
/* some servers mistakenly claim POSIX support */
if
(
rc
!=
-
EOPNOTSUPP
)
goto
iget_no_retry
;
...
...
@@ -994,7 +1010,8 @@ struct inode *cifs_root_iget(struct super_block *sb)
tcon
->
unix_ext
=
false
;
}
rc
=
cifs_get_inode_info
(
&
inode
,
""
,
NULL
,
sb
,
xid
,
NULL
);
convert_delimiter
(
path
,
CIFS_DIR_SEP
(
cifs_sb
));
rc
=
cifs_get_inode_info
(
&
inode
,
path
,
NULL
,
sb
,
xid
,
NULL
);
iget_no_retry:
if
(
!
inode
)
{
...
...
@@ -1023,6 +1040,7 @@ iget_no_retry:
}
out:
kfree
(
path
);
/* can not call macro free_xid here since in a void func
* TODO: This is no longer true
*/
...
...
sources/4.4/ioctl.c
View file @
0688d963
...
...
@@ -272,6 +272,8 @@ long cifs_ioctl(struct file *filep, unsigned int command, unsigned long arg)
rc
=
-
EOPNOTSUPP
;
break
;
case
CIFS_IOC_GET_MNT_INFO
:
if
(
pSMBFile
==
NULL
)
break
;
tcon
=
tlink_tcon
(
pSMBFile
->
tlink
);
rc
=
smb_mnt_get_fsinfo
(
xid
,
tcon
,
(
void
__user
*
)
arg
);
break
;
...
...
sources/4.4/misc.c
View file @
0688d963
...
...
@@ -120,6 +120,7 @@ tconInfoAlloc(void)
++
ret_buf
->
tc_count
;
INIT_LIST_HEAD
(
&
ret_buf
->
openFileList
);
INIT_LIST_HEAD
(
&
ret_buf
->
tcon_list
);
spin_lock_init
(
&
ret_buf
->
open_file_lock
);
#ifdef CONFIG_CIFS_STATS
spin_lock_init
(
&
ret_buf
->
stat_lock
);
#endif
...
...
@@ -465,7 +466,7 @@ is_valid_oplock_break(char *buffer, struct TCP_Server_Info *srv)
continue
;
cifs_stats_inc
(
&
tcon
->
stats
.
cifs_stats
.
num_oplock_brks
);
spin_lock
(
&
cifs_file_list
_lock
);
spin_lock
(
&
tcon
->
open_file
_lock
);
list_for_each
(
tmp2
,
&
tcon
->
openFileList
)
{
netfile
=
list_entry
(
tmp2
,
struct
cifsFileInfo
,
tlist
);
...
...
@@ -495,11 +496,11 @@ is_valid_oplock_break(char *buffer, struct TCP_Server_Info *srv)
&
netfile
->
oplock_break
);
netfile
->
oplock_break_cancelled
=
false
;
spin_unlock
(
&
cifs_file_list
_lock
);
spin_unlock
(
&
tcon
->
open_file
_lock
);
spin_unlock
(
&
cifs_tcp_ses_lock
);
return
true
;
}
spin_unlock
(
&
cifs_file_list
_lock
);
spin_unlock
(
&
tcon
->
open_file
_lock
);
spin_unlock
(
&
cifs_tcp_ses_lock
);
cifs_dbg
(
FYI
,
"No matching file for oplock break
\n
"
);
return
true
;
...
...
@@ -613,9 +614,9 @@ backup_cred(struct cifs_sb_info *cifs_sb)
void
cifs_del_pending_open
(
struct
cifs_pending_open
*
open
)
{
spin_lock
(
&
cifs_file_list
_lock
);
spin_lock
(
&
tlink_tcon
(
open
->
tlink
)
->
open_file
_lock
);
list_del
(
&
open
->
olist
);
spin_unlock
(
&
cifs_file_list
_lock
);
spin_unlock
(
&
tlink_tcon
(
open
->
tlink
)
->
open_file
_lock
);
}
void
...
...
@@ -635,7 +636,7 @@ void
cifs_add_pending_open
(
struct
cifs_fid
*
fid
,
struct
tcon_link
*
tlink
,
struct
cifs_pending_open
*
open
)
{
spin_lock
(
&
cifs_file_list
_lock
);
spin_lock
(
&
tlink_tcon
(
tlink
)
->
open_file
_lock
);
cifs_add_pending_open_locked
(
fid
,
tlink
,
open
);
spin_unlock
(
&
cifs_file_list
_lock
);
spin_unlock
(
&
tlink_tcon
(
open
->
tlink
)
->
open_file
_lock
);
}
sources/4.4/ntlmssp.h
View file @
0688d963
...
...
@@ -133,6 +133,6 @@ typedef struct _AUTHENTICATE_MESSAGE {
int
decode_ntlmssp_challenge
(
char
*
bcc_ptr
,
int
blob_len
,
struct
cifs_ses
*
ses
);
void
build_ntlmssp_negotiate_blob
(
unsigned
char
*
pbuffer
,
struct
cifs_ses
*
ses
);
int
build_ntlmssp_auth_blob
(
unsigned
char
*
pbuffer
,
u16
*
buflen
,
int
build_ntlmssp_auth_blob
(
unsigned
char
*
*
pbuffer
,
u16
*
buflen
,
struct
cifs_ses
*
ses
,
const
struct
nls_table
*
nls_cp
);
sources/4.4/readdir.c
View file @
0688d963
...
...
@@ -282,6 +282,7 @@ initiate_cifs_search(const unsigned int xid, struct file *file)
rc
=
-
ENOMEM
;
goto
error_exit
;
}
spin_lock_init
(
&
cifsFile
->
file_info_lock
);
file
->
private_data
=
cifsFile
;
cifsFile
->
tlink
=
cifs_get_tlink
(
tlink
);
tcon
=
tlink_tcon
(
tlink
);
...
...
@@ -594,14 +595,14 @@ find_cifs_entry(const unsigned int xid, struct cifs_tcon *tcon, loff_t pos,
is_dir_changed
(
file
))
||
(
index_to_find
<
first_entry_in_buffer
))
{
/* close and restart search */
cifs_dbg
(
FYI
,
"search backing up - close and restart search
\n
"
);
spin_lock
(
&
c
ifs_file_list
_lock
);
spin_lock
(
&
c
file
->
file_info
_lock
);
if
(
server
->
ops
->
dir_needs_close
(
cfile
))
{
cfile
->
invalidHandle
=
true
;
spin_unlock
(
&
c
ifs_file_list
_lock
);
spin_unlock
(
&
c
file
->
file_info
_lock
);
if
(
server
->
ops
->
close_dir
)
server
->
ops
->
close_dir
(
xid
,
tcon
,
&
cfile
->
fid
);
}
else
spin_unlock
(
&
c
ifs_file_list
_lock
);
spin_unlock
(
&
c
file
->
file_info
_lock
);
if
(
cfile
->
srch_inf
.
ntwrk_buf_start
)
{
cifs_dbg
(
FYI
,
"freeing SMB ff cache buf on search rewind
\n
"
);
if
(
cfile
->
srch_inf
.
smallBuf
)
...
...
sources/4.4/sess.c
View file @
0688d963
...
...
@@ -364,19 +364,43 @@ void build_ntlmssp_negotiate_blob(unsigned char *pbuffer,
sec_blob
->
DomainName
.
MaximumLength
=
0
;
}
/* We do not malloc the blob, it is passed in pbuffer, because its
maximum possible size is fixed and small, making this approach cleaner.
This function returns the length of the data in the blob */
int
build_ntlmssp_auth_blob
(
unsigned
char
*
pbuffer
,
static
int
size_of_ntlmssp_blob
(
struct
cifs_ses
*
ses
)
{
int
sz
=
sizeof
(
AUTHENTICATE_MESSAGE
)
+
ses
->
auth_key
.
len
-
CIFS_SESS_KEY_SIZE
+
CIFS_CPHTXT_SIZE
+
2
;
if
(
ses
->
domainName
)
sz
+=
2
*
strnlen
(
ses
->
domainName
,
CIFS_MAX_DOMAINNAME_LEN
);
else
sz
+=
2
;
if
(
ses
->
user_name
)
sz
+=
2
*
strnlen
(
ses
->
user_name
,
CIFS_MAX_USERNAME_LEN
);
else
sz
+=
2
;
return
sz
;
}
int
build_ntlmssp_auth_blob
(
unsigned
char
**
pbuffer
,
u16
*
buflen
,
struct
cifs_ses
*
ses
,
const
struct
nls_table
*
nls_cp
)
{
int
rc
;
AUTHENTICATE_MESSAGE
*
sec_blob
=
(
AUTHENTICATE_MESSAGE
*
)
pbuffer
;
AUTHENTICATE_MESSAGE
*
sec_blob
;
__u32
flags
;
unsigned
char
*
tmp
;
rc
=
setup_ntlmv2_rsp
(
ses
,
nls_cp
);
if
(
rc
)
{
cifs_dbg
(
VFS
,
"Error %d during NTLMSSP authentication
\n
"
,
rc
);
*
buflen
=
0
;
goto
setup_ntlmv2_ret
;
}
*
pbuffer
=
kmalloc
(
size_of_ntlmssp_blob
(
ses
),
GFP_KERNEL
);
sec_blob
=
(
AUTHENTICATE_MESSAGE
*
)
*
pbuffer
;
memcpy
(
sec_blob
->
Signature
,
NTLMSSP_SIGNATURE
,
8
);
sec_blob
->
MessageType
=
NtLmAuthenticate
;
...
...
@@ -391,7 +415,7 @@ int build_ntlmssp_auth_blob(unsigned char *pbuffer,
flags
|=
NTLMSSP_NEGOTIATE_KEY_XCH
;
}
tmp
=
pbuffer
+
sizeof
(
AUTHENTICATE_MESSAGE
);
tmp
=
*
pbuffer
+
sizeof
(
AUTHENTICATE_MESSAGE
);
sec_blob
->
NegotiateFlags
=
cpu_to_le32
(
flags
);
sec_blob
->
LmChallengeResponse
.
BufferOffset
=
...
...
@@ -399,13 +423,9 @@ int build_ntlmssp_auth_blob(unsigned char *pbuffer,
sec_blob
->
LmChallengeResponse
.
Length
=
0
;
sec_blob
->
LmChallengeResponse
.
MaximumLength
=
0
;
sec_blob
->
NtChallengeResponse
.
BufferOffset
=
cpu_to_le32
(
tmp
-
pbuffer
);
sec_blob
->
NtChallengeResponse
.
BufferOffset
=
cpu_to_le32
(
tmp
-
*
pbuffer
);
if
(
ses
->
user_name
!=
NULL
)
{
rc
=
setup_ntlmv2_rsp
(
ses
,
nls_cp
);
if
(
rc
)
{
cifs_dbg
(
VFS
,
"Error %d during NTLMSSP authentication
\n
"
,
rc
);
goto
setup_ntlmv2_ret
;
}
memcpy
(
tmp
,
ses
->
auth_key
.
response
+
CIFS_SESS_KEY_SIZE
,
ses
->
auth_key
.
len
-
CIFS_SESS_KEY_SIZE
);
tmp
+=
ses
->
auth_key
.
len
-
CIFS_SESS_KEY_SIZE
;
...
...
@@ -423,7 +443,7 @@ int build_ntlmssp_auth_blob(unsigned char *pbuffer,
}
if
(
ses
->
domainName
==
NULL
)
{
sec_blob
->
DomainName
.
BufferOffset
=
cpu_to_le32
(
tmp
-
pbuffer
);
sec_blob
->
DomainName
.
BufferOffset
=
cpu_to_le32
(
tmp
-
*
pbuffer
);
sec_blob
->
DomainName
.
Length
=
0
;
sec_blob
->
DomainName
.
MaximumLength
=
0
;
tmp
+=
2
;
...
...
@@ -432,14 +452,14 @@ int build_ntlmssp_auth_blob(unsigned char *pbuffer,
len
=
cifs_strtoUTF16
((
__le16
*
)
tmp
,
ses
->
domainName
,
CIFS_MAX_USERNAME_LEN
,
nls_cp
);
len
*=
2
;
/* unicode is 2 bytes each */
sec_blob
->
DomainName
.
BufferOffset
=
cpu_to_le32
(
tmp
-
pbuffer
);
sec_blob
->
DomainName
.
BufferOffset
=
cpu_to_le32
(
tmp
-
*
pbuffer
);
sec_blob
->
DomainName
.
Length
=
cpu_to_le16
(
len
);
sec_blob
->
DomainName
.
MaximumLength
=
cpu_to_le16
(
len
);
tmp
+=
len
;
}
if
(
ses
->
user_name
==
NULL
)
{
sec_blob
->
UserName
.
BufferOffset
=
cpu_to_le32
(
tmp
-
pbuffer
);
sec_blob
->
UserName
.
BufferOffset
=
cpu_to_le32
(
tmp
-
*
pbuffer
);
sec_blob
->
UserName
.
Length
=
0
;
sec_blob
->
UserName
.
MaximumLength
=
0
;
tmp
+=
2
;
...
...
@@ -448,13 +468,13 @@ int build_ntlmssp_auth_blob(unsigned char *pbuffer,
len
=
cifs_strtoUTF16
((
__le16
*
)
tmp
,
ses
->
user_name
,
CIFS_MAX_USERNAME_LEN
,
nls_cp
);
len
*=
2
;
/* unicode is 2 bytes each */
sec_blob
->
UserName
.
BufferOffset
=
cpu_to_le32
(
tmp
-
pbuffer
);
sec_blob
->
UserName
.
BufferOffset
=
cpu_to_le32
(
tmp
-
*
pbuffer
);
sec_blob
->
UserName
.
Length
=
cpu_to_le16
(
len
);
sec_blob
->
UserName
.
MaximumLength
=
cpu_to_le16
(
len
);
tmp
+=
len
;
}
sec_blob
->
WorkstationName
.
BufferOffset
=
cpu_to_le32
(
tmp
-
pbuffer
);
sec_blob
->
WorkstationName
.
BufferOffset
=
cpu_to_le32
(
tmp
-
*
pbuffer
);
sec_blob
->
WorkstationName
.
Length
=
0
;
sec_blob
->
WorkstationName
.
MaximumLength
=
0
;
tmp
+=
2
;
...
...
@@ -463,19 +483,19 @@ int build_ntlmssp_auth_blob(unsigned char *pbuffer,
(
ses
->
ntlmssp
->
server_flags
&
NTLMSSP_NEGOTIATE_EXTENDED_SEC
))
&&
!
calc_seckey
(
ses
))
{
memcpy
(
tmp
,
ses
->
ntlmssp
->
ciphertext
,
CIFS_CPHTXT_SIZE
);
sec_blob
->
SessionKey
.
BufferOffset
=
cpu_to_le32
(
tmp
-
pbuffer
);
sec_blob
->
SessionKey
.
BufferOffset
=
cpu_to_le32
(
tmp
-
*
pbuffer
);
sec_blob
->
SessionKey
.
Length
=
cpu_to_le16
(
CIFS_CPHTXT_SIZE
);
sec_blob
->
SessionKey
.
MaximumLength
=
cpu_to_le16
(
CIFS_CPHTXT_SIZE
);
tmp
+=
CIFS_CPHTXT_SIZE
;
}
else
{
sec_blob
->
SessionKey
.
BufferOffset
=
cpu_to_le32
(
tmp
-
pbuffer
);
sec_blob
->
SessionKey
.
BufferOffset
=
cpu_to_le32
(
tmp
-
*
pbuffer
);
sec_blob
->
SessionKey
.
Length
=
0
;
sec_blob
->
SessionKey
.
MaximumLength
=
0
;
}
*
buflen
=
tmp
-
*
pbuffer
;
setup_ntlmv2_ret:
*
buflen
=
tmp
-
pbuffer
;
return
rc
;
}
...
...
@@ -1266,7 +1286,7 @@ sess_auth_rawntlmssp_authenticate(struct sess_data *sess_data)
struct
cifs_ses
*
ses
=
sess_data
->
ses
;
__u16
bytes_remaining
;
char
*
bcc_ptr
;
char
*
ntlmsspblob
=
NULL
;
unsigned
char
*
ntlmsspblob
=
NULL
;
u16
blob_len
;
cifs_dbg
(
FYI
,
"rawntlmssp session setup authenticate phase
\n
"
);
...
...
@@ -1279,19 +1299,7 @@ sess_auth_rawntlmssp_authenticate(struct sess_data *sess_data)
/* Build security blob before we assemble the request */
pSMB
=
(
SESSION_SETUP_ANDX
*
)
sess_data
->
iov
[
0
].
iov_base
;
smb_buf
=
(
struct
smb_hdr
*
)
pSMB
;
/*
* 5 is an empirical value, large enough to hold
* authenticate message plus max 10 of av paris,
* domain, user, workstation names, flags, etc.
*/
ntlmsspblob
=
kzalloc
(
5
*
sizeof
(
struct
_AUTHENTICATE_MESSAGE
),
GFP_KERNEL
);
if
(
!
ntlmsspblob
)
{
rc
=
-
ENOMEM
;
goto
out
;
}
rc
=
build_ntlmssp_auth_blob
(
ntlmsspblob
,
rc
=
build_ntlmssp_auth_blob
(
&
ntlmsspblob
,
&
blob_len
,
ses
,
sess_data
->
nls_cp
);
if
(
rc
)
goto
out_free_ntlmsspblob
;
...
...
sources/4.4/smb1ops.c
View file @
0688d963
...
...
@@ -851,8 +851,13 @@ cifs_query_dir_first(const unsigned int xid, struct cifs_tcon *tcon,
struct
cifs_fid
*
fid
,
__u16
search_flags
,
struct
cifs_search_info
*
srch_inf
)
{
return
CIFSFindFirst
(
xid
,
tcon
,
path
,
cifs_sb
,
&
fid
->
netfid
,
search_flags
,
srch_inf
,
true
);
int
rc
;
rc
=
CIFSFindFirst
(
xid
,
tcon
,
path
,
cifs_sb
,
&
fid
->
netfid
,
search_flags
,
srch_inf
,
true
);
if
(
rc
)
cifs_dbg
(
FYI
,
"find first failed=%d
\n
"
,
rc
);
return
rc
;
}
static
int
...
...
@@ -1018,6 +1023,15 @@ cifs_dir_needs_close(struct cifsFileInfo *cfile)
return
!
cfile
->
srch_inf
.
endOfSearch
&&
!
cfile
->
invalidHandle
;
}
static
bool
cifs_can_echo
(
struct
TCP_Server_Info
*
server
)
{
if
(
server
->
tcpStatus
==
CifsGood
)
return
true
;
return
false
;
}
struct
smb_version_operations
smb1_operations
=
{
.
send_cancel
=
send_nt_cancel
,
.
compare_fids
=
cifs_compare_fids
,
...
...
@@ -1052,6 +1066,7 @@ struct smb_version_operations smb1_operations = {
.
get_dfs_refer
=
CIFSGetDFSRefer
,
.
qfs_tcon
=
cifs_qfs_tcon
,
.
is_path_accessible
=
cifs_is_path_accessible
,
.
can_echo
=
cifs_can_echo
,
.
query_path_info
=
cifs_query_path_info
,
.
query_file_info
=
cifs_query_file_info
,
.
get_srv_inum
=
cifs_get_srv_inum
,
...
...
sources/4.4/smb2file.c
View file @
0688d963
...
...
@@ -260,7 +260,7 @@ smb2_push_mandatory_locks(struct cifsFileInfo *cfile)
* and check it for zero before using.
*/
max_buf
=
tlink_tcon
(
cfile
->
tlink
)
->
ses
->
server
->
maxBuf
;
if
(
!
max_buf
)
{
if
(
max_buf
<
sizeof
(
struct
smb2_lock_element
)
)
{
free_xid
(
xid
);
return
-
EINVAL
;
}
...
...
sources/4.4/smb2glob.h
View file @
0688d963
...
...
@@ -61,4 +61,14 @@
/* Maximum buffer size value we can send with 1 credit */
#define SMB2_MAX_BUFFER_SIZE 65536
/*
* Maximum number of credits to keep available.
* This value is chosen somewhat arbitrarily. The Windows client
* defaults to 128 credits, the Windows server allows clients up to
* 512 credits, and the NetApp server does not limit clients at all.
* Choose a high enough value such that the client shouldn't limit
* performance.
*/
#define SMB2_MAX_CREDITS_AVAILABLE 32000
#endif
/* _SMB2_GLOB_H */
sources/4.4/smb2inode.c
View file @
0688d963
...
...
@@ -267,9 +267,15 @@ smb2_set_file_info(struct inode *inode, const char *full_path,
struct
tcon_link
*
tlink
;
int
rc
;
if
((
buf
->
CreationTime
==
0
)
&&
(
buf
->
LastAccessTime
==
0
)
&&
(
buf
->
LastWriteTime
==
0
)
&&
(
buf
->
ChangeTime
)
&&
(
buf
->
Attributes
==
0
))
return
0
;
/* would be a no op, no sense sending this */
tlink
=
cifs_sb_tlink
(
cifs_sb
);
if
(
IS_ERR
(
tlink
))
return
PTR_ERR
(
tlink
);
rc
=
smb2_open_op_close
(
xid
,
tlink_tcon
(
tlink
),
cifs_sb
,
full_path
,
FILE_WRITE_ATTRIBUTES
,
FILE_OPEN
,
0
,
buf
,
SMB2_OP_SET_INFO
);
...
...
sources/4.4/smb2misc.c
View file @
0688d963
...
...
@@ -525,19 +525,19 @@ smb2_is_valid_lease_break(char *buffer)
list_for_each
(
tmp1
,
&
server
->
smb_ses_list
)
{
ses
=
list_entry
(
tmp1
,
struct
cifs_ses
,
smb_ses_list
);
spin_lock
(
&
cifs_file_list_lock
);
list_for_each
(
tmp2
,
&
ses
->
tcon_list
)
{
tcon
=
list_entry
(
tmp2
,
struct
cifs_tcon
,
tcon_list
);
spin_lock
(
&
tcon
->
open_file_lock
);
cifs_stats_inc
(
&
tcon
->
stats
.
cifs_stats
.
num_oplock_brks
);
if
(
smb2_tcon_has_lease
(
tcon
,
rsp
,
lw
))
{
spin_unlock
(
&
cifs_file_list
_lock
);
spin_unlock
(
&
tcon
->
open_file
_lock
);
spin_unlock
(
&
cifs_tcp_ses_lock
);
return
true
;
}
spin_unlock
(
&
tcon
->
open_file_lock
);
}
spin_unlock
(
&
cifs_file_list_lock
);
}
}
spin_unlock
(
&
cifs_tcp_ses_lock
);
...
...
@@ -579,7 +579,7 @@ smb2_is_valid_oplock_break(char *buffer, struct TCP_Server_Info *server)
tcon
=
list_entry
(
tmp1
,
struct
cifs_tcon
,
tcon_list
);
cifs_stats_inc
(
&
tcon
->
stats
.
cifs_stats
.
num_oplock_brks
);
spin_lock
(
&
cifs_file_list
_lock
);
spin_lock
(
&
tcon
->
open_file
_lock
);
list_for_each
(
tmp2
,
&
tcon
->
openFileList
)
{
cfile
=
list_entry
(
tmp2
,
struct
cifsFileInfo
,
tlist
);
...
...
@@ -591,7 +591,7 @@ smb2_is_valid_oplock_break(char *buffer, struct TCP_Server_Info *server)
cifs_dbg
(
FYI
,
"file id match, oplock break
\n
"
);
cinode
=
CIFS_I
(
d_inode
(
cfile
->
dentry
));
spin_lock
(
&
cfile
->
file_info_lock
);
if
(
!
CIFS_CACHE_WRITE
(
cinode
)
&&
rsp
->
OplockLevel
==
SMB2_OPLOCK_LEVEL_NONE
)
cfile
->
oplock_break_cancelled
=
true
;
...
...
@@ -613,14 +613,14 @@ smb2_is_valid_oplock_break(char *buffer, struct TCP_Server_Info *server)
clear_bit
(
CIFS_INODE_DOWNGRADE_OPLOCK_TO_L2
,
&
cinode
->
flags
);
spin_unlock
(
&
cfile
->
file_info_lock
);
queue_work
(
cifsiod_wq
,
&
cfile
->
oplock_break
);
spin_unlock
(
&
cifs_file_list
_lock
);
spin_unlock
(
&
tcon
->
open_file
_lock
);
spin_unlock
(
&
cifs_tcp_ses_lock
);
return
true
;
}
spin_unlock
(
&
cifs_file_list
_lock
);
spin_unlock
(
&
tcon
->
open_file
_lock
);
spin_unlock
(
&
cifs_tcp_ses_lock
);
cifs_dbg
(
FYI
,
"No matching file for oplock break
\n
"
);
return
true
;
...
...
@@ -630,3 +630,47 @@ smb2_is_valid_oplock_break(char *buffer, struct TCP_Server_Info *server)
cifs_dbg
(
FYI
,
"Can not process oplock break for non-existent connection
\n
"
);
return
false
;
}
void
smb2_cancelled_close_fid
(
struct
work_struct
*
work
)
{
struct
close_cancelled_open
*
cancelled
=
container_of
(
work
,
struct
close_cancelled_open
,
work
);
cifs_dbg
(
VFS
,
"Close unmatched open
\n
"
);
SMB2_close
(
0
,
cancelled
->
tcon
,
cancelled
->
fid
.
persistent_fid
,
cancelled
->
fid
.
volatile_fid
);
cifs_put_tcon
(
cancelled
->
tcon
);
kfree
(
cancelled
);
}
int
smb2_handle_cancelled_mid
(
char
*
buffer
,
struct
TCP_Server_Info
*
server
)
{
struct
smb2_hdr
*
hdr
=
(
struct
smb2_hdr
*
)
buffer
;
struct
smb2_create_rsp
*
rsp
=
(
struct
smb2_create_rsp
*
)
buffer
;
struct
cifs_tcon
*
tcon
;
struct
close_cancelled_open
*
cancelled
;
if
(
hdr
->
Command
!=
SMB2_CREATE
||
hdr
->
Status
!=
STATUS_SUCCESS
)
return
0
;
cancelled
=
kzalloc
(
sizeof
(
*
cancelled
),
GFP_KERNEL
);
if
(
!
cancelled
)
return
-
ENOMEM
;
tcon
=
smb2_find_smb_tcon
(
server
,
hdr
->
SessionId
,
hdr
->
TreeId
);
if
(
!
tcon
)
{
kfree
(
cancelled
);
return
-
ENOENT
;
}
cancelled
->
fid
.
persistent_fid
=
rsp
->
PersistentFileId
;
cancelled
->
fid
.
volatile_fid
=
rsp
->
VolatileFileId
;
cancelled
->
tcon
=
tcon
;
INIT_WORK
(
&
cancelled
->
work
,
smb2_cancelled_close_fid
);
queue_work
(
cifsiod_wq
,
&
cancelled
->
work
);
return
0
;
}
sources/4.4/smb2ops.c
View file @
0688d963
...
...
@@ -282,7 +282,7 @@ SMB3_request_interfaces(const unsigned int xid, struct cifs_tcon *tcon)
cifs_dbg
(
FYI
,
"Link Speed %lld
\n
"
,
le64_to_cpu
(
out_buf
->
LinkSpeed
));
}
kfree
(
out_buf
);
return
rc
;
}
#endif
/* STATS2 */
...
...
@@ -539,6 +539,7 @@ smb2_set_fid(struct cifsFileInfo *cfile, struct cifs_fid *fid, __u32 oplock)
server
->
ops
->
set_oplock_level
(
cinode
,
oplock
,
fid
->
epoch
,
&
fid
->
purge_cache
);
cinode
->
can_cache_brlcks
=
CIFS_CACHE_WRITE
(
cinode
);
memcpy
(
cfile
->
fid
.
create_guid
,
fid
->
create_guid
,
16
);
}
static
void
...
...
@@ -697,6 +698,7 @@ smb2_clone_range(const unsigned int xid,
cchunk_out:
kfree
(
pcchunk
);
kfree
(
retbuf
);
return
rc
;
}
...
...
@@ -821,7 +823,6 @@ smb2_duplicate_extents(const unsigned int xid,
{
int
rc
;
unsigned
int
ret_data_len
;
char
*
retbuf
=
NULL
;
struct
duplicate_extents_to_file
dup_ext_buf
;
struct
cifs_tcon
*
tcon
=
tlink_tcon
(
trgtfile
->
tlink
);
...
...
@@ -847,7 +848,7 @@ smb2_duplicate_extents(const unsigned int xid,
FSCTL_DUPLICATE_EXTENTS_TO_FILE
,
true
/* is_fsctl */
,
(
char
*
)
&
dup_ext_buf
,
sizeof
(
struct
duplicate_extents_to_file
),
(
char
**
)
&
retbuf
,
NULL
,
&
ret_data_len
);
if
(
ret_data_len
>
0
)
...
...
@@ -870,7 +871,6 @@ smb3_set_integrity(const unsigned int xid, struct cifs_tcon *tcon,
struct
cifsFileInfo
*
cfile
)
{
struct
fsctl_set_integrity_information_req
integr_info
;
char
*
retbuf
=
NULL
;
unsigned
int
ret_data_len
;
integr_info
.
ChecksumAlgorithm
=
cpu_to_le16
(
CHECKSUM_TYPE_UNCHANGED
);
...
...
@@ -882,7 +882,7 @@ smb3_set_integrity(const unsigned int xid, struct cifs_tcon *tcon,
FSCTL_SET_INTEGRITY_INFORMATION
,
true
/* is_fsctl */
,
(
char
*
)
&
integr_info
,
sizeof
(
struct
fsctl_set_integrity_information_req
),
(
char
**
)
&
retbuf
,
NULL
,
&
ret_data_len
);
}
...
...
@@ -913,7 +913,7 @@ smb2_query_dir_first(const unsigned int xid, struct cifs_tcon *tcon,
rc
=
SMB2_open
(
xid
,
&
oparms
,
utf16_path
,
&
oplock
,
NULL
,
NULL
);
kfree
(
utf16_path
);
if
(
rc
)
{
cifs_dbg
(
VFS
,
"open dir failed
\n
"
);
cifs_dbg
(
FYI
,
"open dir failed rc=%d
\n
"
,
rc
);
return
rc
;
}
...
...
@@ -923,7 +923,7 @@ smb2_query_dir_first(const unsigned int xid, struct cifs_tcon *tcon,
rc
=
SMB2_query_directory
(
xid
,
tcon
,
fid
->
persistent_fid
,
fid
->
volatile_fid
,
0
,
srch_inf
);
if
(
rc
)
{
cifs_dbg
(
VFS
,
"query directory failed
\n
"
);
cifs_dbg
(
FYI
,
"query directory failed rc=%d
\n
"
,
rc
);
SMB2_close
(
xid
,
tcon
,
fid
->
persistent_fid
,
fid
->
volatile_fid
);
}
return
rc
;
...
...
@@ -967,6 +967,18 @@ smb2_is_status_pending(char *buf, struct TCP_Server_Info *server, int length)
return
true
;
}
static
bool
smb2_is_session_expired
(
char
*
buf
)
{
struct
smb2_hdr
*
hdr
=
(
struct
smb2_hdr
*
)
buf
;
if
(
hdr
->
Status
!=
STATUS_NETWORK_SESSION_EXPIRED
)
return
false
;
cifs_dbg
(
FYI
,
"Session expired
\n
"
);
return
true
;
}
static
int
smb2_oplock_response
(
struct
cifs_tcon
*
tcon
,
struct
cifs_fid
*
fid
,
struct
cifsInodeInfo
*
cinode
)
...
...
@@ -1041,9 +1053,12 @@ smb2_set_lease_key(struct inode *inode, struct cifs_fid *fid)
static
void
smb2_new_lease_key
(
struct
cifs_fid
*
fid
)
{
ge
t_random_bytes
(
fid
->
lease_key
,
SMB2_LEASE_KEY_SIZE
);
ge
nerate_random_uuid
(
fid
->
lease_key
);
}
#define SMB2_SYMLINK_STRUCT_SIZE \
(sizeof(struct smb2_err_rsp) - 1 + sizeof(struct smb2_symlink_err_rsp))
static
int
smb2_query_symlink
(
const
unsigned
int
xid
,
struct
cifs_tcon
*
tcon
,
const
char
*
full_path
,
char
**
target_path
,
...
...
@@ -1056,7 +1071,10 @@ smb2_query_symlink(const unsigned int xid, struct cifs_tcon *tcon,
struct
cifs_fid
fid
;
struct
smb2_err_rsp
*
err_buf
=
NULL
;
struct
smb2_symlink_err_rsp
*
symlink
;
unsigned
int
sub_len
,
sub_offset
;
unsigned
int
sub_len
;
unsigned
int
sub_offset
;
unsigned
int
print_len
;
unsigned
int
print_offset
;
cifs_dbg
(
FYI
,
"%s: path: %s
\n
"
,
__func__
,
full_path
);
...
...
@@ -1078,11 +1096,33 @@ smb2_query_symlink(const unsigned int xid, struct cifs_tcon *tcon,
kfree
(
utf16_path
);
return
-
ENOENT
;
}
if
(
le32_to_cpu
(
err_buf
->
ByteCount
)
<
sizeof
(
struct
smb2_symlink_err_rsp
)
||
get_rfc1002_length
(
err_buf
)
+
4
<
SMB2_SYMLINK_STRUCT_SIZE
)
{
kfree
(
utf16_path
);
return
-
ENOENT
;
}
/* open must fail on symlink - reset rc */
rc
=
0
;
symlink
=
(
struct
smb2_symlink_err_rsp
*
)
err_buf
->
ErrorData
;
sub_len
=
le16_to_cpu
(
symlink
->
SubstituteNameLength
);
sub_offset
=
le16_to_cpu
(
symlink
->
SubstituteNameOffset
);
print_len
=
le16_to_cpu
(
symlink
->
PrintNameLength
);
print_offset
=
le16_to_cpu
(
symlink
->
PrintNameOffset
);
if
(
get_rfc1002_length
(
err_buf
)
+
4
<
SMB2_SYMLINK_STRUCT_SIZE
+
sub_offset
+
sub_len
)
{
kfree
(
utf16_path
);
return
-
ENOENT
;
}
if
(
get_rfc1002_length
(
err_buf
)
+
4
<
SMB2_SYMLINK_STRUCT_SIZE
+
print_offset
+
print_len
)
{
kfree
(
utf16_path
);
return
-
ENOENT
;
}
*
target_path
=
cifs_strndup_from_utf16
(
(
char
*
)
symlink
->
PathBuffer
+
sub_offset
,
sub_len
,
true
,
cifs_sb
->
local_nls
);
...
...
@@ -1489,6 +1529,7 @@ struct smb_version_operations smb20_operations = {
.
clear_stats
=
smb2_clear_stats
,
.
print_stats
=
smb2_print_stats
,
.
is_oplock_break
=
smb2_is_valid_oplock_break
,
.
handle_cancelled_mid
=
smb2_handle_cancelled_mid
,
.
downgrade_oplock
=
smb2_downgrade_oplock
,
.
need_neg
=
smb2_need_neg
,
.
negotiate
=
smb2_negotiate
,
...
...
@@ -1529,6 +1570,7 @@ struct smb_version_operations smb20_operations = {
.
close_dir
=
smb2_close_dir
,
.
calc_smb_size
=
smb2_calc_size
,
.
is_status_pending
=
smb2_is_status_pending
,
.
is_session_expired
=
smb2_is_session_expired
,
.
oplock_response
=
smb2_oplock_response
,
.
queryfs
=
smb2_queryfs
,
.
mand_lock
=
smb2_mand_lock
,
...
...
@@ -1567,6 +1609,7 @@ struct smb_version_operations smb21_operations = {
.
clear_stats
=
smb2_clear_stats
,
.
print_stats
=
smb2_print_stats
,
.
is_oplock_break
=
smb2_is_valid_oplock_break
,
.
handle_cancelled_mid
=
smb2_handle_cancelled_mid
,
.
downgrade_oplock
=
smb2_downgrade_oplock
,
.
need_neg
=
smb2_need_neg
,
.
negotiate
=
smb2_negotiate
,
...
...
@@ -1609,6 +1652,7 @@ struct smb_version_operations smb21_operations = {
.
close_dir
=
smb2_close_dir
,
.
calc_smb_size
=
smb2_calc_size
,
.
is_status_pending
=
smb2_is_status_pending
,
.
is_session_expired
=
smb2_is_session_expired
,
.
oplock_response
=
smb2_oplock_response
,
.
queryfs
=
smb2_queryfs
,
.
mand_lock
=
smb2_mand_lock
,
...
...
@@ -1648,6 +1692,7 @@ struct smb_version_operations smb30_operations = {
.
print_stats
=
smb2_print_stats
,
.
dump_share_caps
=
smb2_dump_share_caps
,
.
is_oplock_break
=
smb2_is_valid_oplock_break
,
.
handle_cancelled_mid
=
smb2_handle_cancelled_mid
,
.
downgrade_oplock
=
smb2_downgrade_oplock
,
.
need_neg
=
smb2_need_neg
,
.
negotiate
=
smb2_negotiate
,
...
...
@@ -1690,6 +1735,7 @@ struct smb_version_operations smb30_operations = {
.
close_dir
=
smb2_close_dir
,
.
calc_smb_size
=
smb2_calc_size
,
.
is_status_pending
=
smb2_is_status_pending
,
.
is_session_expired
=
smb2_is_session_expired
,
.
oplock_response
=
smb2_oplock_response
,
.
queryfs
=
smb2_queryfs
,
.
mand_lock
=
smb2_mand_lock
,
...
...
@@ -1735,6 +1781,7 @@ struct smb_version_operations smb311_operations = {
.
print_stats
=
smb2_print_stats
,
.
dump_share_caps
=
smb2_dump_share_caps
,
.
is_oplock_break
=
smb2_is_valid_oplock_break
,
.
handle_cancelled_mid
=
smb2_handle_cancelled_mid
,
.
downgrade_oplock
=
smb2_downgrade_oplock
,
.
need_neg
=
smb2_need_neg
,
.
negotiate
=
smb2_negotiate
,
...
...
@@ -1777,6 +1824,7 @@ struct smb_version_operations smb311_operations = {
.
close_dir
=
smb2_close_dir
,
.
calc_smb_size
=
smb2_calc_size
,
.
is_status_pending
=
smb2_is_status_pending
,
.
is_session_expired
=
smb2_is_session_expired
,
.
oplock_response
=
smb2_oplock_response
,
.
queryfs
=
smb2_queryfs
,
.
mand_lock
=
smb2_mand_lock
,
...
...
sources/4.4/smb2pdu.c
View file @
0688d963
...
...
@@ -103,7 +103,21 @@ smb2_hdr_assemble(struct smb2_hdr *hdr, __le16 smb2_cmd /* command */ ,
hdr
->
ProtocolId
[
3
]
=
'B'
;
hdr
->
StructureSize
=
cpu_to_le16
(
64
);
hdr
->
Command
=
smb2_cmd
;
hdr
->
CreditRequest
=
cpu_to_le16
(
2
);
/* BB make this dynamic */
if
(
tcon
&&
tcon
->
ses
&&
tcon
->
ses
->
server
)
{
struct
TCP_Server_Info
*
server
=
tcon
->
ses
->
server
;
spin_lock
(
&
server
->
req_lock
);
/* Request up to 2 credits but don't go over the limit. */
if
(
server
->
credits
>=
SMB2_MAX_CREDITS_AVAILABLE
)
hdr
->
CreditRequest
=
cpu_to_le16
(
0
);
else
hdr
->
CreditRequest
=
cpu_to_le16
(
min_t
(
int
,
SMB2_MAX_CREDITS_AVAILABLE
-
server
->
credits
,
2
));
spin_unlock
(
&
server
->
req_lock
);
}
else
{
hdr
->
CreditRequest
=
cpu_to_le16
(
2
);
}
hdr
->
ProcessId
=
cpu_to_le32
((
__u16
)
current
->
tgid
);
if
(
!
tcon
)
...
...
@@ -264,7 +278,7 @@ out:
case
SMB2_CHANGE_NOTIFY
:
case
SMB2_QUERY_INFO
:
case
SMB2_SET_INFO
:
r
eturn
-
EAGAIN
;
r
c
=
-
EAGAIN
;
}
unload_nls
(
nls_codepage
);
return
rc
;
...
...
@@ -347,7 +361,7 @@ assemble_neg_contexts(struct smb2_negotiate_req *req)
build_encrypt_ctxt
((
struct
smb2_encryption_neg_context
*
)
pneg_ctxt
);
req
->
NegotiateContextOffset
=
cpu_to_le32
(
OFFSET_OF_NEG_CONTEXT
);
req
->
NegotiateContextCount
=
cpu_to_le16
(
2
);
inc_rfc1001_len
(
req
,
4
+
sizeof
(
struct
smb2_preauth_neg_context
)
+
2
inc_rfc1001_len
(
req
,
4
+
sizeof
(
struct
smb2_preauth_neg_context
)
+
sizeof
(
struct
smb2_encryption_neg_context
));
/* calculate hash */
}
#else
...
...
@@ -512,14 +526,21 @@ int smb3_validate_negotiate(const unsigned int xid, struct cifs_tcon *tcon)
/*
* validation ioctl must be signed, so no point sending this if we
* can not sign it. We could eventually change this to selectively
* can not sign it (ie are not known user). Even if signing is not
* required (enabled but not negotiated), in those cases we selectively
* sign just this, the first and only signed request on a connection.
* This is good enough for now since a user who wants better security
* would also enable signing on the mount. Having validation of
* negotiate info for signed connections helps reduce attack vectors
* Having validation of negotiate info helps reduce attack vectors.
*/
if
(
tcon
->
ses
->
server
->
sign
==
false
)
if
(
tcon
->
ses
->
session_flags
&
SMB2_SESSION_FLAG_IS_GUEST
)
return
0
;
/* validation requires signing */
if
(
tcon
->
ses
->
user_name
==
NULL
)
{
cifs_dbg
(
FYI
,
"Can't validate negotiate: null user mount
\n
"
);
return
0
;
/* validation requires signing */
}
if
(
tcon
->
ses
->
session_flags
&
SMB2_SESSION_FLAG_IS_NULL
)
cifs_dbg
(
VFS
,
"Unexpected null user (anonymous) auth flag sent by server
\n
"
);
vneg_inbuf
.
Capabilities
=
cpu_to_le32
(
tcon
->
ses
->
server
->
vals
->
req_capabilities
);
...
...
@@ -550,8 +571,12 @@ int smb3_validate_negotiate(const unsigned int xid, struct cifs_tcon *tcon)
}
if
(
rsplen
!=
sizeof
(
struct
validate_negotiate_info_rsp
))
{
cifs_dbg
(
VFS
,
"invalid size of protocol negotiate response
\n
"
);
return
-
EIO
;
cifs_dbg
(
VFS
,
"invalid protocol negotiate response size: %d
\n
"
,
rsplen
);
/* relax check since Mac returns max bufsize allowed on ioctl */
if
(
rsplen
>
CIFSMaxBufSize
)
return
-
EIO
;
}
/* check validate negotiate info response matches what we got earlier */
...
...
@@ -591,8 +616,9 @@ SMB2_sess_setup(const unsigned int xid, struct cifs_ses *ses,
u16
blob_length
=
0
;
struct
key
*
spnego_key
=
NULL
;
char
*
security_blob
=
NULL
;
char
*
ntlmssp_blob
=
NULL
;
unsigned
char
*
ntlmssp_blob
=
NULL
;
bool
use_spnego
=
false
;
/* else use raw ntlmssp */
u64
previous_session
=
ses
->
Suid
;
cifs_dbg
(
FYI
,
"Session Setup
\n
"
);
...
...
@@ -630,6 +656,10 @@ ssetup_ntlmssp_authenticate:
return
rc
;
req
->
hdr
.
SessionId
=
0
;
/* First session, not a reauthenticate */
/* if reconnect, we need to send previous sess id, otherwise it is 0 */
req
->
PreviousSessionId
=
previous_session
;
req
->
Flags
=
0
;
/* MBZ */
/* to enable echos and oplocks */
req
->
hdr
.
CreditRequest
=
cpu_to_le16
(
3
);
...
...
@@ -716,13 +746,7 @@ ssetup_ntlmssp_authenticate:
iov
[
1
].
iov_len
=
blob_length
;
}
else
if
(
phase
==
NtLmAuthenticate
)
{
req
->
hdr
.
SessionId
=
ses
->
Suid
;
ntlmssp_blob
=
kzalloc
(
sizeof
(
struct
_NEGOTIATE_MESSAGE
)
+
500
,
GFP_KERNEL
);
if
(
ntlmssp_blob
==
NULL
)
{
rc
=
-
ENOMEM
;
goto
ssetup_exit
;
}
rc
=
build_ntlmssp_auth_blob
(
ntlmssp_blob
,
&
blob_length
,
ses
,
rc
=
build_ntlmssp_auth_blob
(
&
ntlmssp_blob
,
&
blob_length
,
ses
,
nls_cp
);
if
(
rc
)
{
cifs_dbg
(
FYI
,
"build_ntlmssp_auth_blob failed %d
\n
"
,
...
...
@@ -919,9 +943,6 @@ SMB2_tcon(const unsigned int xid, struct cifs_ses *ses, const char *tree,
else
return
-
EIO
;
if
(
tcon
&&
tcon
->
bad_network_name
)
return
-
ENOENT
;
if
((
tcon
&&
tcon
->
seal
)
&&
((
ses
->
server
->
capabilities
&
SMB2_GLOBAL_CAP_ENCRYPTION
)
==
0
))
{
cifs_dbg
(
VFS
,
"encryption requested but no server support"
);
...
...
@@ -939,6 +960,10 @@ SMB2_tcon(const unsigned int xid, struct cifs_ses *ses, const char *tree,
return
-
EINVAL
;
}
/* SMB2 TREE_CONNECT request must be called with TreeId == 0 */
if
(
tcon
)
tcon
->
tid
=
0
;
rc
=
small_smb2_init
(
SMB2_TREE_CONNECT
,
tcon
,
(
void
**
)
&
req
);
if
(
rc
)
{
kfree
(
unc_path
);
...
...
@@ -1019,8 +1044,6 @@ tcon_exit:
tcon_error_exit:
if
(
rsp
->
hdr
.
Status
==
STATUS_BAD_NETWORK_NAME
)
{
cifs_dbg
(
VFS
,
"BAD_NETWORK_NAME: %s
\n
"
,
tree
);
if
(
tcon
)
tcon
->
bad_network_name
=
true
;
}
goto
tcon_exit
;
}
...
...
@@ -1173,7 +1196,7 @@ create_durable_v2_buf(struct cifs_fid *pfid)
buf
->
dcontext
.
Timeout
=
0
;
/* Should this be configurable by workload */
buf
->
dcontext
.
Flags
=
cpu_to_le32
(
SMB2_DHANDLE_FLAG_PERSISTENT
);
ge
t_random_bytes
(
buf
->
dcontext
.
CreateGuid
,
16
);
ge
nerate_random_uuid
(
buf
->
dcontext
.
CreateGuid
);
memcpy
(
pfid
->
create_guid
,
buf
->
dcontext
.
CreateGuid
,
16
);
/* SMB2_CREATE_DURABLE_HANDLE_REQUEST is "DH2Q" */
...
...
@@ -1506,8 +1529,12 @@ SMB2_ioctl(const unsigned int xid, struct cifs_tcon *tcon, u64 persistent_fid,
* than one credit. Windows typically sets this smaller, but for some
* ioctls it may be useful to allow server to send more. No point
* limiting what the server can send as long as fits in one credit
* Unfortunately - we can not handle more than CIFS_MAX_MSG_SIZE
* (by default, note that it can be overridden to make max larger)
* in responses (except for read responses which can be bigger.
* We may want to bump this limit up
*/
req
->
MaxOutputResponse
=
cpu_to_le32
(
0xFF00
);
/* < 64K uses 1 credit */
req
->
MaxOutputResponse
=
cpu_to_le32
(
CIFSMaxBufSize
);
if
(
is_fsctl
)
req
->
Flags
=
cpu_to_le32
(
SMB2_0_IOCTL_IS_FSCTL
);
...
...
@@ -1809,6 +1836,54 @@ smb2_echo_callback(struct mid_q_entry *mid)
add_credits
(
server
,
credits_received
,
CIFS_ECHO_OP
);
}
void
smb2_reconnect_server
(
struct
work_struct
*
work
)
{
struct
TCP_Server_Info
*
server
=
container_of
(
work
,
struct
TCP_Server_Info
,
reconnect
.
work
);
struct
cifs_ses
*
ses
;
struct
cifs_tcon
*
tcon
,
*
tcon2
;
struct
list_head
tmp_list
;
int
tcon_exist
=
false
;
/* Prevent simultaneous reconnects that can corrupt tcon->rlist list */
mutex_lock
(
&
server
->
reconnect_mutex
);
INIT_LIST_HEAD
(
&
tmp_list
);
cifs_dbg
(
FYI
,
"Need negotiate, reconnecting tcons
\n
"
);
spin_lock
(
&
cifs_tcp_ses_lock
);
list_for_each_entry
(
ses
,
&
server
->
smb_ses_list
,
smb_ses_list
)
{
list_for_each_entry
(
tcon
,
&
ses
->
tcon_list
,
tcon_list
)
{
if
(
tcon
->
need_reconnect
)
{
tcon
->
tc_count
++
;
list_add_tail
(
&
tcon
->
rlist
,
&
tmp_list
);
tcon_exist
=
true
;
}
}
}
/*
* Get the reference to server struct to be sure that the last call of
* cifs_put_tcon() in the loop below won't release the server pointer.
*/
if
(
tcon_exist
)
server
->
srv_count
++
;
spin_unlock
(
&
cifs_tcp_ses_lock
);
list_for_each_entry_safe
(
tcon
,
tcon2
,
&
tmp_list
,
rlist
)
{
smb2_reconnect
(
SMB2_ECHO
,
tcon
);
list_del_init
(
&
tcon
->
rlist
);
cifs_put_tcon
(
tcon
);
}
cifs_dbg
(
FYI
,
"Reconnecting tcons finished
\n
"
);
mutex_unlock
(
&
server
->
reconnect_mutex
);
/* now we can safely release srv struct */
if
(
tcon_exist
)
cifs_put_tcp_session
(
server
,
1
);
}
int
SMB2_echo
(
struct
TCP_Server_Info
*
server
)
{
...
...
@@ -1820,6 +1895,12 @@ SMB2_echo(struct TCP_Server_Info *server)
cifs_dbg
(
FYI
,
"In echo request
\n
"
);
if
(
server
->
tcpStatus
==
CifsNeedNegotiate
)
{
/* No need to send echo on newly established connections */
queue_delayed_work
(
cifsiod_wq
,
&
server
->
reconnect
,
0
);
return
rc
;
}
rc
=
small_smb2_init
(
SMB2_ECHO
,
NULL
,
(
void
**
)
&
req
);
if
(
rc
)
return
rc
;
...
...
@@ -2038,6 +2119,7 @@ smb2_async_readv(struct cifs_readdata *rdata)
if
(
rdata
->
credits
)
{
buf
->
CreditCharge
=
cpu_to_le16
(
DIV_ROUND_UP
(
rdata
->
bytes
,
SMB2_MAX_BUFFER_SIZE
));
buf
->
CreditRequest
=
buf
->
CreditCharge
;
spin_lock
(
&
server
->
req_lock
);
server
->
credits
+=
rdata
->
credits
-
le16_to_cpu
(
buf
->
CreditCharge
);
...
...
@@ -2224,6 +2306,7 @@ smb2_async_writev(struct cifs_writedata *wdata,
if
(
wdata
->
credits
)
{
req
->
hdr
.
CreditCharge
=
cpu_to_le16
(
DIV_ROUND_UP
(
wdata
->
bytes
,
SMB2_MAX_BUFFER_SIZE
));
req
->
hdr
.
CreditRequest
=
req
->
hdr
.
CreditCharge
;
spin_lock
(
&
server
->
req_lock
);
server
->
credits
+=
wdata
->
credits
-
le16_to_cpu
(
req
->
hdr
.
CreditCharge
);
...
...
@@ -2692,8 +2775,8 @@ copy_fs_info_to_kstatfs(struct smb2_fs_full_size_info *pfs_inf,
kst
->
f_bsize
=
le32_to_cpu
(
pfs_inf
->
BytesPerSector
)
*
le32_to_cpu
(
pfs_inf
->
SectorsPerAllocationUnit
);
kst
->
f_blocks
=
le64_to_cpu
(
pfs_inf
->
TotalAllocationUnits
);
kst
->
f_bfree
=
le64_to_cpu
(
pfs_inf
->
ActualAvailableAllocationUnits
);
kst
->
f_bavail
=
le64_to_cpu
(
pfs_inf
->
CallerAvailableAllocationUnits
);
kst
->
f_bfree
=
kst
->
f_bavail
=
le64_to_cpu
(
pfs_inf
->
CallerAvailableAllocationUnits
);
return
;
}
...
...
sources/4.4/smb2pdu.h
View file @
0688d963
...
...
@@ -82,8 +82,8 @@
#define NUMBER_OF_SMB2_COMMANDS 0x0013
/*
BB FIXME - analyze following length BB
*/
#define MAX_SMB2_HDR_SIZE 0x
78
/* 4 len + 64 hdr + (2*24 wct) + 2 bct + 2 pad */
/*
4 len + 52 transform hdr + 64 hdr + 56 create rsp
*/
#define MAX_SMB2_HDR_SIZE 0x
00b0
#define SMB2_PROTO_NUMBER cpu_to_le32(0x424d53fe)
...
...
@@ -276,7 +276,7 @@ struct smb2_sess_setup_req {
__le32
Channel
;
__le16
SecurityBufferOffset
;
__le16
SecurityBufferLength
;
__
le
64
PreviousSessionId
;
__
u
64
PreviousSessionId
;
__u8
Buffer
[
1
];
/* variable length GSS security buffer */
}
__packed
;
...
...
sources/4.4/smb2proto.h
View file @
0688d963
...
...
@@ -47,6 +47,10 @@ extern struct mid_q_entry *smb2_setup_request(struct cifs_ses *ses,
struct
smb_rqst
*
rqst
);
extern
struct
mid_q_entry
*
smb2_setup_async_request
(
struct
TCP_Server_Info
*
server
,
struct
smb_rqst
*
rqst
);
extern
struct
cifs_ses
*
smb2_find_smb_ses
(
struct
TCP_Server_Info
*
server
,
__u64
ses_id
);
extern
struct
cifs_tcon
*
smb2_find_smb_tcon
(
struct
TCP_Server_Info
*
server
,
__u64
ses_id
,
__u32
tid
);
extern
int
smb2_calc_signature
(
struct
smb_rqst
*
rqst
,
struct
TCP_Server_Info
*
server
);
extern
int
smb3_calc_signature
(
struct
smb_rqst
*
rqst
,
...
...
@@ -95,6 +99,7 @@ extern int smb2_open_file(const unsigned int xid,
extern
int
smb2_unlock_range
(
struct
cifsFileInfo
*
cfile
,
struct
file_lock
*
flock
,
const
unsigned
int
xid
);
extern
int
smb2_push_mandatory_locks
(
struct
cifsFileInfo
*
cfile
);
extern
void
smb2_reconnect_server
(
struct
work_struct
*
work
);
/*
* SMB2 Worker functions - most of protocol specific implementation details
...
...
@@ -156,6 +161,9 @@ extern int SMB2_set_compression(const unsigned int xid, struct cifs_tcon *tcon,
extern
int
SMB2_oplock_break
(
const
unsigned
int
xid
,
struct
cifs_tcon
*
tcon
,
const
u64
persistent_fid
,
const
u64
volatile_fid
,
const
__u8
oplock_level
);
extern
int
smb2_handle_cancelled_mid
(
char
*
buffer
,
struct
TCP_Server_Info
*
server
);
void
smb2_cancelled_close_fid
(
struct
work_struct
*
work
);
extern
int
SMB2_QFS_info
(
const
unsigned
int
xid
,
struct
cifs_tcon
*
tcon
,
u64
persistent_file_id
,
u64
volatile_file_id
,
struct
kstatfs
*
FSData
);
...
...
sources/4.4/smb2transport.c
View file @
0688d963
...
...
@@ -115,22 +115,68 @@ smb3_crypto_shash_allocate(struct TCP_Server_Info *server)
}
static
struct
cifs_ses
*
smb2_find_smb_ses
(
struct
smb2_hdr
*
smb2hdr
,
struct
TCP_Server_Info
*
server
)
smb2_find_smb_ses
_unlocked
(
struct
TCP_Server_Info
*
server
,
__u64
ses_id
)
{
struct
cifs_ses
*
ses
;
spin_lock
(
&
cifs_tcp_ses_lock
);
list_for_each_entry
(
ses
,
&
server
->
smb_ses_list
,
smb_ses_list
)
{
if
(
ses
->
Suid
!=
s
mb2hdr
->
SessionI
d
)
if
(
ses
->
Suid
!=
s
es_i
d
)
continue
;
spin_unlock
(
&
cifs_tcp_ses_lock
);
return
ses
;
}
return
NULL
;
}
struct
cifs_ses
*
smb2_find_smb_ses
(
struct
TCP_Server_Info
*
server
,
__u64
ses_id
)
{
struct
cifs_ses
*
ses
;
spin_lock
(
&
cifs_tcp_ses_lock
);
ses
=
smb2_find_smb_ses_unlocked
(
server
,
ses_id
);
spin_unlock
(
&
cifs_tcp_ses_lock
);
return
ses
;
}
static
struct
cifs_tcon
*
smb2_find_smb_sess_tcon_unlocked
(
struct
cifs_ses
*
ses
,
__u32
tid
)
{
struct
cifs_tcon
*
tcon
;
list_for_each_entry
(
tcon
,
&
ses
->
tcon_list
,
tcon_list
)
{
if
(
tcon
->
tid
!=
tid
)
continue
;
++
tcon
->
tc_count
;
return
tcon
;
}
return
NULL
;
}
/*
* Obtain tcon corresponding to the tid in the given
* cifs_ses
*/
struct
cifs_tcon
*
smb2_find_smb_tcon
(
struct
TCP_Server_Info
*
server
,
__u64
ses_id
,
__u32
tid
)
{
struct
cifs_ses
*
ses
;
struct
cifs_tcon
*
tcon
;
spin_lock
(
&
cifs_tcp_ses_lock
);
ses
=
smb2_find_smb_ses_unlocked
(
server
,
ses_id
);
if
(
!
ses
)
{
spin_unlock
(
&
cifs_tcp_ses_lock
);
return
NULL
;
}
tcon
=
smb2_find_smb_sess_tcon_unlocked
(
ses
,
tid
);
spin_unlock
(
&
cifs_tcp_ses_lock
);
return
tcon
;
}
int
smb2_calc_signature
(
struct
smb_rqst
*
rqst
,
struct
TCP_Server_Info
*
server
)
...
...
@@ -143,7 +189,7 @@ smb2_calc_signature(struct smb_rqst *rqst, struct TCP_Server_Info *server)
struct
smb2_hdr
*
smb2_pdu
=
(
struct
smb2_hdr
*
)
iov
[
0
].
iov_base
;
struct
cifs_ses
*
ses
;
ses
=
smb2_find_smb_ses
(
s
mb2_pdu
,
server
);
ses
=
smb2_find_smb_ses
(
s
erver
,
smb2_pdu
->
SessionId
);
if
(
!
ses
)
{
cifs_dbg
(
VFS
,
"%s: Could not find session
\n
"
,
__func__
);
return
0
;
...
...
@@ -314,7 +360,7 @@ smb3_calc_signature(struct smb_rqst *rqst, struct TCP_Server_Info *server)
struct
smb2_hdr
*
smb2_pdu
=
(
struct
smb2_hdr
*
)
iov
[
0
].
iov_base
;
struct
cifs_ses
*
ses
;
ses
=
smb2_find_smb_ses
(
s
mb2_pdu
,
server
);
ses
=
smb2_find_smb_ses
(
s
erver
,
smb2_pdu
->
SessionId
);
if
(
!
ses
)
{
cifs_dbg
(
VFS
,
"%s: Could not find session
\n
"
,
__func__
);
return
0
;
...
...
sources/4.4/transport.c
View file @
0688d963
...
...
@@ -786,9 +786,11 @@ SendReceive2(const unsigned int xid, struct cifs_ses *ses,
rc
=
wait_for_response
(
ses
->
server
,
midQ
);
if
(
rc
!=
0
)
{
cifs_dbg
(
FYI
,
"Cancelling wait for mid %llu
\n
"
,
midQ
->
mid
);
send_cancel
(
ses
->
server
,
buf
,
midQ
);
spin_lock
(
&
GlobalMid_Lock
);
if
(
midQ
->
mid_state
==
MID_REQUEST_SUBMITTED
)
{
midQ
->
mid_flags
|=
MID_WAIT_CANCELLED
;
midQ
->
callback
=
DeleteMidQEntry
;
spin_unlock
(
&
GlobalMid_Lock
);
cifs_small_buf_release
(
buf
);
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment