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
5e9ae94e
Commit
5e9ae94e
authored
Feb 08, 2018
by
Vitaly Lipatov
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
update 4.1 up to v4.1.49
parent
4f75e546
Hide whitespace changes
Inline
Side-by-side
Showing
20 changed files
with
443 additions
and
110 deletions
+443
-110
cifs_fs_sb.h
sources/4.1/cifs_fs_sb.h
+4
-0
cifs_unicode.c
sources/4.1/cifs_unicode.c
+35
-4
cifs_unicode.h
sources/4.1/cifs_unicode.h
+3
-0
cifsencrypt.c
sources/4.1/cifsencrypt.c
+10
-6
cifsfs.c
sources/4.1/cifsfs.c
+13
-1
cifsglob.h
sources/4.1/cifsglob.h
+3
-1
cifsproto.h
sources/4.1/cifsproto.h
+3
-0
cifssmb.c
sources/4.1/cifssmb.c
+3
-0
connect.c
sources/4.1/connect.c
+104
-13
dir.c
sources/4.1/dir.c
+52
-11
file.c
sources/4.1/file.c
+10
-3
inode.c
sources/4.1/inode.c
+22
-4
ntlmssp.h
sources/4.1/ntlmssp.h
+1
-1
sess.c
sources/4.1/sess.c
+42
-34
smb1ops.c
sources/4.1/smb1ops.c
+17
-2
smb2file.c
sources/4.1/smb2file.c
+1
-1
smb2ops.c
sources/4.1/smb2ops.c
+31
-3
smb2pdu.c
sources/4.1/smb2pdu.c
+86
-24
smb2pdu.h
sources/4.1/smb2pdu.h
+2
-2
smb2proto.h
sources/4.1/smb2proto.h
+1
-0
No files found.
sources/4.1/cifs_fs_sb.h
View file @
5e9ae94e
...
...
@@ -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.1/cifs_unicode.c
View file @
5e9ae94e
...
...
@@ -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.1/cifs_unicode.h
View file @
5e9ae94e
...
...
@@ -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.1/cifsencrypt.c
View file @
5e9ae94e
...
...
@@ -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.1/cifsfs.c
View file @
5e9ae94e
...
...
@@ -682,6 +682,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
);
...
...
@@ -720,7 +728,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
;
...
...
sources/4.1/cifsglob.h
View file @
5e9ae94e
...
...
@@ -615,6 +615,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 */
};
...
...
@@ -814,6 +816,7 @@ 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
;
struct
cifs_ses
*
ses
;
/* pointer to session associated with */
char
treeName
[
MAX_TREE_SIZE
+
1
];
/* UNC name of resource in ASCII */
...
...
@@ -888,7 +891,6 @@ struct cifs_tcon {
bool
need_reconnect
:
1
;
/* connection reset, tid now invalid */
#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
;
...
...
sources/4.1/cifsproto.h
View file @
5e9ae94e
...
...
@@ -207,6 +207,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.1/cifssmb.c
View file @
5e9ae94e
...
...
@@ -716,6 +716,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
;
...
...
sources/4.1/connect.c
View file @
5e9ae94e
...
...
@@ -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
...
...
@@ -399,6 +402,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
;
}
...
...
@@ -408,16 +414,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
;
...
...
@@ -2072,8 +2089,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
;
...
...
@@ -2090,6 +2107,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
);
...
...
@@ -2154,6 +2184,10 @@ 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
,
...
...
@@ -2306,7 +2340,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
...
...
@@ -2479,7 +2513,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
;
}
...
...
@@ -2569,7 +2603,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
;
...
...
@@ -3439,6 +3473,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
)
{
...
...
@@ -3565,6 +3637,16 @@ remote_path_check:
kfree
(
full_path
);
goto
mount_fail_check
;
}
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
);
}
...
...
@@ -3628,7 +3710,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
);
}
...
...
@@ -3834,6 +3916,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
);
}
...
...
@@ -3879,6 +3962,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
);
...
...
@@ -3938,7 +4029,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.1/dir.c
View file @
5e9ae94e
...
...
@@ -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.1/file.c
View file @
5e9ae94e
...
...
@@ -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
;
...
...
@@ -2543,7 +2550,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 +2963,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 +3549,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
);
...
...
sources/4.1/inode.c
View file @
5e9ae94e
...
...
@@ -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
*/
...
...
@@ -2121,7 +2139,7 @@ cifs_setattr_unix(struct dentry *direntry, struct iattr *attrs)
if
(
cifs_sb
->
mnt_cifs_flags
&
CIFS_MOUNT_NO_PERM
)
attrs
->
ia_valid
|=
ATTR_FORCE
;
rc
=
inode_change_ok
(
inode
,
attrs
);
rc
=
setattr_prepare
(
direntry
,
attrs
);
if
(
rc
<
0
)
goto
out
;
...
...
@@ -2261,7 +2279,7 @@ cifs_setattr_nounix(struct dentry *direntry, struct iattr *attrs)
if
(
cifs_sb
->
mnt_cifs_flags
&
CIFS_MOUNT_NO_PERM
)
attrs
->
ia_valid
|=
ATTR_FORCE
;
rc
=
inode_change_ok
(
inode
,
attrs
);
rc
=
setattr_prepare
(
direntry
,
attrs
);
if
(
rc
<
0
)
{
free_xid
(
xid
);
return
rc
;
...
...
sources/4.1/ntlmssp.h
View file @
5e9ae94e
...
...
@@ -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.1/sess.c
View file @
5e9ae94e
...
...
@@ -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.1/smb1ops.c
View file @
5e9ae94e
...
...
@@ -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.1/smb2file.c
View file @
5e9ae94e
...
...
@@ -241,7 +241,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.1/smb2ops.c
View file @
5e9ae94e
...
...
@@ -847,7 +847,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
;
}
...
...
@@ -857,7 +857,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
;
...
...
@@ -978,6 +978,9 @@ smb2_new_lease_key(struct cifs_fid *fid)
get_random_bytes
(
fid
->
lease_key
,
SMB2_LEASE_KEY_SIZE
);
}
#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
,
...
...
@@ -990,7 +993,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
);
...
...
@@ -1012,11 +1018,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
);
...
...
sources/4.1/smb2pdu.c
View file @
5e9ae94e
...
...
@@ -264,7 +264,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
;
...
...
@@ -453,15 +453,22 @@ 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
->
se
rver
->
sign
==
false
)
if
(
tcon
->
ses
->
se
ssion_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
);
memcpy
(
vneg_inbuf
.
Guid
,
tcon
->
ses
->
server
->
client_guid
,
...
...
@@ -491,8 +498,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 */
...
...
@@ -532,7 +543,7 @@ 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 */
cifs_dbg
(
FYI
,
"Session Setup
\n
"
);
...
...
@@ -657,13 +668,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
"
,
...
...
@@ -860,9 +865,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
;
unc_path
=
kmalloc
(
MAX_SHARENAME_LENGTH
*
2
,
GFP_KERNEL
);
if
(
unc_path
==
NULL
)
return
-
ENOMEM
;
...
...
@@ -874,6 +876,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
);
...
...
@@ -952,8 +958,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
;
}
...
...
@@ -1320,8 +1324,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
);
...
...
@@ -1621,6 +1629,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
)
{
...
...
@@ -1632,6 +1688,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
;
...
...
@@ -2499,8 +2561,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.1/smb2pdu.h
View file @
5e9ae94e
...
...
@@ -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)
...
...
sources/4.1/smb2proto.h
View file @
5e9ae94e
...
...
@@ -95,6 +95,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
...
...
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