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
892812f0
Commit
892812f0
authored
Jan 31, 2018
by
Vitaly Lipatov
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
update 4.9 up to v4.9.78
parent
5a6c30ec
Hide whitespace changes
Inline
Side-by-side
Showing
23 changed files
with
428 additions
and
130 deletions
+428
-130
cifs_dfs_ref.c
sources/4.9/cifs_dfs_ref.c
+4
-3
cifs_unicode.c
sources/4.9/cifs_unicode.c
+6
-0
cifs_unicode.h
sources/4.9/cifs_unicode.h
+3
-2
cifsfs.c
sources/4.9/cifsfs.c
+14
-3
cifsglob.h
sources/4.9/cifsglob.h
+18
-1
cifsproto.h
sources/4.9/cifsproto.h
+3
-0
cifssmb.c
sources/4.9/cifssmb.c
+14
-0
connect.c
sources/4.9/connect.c
+59
-17
dir.c
sources/4.9/dir.c
+13
-6
file.c
sources/4.9/file.c
+26
-5
ioctl.c
sources/4.9/ioctl.c
+5
-1
misc.c
sources/4.9/misc.c
+1
-1
readdir.c
sources/4.9/readdir.c
+1
-0
smb1ops.c
sources/4.9/smb1ops.c
+17
-2
smb2file.c
sources/4.9/smb2file.c
+1
-1
smb2misc.c
sources/4.9/smb2misc.c
+47
-2
smb2ops.c
sources/4.9/smb2ops.c
+23
-2
smb2pdu.c
sources/4.9/smb2pdu.c
+99
-44
smb2pdu.h
sources/4.9/smb2pdu.h
+4
-2
smb2proto.h
sources/4.9/smb2proto.h
+8
-0
smb2transport.c
sources/4.9/smb2transport.c
+52
-6
smbencrypt.c
sources/4.9/smbencrypt.c
+8
-32
transport.c
sources/4.9/transport.c
+2
-0
No files found.
sources/4.9/cifs_dfs_ref.c
View file @
892812f0
...
...
@@ -245,7 +245,8 @@ compose_mount_options_err:
* @fullpath: full path in UNC format
* @ref: server's referral
*/
static
struct
vfsmount
*
cifs_dfs_do_refmount
(
struct
cifs_sb_info
*
cifs_sb
,
static
struct
vfsmount
*
cifs_dfs_do_refmount
(
struct
dentry
*
mntpt
,
struct
cifs_sb_info
*
cifs_sb
,
const
char
*
fullpath
,
const
struct
dfs_info3_param
*
ref
)
{
struct
vfsmount
*
mnt
;
...
...
@@ -259,7 +260,7 @@ static struct vfsmount *cifs_dfs_do_refmount(struct cifs_sb_info *cifs_sb,
if
(
IS_ERR
(
mountdata
))
return
(
struct
vfsmount
*
)
mountdata
;
mnt
=
vfs_
kern_mount
(
&
cifs_fs_type
,
0
,
devname
,
mountdata
);
mnt
=
vfs_
submount
(
mntpt
,
&
cifs_fs_type
,
devname
,
mountdata
);
kfree
(
mountdata
);
kfree
(
devname
);
return
mnt
;
...
...
@@ -334,7 +335,7 @@ static struct vfsmount *cifs_dfs_do_automount(struct dentry *mntpt)
mnt
=
ERR_PTR
(
-
EINVAL
);
break
;
}
mnt
=
cifs_dfs_do_refmount
(
cifs_sb
,
mnt
=
cifs_dfs_do_refmount
(
mntpt
,
cifs_sb
,
full_path
,
referrals
+
i
);
cifs_dbg
(
FYI
,
"%s: cifs_dfs_do_refmount:%s , mnt:%p
\n
"
,
__func__
,
referrals
[
i
].
node_name
,
mnt
);
...
...
sources/4.9/cifs_unicode.c
View file @
892812f0
...
...
@@ -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
;
...
...
@@ -418,6 +421,9 @@ static __le16 convert_to_sfm_char(char src_char, bool end_of_string)
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
;
...
...
sources/4.9/cifs_unicode.h
View file @
892812f0
...
...
@@ -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,8 +65,8 @@
#define SFM_LESSTHAN ((__u16) 0xF023)
#define SFM_PIPE ((__u16) 0xF027)
#define SFM_SLASH ((__u16) 0xF026)
#define SFM_
PERIOD
((__u16) 0xF028)
#define SFM_
SPACE
((__u16) 0xF029)
#define SFM_
SPACE
((__u16) 0xF028)
#define SFM_
PERIOD
((__u16) 0xF029)
/*
* Mapping mechanism to use when one of the seven reserved characters is
...
...
sources/4.9/cifsfs.c
View file @
892812f0
...
...
@@ -87,6 +87,7 @@ extern mempool_t *cifs_req_poolp;
extern
mempool_t
*
cifs_mid_poolp
;
struct
workqueue_struct
*
cifsiod_wq
;
struct
workqueue_struct
*
cifsoplockd_wq
;
__u32
cifs_lock_secret
;
/*
...
...
@@ -1286,9 +1287,16 @@ init_cifs(void)
goto
out_clean_proc
;
}
cifsoplockd_wq
=
alloc_workqueue
(
"cifsoplockd"
,
WQ_FREEZABLE
|
WQ_MEM_RECLAIM
,
0
);
if
(
!
cifsoplockd_wq
)
{
rc
=
-
ENOMEM
;
goto
out_destroy_cifsiod_wq
;
}
rc
=
cifs_fscache_register
();
if
(
rc
)
goto
out_destroy_wq
;
goto
out_destroy_
cifsoplockd_
wq
;
rc
=
cifs_init_inodecache
();
if
(
rc
)
...
...
@@ -1336,7 +1344,9 @@ out_destroy_inodecache:
cifs_destroy_inodecache
();
out_unreg_fscache:
cifs_fscache_unregister
();
out_destroy_wq:
out_destroy_cifsoplockd_wq:
destroy_workqueue
(
cifsoplockd_wq
);
out_destroy_cifsiod_wq:
destroy_workqueue
(
cifsiod_wq
);
out_clean_proc:
cifs_proc_clean
();
...
...
@@ -1353,12 +1363,13 @@ exit_cifs(void)
exit_cifs_idmap
();
#endif
#ifdef CONFIG_CIFS_UPCALL
unregister_key_type
(
&
cifs_spnego_key_type
);
exit_cifs_spnego
(
);
#endif
cifs_destroy_request_bufs
();
cifs_destroy_mids
();
cifs_destroy_inodecache
();
cifs_fscache_unregister
();
destroy_workqueue
(
cifsoplockd_wq
);
destroy_workqueue
(
cifsiod_wq
);
cifs_proc_clean
();
}
...
...
sources/4.9/cifsglob.h
View file @
892812f0
...
...
@@ -241,6 +241,7 @@ struct smb_version_operations {
/* verify the message */
int
(
*
check_message
)(
char
*
,
unsigned
int
,
struct
TCP_Server_Info
*
);
bool
(
*
is_oplock_break
)(
char
*
,
struct
TCP_Server_Info
*
);
int
(
*
handle_cancelled_mid
)(
char
*
,
struct
TCP_Server_Info
*
);
void
(
*
downgrade_oplock
)(
struct
TCP_Server_Info
*
,
struct
cifsInodeInfo
*
,
bool
);
/* process transaction2 response */
...
...
@@ -364,6 +365,8 @@ struct smb_version_operations {
unsigned
int
(
*
calc_smb_size
)(
void
*
);
/* check for STATUS_PENDING and process it in a positive case */
bool
(
*
is_status_pending
)(
char
*
,
struct
TCP_Server_Info
*
,
int
);
/* check for STATUS_NETWORK_SESSION_EXPIRED */
bool
(
*
is_session_expired
)(
char
*
);
/* send oplock break response */
int
(
*
oplock_response
)(
struct
cifs_tcon
*
,
struct
cifs_fid
*
,
struct
cifsInodeInfo
*
);
...
...
@@ -646,6 +649,8 @@ struct TCP_Server_Info {
unsigned
int
max_read
;
unsigned
int
max_write
;
__u8
preauth_hash
[
512
];
struct
delayed_work
reconnect
;
/* reconnect workqueue job */
struct
mutex
reconnect_mutex
;
/* prevent simultaneous reconnects */
#endif
/* CONFIG_CIFS_SMB2 */
unsigned
long
echo_interval
;
};
...
...
@@ -849,6 +854,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
;
spinlock_t
open_file_lock
;
/* protects list above */
struct
cifs_ses
*
ses
;
/* pointer to session associated with */
...
...
@@ -922,11 +928,11 @@ struct cifs_tcon {
bool
broken_posix_open
;
/* e.g. Samba server versions < 3.3.2, 3.2.9 */
bool
broken_sparse_sup
;
/* if server or share does not support sparse */
bool
need_reconnect
:
1
;
/* connection reset, tid now invalid */
bool
need_reopen_files
:
1
;
/* need to reopen tcon file handles */
bool
use_resilient
:
1
;
/* use resilient instead of durable handles */
bool
use_persistent
:
1
;
/* use persistent instead of durable handles */
#ifdef CONFIG_CIFS_SMB2
bool
print
:
1
;
/* set if connection to printer share */
bool
bad_network_name
:
1
;
/* set if ret status STATUS_BAD_NETWORK_NAME */
__le32
capabilities
;
__u32
share_flags
;
__u32
maximal_access
;
...
...
@@ -1319,12 +1325,19 @@ struct mid_q_entry {
void
*
callback_data
;
/* general purpose pointer for callback */
void
*
resp_buf
;
/* pointer to received SMB header */
int
mid_state
;
/* wish this were enum but can not pass to wait_event */
unsigned
int
mid_flags
;
__le16
command
;
/* smb command code */
bool
large_buf
:
1
;
/* if valid response, is pointer to large buf */
bool
multiRsp
:
1
;
/* multiple trans2 responses for one request */
bool
multiEnd
:
1
;
/* both received */
};
struct
close_cancelled_open
{
struct
cifs_fid
fid
;
struct
cifs_tcon
*
tcon
;
struct
work_struct
work
;
};
/* Make code in transport.c a little cleaner by moving
update of optional stats into function below */
#ifdef CONFIG_CIFS_STATS2
...
...
@@ -1456,6 +1469,9 @@ static inline void free_dfs_info_array(struct dfs_info3_param *param,
#define MID_RESPONSE_MALFORMED 0x10
#define MID_SHUTDOWN 0x20
/* Flags */
#define MID_WAIT_CANCELLED 1
/* Cancelled while waiting for response */
/* Types of response buffer returned from SendReceive2 */
#define CIFS_NO_BUFFER 0
/* Response buffer not returned */
#define CIFS_SMALL_BUFFER 1
...
...
@@ -1645,6 +1661,7 @@ void cifs_oplock_break(struct work_struct *work);
extern
const
struct
slow_work_ops
cifs_oplock_break_ops
;
extern
struct
workqueue_struct
*
cifsiod_wq
;
extern
struct
workqueue_struct
*
cifsoplockd_wq
;
extern
__u32
cifs_lock_secret
;
extern
mempool_t
*
cifs_mid_poolp
;
...
...
sources/4.9/cifsproto.h
View file @
892812f0
...
...
@@ -206,6 +206,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.9/cifssmb.c
View file @
892812f0
...
...
@@ -717,6 +717,9 @@ CIFSSMBEcho(struct TCP_Server_Info *server)
if
(
rc
)
return
rc
;
if
(
server
->
capabilities
&
CAP_UNICODE
)
smb
->
hdr
.
Flags2
|=
SMBFLG2_UNICODE
;
/* set up echo request */
smb
->
hdr
.
Tid
=
0xffff
;
smb
->
hdr
.
WordCount
=
1
;
...
...
@@ -1430,6 +1433,8 @@ cifs_readv_discard(struct TCP_Server_Info *server, struct mid_q_entry *mid)
length
=
discard_remaining_data
(
server
);
dequeue_mid
(
mid
,
rdata
->
result
);
mid
->
resp_buf
=
server
->
smallbuf
;
server
->
smallbuf
=
NULL
;
return
length
;
}
...
...
@@ -1459,6 +1464,13 @@ cifs_readv_receive(struct TCP_Server_Info *server, struct mid_q_entry *mid)
return
length
;
server
->
total_read
+=
length
;
if
(
server
->
ops
->
is_session_expired
&&
server
->
ops
->
is_session_expired
(
buf
))
{
cifs_reconnect
(
server
);
wake_up
(
&
server
->
response_q
);
return
-
1
;
}
if
(
server
->
ops
->
is_status_pending
&&
server
->
ops
->
is_status_pending
(
buf
,
server
,
0
))
{
discard_remaining_data
(
server
);
...
...
@@ -1541,6 +1553,8 @@ cifs_readv_receive(struct TCP_Server_Info *server, struct mid_q_entry *mid)
return
cifs_readv_discard
(
server
,
mid
);
dequeue_mid
(
mid
,
false
);
mid
->
resp_buf
=
server
->
smallbuf
;
server
->
smallbuf
=
NULL
;
return
length
;
}
...
...
sources/4.9/connect.c
View file @
892812f0
...
...
@@ -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
...
...
@@ -794,6 +797,13 @@ standard_receive3(struct TCP_Server_Info *server, struct mid_q_entry *mid)
cifs_dump_mem
(
"Bad SMB: "
,
buf
,
min_t
(
unsigned
int
,
server
->
total_read
,
48
));
if
(
server
->
ops
->
is_session_expired
&&
server
->
ops
->
is_session_expired
(
buf
))
{
cifs_reconnect
(
server
);
wake_up
(
&
server
->
response_q
);
return
-
1
;
}
if
(
server
->
ops
->
is_status_pending
&&
server
->
ops
->
is_status_pending
(
buf
,
server
,
length
))
return
-
1
;
...
...
@@ -880,10 +890,19 @@ cifs_demultiplex_thread(void *p)
server
->
lstrp
=
jiffies
;
if
(
mid_entry
!=
NULL
)
{
if
((
mid_entry
->
mid_flags
&
MID_WAIT_CANCELLED
)
&&
mid_entry
->
mid_state
==
MID_RESPONSE_RECEIVED
&&
server
->
ops
->
handle_cancelled_mid
)
server
->
ops
->
handle_cancelled_mid
(
mid_entry
->
resp_buf
,
server
);
if
(
!
mid_entry
->
multiRsp
||
mid_entry
->
multiEnd
)
mid_entry
->
callback
(
mid_entry
);
}
else
if
(
!
server
->
ops
->
is_oplock_break
||
!
server
->
ops
->
is_oplock_break
(
buf
,
server
))
{
}
else
if
(
server
->
ops
->
is_oplock_break
&&
server
->
ops
->
is_oplock_break
(
buf
,
server
))
{
cifs_dbg
(
FYI
,
"Received oplock break
\n
"
);
}
else
{
cifs_dbg
(
VFS
,
"No task to wake, unknown frame received! NumMids %d
\n
"
,
atomic_read
(
&
midCount
));
cifs_dump_mem
(
"Received Data is: "
,
buf
,
...
...
@@ -2105,8 +2124,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
;
...
...
@@ -2123,6 +2142,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
);
...
...
@@ -2187,6 +2219,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
,
...
...
@@ -2345,7 +2381,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
...
...
@@ -2519,7 +2555,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
;
}
...
...
@@ -2609,7 +2645,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
;
...
...
@@ -2815,16 +2851,14 @@ match_prepath(struct super_block *sb, struct cifs_mnt_data *mnt_data)
{
struct
cifs_sb_info
*
old
=
CIFS_SB
(
sb
);
struct
cifs_sb_info
*
new
=
mnt_data
->
cifs_sb
;
bool
old_set
=
old
->
mnt_cifs_flags
&
CIFS_MOUNT_USE_PREFIX_PATH
;
bool
new_set
=
new
->
mnt_cifs_flags
&
CIFS_MOUNT_USE_PREFIX_PATH
;
if
(
old
->
mnt_cifs_flags
&
CIFS_MOUNT_USE_PREFIX_PATH
)
{
if
(
!
(
new
->
mnt_cifs_flags
&
CIFS_MOUNT_USE_PREFIX_PATH
))
return
0
;
/* The prepath should be null terminated strings */
if
(
strcmp
(
new
->
prepath
,
old
->
prepath
))
return
0
;
if
(
old_set
&&
new_set
&&
!
strcmp
(
new
->
prepath
,
old
->
prepath
))
return
1
;
}
else
if
(
!
old_set
&&
!
new_set
)
return
1
;
return
0
;
}
...
...
@@ -3797,7 +3831,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
);
}
...
...
@@ -4049,6 +4083,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
);
...
...
@@ -4108,7 +4150,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.9/dir.c
View file @
892812f0
...
...
@@ -183,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
]
==
'\\'
)
{
...
...
@@ -494,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
"
,
...
...
@@ -510,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
)
...
...
@@ -770,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.9/file.c
View file @
892812f0
...
...
@@ -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
;
...
...
@@ -785,6 +792,11 @@ cifs_reopen_persistent_handles(struct cifs_tcon *tcon)
struct
list_head
*
tmp1
;
struct
list_head
tmp_list
;
if
(
!
tcon
->
use_persistent
||
!
tcon
->
need_reopen_files
)
return
;
tcon
->
need_reopen_files
=
false
;
cifs_dbg
(
FYI
,
"Reopen persistent handles"
);
INIT_LIST_HEAD
(
&
tmp_list
);
...
...
@@ -801,7 +813,8 @@ cifs_reopen_persistent_handles(struct cifs_tcon *tcon)
list_for_each_safe
(
tmp
,
tmp1
,
&
tmp_list
)
{
open_file
=
list_entry
(
tmp
,
struct
cifsFileInfo
,
rlist
);
cifs_reopen_file
(
open_file
,
false
/* do not flush */
);
if
(
cifs_reopen_file
(
open_file
,
false
/* do not flush */
))
tcon
->
need_reopen_files
=
true
;
list_del_init
(
&
open_file
->
rlist
);
cifsFileInfo_put
(
open_file
);
}
...
...
@@ -2599,7 +2612,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
)
{
...
...
@@ -2886,7 +2899,15 @@ cifs_readdata_to_iov(struct cifs_readdata *rdata, struct iov_iter *iter)
for
(
i
=
0
;
i
<
rdata
->
nr_pages
;
i
++
)
{
struct
page
*
page
=
rdata
->
pages
[
i
];
size_t
copy
=
min_t
(
size_t
,
remaining
,
PAGE_SIZE
);
size_t
written
=
copy_page_to_iter
(
page
,
0
,
copy
,
iter
);
size_t
written
;
if
(
unlikely
(
iter
->
type
&
ITER_PIPE
))
{
void
*
addr
=
kmap_atomic
(
page
);
written
=
copy_to_iter
(
addr
,
copy
,
iter
);
kunmap_atomic
(
addr
);
}
else
written
=
copy_page_to_iter
(
page
,
0
,
copy
,
iter
);
remaining
-=
written
;
if
(
written
<
copy
&&
iov_iter_count
(
iter
)
>
0
)
break
;
...
...
@@ -2996,7 +3017,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
)
{
...
...
@@ -3571,7 +3592,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.9/ioctl.c
View file @
892812f0
...
...
@@ -189,7 +189,7 @@ long cifs_ioctl(struct file *filep, unsigned int command, unsigned long arg)
xid
=
get_xid
();
cifs_sb
=
CIFS_SB
(
inode
->
i_sb
);
cifs_dbg
(
VFS
,
"cifs ioctl 0x%x
\n
"
,
command
);
cifs_dbg
(
FYI
,
"cifs ioctl 0x%x
\n
"
,
command
);
switch
(
command
)
{
case
FS_IOC_GETFLAGS
:
if
(
pSMBFile
==
NULL
)
...
...
@@ -264,10 +264,14 @@ long cifs_ioctl(struct file *filep, unsigned int command, unsigned long arg)
rc
=
-
EOPNOTSUPP
;
break
;
case
CIFS_IOC_GET_MNT_INFO
:
if
(
pSMBFile
==
NULL
)
break
;
tcon
=
tlink_tcon
(
pSMBFile
->
tlink
);
rc
=
smb_mnt_get_fsinfo
(
xid
,
tcon
,
(
void
__user
*
)
arg
);
break
;
case
CIFS_ENUMERATE_SNAPSHOTS
:
if
(
pSMBFile
==
NULL
)
break
;
if
(
arg
==
0
)
{
rc
=
-
EINVAL
;
goto
cifs_ioc_exit
;
...
...
sources/4.9/misc.c
View file @
892812f0
...
...
@@ -492,7 +492,7 @@ is_valid_oplock_break(char *buffer, struct TCP_Server_Info *srv)
CIFS_INODE_DOWNGRADE_OPLOCK_TO_L2
,
&
pCifsInode
->
flags
);
queue_work
(
cifs
io
d_wq
,
queue_work
(
cifs
oplock
d_wq
,
&
netfile
->
oplock_break
);
netfile
->
oplock_break_cancelled
=
false
;
...
...
sources/4.9/readdir.c
View file @
892812f0
...
...
@@ -285,6 +285,7 @@ initiate_cifs_search(const unsigned int xid, struct file *file)
rc
=
-
ENOMEM
;
goto
error_exit
;
}
spin_lock_init
(
&
cifsFile
->
file_info_lock
);
file
->
private_data
=
cifsFile
;
cifsFile
->
tlink
=
cifs_get_tlink
(
tlink
);
tcon
=
tlink_tcon
(
tlink
);
...
...
sources/4.9/smb1ops.c
View file @
892812f0
...
...
@@ -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.9/smb2file.c
View file @
892812f0
...
...
@@ -260,7 +260,7 @@ smb2_push_mandatory_locks(struct cifsFileInfo *cfile)
* and check it for zero before using.
*/
max_buf
=
tlink_tcon
(
cfile
->
tlink
)
->
ses
->
server
->
maxBuf
;
if
(
!
max_buf
)
{
if
(
max_buf
<
sizeof
(
struct
smb2_lock_element
)
)
{
free_xid
(
xid
);
return
-
EINVAL
;
}
...
...
sources/4.9/smb2misc.c
View file @
892812f0
...
...
@@ -494,7 +494,7 @@ smb2_tcon_has_lease(struct cifs_tcon *tcon, struct smb2_lease_break *rsp,
else
cfile
->
oplock_break_cancelled
=
true
;
queue_work
(
cifs
io
d_wq
,
&
cfile
->
oplock_break
);
queue_work
(
cifs
oplock
d_wq
,
&
cfile
->
oplock_break
);
kfree
(
lw
);
return
true
;
}
...
...
@@ -638,7 +638,8 @@ smb2_is_valid_oplock_break(char *buffer, struct TCP_Server_Info *server)
CIFS_INODE_DOWNGRADE_OPLOCK_TO_L2
,
&
cinode
->
flags
);
spin_unlock
(
&
cfile
->
file_info_lock
);
queue_work
(
cifsiod_wq
,
&
cfile
->
oplock_break
);
queue_work
(
cifsoplockd_wq
,
&
cfile
->
oplock_break
);
spin_unlock
(
&
tcon
->
open_file_lock
);
spin_unlock
(
&
cifs_tcp_ses_lock
);
...
...
@@ -654,3 +655,47 @@ smb2_is_valid_oplock_break(char *buffer, struct TCP_Server_Info *server)
cifs_dbg
(
FYI
,
"Can not process oplock break for non-existent connection
\n
"
);
return
false
;
}
void
smb2_cancelled_close_fid
(
struct
work_struct
*
work
)
{
struct
close_cancelled_open
*
cancelled
=
container_of
(
work
,
struct
close_cancelled_open
,
work
);
cifs_dbg
(
VFS
,
"Close unmatched open
\n
"
);
SMB2_close
(
0
,
cancelled
->
tcon
,
cancelled
->
fid
.
persistent_fid
,
cancelled
->
fid
.
volatile_fid
);
cifs_put_tcon
(
cancelled
->
tcon
);
kfree
(
cancelled
);
}
int
smb2_handle_cancelled_mid
(
char
*
buffer
,
struct
TCP_Server_Info
*
server
)
{
struct
smb2_hdr
*
hdr
=
(
struct
smb2_hdr
*
)
buffer
;
struct
smb2_create_rsp
*
rsp
=
(
struct
smb2_create_rsp
*
)
buffer
;
struct
cifs_tcon
*
tcon
;
struct
close_cancelled_open
*
cancelled
;
if
(
hdr
->
Command
!=
SMB2_CREATE
||
hdr
->
Status
!=
STATUS_SUCCESS
)
return
0
;
cancelled
=
kzalloc
(
sizeof
(
*
cancelled
),
GFP_KERNEL
);
if
(
!
cancelled
)
return
-
ENOMEM
;
tcon
=
smb2_find_smb_tcon
(
server
,
hdr
->
SessionId
,
hdr
->
TreeId
);
if
(
!
tcon
)
{
kfree
(
cancelled
);
return
-
ENOENT
;
}
cancelled
->
fid
.
persistent_fid
=
rsp
->
PersistentFileId
;
cancelled
->
fid
.
volatile_fid
=
rsp
->
VolatileFileId
;
cancelled
->
tcon
=
tcon
;
INIT_WORK
(
&
cancelled
->
work
,
smb2_cancelled_close_fid
);
queue_work
(
cifsiod_wq
,
&
cancelled
->
work
);
return
0
;
}
sources/4.9/smb2ops.c
View file @
892812f0
...
...
@@ -927,6 +927,7 @@ smb3_enum_snapshots(const unsigned int xid, struct cifs_tcon *tcon,
}
if
(
snapshot_in
.
snapshot_array_size
<
sizeof
(
struct
smb_snapshot_array
))
{
rc
=
-
ERANGE
;
kfree
(
retbuf
);
return
rc
;
}
...
...
@@ -967,7 +968,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
;
}
...
...
@@ -977,7 +978,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
;
...
...
@@ -1021,6 +1022,18 @@ smb2_is_status_pending(char *buf, struct TCP_Server_Info *server, int length)
return
true
;
}
static
bool
smb2_is_session_expired
(
char
*
buf
)
{
struct
smb2_hdr
*
hdr
=
(
struct
smb2_hdr
*
)
buf
;
if
(
hdr
->
Status
!=
STATUS_NETWORK_SESSION_EXPIRED
)
return
false
;
cifs_dbg
(
FYI
,
"Session expired
\n
"
);
return
true
;
}
static
int
smb2_oplock_response
(
struct
cifs_tcon
*
tcon
,
struct
cifs_fid
*
fid
,
struct
cifsInodeInfo
*
cinode
)
...
...
@@ -1571,6 +1584,7 @@ struct smb_version_operations smb20_operations = {
.
clear_stats
=
smb2_clear_stats
,
.
print_stats
=
smb2_print_stats
,
.
is_oplock_break
=
smb2_is_valid_oplock_break
,
.
handle_cancelled_mid
=
smb2_handle_cancelled_mid
,
.
downgrade_oplock
=
smb2_downgrade_oplock
,
.
need_neg
=
smb2_need_neg
,
.
negotiate
=
smb2_negotiate
,
...
...
@@ -1613,6 +1627,7 @@ struct smb_version_operations smb20_operations = {
.
close_dir
=
smb2_close_dir
,
.
calc_smb_size
=
smb2_calc_size
,
.
is_status_pending
=
smb2_is_status_pending
,
.
is_session_expired
=
smb2_is_session_expired
,
.
oplock_response
=
smb2_oplock_response
,
.
queryfs
=
smb2_queryfs
,
.
mand_lock
=
smb2_mand_lock
,
...
...
@@ -1651,6 +1666,7 @@ struct smb_version_operations smb21_operations = {
.
clear_stats
=
smb2_clear_stats
,
.
print_stats
=
smb2_print_stats
,
.
is_oplock_break
=
smb2_is_valid_oplock_break
,
.
handle_cancelled_mid
=
smb2_handle_cancelled_mid
,
.
downgrade_oplock
=
smb2_downgrade_oplock
,
.
need_neg
=
smb2_need_neg
,
.
negotiate
=
smb2_negotiate
,
...
...
@@ -1693,6 +1709,7 @@ struct smb_version_operations smb21_operations = {
.
close_dir
=
smb2_close_dir
,
.
calc_smb_size
=
smb2_calc_size
,
.
is_status_pending
=
smb2_is_status_pending
,
.
is_session_expired
=
smb2_is_session_expired
,
.
oplock_response
=
smb2_oplock_response
,
.
queryfs
=
smb2_queryfs
,
.
mand_lock
=
smb2_mand_lock
,
...
...
@@ -1733,6 +1750,7 @@ struct smb_version_operations smb30_operations = {
.
print_stats
=
smb2_print_stats
,
.
dump_share_caps
=
smb2_dump_share_caps
,
.
is_oplock_break
=
smb2_is_valid_oplock_break
,
.
handle_cancelled_mid
=
smb2_handle_cancelled_mid
,
.
downgrade_oplock
=
smb2_downgrade_oplock
,
.
need_neg
=
smb2_need_neg
,
.
negotiate
=
smb2_negotiate
,
...
...
@@ -1775,6 +1793,7 @@ struct smb_version_operations smb30_operations = {
.
close_dir
=
smb2_close_dir
,
.
calc_smb_size
=
smb2_calc_size
,
.
is_status_pending
=
smb2_is_status_pending
,
.
is_session_expired
=
smb2_is_session_expired
,
.
oplock_response
=
smb2_oplock_response
,
.
queryfs
=
smb2_queryfs
,
.
mand_lock
=
smb2_mand_lock
,
...
...
@@ -1821,6 +1840,7 @@ struct smb_version_operations smb311_operations = {
.
print_stats
=
smb2_print_stats
,
.
dump_share_caps
=
smb2_dump_share_caps
,
.
is_oplock_break
=
smb2_is_valid_oplock_break
,
.
handle_cancelled_mid
=
smb2_handle_cancelled_mid
,
.
downgrade_oplock
=
smb2_downgrade_oplock
,
.
need_neg
=
smb2_need_neg
,
.
negotiate
=
smb2_negotiate
,
...
...
@@ -1863,6 +1883,7 @@ struct smb_version_operations smb311_operations = {
.
close_dir
=
smb2_close_dir
,
.
calc_smb_size
=
smb2_calc_size
,
.
is_status_pending
=
smb2_is_status_pending
,
.
is_session_expired
=
smb2_is_session_expired
,
.
oplock_response
=
smb2_oplock_response
,
.
queryfs
=
smb2_queryfs
,
.
mand_lock
=
smb2_mand_lock
,
...
...
sources/4.9/smb2pdu.c
View file @
892812f0
...
...
@@ -250,16 +250,19 @@ smb2_reconnect(__le16 smb2_command, struct cifs_tcon *tcon)
}
cifs_mark_open_files_invalid
(
tcon
);
if
(
tcon
->
use_persistent
)
tcon
->
need_reopen_files
=
true
;
rc
=
SMB2_tcon
(
0
,
tcon
->
ses
,
tcon
->
treeName
,
tcon
,
nls_codepage
);
mutex_unlock
(
&
tcon
->
ses
->
session_mutex
);
if
(
tcon
->
use_persistent
)
cifs_reopen_persistent_handles
(
tcon
);
cifs_dbg
(
FYI
,
"reconnect tcon rc = %d
\n
"
,
rc
);
if
(
rc
)
goto
out
;
if
(
smb2_command
!=
SMB2_INTERNAL_CMD
)
queue_delayed_work
(
cifsiod_wq
,
&
server
->
reconnect
,
0
);
atomic_inc
(
&
tconInfoReconnectCount
);
out:
/*
...
...
@@ -280,7 +283,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
;
...
...
@@ -363,7 +366,7 @@ assemble_neg_contexts(struct smb2_negotiate_req *req)
build_encrypt_ctxt
((
struct
smb2_encryption_neg_context
*
)
pneg_ctxt
);
req
->
NegotiateContextOffset
=
cpu_to_le32
(
OFFSET_OF_NEG_CONTEXT
);
req
->
NegotiateContextCount
=
cpu_to_le16
(
2
);
inc_rfc1001_len
(
req
,
4
+
sizeof
(
struct
smb2_preauth_neg_context
)
+
2
inc_rfc1001_len
(
req
,
4
+
sizeof
(
struct
smb2_preauth_neg_context
)
+
sizeof
(
struct
smb2_encryption_neg_context
));
/* calculate hash */
}
#else
...
...
@@ -528,15 +531,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
,
...
...
@@ -566,8 +576,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 */
...
...
@@ -1003,6 +1017,8 @@ SMB2_sess_setup(const unsigned int xid, struct cifs_ses *ses,
while
(
sess_data
->
func
)
sess_data
->
func
(
sess_data
);
if
((
ses
->
session_flags
&
SMB2_SESSION_FLAG_IS_GUEST
)
&&
(
ses
->
sign
))
cifs_dbg
(
VFS
,
"signing requested but authenticated as guest
\n
"
);
rc
=
sess_data
->
result
;
out:
kfree
(
sess_data
);
...
...
@@ -1081,9 +1097,6 @@ SMB2_tcon(const unsigned int xid, struct cifs_ses *ses, const char *tree,
else
return
-
EIO
;
if
(
tcon
&&
tcon
->
bad_network_name
)
return
-
ENOENT
;
if
((
tcon
&&
tcon
->
seal
)
&&
((
ses
->
server
->
capabilities
&
SMB2_GLOBAL_CAP_ENCRYPTION
)
==
0
))
{
cifs_dbg
(
VFS
,
"encryption requested but no server support"
);
...
...
@@ -1101,6 +1114,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
);
...
...
@@ -1181,8 +1198,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
;
}
...
...
@@ -1668,8 +1683,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
);
...
...
@@ -1972,6 +1991,63 @@ 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
;
int
rc
;
int
resched
=
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
->
need_reopen_files
)
{
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
)
{
rc
=
smb2_reconnect
(
SMB2_INTERNAL_CMD
,
tcon
);
if
(
!
rc
)
cifs_reopen_persistent_handles
(
tcon
);
else
resched
=
true
;
list_del_init
(
&
tcon
->
rlist
);
cifs_put_tcon
(
tcon
);
}
cifs_dbg
(
FYI
,
"Reconnecting tcons finished
\n
"
);
if
(
resched
)
queue_delayed_work
(
cifsiod_wq
,
&
server
->
reconnect
,
2
*
HZ
);
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
)
{
...
...
@@ -1984,32 +2060,11 @@ SMB2_echo(struct TCP_Server_Info *server)
cifs_dbg
(
FYI
,
"In echo request
\n
"
);
if
(
server
->
tcpStatus
==
CifsNeedNegotiate
)
{
struct
list_head
*
tmp
,
*
tmp2
;
struct
cifs_ses
*
ses
;
struct
cifs_tcon
*
tcon
;
cifs_dbg
(
FYI
,
"Need negotiate, reconnecting tcons
\n
"
);
spin_lock
(
&
cifs_tcp_ses_lock
);
list_for_each
(
tmp
,
&
server
->
smb_ses_list
)
{
ses
=
list_entry
(
tmp
,
struct
cifs_ses
,
smb_ses_list
);
list_for_each
(
tmp2
,
&
ses
->
tcon_list
)
{
tcon
=
list_entry
(
tmp2
,
struct
cifs_tcon
,
tcon_list
);
/* add check for persistent handle reconnect */
if
(
tcon
&&
tcon
->
need_reconnect
)
{
spin_unlock
(
&
cifs_tcp_ses_lock
);
rc
=
smb2_reconnect
(
SMB2_ECHO
,
tcon
);
spin_lock
(
&
cifs_tcp_ses_lock
);
}
}
}
spin_unlock
(
&
cifs_tcp_ses_lock
);
/* No need to send echo on newly established connections */
queue_delayed_work
(
cifsiod_wq
,
&
server
->
reconnect
,
0
);
return
rc
;
}
/* if no session, renegotiate failed above */
if
(
server
->
tcpStatus
==
CifsNeedNegotiate
)
return
-
EIO
;
rc
=
small_smb2_init
(
SMB2_ECHO
,
NULL
,
(
void
**
)
&
req
);
if
(
rc
)
return
rc
;
...
...
@@ -2884,8 +2939,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.9/smb2pdu.h
View file @
892812f0
...
...
@@ -80,10 +80,12 @@
#define SMB2_SET_INFO cpu_to_le16(SMB2_SET_INFO_HE)
#define SMB2_OPLOCK_BREAK cpu_to_le16(SMB2_OPLOCK_BREAK_HE)
#define SMB2_INTERNAL_CMD cpu_to_le16(0xFFFF)
#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)
#define SMB2_TRANSFORM_PROTO_NUM cpu_to_le32(0x424d53fd)
...
...
sources/4.9/smb2proto.h
View file @
892812f0
...
...
@@ -48,6 +48,10 @@ extern struct mid_q_entry *smb2_setup_request(struct cifs_ses *ses,
struct
smb_rqst
*
rqst
);
extern
struct
mid_q_entry
*
smb2_setup_async_request
(
struct
TCP_Server_Info
*
server
,
struct
smb_rqst
*
rqst
);
extern
struct
cifs_ses
*
smb2_find_smb_ses
(
struct
TCP_Server_Info
*
server
,
__u64
ses_id
);
extern
struct
cifs_tcon
*
smb2_find_smb_tcon
(
struct
TCP_Server_Info
*
server
,
__u64
ses_id
,
__u32
tid
);
extern
int
smb2_calc_signature
(
struct
smb_rqst
*
rqst
,
struct
TCP_Server_Info
*
server
);
extern
int
smb3_calc_signature
(
struct
smb_rqst
*
rqst
,
...
...
@@ -96,6 +100,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
...
...
@@ -157,6 +162,9 @@ extern int SMB2_set_compression(const unsigned int xid, struct cifs_tcon *tcon,
extern
int
SMB2_oplock_break
(
const
unsigned
int
xid
,
struct
cifs_tcon
*
tcon
,
const
u64
persistent_fid
,
const
u64
volatile_fid
,
const
__u8
oplock_level
);
extern
int
smb2_handle_cancelled_mid
(
char
*
buffer
,
struct
TCP_Server_Info
*
server
);
void
smb2_cancelled_close_fid
(
struct
work_struct
*
work
);
extern
int
SMB2_QFS_info
(
const
unsigned
int
xid
,
struct
cifs_tcon
*
tcon
,
u64
persistent_file_id
,
u64
volatile_file_id
,
struct
kstatfs
*
FSData
);
...
...
sources/4.9/smb2transport.c
View file @
892812f0
...
...
@@ -115,22 +115,68 @@ smb3_crypto_shash_allocate(struct TCP_Server_Info *server)
}
static
struct
cifs_ses
*
smb2_find_smb_ses
(
struct
smb2_hdr
*
smb2hdr
,
struct
TCP_Server_Info
*
server
)
smb2_find_smb_ses
_unlocked
(
struct
TCP_Server_Info
*
server
,
__u64
ses_id
)
{
struct
cifs_ses
*
ses
;
spin_lock
(
&
cifs_tcp_ses_lock
);
list_for_each_entry
(
ses
,
&
server
->
smb_ses_list
,
smb_ses_list
)
{
if
(
ses
->
Suid
!=
s
mb2hdr
->
SessionI
d
)
if
(
ses
->
Suid
!=
s
es_i
d
)
continue
;
spin_unlock
(
&
cifs_tcp_ses_lock
);
return
ses
;
}
return
NULL
;
}
struct
cifs_ses
*
smb2_find_smb_ses
(
struct
TCP_Server_Info
*
server
,
__u64
ses_id
)
{
struct
cifs_ses
*
ses
;
spin_lock
(
&
cifs_tcp_ses_lock
);
ses
=
smb2_find_smb_ses_unlocked
(
server
,
ses_id
);
spin_unlock
(
&
cifs_tcp_ses_lock
);
return
ses
;
}
static
struct
cifs_tcon
*
smb2_find_smb_sess_tcon_unlocked
(
struct
cifs_ses
*
ses
,
__u32
tid
)
{
struct
cifs_tcon
*
tcon
;
list_for_each_entry
(
tcon
,
&
ses
->
tcon_list
,
tcon_list
)
{
if
(
tcon
->
tid
!=
tid
)
continue
;
++
tcon
->
tc_count
;
return
tcon
;
}
return
NULL
;
}
/*
* Obtain tcon corresponding to the tid in the given
* cifs_ses
*/
struct
cifs_tcon
*
smb2_find_smb_tcon
(
struct
TCP_Server_Info
*
server
,
__u64
ses_id
,
__u32
tid
)
{
struct
cifs_ses
*
ses
;
struct
cifs_tcon
*
tcon
;
spin_lock
(
&
cifs_tcp_ses_lock
);
ses
=
smb2_find_smb_ses_unlocked
(
server
,
ses_id
);
if
(
!
ses
)
{
spin_unlock
(
&
cifs_tcp_ses_lock
);
return
NULL
;
}
tcon
=
smb2_find_smb_sess_tcon_unlocked
(
ses
,
tid
);
spin_unlock
(
&
cifs_tcp_ses_lock
);
return
tcon
;
}
int
smb2_calc_signature
(
struct
smb_rqst
*
rqst
,
struct
TCP_Server_Info
*
server
)
...
...
@@ -142,7 +188,7 @@ smb2_calc_signature(struct smb_rqst *rqst, struct TCP_Server_Info *server)
struct
smb2_hdr
*
smb2_pdu
=
(
struct
smb2_hdr
*
)
iov
[
0
].
iov_base
;
struct
cifs_ses
*
ses
;
ses
=
smb2_find_smb_ses
(
s
mb2_pdu
,
server
);
ses
=
smb2_find_smb_ses
(
s
erver
,
smb2_pdu
->
SessionId
);
if
(
!
ses
)
{
cifs_dbg
(
VFS
,
"%s: Could not find session
\n
"
,
__func__
);
return
0
;
...
...
@@ -359,7 +405,7 @@ smb3_calc_signature(struct smb_rqst *rqst, struct TCP_Server_Info *server)
struct
smb2_hdr
*
smb2_pdu
=
(
struct
smb2_hdr
*
)
iov
[
0
].
iov_base
;
struct
cifs_ses
*
ses
;
ses
=
smb2_find_smb_ses
(
s
mb2_pdu
,
server
);
ses
=
smb2_find_smb_ses
(
s
erver
,
smb2_pdu
->
SessionId
);
if
(
!
ses
)
{
cifs_dbg
(
VFS
,
"%s: Could not find session
\n
"
,
__func__
);
return
0
;
...
...
sources/4.9/smbencrypt.c
View file @
892812f0
...
...
@@ -23,7 +23,7 @@
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include <
crypto/skcipher
.h>
#include <
linux/crypto
.h>
#include <linux/module.h>
#include <linux/slab.h>
#include <linux/fs.h>
...
...
@@ -69,46 +69,22 @@ str_to_key(unsigned char *str, unsigned char *key)
static
int
smbhash
(
unsigned
char
*
out
,
const
unsigned
char
*
in
,
unsigned
char
*
key
)
{
int
rc
;
unsigned
char
key2
[
8
];
struct
crypto_skcipher
*
tfm_des
;
struct
scatterlist
sgin
,
sgout
;
struct
skcipher_request
*
req
;
struct
crypto_cipher
*
tfm_des
;
str_to_key
(
key
,
key2
);
tfm_des
=
crypto_alloc_
skcipher
(
"ecb(des)"
,
0
,
CRYPTO_ALG_ASYNC
);
tfm_des
=
crypto_alloc_
cipher
(
"des"
,
0
,
0
);
if
(
IS_ERR
(
tfm_des
))
{
rc
=
PTR_ERR
(
tfm_des
);
cifs_dbg
(
VFS
,
"could not allocate des crypto API
\n
"
);
goto
smbhash_err
;
}
req
=
skcipher_request_alloc
(
tfm_des
,
GFP_KERNEL
);
if
(
!
req
)
{
rc
=
-
ENOMEM
;
cifs_dbg
(
VFS
,
"could not allocate des crypto API
\n
"
);
goto
smbhash_free_skcipher
;
return
PTR_ERR
(
tfm_des
)
;
}
crypto_skcipher_setkey
(
tfm_des
,
key2
,
8
);
sg_init_one
(
&
sgin
,
in
,
8
);
sg_init_one
(
&
sgout
,
out
,
8
);
crypto_cipher_setkey
(
tfm_des
,
key2
,
8
);
crypto_cipher_encrypt_one
(
tfm_des
,
out
,
in
);
crypto_free_cipher
(
tfm_des
);
skcipher_request_set_callback
(
req
,
0
,
NULL
,
NULL
);
skcipher_request_set_crypt
(
req
,
&
sgin
,
&
sgout
,
8
,
NULL
);
rc
=
crypto_skcipher_encrypt
(
req
);
if
(
rc
)
cifs_dbg
(
VFS
,
"could not encrypt crypt key rc: %d
\n
"
,
rc
);
skcipher_request_free
(
req
);
smbhash_free_skcipher:
crypto_free_skcipher
(
tfm_des
);
smbhash_err:
return
rc
;
return
0
;
}
static
int
...
...
sources/4.9/transport.c
View file @
892812f0
...
...
@@ -727,9 +727,11 @@ SendReceive2(const unsigned int xid, struct cifs_ses *ses,
rc
=
wait_for_response
(
ses
->
server
,
midQ
);
if
(
rc
!=
0
)
{
cifs_dbg
(
FYI
,
"Cancelling wait for mid %llu
\n
"
,
midQ
->
mid
);
send_cancel
(
ses
->
server
,
buf
,
midQ
);
spin_lock
(
&
GlobalMid_Lock
);
if
(
midQ
->
mid_state
==
MID_REQUEST_SUBMITTED
)
{
midQ
->
mid_flags
|=
MID_WAIT_CANCELLED
;
midQ
->
callback
=
DeleteMidQEntry
;
spin_unlock
(
&
GlobalMid_Lock
);
cifs_small_buf_release
(
buf
);
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment