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 @@
...
@@ -46,6 +46,9 @@
#define CIFS_MOUNT_CIFS_BACKUPUID 0x200000
/* backup intent bit for a user */
#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_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_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
cifs_sb_info
{
struct
rb_root
tlink_tree
;
struct
rb_root
tlink_tree
;
...
@@ -67,5 +70,6 @@ struct cifs_sb_info {
...
@@ -67,5 +70,6 @@ struct cifs_sb_info {
struct
backing_dev_info
bdi
;
struct
backing_dev_info
bdi
;
struct
delayed_work
prune_tlinks
;
struct
delayed_work
prune_tlinks
;
struct
rcu_head
rcu
;
struct
rcu_head
rcu
;
char
*
prepath
;
};
};
#endif
/* _CIFS_FS_SB_H */
#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)
...
@@ -83,6 +83,9 @@ convert_sfm_char(const __u16 src_char, char *target)
case
SFM_COLON
:
case
SFM_COLON
:
*
target
=
':'
;
*
target
=
':'
;
break
;
break
;
case
SFM_DOUBLEQUOTE
:
*
target
=
'"'
;
break
;
case
SFM_ASTERISK
:
case
SFM_ASTERISK
:
*
target
=
'*'
;
*
target
=
'*'
;
break
;
break
;
...
@@ -101,6 +104,12 @@ convert_sfm_char(const __u16 src_char, char *target)
...
@@ -101,6 +104,12 @@ convert_sfm_char(const __u16 src_char, char *target)
case
SFM_SLASH
:
case
SFM_SLASH
:
*
target
=
'\\'
;
*
target
=
'\\'
;
break
;
break
;
case
SFM_SPACE
:
*
target
=
' '
;
break
;
case
SFM_PERIOD
:
*
target
=
'.'
;
break
;
default:
default:
return
false
;
return
false
;
}
}
...
@@ -404,7 +413,7 @@ static __le16 convert_to_sfu_char(char src_char)
...
@@ -404,7 +413,7 @@ static __le16 convert_to_sfu_char(char src_char)
return
dest_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
;
__le16
dest_char
;
...
@@ -412,6 +421,9 @@ static __le16 convert_to_sfm_char(char src_char)
...
@@ -412,6 +421,9 @@ static __le16 convert_to_sfm_char(char src_char)
case
':'
:
case
':'
:
dest_char
=
cpu_to_le16
(
SFM_COLON
);
dest_char
=
cpu_to_le16
(
SFM_COLON
);
break
;
break
;
case
'"'
:
dest_char
=
cpu_to_le16
(
SFM_DOUBLEQUOTE
);
break
;
case
'*'
:
case
'*'
:
dest_char
=
cpu_to_le16
(
SFM_ASTERISK
);
dest_char
=
cpu_to_le16
(
SFM_ASTERISK
);
break
;
break
;
...
@@ -427,6 +439,18 @@ static __le16 convert_to_sfm_char(char src_char)
...
@@ -427,6 +439,18 @@ static __le16 convert_to_sfm_char(char src_char)
case
'|'
:
case
'|'
:
dest_char
=
cpu_to_le16
(
SFM_PIPE
);
dest_char
=
cpu_to_le16
(
SFM_PIPE
);
break
;
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:
default:
dest_char
=
0
;
dest_char
=
0
;
}
}
...
@@ -469,9 +493,16 @@ cifsConvertToUTF16(__le16 *target, const char *source, int srclen,
...
@@ -469,9 +493,16 @@ cifsConvertToUTF16(__le16 *target, const char *source, int srclen,
/* see if we must remap this char */
/* see if we must remap this char */
if
(
map_chars
==
SFU_MAP_UNI_RSVD
)
if
(
map_chars
==
SFU_MAP_UNI_RSVD
)
dst_char
=
convert_to_sfu_char
(
src_char
);
dst_char
=
convert_to_sfu_char
(
src_char
);
else
if
(
map_chars
==
SFM_MAP_UNI_RSVD
)
else
if
(
map_chars
==
SFM_MAP_UNI_RSVD
)
{
dst_char
=
convert_to_sfm_char
(
src_char
);
bool
end_of_string
;
else
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
;
dst_char
=
0
;
/*
/*
* FIXME: We can not handle remapping backslash (UNI_SLASH)
* FIXME: We can not handle remapping backslash (UNI_SLASH)
...
...
sources/4.1/cifs_unicode.h
View file @
5e9ae94e
...
@@ -57,6 +57,7 @@
...
@@ -57,6 +57,7 @@
* not conflict (although almost does) with the mapping above.
* not conflict (although almost does) with the mapping above.
*/
*/
#define SFM_DOUBLEQUOTE ((__u16) 0xF020)
#define SFM_ASTERISK ((__u16) 0xF021)
#define SFM_ASTERISK ((__u16) 0xF021)
#define SFM_QUESTION ((__u16) 0xF025)
#define SFM_QUESTION ((__u16) 0xF025)
#define SFM_COLON ((__u16) 0xF022)
#define SFM_COLON ((__u16) 0xF022)
...
@@ -64,6 +65,8 @@
...
@@ -64,6 +65,8 @@
#define SFM_LESSTHAN ((__u16) 0xF023)
#define SFM_LESSTHAN ((__u16) 0xF023)
#define SFM_PIPE ((__u16) 0xF027)
#define SFM_PIPE ((__u16) 0xF027)
#define SFM_SLASH ((__u16) 0xF026)
#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
* 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)
...
@@ -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
);
memcpy
(
ses
->
auth_key
.
response
+
baselen
,
tiblob
,
tilen
);
mutex_lock
(
&
ses
->
server
->
srv_mutex
);
rc
=
crypto_hmacmd5_alloc
(
ses
->
server
);
rc
=
crypto_hmacmd5_alloc
(
ses
->
server
);
if
(
rc
)
{
if
(
rc
)
{
cifs_dbg
(
VFS
,
"could not crypto alloc hmacmd5 rc %d
\n
"
,
rc
);
cifs_dbg
(
VFS
,
"could not crypto alloc hmacmd5 rc %d
\n
"
,
rc
);
goto
setup_ntlmv2_rsp_ret
;
goto
unlock
;
}
}
/* calculate ntlmv2_hash */
/* calculate ntlmv2_hash */
rc
=
calc_ntlmv2_hash
(
ses
,
ntlmv2_hash
,
nls_cp
);
rc
=
calc_ntlmv2_hash
(
ses
,
ntlmv2_hash
,
nls_cp
);
if
(
rc
)
{
if
(
rc
)
{
cifs_dbg
(
VFS
,
"could not get v2 hash rc %d
\n
"
,
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) */
/* calculate first part of the client response (CR1) */
rc
=
CalcNTLMv2_response
(
ses
,
ntlmv2_hash
);
rc
=
CalcNTLMv2_response
(
ses
,
ntlmv2_hash
);
if
(
rc
)
{
if
(
rc
)
{
cifs_dbg
(
VFS
,
"Could not calculate CR1 rc: %d
\n
"
,
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 */
/* now calculate the session key for NTLMv2 */
...
@@ -757,13 +759,13 @@ setup_ntlmv2_rsp(struct cifs_ses *ses, const struct nls_table *nls_cp)
...
@@ -757,13 +759,13 @@ setup_ntlmv2_rsp(struct cifs_ses *ses, const struct nls_table *nls_cp)
if
(
rc
)
{
if
(
rc
)
{
cifs_dbg
(
VFS
,
"%s: Could not set NTLMV2 Hash as a key
\n
"
,
cifs_dbg
(
VFS
,
"%s: Could not set NTLMV2 Hash as a key
\n
"
,
__func__
);
__func__
);
goto
setup_ntlmv2_rsp_ret
;
goto
unlock
;
}
}
rc
=
crypto_shash_init
(
&
ses
->
server
->
secmech
.
sdeschmacmd5
->
shash
);
rc
=
crypto_shash_init
(
&
ses
->
server
->
secmech
.
sdeschmacmd5
->
shash
);
if
(
rc
)
{
if
(
rc
)
{
cifs_dbg
(
VFS
,
"%s: Could not init hmacmd5
\n
"
,
__func__
);
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
,
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)
...
@@ -771,7 +773,7 @@ setup_ntlmv2_rsp(struct cifs_ses *ses, const struct nls_table *nls_cp)
CIFS_HMAC_MD5_HASH_SIZE
);
CIFS_HMAC_MD5_HASH_SIZE
);
if
(
rc
)
{
if
(
rc
)
{
cifs_dbg
(
VFS
,
"%s: Could not update with response
\n
"
,
__func__
);
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
,
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)
...
@@ -779,6 +781,8 @@ setup_ntlmv2_rsp(struct cifs_ses *ses, const struct nls_table *nls_cp)
if
(
rc
)
if
(
rc
)
cifs_dbg
(
VFS
,
"%s: Could not generate md5 hash
\n
"
,
__func__
);
cifs_dbg
(
VFS
,
"%s: Could not generate md5 hash
\n
"
,
__func__
);
unlock:
mutex_unlock
(
&
ses
->
server
->
srv_mutex
);
setup_ntlmv2_rsp_ret:
setup_ntlmv2_rsp_ret:
kfree
(
tiblob
);
kfree
(
tiblob
);
...
...
sources/4.1/cifsfs.c
View file @
5e9ae94e
...
@@ -682,6 +682,14 @@ cifs_do_mount(struct file_system_type *fs_type,
...
@@ -682,6 +682,14 @@ cifs_do_mount(struct file_system_type *fs_type,
goto
out_cifs_sb
;
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
);
cifs_setup_cifs_sb
(
volume_info
,
cifs_sb
);
rc
=
cifs_mount
(
cifs_sb
,
volume_info
);
rc
=
cifs_mount
(
cifs_sb
,
volume_info
);
...
@@ -720,7 +728,11 @@ cifs_do_mount(struct file_system_type *fs_type,
...
@@ -720,7 +728,11 @@ cifs_do_mount(struct file_system_type *fs_type,
sb
->
s_flags
|=
MS_ACTIVE
;
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
))
if
(
IS_ERR
(
root
))
goto
out_super
;
goto
out_super
;
...
...
sources/4.1/cifsglob.h
View file @
5e9ae94e
...
@@ -615,6 +615,8 @@ struct TCP_Server_Info {
...
@@ -615,6 +615,8 @@ struct TCP_Server_Info {
#ifdef CONFIG_CIFS_SMB2
#ifdef CONFIG_CIFS_SMB2
unsigned
int
max_read
;
unsigned
int
max_read
;
unsigned
int
max_write
;
unsigned
int
max_write
;
struct
delayed_work
reconnect
;
/* reconnect workqueue job */
struct
mutex
reconnect_mutex
;
/* prevent simultaneous reconnects */
#endif
/* CONFIG_CIFS_SMB2 */
#endif
/* CONFIG_CIFS_SMB2 */
};
};
...
@@ -814,6 +816,7 @@ cap_unix(struct cifs_ses *ses)
...
@@ -814,6 +816,7 @@ cap_unix(struct cifs_ses *ses)
struct
cifs_tcon
{
struct
cifs_tcon
{
struct
list_head
tcon_list
;
struct
list_head
tcon_list
;
int
tc_count
;
int
tc_count
;
struct
list_head
rlist
;
/* reconnect list */
struct
list_head
openFileList
;
struct
list_head
openFileList
;
struct
cifs_ses
*
ses
;
/* pointer to session associated with */
struct
cifs_ses
*
ses
;
/* pointer to session associated with */
char
treeName
[
MAX_TREE_SIZE
+
1
];
/* UNC name of resource in ASCII */
char
treeName
[
MAX_TREE_SIZE
+
1
];
/* UNC name of resource in ASCII */
...
@@ -888,7 +891,6 @@ struct cifs_tcon {
...
@@ -888,7 +891,6 @@ struct cifs_tcon {
bool
need_reconnect
:
1
;
/* connection reset, tid now invalid */
bool
need_reconnect
:
1
;
/* connection reset, tid now invalid */
#ifdef CONFIG_CIFS_SMB2
#ifdef CONFIG_CIFS_SMB2
bool
print
:
1
;
/* set if connection to printer share */
bool
print
:
1
;
/* set if connection to printer share */
bool
bad_network_name
:
1
;
/* set if ret status STATUS_BAD_NETWORK_NAME */
__le32
capabilities
;
__le32
capabilities
;
__u32
share_flags
;
__u32
share_flags
;
__u32
maximal_access
;
__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,
...
@@ -207,6 +207,9 @@ extern void cifs_add_pending_open_locked(struct cifs_fid *fid,
struct
tcon_link
*
tlink
,
struct
tcon_link
*
tlink
,
struct
cifs_pending_open
*
open
);
struct
cifs_pending_open
*
open
);
extern
void
cifs_del_pending_open
(
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)
#if IS_ENABLED(CONFIG_CIFS_DFS_UPCALL)
extern
void
cifs_dfs_release_automount_timer
(
void
);
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)
...
@@ -716,6 +716,9 @@ CIFSSMBEcho(struct TCP_Server_Info *server)
if
(
rc
)
if
(
rc
)
return
rc
;
return
rc
;
if
(
server
->
capabilities
&
CAP_UNICODE
)
smb
->
hdr
.
Flags2
|=
SMBFLG2_UNICODE
;
/* set up echo request */
/* set up echo request */
smb
->
hdr
.
Tid
=
0xffff
;
smb
->
hdr
.
Tid
=
0xffff
;
smb
->
hdr
.
WordCount
=
1
;
smb
->
hdr
.
WordCount
=
1
;
...
...
sources/4.1/connect.c
View file @
5e9ae94e
...
@@ -52,6 +52,9 @@
...
@@ -52,6 +52,9 @@
#include "nterr.h"
#include "nterr.h"
#include "rfc1002pdu.h"
#include "rfc1002pdu.h"
#include "fscache.h"
#include "fscache.h"
#ifdef CONFIG_CIFS_SMB2
#include "smb2proto.h"
#endif
#define CIFS_PORT 445
#define CIFS_PORT 445
#define RFC1001_PORT 139
#define RFC1001_PORT 139
...
@@ -399,6 +402,9 @@ cifs_reconnect(struct TCP_Server_Info *server)
...
@@ -399,6 +402,9 @@ cifs_reconnect(struct TCP_Server_Info *server)
}
}
}
while
(
server
->
tcpStatus
==
CifsNeedReconnect
);
}
while
(
server
->
tcpStatus
==
CifsNeedReconnect
);
if
(
server
->
tcpStatus
==
CifsNeedNegotiate
)
mod_delayed_work
(
cifsiod_wq
,
&
server
->
echo
,
0
);
return
rc
;
return
rc
;
}
}
...
@@ -408,16 +414,27 @@ cifs_echo_request(struct work_struct *work)
...
@@ -408,16 +414,27 @@ cifs_echo_request(struct work_struct *work)
int
rc
;
int
rc
;
struct
TCP_Server_Info
*
server
=
container_of
(
work
,
struct
TCP_Server_Info
*
server
=
container_of
(
work
,
struct
TCP_Server_Info
,
echo
.
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
* We cannot send an echo if it is disabled.
* NEGOTIATE_PROTOCOL request is done, which is indicated by
* Also, no need to ping if we got a response recently.
* server->ops->need_neg() == true. 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
))
||
(
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
;
goto
requeue_echo
;
rc
=
server
->
ops
->
echo
?
server
->
ops
->
echo
(
server
)
:
-
ENOSYS
;
rc
=
server
->
ops
->
echo
?
server
->
ops
->
echo
(
server
)
:
-
ENOSYS
;
...
@@ -2072,8 +2089,8 @@ cifs_find_tcp_session(struct smb_vol *vol)
...
@@ -2072,8 +2089,8 @@ cifs_find_tcp_session(struct smb_vol *vol)
return
NULL
;
return
NULL
;
}
}
static
void
void
cifs_put_tcp_session
(
struct
TCP_Server_Info
*
server
)
cifs_put_tcp_session
(
struct
TCP_Server_Info
*
server
,
int
from_reconnect
)
{
{
struct
task_struct
*
task
;
struct
task_struct
*
task
;
...
@@ -2090,6 +2107,19 @@ cifs_put_tcp_session(struct TCP_Server_Info *server)
...
@@ -2090,6 +2107,19 @@ cifs_put_tcp_session(struct TCP_Server_Info *server)
cancel_delayed_work_sync
(
&
server
->
echo
);
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
);
spin_lock
(
&
GlobalMid_Lock
);
server
->
tcpStatus
=
CifsExiting
;
server
->
tcpStatus
=
CifsExiting
;
spin_unlock
(
&
GlobalMid_Lock
);
spin_unlock
(
&
GlobalMid_Lock
);
...
@@ -2154,6 +2184,10 @@ cifs_get_tcp_session(struct smb_vol *volume_info)
...
@@ -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
->
tcp_ses_list
);
INIT_LIST_HEAD
(
&
tcp_ses
->
smb_ses_list
);
INIT_LIST_HEAD
(
&
tcp_ses
->
smb_ses_list
);
INIT_DELAYED_WORK
(
&
tcp_ses
->
echo
,
cifs_echo_request
);
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
,
memcpy
(
&
tcp_ses
->
srcaddr
,
&
volume_info
->
srcaddr
,
sizeof
(
tcp_ses
->
srcaddr
));
sizeof
(
tcp_ses
->
srcaddr
));
memcpy
(
&
tcp_ses
->
dstaddr
,
&
volume_info
->
dstaddr
,
memcpy
(
&
tcp_ses
->
dstaddr
,
&
volume_info
->
dstaddr
,
...
@@ -2306,7 +2340,7 @@ cifs_put_smb_ses(struct cifs_ses *ses)
...
@@ -2306,7 +2340,7 @@ cifs_put_smb_ses(struct cifs_ses *ses)
spin_unlock
(
&
cifs_tcp_ses_lock
);
spin_unlock
(
&
cifs_tcp_ses_lock
);
sesInfoFree
(
ses
);
sesInfoFree
(
ses
);
cifs_put_tcp_session
(
server
);
cifs_put_tcp_session
(
server
,
0
);
}
}
#ifdef CONFIG_KEYS
#ifdef CONFIG_KEYS
...
@@ -2479,7 +2513,7 @@ cifs_get_smb_ses(struct TCP_Server_Info *server, struct smb_vol *volume_info)
...
@@ -2479,7 +2513,7 @@ cifs_get_smb_ses(struct TCP_Server_Info *server, struct smb_vol *volume_info)
mutex_unlock
(
&
ses
->
session_mutex
);
mutex_unlock
(
&
ses
->
session_mutex
);
/* existing SMB ses has a server reference already */
/* existing SMB ses has a server reference already */
cifs_put_tcp_session
(
server
);
cifs_put_tcp_session
(
server
,
0
);
free_xid
(
xid
);
free_xid
(
xid
);
return
ses
;
return
ses
;
}
}
...
@@ -2569,7 +2603,7 @@ cifs_find_tcon(struct cifs_ses *ses, const char *unc)
...
@@ -2569,7 +2603,7 @@ cifs_find_tcon(struct cifs_ses *ses, const char *unc)
return
NULL
;
return
NULL
;
}
}
static
void
void
cifs_put_tcon
(
struct
cifs_tcon
*
tcon
)
cifs_put_tcon
(
struct
cifs_tcon
*
tcon
)
{
{
unsigned
int
xid
;
unsigned
int
xid
;
...
@@ -3439,6 +3473,44 @@ cifs_get_volume_info(char *mount_data, const char *devname)
...
@@ -3439,6 +3473,44 @@ cifs_get_volume_info(char *mount_data, const char *devname)
return
volume_info
;
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
int
cifs_mount
(
struct
cifs_sb_info
*
cifs_sb
,
struct
smb_vol
*
volume_info
)
cifs_mount
(
struct
cifs_sb_info
*
cifs_sb
,
struct
smb_vol
*
volume_info
)
{
{
...
@@ -3565,6 +3637,16 @@ remote_path_check:
...
@@ -3565,6 +3637,16 @@ remote_path_check:
kfree
(
full_path
);
kfree
(
full_path
);
goto
mount_fail_check
;
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
);
kfree
(
full_path
);
}
}
...
@@ -3628,7 +3710,7 @@ mount_fail_check:
...
@@ -3628,7 +3710,7 @@ mount_fail_check:
else
if
(
ses
)
else
if
(
ses
)
cifs_put_smb_ses
(
ses
);
cifs_put_smb_ses
(
ses
);
else
else
cifs_put_tcp_session
(
server
);
cifs_put_tcp_session
(
server
,
0
);
bdi_destroy
(
&
cifs_sb
->
bdi
);
bdi_destroy
(
&
cifs_sb
->
bdi
);
}
}
...
@@ -3834,6 +3916,7 @@ cifs_umount(struct cifs_sb_info *cifs_sb)
...
@@ -3834,6 +3916,7 @@ cifs_umount(struct cifs_sb_info *cifs_sb)
bdi_destroy
(
&
cifs_sb
->
bdi
);
bdi_destroy
(
&
cifs_sb
->
bdi
);
kfree
(
cifs_sb
->
mountdata
);
kfree
(
cifs_sb
->
mountdata
);
kfree
(
cifs_sb
->
prepath
);
call_rcu
(
&
cifs_sb
->
rcu
,
delayed_free
);
call_rcu
(
&
cifs_sb
->
rcu
,
delayed_free
);
}
}
...
@@ -3879,6 +3962,14 @@ cifs_setup_session(const unsigned int xid, struct cifs_ses *ses,
...
@@ -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
"
,
cifs_dbg
(
FYI
,
"Security Mode: 0x%x Capabilities: 0x%x TimeAdjust: %d
\n
"
,
server
->
sec_mode
,
server
->
capabilities
,
server
->
timeAdj
);
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
)
if
(
server
->
ops
->
sess_setup
)
rc
=
server
->
ops
->
sess_setup
(
xid
,
ses
,
nls_info
);
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)
...
@@ -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
);
ses
=
cifs_get_smb_ses
(
master_tcon
->
ses
->
server
,
vol_info
);
if
(
IS_ERR
(
ses
))
{
if
(
IS_ERR
(
ses
))
{
tcon
=
(
struct
cifs_tcon
*
)
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
;
goto
out
;
}
}
...
...
sources/4.1/dir.c
View file @
5e9ae94e
...
@@ -84,6 +84,7 @@ build_path_from_dentry(struct dentry *direntry)
...
@@ -84,6 +84,7 @@ build_path_from_dentry(struct dentry *direntry)
struct
dentry
*
temp
;
struct
dentry
*
temp
;
int
namelen
;
int
namelen
;
int
dfsplen
;
int
dfsplen
;
int
pplen
=
0
;
char
*
full_path
;
char
*
full_path
;
char
dirsep
;
char
dirsep
;
struct
cifs_sb_info
*
cifs_sb
=
CIFS_SB
(
direntry
->
d_sb
);
struct
cifs_sb_info
*
cifs_sb
=
CIFS_SB
(
direntry
->
d_sb
);
...
@@ -95,8 +96,12 @@ build_path_from_dentry(struct dentry *direntry)
...
@@ -95,8 +96,12 @@ build_path_from_dentry(struct dentry *direntry)
dfsplen
=
strnlen
(
tcon
->
treeName
,
MAX_TREE_SIZE
+
1
);
dfsplen
=
strnlen
(
tcon
->
treeName
,
MAX_TREE_SIZE
+
1
);
else
else
dfsplen
=
0
;
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:
cifs_bp_rename_retry:
namelen
=
dfsplen
;
namelen
=
dfsplen
+
pplen
;
seq
=
read_seqbegin
(
&
rename_lock
);
seq
=
read_seqbegin
(
&
rename_lock
);
rcu_read_lock
();
rcu_read_lock
();
for
(
temp
=
direntry
;
!
IS_ROOT
(
temp
);)
{
for
(
temp
=
direntry
;
!
IS_ROOT
(
temp
);)
{
...
@@ -137,7 +142,7 @@ cifs_bp_rename_retry:
...
@@ -137,7 +142,7 @@ cifs_bp_rename_retry:
}
}
}
}
rcu_read_unlock
();
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
"
,
cifs_dbg
(
FYI
,
"did not end path lookup where expected. namelen=%ddfsplen=%d
\n
"
,
namelen
,
dfsplen
);
namelen
,
dfsplen
);
/* presumably this is only possible if racing with a rename
/* presumably this is only possible if racing with a rename
...
@@ -153,6 +158,17 @@ cifs_bp_rename_retry:
...
@@ -153,6 +158,17 @@ cifs_bp_rename_retry:
those safely to '/' if any are found in the middle of the prepath */
those safely to '/' if any are found in the middle of the prepath */
/* BB test paths to Windows with '/' in the midst of 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
)
{
if
(
dfsplen
)
{
strncpy
(
full_path
,
tcon
->
treeName
,
dfsplen
);
strncpy
(
full_path
,
tcon
->
treeName
,
dfsplen
);
if
(
cifs_sb
->
mnt_cifs_flags
&
CIFS_MOUNT_POSIX_PATHS
)
{
if
(
cifs_sb
->
mnt_cifs_flags
&
CIFS_MOUNT_POSIX_PATHS
)
{
...
@@ -167,15 +183,21 @@ cifs_bp_rename_retry:
...
@@ -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.
* Don't allow the separator character in a path component.
* The VFS will not allow "/", but "\" is allowed by posix.
* The VFS will not allow "/", but "\" is allowed by posix.
*/
*/
static
int
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
);
struct
cifs_sb_info
*
cifs_sb
=
CIFS_SB
(
direntry
->
d_sb
);
int
i
;
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
))
{
if
(
!
(
cifs_sb
->
mnt_cifs_flags
&
CIFS_MOUNT_POSIX_PATHS
))
{
for
(
i
=
0
;
i
<
direntry
->
d_name
.
len
;
i
++
)
{
for
(
i
=
0
;
i
<
direntry
->
d_name
.
len
;
i
++
)
{
if
(
direntry
->
d_name
.
name
[
i
]
==
'\\'
)
{
if
(
direntry
->
d_name
.
name
[
i
]
==
'\\'
)
{
...
@@ -231,6 +253,13 @@ cifs_do_create(struct inode *inode, struct dentry *direntry, unsigned int xid,
...
@@ -231,6 +253,13 @@ cifs_do_create(struct inode *inode, struct dentry *direntry, unsigned int xid,
goto
cifs_create_get_file_info
;
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
))
{
if
(
!
S_ISREG
(
newinode
->
i_mode
))
{
/*
/*
* The server may allow us to open things like
* The server may allow us to open things like
...
@@ -404,10 +433,14 @@ cifs_create_set_dentry:
...
@@ -404,10 +433,14 @@ cifs_create_set_dentry:
if
(
rc
!=
0
)
{
if
(
rc
!=
0
)
{
cifs_dbg
(
FYI
,
"Create worked, get_inode_info failed rc = %d
\n
"
,
cifs_dbg
(
FYI
,
"Create worked, get_inode_info failed rc = %d
\n
"
,
rc
);
rc
);
if
(
server
->
ops
->
close
)
goto
out_err
;
server
->
ops
->
close
(
xid
,
tcon
,
fid
);
goto
out
;
}
}
if
(
S_ISDIR
(
newinode
->
i_mode
))
{
rc
=
-
EISDIR
;
goto
out_err
;
}
d_drop
(
direntry
);
d_drop
(
direntry
);
d_add
(
direntry
,
newinode
);
d_add
(
direntry
,
newinode
);
...
@@ -415,6 +448,13 @@ out:
...
@@ -415,6 +448,13 @@ out:
kfree
(
buf
);
kfree
(
buf
);
kfree
(
full_path
);
kfree
(
full_path
);
return
rc
;
return
rc
;
out_err:
if
(
server
->
ops
->
close
)
server
->
ops
->
close
(
xid
,
tcon
,
fid
);
if
(
newinode
)
iput
(
newinode
);
goto
out
;
}
}
int
int
...
@@ -460,10 +500,6 @@ cifs_atomic_open(struct inode *inode, struct dentry *direntry,
...
@@ -460,10 +500,6 @@ cifs_atomic_open(struct inode *inode, struct dentry *direntry,
return
finish_no_open
(
file
,
res
);
return
finish_no_open
(
file
,
res
);
}
}
rc
=
check_name
(
direntry
);
if
(
rc
)
return
rc
;
xid
=
get_xid
();
xid
=
get_xid
();
cifs_dbg
(
FYI
,
"parent inode = 0x%p name is: %pd and dentry = 0x%p
\n
"
,
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,
...
@@ -476,6 +512,11 @@ cifs_atomic_open(struct inode *inode, struct dentry *direntry,
}
}
tcon
=
tlink_tcon
(
tlink
);
tcon
=
tlink_tcon
(
tlink
);
rc
=
check_name
(
direntry
,
tcon
);
if
(
rc
)
goto
out
;
server
=
tcon
->
ses
->
server
;
server
=
tcon
->
ses
->
server
;
if
(
server
->
ops
->
new_lease_key
)
if
(
server
->
ops
->
new_lease_key
)
...
@@ -736,7 +777,7 @@ cifs_lookup(struct inode *parent_dir_inode, struct dentry *direntry,
...
@@ -736,7 +777,7 @@ cifs_lookup(struct inode *parent_dir_inode, struct dentry *direntry,
}
}
pTcon
=
tlink_tcon
(
tlink
);
pTcon
=
tlink_tcon
(
tlink
);
rc
=
check_name
(
direntry
);
rc
=
check_name
(
direntry
,
pTcon
);
if
(
rc
)
if
(
rc
)
goto
lookup_out
;
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,
...
@@ -226,6 +226,13 @@ cifs_nt_open(char *full_path, struct inode *inode, struct cifs_sb_info *cifs_sb,
if
(
backup_cred
(
cifs_sb
))
if
(
backup_cred
(
cifs_sb
))
create_options
|=
CREATE_OPEN_BACKUP_INTENT
;
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
.
tcon
=
tcon
;
oparms
.
cifs_sb
=
cifs_sb
;
oparms
.
cifs_sb
=
cifs_sb
;
oparms
.
desired_access
=
desired_access
;
oparms
.
desired_access
=
desired_access
;
...
@@ -2543,7 +2550,7 @@ cifs_write_from_iter(loff_t offset, size_t len, struct iov_iter *from,
...
@@ -2543,7 +2550,7 @@ cifs_write_from_iter(loff_t offset, size_t len, struct iov_iter *from,
wdata
->
credits
=
credits
;
wdata
->
credits
=
credits
;
if
(
!
wdata
->
cfile
->
invalidHandle
||
if
(
!
wdata
->
cfile
->
invalidHandle
||
!
cifs_reopen_file
(
wdata
->
cfile
,
false
))
!
(
rc
=
cifs_reopen_file
(
wdata
->
cfile
,
false
)
))
rc
=
server
->
ops
->
async_writev
(
wdata
,
rc
=
server
->
ops
->
async_writev
(
wdata
,
cifs_uncached_writedata_release
);
cifs_uncached_writedata_release
);
if
(
rc
)
{
if
(
rc
)
{
...
@@ -2956,7 +2963,7 @@ cifs_send_async_read(loff_t offset, size_t len, struct cifsFileInfo *open_file,
...
@@ -2956,7 +2963,7 @@ cifs_send_async_read(loff_t offset, size_t len, struct cifsFileInfo *open_file,
rdata
->
credits
=
credits
;
rdata
->
credits
=
credits
;
if
(
!
rdata
->
cfile
->
invalidHandle
||
if
(
!
rdata
->
cfile
->
invalidHandle
||
!
cifs_reopen_file
(
rdata
->
cfile
,
true
))
!
(
rc
=
cifs_reopen_file
(
rdata
->
cfile
,
true
)
))
rc
=
server
->
ops
->
async_readv
(
rdata
);
rc
=
server
->
ops
->
async_readv
(
rdata
);
error:
error:
if
(
rc
)
{
if
(
rc
)
{
...
@@ -3542,7 +3549,7 @@ static int cifs_readpages(struct file *file, struct address_space *mapping,
...
@@ -3542,7 +3549,7 @@ static int cifs_readpages(struct file *file, struct address_space *mapping,
}
}
if
(
!
rdata
->
cfile
->
invalidHandle
||
if
(
!
rdata
->
cfile
->
invalidHandle
||
!
cifs_reopen_file
(
rdata
->
cfile
,
true
))
!
(
rc
=
cifs_reopen_file
(
rdata
->
cfile
,
true
)
))
rc
=
server
->
ops
->
async_readv
(
rdata
);
rc
=
server
->
ops
->
async_readv
(
rdata
);
if
(
rc
)
{
if
(
rc
)
{
add_credits_and_wake_if
(
server
,
rdata
->
credits
,
0
);
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)
...
@@ -983,10 +983,26 @@ struct inode *cifs_root_iget(struct super_block *sb)
struct
inode
*
inode
=
NULL
;
struct
inode
*
inode
=
NULL
;
long
rc
;
long
rc
;
struct
cifs_tcon
*
tcon
=
cifs_sb_master_tcon
(
cifs_sb
);
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
();
xid
=
get_xid
();
if
(
tcon
->
unix_ext
)
{
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 */
/* some servers mistakenly claim POSIX support */
if
(
rc
!=
-
EOPNOTSUPP
)
if
(
rc
!=
-
EOPNOTSUPP
)
goto
iget_no_retry
;
goto
iget_no_retry
;
...
@@ -994,7 +1010,8 @@ struct inode *cifs_root_iget(struct super_block *sb)
...
@@ -994,7 +1010,8 @@ struct inode *cifs_root_iget(struct super_block *sb)
tcon
->
unix_ext
=
false
;
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:
iget_no_retry:
if
(
!
inode
)
{
if
(
!
inode
)
{
...
@@ -1023,6 +1040,7 @@ iget_no_retry:
...
@@ -1023,6 +1040,7 @@ iget_no_retry:
}
}
out:
out:
kfree
(
path
);
/* can not call macro free_xid here since in a void func
/* can not call macro free_xid here since in a void func
* TODO: This is no longer true
* TODO: This is no longer true
*/
*/
...
@@ -2121,7 +2139,7 @@ cifs_setattr_unix(struct dentry *direntry, struct iattr *attrs)
...
@@ -2121,7 +2139,7 @@ cifs_setattr_unix(struct dentry *direntry, struct iattr *attrs)
if
(
cifs_sb
->
mnt_cifs_flags
&
CIFS_MOUNT_NO_PERM
)
if
(
cifs_sb
->
mnt_cifs_flags
&
CIFS_MOUNT_NO_PERM
)
attrs
->
ia_valid
|=
ATTR_FORCE
;
attrs
->
ia_valid
|=
ATTR_FORCE
;
rc
=
inode_change_ok
(
inode
,
attrs
);
rc
=
setattr_prepare
(
direntry
,
attrs
);
if
(
rc
<
0
)
if
(
rc
<
0
)
goto
out
;
goto
out
;
...
@@ -2261,7 +2279,7 @@ cifs_setattr_nounix(struct dentry *direntry, struct iattr *attrs)
...
@@ -2261,7 +2279,7 @@ cifs_setattr_nounix(struct dentry *direntry, struct iattr *attrs)
if
(
cifs_sb
->
mnt_cifs_flags
&
CIFS_MOUNT_NO_PERM
)
if
(
cifs_sb
->
mnt_cifs_flags
&
CIFS_MOUNT_NO_PERM
)
attrs
->
ia_valid
|=
ATTR_FORCE
;
attrs
->
ia_valid
|=
ATTR_FORCE
;
rc
=
inode_change_ok
(
inode
,
attrs
);
rc
=
setattr_prepare
(
direntry
,
attrs
);
if
(
rc
<
0
)
{
if
(
rc
<
0
)
{
free_xid
(
xid
);
free_xid
(
xid
);
return
rc
;
return
rc
;
...
...
sources/4.1/ntlmssp.h
View file @
5e9ae94e
...
@@ -133,6 +133,6 @@ typedef struct _AUTHENTICATE_MESSAGE {
...
@@ -133,6 +133,6 @@ typedef struct _AUTHENTICATE_MESSAGE {
int
decode_ntlmssp_challenge
(
char
*
bcc_ptr
,
int
blob_len
,
struct
cifs_ses
*
ses
);
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
);
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
,
struct
cifs_ses
*
ses
,
const
struct
nls_table
*
nls_cp
);
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,
...
@@ -364,19 +364,43 @@ void build_ntlmssp_negotiate_blob(unsigned char *pbuffer,
sec_blob
->
DomainName
.
MaximumLength
=
0
;
sec_blob
->
DomainName
.
MaximumLength
=
0
;
}
}
/* We do not malloc the blob, it is passed in pbuffer, because its
static
int
size_of_ntlmssp_blob
(
struct
cifs_ses
*
ses
)
maximum possible size is fixed and small, making this approach cleaner.
{
This function returns the length of the data in the blob */
int
sz
=
sizeof
(
AUTHENTICATE_MESSAGE
)
+
ses
->
auth_key
.
len
int
build_ntlmssp_auth_blob
(
unsigned
char
*
pbuffer
,
-
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
,
u16
*
buflen
,
struct
cifs_ses
*
ses
,
struct
cifs_ses
*
ses
,
const
struct
nls_table
*
nls_cp
)
const
struct
nls_table
*
nls_cp
)
{
{
int
rc
;
int
rc
;
AUTHENTICATE_MESSAGE
*
sec_blob
=
(
AUTHENTICATE_MESSAGE
*
)
pbuffer
;
AUTHENTICATE_MESSAGE
*
sec_blob
;
__u32
flags
;
__u32
flags
;
unsigned
char
*
tmp
;
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
);
memcpy
(
sec_blob
->
Signature
,
NTLMSSP_SIGNATURE
,
8
);
sec_blob
->
MessageType
=
NtLmAuthenticate
;
sec_blob
->
MessageType
=
NtLmAuthenticate
;
...
@@ -391,7 +415,7 @@ int build_ntlmssp_auth_blob(unsigned char *pbuffer,
...
@@ -391,7 +415,7 @@ int build_ntlmssp_auth_blob(unsigned char *pbuffer,
flags
|=
NTLMSSP_NEGOTIATE_KEY_XCH
;
flags
|=
NTLMSSP_NEGOTIATE_KEY_XCH
;
}
}
tmp
=
pbuffer
+
sizeof
(
AUTHENTICATE_MESSAGE
);
tmp
=
*
pbuffer
+
sizeof
(
AUTHENTICATE_MESSAGE
);
sec_blob
->
NegotiateFlags
=
cpu_to_le32
(
flags
);
sec_blob
->
NegotiateFlags
=
cpu_to_le32
(
flags
);
sec_blob
->
LmChallengeResponse
.
BufferOffset
=
sec_blob
->
LmChallengeResponse
.
BufferOffset
=
...
@@ -399,13 +423,9 @@ int build_ntlmssp_auth_blob(unsigned char *pbuffer,
...
@@ -399,13 +423,9 @@ int build_ntlmssp_auth_blob(unsigned char *pbuffer,
sec_blob
->
LmChallengeResponse
.
Length
=
0
;
sec_blob
->
LmChallengeResponse
.
Length
=
0
;
sec_blob
->
LmChallengeResponse
.
MaximumLength
=
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
)
{
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
,
memcpy
(
tmp
,
ses
->
auth_key
.
response
+
CIFS_SESS_KEY_SIZE
,
ses
->
auth_key
.
len
-
CIFS_SESS_KEY_SIZE
);
ses
->
auth_key
.
len
-
CIFS_SESS_KEY_SIZE
);
tmp
+=
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,
...
@@ -423,7 +443,7 @@ int build_ntlmssp_auth_blob(unsigned char *pbuffer,
}
}
if
(
ses
->
domainName
==
NULL
)
{
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
.
Length
=
0
;
sec_blob
->
DomainName
.
MaximumLength
=
0
;
sec_blob
->
DomainName
.
MaximumLength
=
0
;
tmp
+=
2
;
tmp
+=
2
;
...
@@ -432,14 +452,14 @@ int build_ntlmssp_auth_blob(unsigned char *pbuffer,
...
@@ -432,14 +452,14 @@ int build_ntlmssp_auth_blob(unsigned char *pbuffer,
len
=
cifs_strtoUTF16
((
__le16
*
)
tmp
,
ses
->
domainName
,
len
=
cifs_strtoUTF16
((
__le16
*
)
tmp
,
ses
->
domainName
,
CIFS_MAX_USERNAME_LEN
,
nls_cp
);
CIFS_MAX_USERNAME_LEN
,
nls_cp
);
len
*=
2
;
/* unicode is 2 bytes each */
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
.
Length
=
cpu_to_le16
(
len
);
sec_blob
->
DomainName
.
MaximumLength
=
cpu_to_le16
(
len
);
sec_blob
->
DomainName
.
MaximumLength
=
cpu_to_le16
(
len
);
tmp
+=
len
;
tmp
+=
len
;
}
}
if
(
ses
->
user_name
==
NULL
)
{
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
.
Length
=
0
;
sec_blob
->
UserName
.
MaximumLength
=
0
;
sec_blob
->
UserName
.
MaximumLength
=
0
;
tmp
+=
2
;
tmp
+=
2
;
...
@@ -448,13 +468,13 @@ int build_ntlmssp_auth_blob(unsigned char *pbuffer,
...
@@ -448,13 +468,13 @@ int build_ntlmssp_auth_blob(unsigned char *pbuffer,
len
=
cifs_strtoUTF16
((
__le16
*
)
tmp
,
ses
->
user_name
,
len
=
cifs_strtoUTF16
((
__le16
*
)
tmp
,
ses
->
user_name
,
CIFS_MAX_USERNAME_LEN
,
nls_cp
);
CIFS_MAX_USERNAME_LEN
,
nls_cp
);
len
*=
2
;
/* unicode is 2 bytes each */
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
.
Length
=
cpu_to_le16
(
len
);
sec_blob
->
UserName
.
MaximumLength
=
cpu_to_le16
(
len
);
sec_blob
->
UserName
.
MaximumLength
=
cpu_to_le16
(
len
);
tmp
+=
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
.
Length
=
0
;
sec_blob
->
WorkstationName
.
MaximumLength
=
0
;
sec_blob
->
WorkstationName
.
MaximumLength
=
0
;
tmp
+=
2
;
tmp
+=
2
;
...
@@ -463,19 +483,19 @@ int build_ntlmssp_auth_blob(unsigned char *pbuffer,
...
@@ -463,19 +483,19 @@ int build_ntlmssp_auth_blob(unsigned char *pbuffer,
(
ses
->
ntlmssp
->
server_flags
&
NTLMSSP_NEGOTIATE_EXTENDED_SEC
))
(
ses
->
ntlmssp
->
server_flags
&
NTLMSSP_NEGOTIATE_EXTENDED_SEC
))
&&
!
calc_seckey
(
ses
))
{
&&
!
calc_seckey
(
ses
))
{
memcpy
(
tmp
,
ses
->
ntlmssp
->
ciphertext
,
CIFS_CPHTXT_SIZE
);
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
.
Length
=
cpu_to_le16
(
CIFS_CPHTXT_SIZE
);
sec_blob
->
SessionKey
.
MaximumLength
=
sec_blob
->
SessionKey
.
MaximumLength
=
cpu_to_le16
(
CIFS_CPHTXT_SIZE
);
cpu_to_le16
(
CIFS_CPHTXT_SIZE
);
tmp
+=
CIFS_CPHTXT_SIZE
;
tmp
+=
CIFS_CPHTXT_SIZE
;
}
else
{
}
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
.
Length
=
0
;
sec_blob
->
SessionKey
.
MaximumLength
=
0
;
sec_blob
->
SessionKey
.
MaximumLength
=
0
;
}
}
*
buflen
=
tmp
-
*
pbuffer
;
setup_ntlmv2_ret:
setup_ntlmv2_ret:
*
buflen
=
tmp
-
pbuffer
;
return
rc
;
return
rc
;
}
}
...
@@ -1266,7 +1286,7 @@ sess_auth_rawntlmssp_authenticate(struct sess_data *sess_data)
...
@@ -1266,7 +1286,7 @@ sess_auth_rawntlmssp_authenticate(struct sess_data *sess_data)
struct
cifs_ses
*
ses
=
sess_data
->
ses
;
struct
cifs_ses
*
ses
=
sess_data
->
ses
;
__u16
bytes_remaining
;
__u16
bytes_remaining
;
char
*
bcc_ptr
;
char
*
bcc_ptr
;
char
*
ntlmsspblob
=
NULL
;
unsigned
char
*
ntlmsspblob
=
NULL
;
u16
blob_len
;
u16
blob_len
;
cifs_dbg
(
FYI
,
"rawntlmssp session setup authenticate phase
\n
"
);
cifs_dbg
(
FYI
,
"rawntlmssp session setup authenticate phase
\n
"
);
...
@@ -1279,19 +1299,7 @@ sess_auth_rawntlmssp_authenticate(struct sess_data *sess_data)
...
@@ -1279,19 +1299,7 @@ sess_auth_rawntlmssp_authenticate(struct sess_data *sess_data)
/* Build security blob before we assemble the request */
/* Build security blob before we assemble the request */
pSMB
=
(
SESSION_SETUP_ANDX
*
)
sess_data
->
iov
[
0
].
iov_base
;
pSMB
=
(
SESSION_SETUP_ANDX
*
)
sess_data
->
iov
[
0
].
iov_base
;
smb_buf
=
(
struct
smb_hdr
*
)
pSMB
;
smb_buf
=
(
struct
smb_hdr
*
)
pSMB
;
/*
rc
=
build_ntlmssp_auth_blob
(
&
ntlmsspblob
,
* 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
,
&
blob_len
,
ses
,
sess_data
->
nls_cp
);
&
blob_len
,
ses
,
sess_data
->
nls_cp
);
if
(
rc
)
if
(
rc
)
goto
out_free_ntlmsspblob
;
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,
...
@@ -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_fid
*
fid
,
__u16
search_flags
,
struct
cifs_search_info
*
srch_inf
)
struct
cifs_search_info
*
srch_inf
)
{
{
return
CIFSFindFirst
(
xid
,
tcon
,
path
,
cifs_sb
,
int
rc
;
&
fid
->
netfid
,
search_flags
,
srch_inf
,
true
);
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
static
int
...
@@ -1018,6 +1023,15 @@ cifs_dir_needs_close(struct cifsFileInfo *cfile)
...
@@ -1018,6 +1023,15 @@ cifs_dir_needs_close(struct cifsFileInfo *cfile)
return
!
cfile
->
srch_inf
.
endOfSearch
&&
!
cfile
->
invalidHandle
;
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
=
{
struct
smb_version_operations
smb1_operations
=
{
.
send_cancel
=
send_nt_cancel
,
.
send_cancel
=
send_nt_cancel
,
.
compare_fids
=
cifs_compare_fids
,
.
compare_fids
=
cifs_compare_fids
,
...
@@ -1052,6 +1066,7 @@ struct smb_version_operations smb1_operations = {
...
@@ -1052,6 +1066,7 @@ struct smb_version_operations smb1_operations = {
.
get_dfs_refer
=
CIFSGetDFSRefer
,
.
get_dfs_refer
=
CIFSGetDFSRefer
,
.
qfs_tcon
=
cifs_qfs_tcon
,
.
qfs_tcon
=
cifs_qfs_tcon
,
.
is_path_accessible
=
cifs_is_path_accessible
,
.
is_path_accessible
=
cifs_is_path_accessible
,
.
can_echo
=
cifs_can_echo
,
.
query_path_info
=
cifs_query_path_info
,
.
query_path_info
=
cifs_query_path_info
,
.
query_file_info
=
cifs_query_file_info
,
.
query_file_info
=
cifs_query_file_info
,
.
get_srv_inum
=
cifs_get_srv_inum
,
.
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)
...
@@ -241,7 +241,7 @@ smb2_push_mandatory_locks(struct cifsFileInfo *cfile)
* and check it for zero before using.
* and check it for zero before using.
*/
*/
max_buf
=
tlink_tcon
(
cfile
->
tlink
)
->
ses
->
server
->
maxBuf
;
max_buf
=
tlink_tcon
(
cfile
->
tlink
)
->
ses
->
server
->
maxBuf
;
if
(
!
max_buf
)
{
if
(
max_buf
<
sizeof
(
struct
smb2_lock_element
)
)
{
free_xid
(
xid
);
free_xid
(
xid
);
return
-
EINVAL
;
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,
...
@@ -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
);
rc
=
SMB2_open
(
xid
,
&
oparms
,
utf16_path
,
&
oplock
,
NULL
,
NULL
);
kfree
(
utf16_path
);
kfree
(
utf16_path
);
if
(
rc
)
{
if
(
rc
)
{
cifs_dbg
(
VFS
,
"open dir failed
\n
"
);
cifs_dbg
(
FYI
,
"open dir failed rc=%d
\n
"
,
rc
);
return
rc
;
return
rc
;
}
}
...
@@ -857,7 +857,7 @@ smb2_query_dir_first(const unsigned int xid, struct cifs_tcon *tcon,
...
@@ -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
,
rc
=
SMB2_query_directory
(
xid
,
tcon
,
fid
->
persistent_fid
,
fid
->
volatile_fid
,
0
,
srch_inf
);
fid
->
volatile_fid
,
0
,
srch_inf
);
if
(
rc
)
{
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
);
SMB2_close
(
xid
,
tcon
,
fid
->
persistent_fid
,
fid
->
volatile_fid
);
}
}
return
rc
;
return
rc
;
...
@@ -978,6 +978,9 @@ smb2_new_lease_key(struct cifs_fid *fid)
...
@@ -978,6 +978,9 @@ smb2_new_lease_key(struct cifs_fid *fid)
get_random_bytes
(
fid
->
lease_key
,
SMB2_LEASE_KEY_SIZE
);
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
static
int
smb2_query_symlink
(
const
unsigned
int
xid
,
struct
cifs_tcon
*
tcon
,
smb2_query_symlink
(
const
unsigned
int
xid
,
struct
cifs_tcon
*
tcon
,
const
char
*
full_path
,
char
**
target_path
,
const
char
*
full_path
,
char
**
target_path
,
...
@@ -990,7 +993,10 @@ smb2_query_symlink(const unsigned int xid, struct cifs_tcon *tcon,
...
@@ -990,7 +993,10 @@ smb2_query_symlink(const unsigned int xid, struct cifs_tcon *tcon,
struct
cifs_fid
fid
;
struct
cifs_fid
fid
;
struct
smb2_err_rsp
*
err_buf
=
NULL
;
struct
smb2_err_rsp
*
err_buf
=
NULL
;
struct
smb2_symlink_err_rsp
*
symlink
;
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
);
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,
...
@@ -1012,11 +1018,33 @@ smb2_query_symlink(const unsigned int xid, struct cifs_tcon *tcon,
kfree
(
utf16_path
);
kfree
(
utf16_path
);
return
-
ENOENT
;
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 */
/* open must fail on symlink - reset rc */
rc
=
0
;
rc
=
0
;
symlink
=
(
struct
smb2_symlink_err_rsp
*
)
err_buf
->
ErrorData
;
symlink
=
(
struct
smb2_symlink_err_rsp
*
)
err_buf
->
ErrorData
;
sub_len
=
le16_to_cpu
(
symlink
->
SubstituteNameLength
);
sub_len
=
le16_to_cpu
(
symlink
->
SubstituteNameLength
);
sub_offset
=
le16_to_cpu
(
symlink
->
SubstituteNameOffset
);
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
(
*
target_path
=
cifs_strndup_from_utf16
(
(
char
*
)
symlink
->
PathBuffer
+
sub_offset
,
(
char
*
)
symlink
->
PathBuffer
+
sub_offset
,
sub_len
,
true
,
cifs_sb
->
local_nls
);
sub_len
,
true
,
cifs_sb
->
local_nls
);
...
...
sources/4.1/smb2pdu.c
View file @
5e9ae94e
...
@@ -264,7 +264,7 @@ out:
...
@@ -264,7 +264,7 @@ out:
case
SMB2_CHANGE_NOTIFY
:
case
SMB2_CHANGE_NOTIFY
:
case
SMB2_QUERY_INFO
:
case
SMB2_QUERY_INFO
:
case
SMB2_SET_INFO
:
case
SMB2_SET_INFO
:
r
eturn
-
EAGAIN
;
r
c
=
-
EAGAIN
;
}
}
unload_nls
(
nls_codepage
);
unload_nls
(
nls_codepage
);
return
rc
;
return
rc
;
...
@@ -453,15 +453,22 @@ int smb3_validate_negotiate(const unsigned int xid, struct cifs_tcon *tcon)
...
@@ -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
* 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.
* 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
* Having validation of negotiate info helps reduce attack vectors.
* would also enable signing on the mount. Having validation of
* negotiate info for signed connections 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 */
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
=
vneg_inbuf
.
Capabilities
=
cpu_to_le32
(
tcon
->
ses
->
server
->
vals
->
req_capabilities
);
cpu_to_le32
(
tcon
->
ses
->
server
->
vals
->
req_capabilities
);
memcpy
(
vneg_inbuf
.
Guid
,
tcon
->
ses
->
server
->
client_guid
,
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)
...
@@ -491,8 +498,12 @@ int smb3_validate_negotiate(const unsigned int xid, struct cifs_tcon *tcon)
}
}
if
(
rsplen
!=
sizeof
(
struct
validate_negotiate_info_rsp
))
{
if
(
rsplen
!=
sizeof
(
struct
validate_negotiate_info_rsp
))
{
cifs_dbg
(
VFS
,
"invalid size of protocol negotiate response
\n
"
);
cifs_dbg
(
VFS
,
"invalid protocol negotiate response size: %d
\n
"
,
return
-
EIO
;
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 */
/* 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,
...
@@ -532,7 +543,7 @@ SMB2_sess_setup(const unsigned int xid, struct cifs_ses *ses,
u16
blob_length
=
0
;
u16
blob_length
=
0
;
struct
key
*
spnego_key
=
NULL
;
struct
key
*
spnego_key
=
NULL
;
char
*
security_blob
=
NULL
;
char
*
security_blob
=
NULL
;
char
*
ntlmssp_blob
=
NULL
;
unsigned
char
*
ntlmssp_blob
=
NULL
;
bool
use_spnego
=
false
;
/* else use raw ntlmssp */
bool
use_spnego
=
false
;
/* else use raw ntlmssp */
cifs_dbg
(
FYI
,
"Session Setup
\n
"
);
cifs_dbg
(
FYI
,
"Session Setup
\n
"
);
...
@@ -657,13 +668,7 @@ ssetup_ntlmssp_authenticate:
...
@@ -657,13 +668,7 @@ ssetup_ntlmssp_authenticate:
iov
[
1
].
iov_len
=
blob_length
;
iov
[
1
].
iov_len
=
blob_length
;
}
else
if
(
phase
==
NtLmAuthenticate
)
{
}
else
if
(
phase
==
NtLmAuthenticate
)
{
req
->
hdr
.
SessionId
=
ses
->
Suid
;
req
->
hdr
.
SessionId
=
ses
->
Suid
;
ntlmssp_blob
=
kzalloc
(
sizeof
(
struct
_NEGOTIATE_MESSAGE
)
+
500
,
rc
=
build_ntlmssp_auth_blob
(
&
ntlmssp_blob
,
&
blob_length
,
ses
,
GFP_KERNEL
);
if
(
ntlmssp_blob
==
NULL
)
{
rc
=
-
ENOMEM
;
goto
ssetup_exit
;
}
rc
=
build_ntlmssp_auth_blob
(
ntlmssp_blob
,
&
blob_length
,
ses
,
nls_cp
);
nls_cp
);
if
(
rc
)
{
if
(
rc
)
{
cifs_dbg
(
FYI
,
"build_ntlmssp_auth_blob failed %d
\n
"
,
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,
...
@@ -860,9 +865,6 @@ SMB2_tcon(const unsigned int xid, struct cifs_ses *ses, const char *tree,
else
else
return
-
EIO
;
return
-
EIO
;
if
(
tcon
&&
tcon
->
bad_network_name
)
return
-
ENOENT
;
unc_path
=
kmalloc
(
MAX_SHARENAME_LENGTH
*
2
,
GFP_KERNEL
);
unc_path
=
kmalloc
(
MAX_SHARENAME_LENGTH
*
2
,
GFP_KERNEL
);
if
(
unc_path
==
NULL
)
if
(
unc_path
==
NULL
)
return
-
ENOMEM
;
return
-
ENOMEM
;
...
@@ -874,6 +876,10 @@ SMB2_tcon(const unsigned int xid, struct cifs_ses *ses, const char *tree,
...
@@ -874,6 +876,10 @@ SMB2_tcon(const unsigned int xid, struct cifs_ses *ses, const char *tree,
return
-
EINVAL
;
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
);
rc
=
small_smb2_init
(
SMB2_TREE_CONNECT
,
tcon
,
(
void
**
)
&
req
);
if
(
rc
)
{
if
(
rc
)
{
kfree
(
unc_path
);
kfree
(
unc_path
);
...
@@ -952,8 +958,6 @@ tcon_exit:
...
@@ -952,8 +958,6 @@ tcon_exit:
tcon_error_exit:
tcon_error_exit:
if
(
rsp
->
hdr
.
Status
==
STATUS_BAD_NETWORK_NAME
)
{
if
(
rsp
->
hdr
.
Status
==
STATUS_BAD_NETWORK_NAME
)
{
cifs_dbg
(
VFS
,
"BAD_NETWORK_NAME: %s
\n
"
,
tree
);
cifs_dbg
(
VFS
,
"BAD_NETWORK_NAME: %s
\n
"
,
tree
);
if
(
tcon
)
tcon
->
bad_network_name
=
true
;
}
}
goto
tcon_exit
;
goto
tcon_exit
;
}
}
...
@@ -1320,8 +1324,12 @@ SMB2_ioctl(const unsigned int xid, struct cifs_tcon *tcon, u64 persistent_fid,
...
@@ -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
* than one credit. Windows typically sets this smaller, but for some
* ioctls it may be useful to allow server to send more. No point
* 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
* 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
)
if
(
is_fsctl
)
req
->
Flags
=
cpu_to_le32
(
SMB2_0_IOCTL_IS_FSCTL
);
req
->
Flags
=
cpu_to_le32
(
SMB2_0_IOCTL_IS_FSCTL
);
...
@@ -1621,6 +1629,54 @@ smb2_echo_callback(struct mid_q_entry *mid)
...
@@ -1621,6 +1629,54 @@ smb2_echo_callback(struct mid_q_entry *mid)
add_credits
(
server
,
credits_received
,
CIFS_ECHO_OP
);
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
int
SMB2_echo
(
struct
TCP_Server_Info
*
server
)
SMB2_echo
(
struct
TCP_Server_Info
*
server
)
{
{
...
@@ -1632,6 +1688,12 @@ 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
"
);
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
);
rc
=
small_smb2_init
(
SMB2_ECHO
,
NULL
,
(
void
**
)
&
req
);
if
(
rc
)
if
(
rc
)
return
rc
;
return
rc
;
...
@@ -2499,8 +2561,8 @@ copy_fs_info_to_kstatfs(struct smb2_fs_full_size_info *pfs_inf,
...
@@ -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
)
*
kst
->
f_bsize
=
le32_to_cpu
(
pfs_inf
->
BytesPerSector
)
*
le32_to_cpu
(
pfs_inf
->
SectorsPerAllocationUnit
);
le32_to_cpu
(
pfs_inf
->
SectorsPerAllocationUnit
);
kst
->
f_blocks
=
le64_to_cpu
(
pfs_inf
->
TotalAllocationUnits
);
kst
->
f_blocks
=
le64_to_cpu
(
pfs_inf
->
TotalAllocationUnits
);
kst
->
f_bfree
=
le64_to_cpu
(
pfs_inf
->
ActualAvailableAllocationUnits
);
kst
->
f_bfree
=
kst
->
f_bavail
=
kst
->
f_bavail
=
le64_to_cpu
(
pfs_inf
->
CallerAvailableAllocationUnits
);
le64_to_cpu
(
pfs_inf
->
CallerAvailableAllocationUnits
);
return
;
return
;
}
}
...
...
sources/4.1/smb2pdu.h
View file @
5e9ae94e
...
@@ -82,8 +82,8 @@
...
@@ -82,8 +82,8 @@
#define NUMBER_OF_SMB2_COMMANDS 0x0013
#define NUMBER_OF_SMB2_COMMANDS 0x0013
/*
BB FIXME - analyze following length BB
*/
/*
4 len + 52 transform hdr + 64 hdr + 56 create rsp
*/
#define MAX_SMB2_HDR_SIZE 0x
78
/* 4 len + 64 hdr + (2*24 wct) + 2 bct + 2 pad */
#define MAX_SMB2_HDR_SIZE 0x
00b0
#define SMB2_PROTO_NUMBER cpu_to_le32(0x424d53fe)
#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,
...
@@ -95,6 +95,7 @@ extern int smb2_open_file(const unsigned int xid,
extern
int
smb2_unlock_range
(
struct
cifsFileInfo
*
cfile
,
extern
int
smb2_unlock_range
(
struct
cifsFileInfo
*
cfile
,
struct
file_lock
*
flock
,
const
unsigned
int
xid
);
struct
file_lock
*
flock
,
const
unsigned
int
xid
);
extern
int
smb2_push_mandatory_locks
(
struct
cifsFileInfo
*
cfile
);
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
* 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