Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
xiphi1978
linux
提交
1982c344
L
linux
项目概览
xiphi1978
/
linux
通知
2
Star
0
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
L
linux
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
提交
Issue看板
体验新版 GitCode,发现更多精彩内容 >>
提交
1982c344
编写于
8月 17, 2005
作者:
S
Steve French
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
[CIFS] Ensure that cifs multiplex ids do not collide.
Signed-off-by: Steve French (sfrench@us.ibm.com)
上级
a59c6586
变更
6
隐藏空白更改
内联
并排
Showing
6 changed file
with
113 addition
and
29 deletion
+113
-29
fs/cifs/cifsglob.h
fs/cifs/cifsglob.h
+1
-0
fs/cifs/cifspdu.h
fs/cifs/cifspdu.h
+9
-10
fs/cifs/cifsproto.h
fs/cifs/cifsproto.h
+3
-3
fs/cifs/cifssmb.c
fs/cifs/cifssmb.c
+14
-9
fs/cifs/connect.c
fs/cifs/connect.c
+9
-0
fs/cifs/misc.c
fs/cifs/misc.c
+77
-7
未找到文件。
fs/cifs/cifsglob.h
浏览文件 @
1982c344
...
...
@@ -147,6 +147,7 @@ struct TCP_Server_Info {
/* (returned on Negotiate */
int
capabilities
;
/* allow selective disabling of caps by smb sess */
__u16
timeZone
;
__u16
CurrentMid
;
/* multiplex id - rotating counter */
char
cryptKey
[
CIFS_CRYPTO_KEY_SIZE
];
char
workstation_RFC1001_name
[
16
];
/* 16th byte is always zero */
__u32
sequence_number
;
/* needed for CIFS PDU signature */
...
...
fs/cifs/cifspdu.h
浏览文件 @
1982c344
...
...
@@ -1961,18 +1961,17 @@ struct data_blob {
perhaps add a CreateDevice - to create Pipes and other special .inodes
Also note POSIX open flags
2) Close - to return the last write time to do cache across close more safely
3)
PosixQFSInfo - to return statfs info
4) FindFirst return unique inode number - what about resume key, two
forms short (matches readdir) and full (enough info to cache inodes)
5
) Mkdir - set mode
3)
FindFirst return unique inode number - what about resume key, two
forms short (matches readdir) and full (enough info to cache inodes)
4
) Mkdir - set mode
And under consideration:
6
) FindClose2 (return nanosecond timestamp ??)
7
) Use nanosecond timestamps throughout all time fields if
5
) FindClose2 (return nanosecond timestamp ??)
6
) Use nanosecond timestamps throughout all time fields if
corresponding attribute flag is set
8) sendfile - handle based copy
9) Direct i/o
10) "POSIX ACL" support
11) Misc fcntls?
7) sendfile - handle based copy
8) Direct i/o
9) Misc fcntls?
what about fixing 64 bit alignment
...
...
@@ -2028,7 +2027,7 @@ struct data_blob {
*/
/* xsymlink is a symlink format that can be used
/* xsymlink is a symlink format
(used by MacOS)
that can be used
to save symlink info in a regular file when
mounted to operating systems that do not
support the cifs Unix extensions or EAs (for xattr
...
...
fs/cifs/cifsproto.h
浏览文件 @
1982c344
...
...
@@ -61,9 +61,9 @@ extern int decode_negTokenInit(unsigned char *security_blob, int length,
extern
int
cifs_inet_pton
(
int
,
char
*
source
,
void
*
dst
);
extern
int
map_smb_to_linux_error
(
struct
smb_hdr
*
smb
);
extern
void
header_assemble
(
struct
smb_hdr
*
,
char
/* command */
,
const
struct
cifsTconInfo
*
,
int
/* specifies length
of fixed section (word count) in two byte units */
);
const
struct
cifsTconInfo
*
,
int
/* length of
fixed section (word count) in two byte units */
);
extern
__u16
GetNextMid
(
struct
TCP_Server_Info
*
server
);
extern
struct
oplock_q_entry
*
AllocOplockQEntry
(
struct
inode
*
,
u16
,
struct
cifsTconInfo
*
);
extern
void
DeleteOplockQEntry
(
struct
oplock_q_entry
*
);
...
...
fs/cifs/cifssmb.c
浏览文件 @
1982c344
...
...
@@ -330,7 +330,7 @@ CIFSSMBNegotiate(unsigned int xid, struct cifsSesInfo *ses)
(
void
**
)
&
pSMB
,
(
void
**
)
&
pSMBr
);
if
(
rc
)
return
rc
;
pSMB
->
hdr
.
Mid
=
GetNextMid
(
server
);
pSMB
->
hdr
.
Flags2
|=
SMBFLG2_UNICODE
;
if
(
extended_security
)
pSMB
->
hdr
.
Flags2
|=
SMBFLG2_EXT_SEC
;
...
...
@@ -415,15 +415,14 @@ CIFSSMBNegotiate(unsigned int xid, struct cifsSesInfo *ses)
if
(
server
->
secMode
&
SECMODE_SIGN_REQUIRED
)
cERROR
(
1
,
(
"Server requires /proc/fs/cifs/PacketSigningEnabled"
));
server
->
secMode
&=
~
(
SECMODE_SIGN_ENABLED
|
SECMODE_SIGN_REQUIRED
);
server
->
secMode
&=
~
(
SECMODE_SIGN_ENABLED
|
SECMODE_SIGN_REQUIRED
);
}
else
if
(
sign_CIFS_PDUs
==
1
)
{
if
((
server
->
secMode
&
SECMODE_SIGN_REQUIRED
)
==
0
)
server
->
secMode
&=
~
(
SECMODE_SIGN_ENABLED
|
SECMODE_SIGN_REQUIRED
);
server
->
secMode
&=
~
(
SECMODE_SIGN_ENABLED
|
SECMODE_SIGN_REQUIRED
);
}
}
cifs_buf_release
(
pSMB
);
return
rc
;
}
...
...
@@ -519,6 +518,8 @@ CIFSSMBLogoff(const int xid, struct cifsSesInfo *ses)
smb_buffer_response
=
(
struct
smb_hdr
*
)
pSMB
;
/* BB removeme BB */
if
(
ses
->
server
)
{
pSMB
->
hdr
.
Mid
=
GetNextMid
(
ses
->
server
);
if
(
ses
->
server
->
secMode
&
(
SECMODE_SIGN_REQUIRED
|
SECMODE_SIGN_ENABLED
))
pSMB
->
hdr
.
Flags2
|=
SMBFLG2_SECURITY_SIGNATURE
;
...
...
@@ -2519,11 +2520,12 @@ CIFSFindFirst(const int xid, struct cifsTconInfo *tcon,
rc
=
SendReceive
(
xid
,
tcon
->
ses
,
(
struct
smb_hdr
*
)
pSMB
,
(
struct
smb_hdr
*
)
pSMBr
,
&
bytes_returned
,
0
);
if
(
rc
)
{
/* BB add logic to retry regular search if Unix search
rejected unexpectedly by server */
if
(
rc
)
{
/* BB add logic to retry regular search if Unix search rejected unexpectedly by server */
/* BB Add code to handle unsupported level rc */
cFYI
(
1
,
(
"Error in FindFirst = %d"
,
rc
));
cifs_buf_release
(
pSMB
);
if
(
pSMB
)
cifs_buf_release
(
pSMB
);
/* BB eventually could optimize out free and realloc of buf */
/* for this case */
...
...
@@ -2857,7 +2859,10 @@ CIFSGetDFSRefer(const int xid, struct cifsSesInfo *ses,
(
void
**
)
&
pSMBr
);
if
(
rc
)
return
rc
;
/* server pointer checked in called function,
but should never be null here anyway */
pSMB
->
hdr
.
Mid
=
GetNextMid
(
ses
->
server
);
pSMB
->
hdr
.
Tid
=
ses
->
ipc_tid
;
pSMB
->
hdr
.
Uid
=
ses
->
Suid
;
if
(
ses
->
capabilities
&
CAP_STATUS32
)
{
...
...
fs/cifs/connect.c
浏览文件 @
1982c344
...
...
@@ -1857,6 +1857,7 @@ CIFSSessSetup(unsigned int xid, struct cifsSesInfo *ses,
header_assemble
(
smb_buffer
,
SMB_COM_SESSION_SETUP_ANDX
,
NULL
/* no tCon exists yet */
,
13
/* wct */
);
smb_buffer
->
Mid
=
GetNextMid
(
ses
->
server
);
pSMB
->
req_no_secext
.
AndXCommand
=
0xFF
;
pSMB
->
req_no_secext
.
MaxBufferSize
=
cpu_to_le16
(
ses
->
server
->
maxBuf
);
pSMB
->
req_no_secext
.
MaxMpxCount
=
cpu_to_le16
(
ses
->
server
->
maxReq
);
...
...
@@ -2132,6 +2133,8 @@ CIFSSpnegoSessSetup(unsigned int xid, struct cifsSesInfo *ses,
/* send SMBsessionSetup here */
header_assemble
(
smb_buffer
,
SMB_COM_SESSION_SETUP_ANDX
,
NULL
/* no tCon exists yet */
,
12
/* wct */
);
smb_buffer
->
Mid
=
GetNextMid
(
ses
->
server
);
pSMB
->
req
.
hdr
.
Flags2
|=
SMBFLG2_EXT_SEC
;
pSMB
->
req
.
AndXCommand
=
0xFF
;
pSMB
->
req
.
MaxBufferSize
=
cpu_to_le16
(
ses
->
server
->
maxBuf
);
...
...
@@ -2398,6 +2401,8 @@ CIFSNTLMSSPNegotiateSessSetup(unsigned int xid,
/* send SMBsessionSetup here */
header_assemble
(
smb_buffer
,
SMB_COM_SESSION_SETUP_ANDX
,
NULL
/* no tCon exists yet */
,
12
/* wct */
);
smb_buffer
->
Mid
=
GetNextMid
(
ses
->
server
);
pSMB
->
req
.
hdr
.
Flags2
|=
SMBFLG2_EXT_SEC
;
pSMB
->
req
.
hdr
.
Flags
|=
(
SMBFLG_CASELESS
|
SMBFLG_CANONICAL_PATH_FORMAT
);
...
...
@@ -2740,6 +2745,8 @@ CIFSNTLMSSPAuthSessSetup(unsigned int xid, struct cifsSesInfo *ses,
/* send SMBsessionSetup here */
header_assemble
(
smb_buffer
,
SMB_COM_SESSION_SETUP_ANDX
,
NULL
/* no tCon exists yet */
,
12
/* wct */
);
smb_buffer
->
Mid
=
GetNextMid
(
ses
->
server
);
pSMB
->
req
.
hdr
.
Flags
|=
(
SMBFLG_CASELESS
|
SMBFLG_CANONICAL_PATH_FORMAT
);
pSMB
->
req
.
hdr
.
Flags2
|=
SMBFLG2_EXT_SEC
;
pSMB
->
req
.
AndXCommand
=
0xFF
;
...
...
@@ -3111,6 +3118,8 @@ CIFSTCon(unsigned int xid, struct cifsSesInfo *ses,
header_assemble
(
smb_buffer
,
SMB_COM_TREE_CONNECT_ANDX
,
NULL
/*no tid */
,
4
/*wct */
);
smb_buffer
->
Mid
=
GetNextMid
(
ses
->
server
);
smb_buffer
->
Uid
=
ses
->
Suid
;
pSMB
=
(
TCONX_REQ
*
)
smb_buffer
;
pSMBr
=
(
TCONX_RSP
*
)
smb_buffer_response
;
...
...
fs/cifs/misc.c
浏览文件 @
1982c344
...
...
@@ -34,8 +34,6 @@ extern mempool_t *cifs_sm_req_poolp;
extern
mempool_t
*
cifs_req_poolp
;
extern
struct
task_struct
*
oplockThread
;
static
__u16
GlobalMid
;
/* multiplex id - rotating counter */
/* The xid serves as a useful identifier for each incoming vfs request,
in a similar way to the mid which is useful to track each sent smb,
and CurrentXid can also provide a running counter (although it
...
...
@@ -51,6 +49,8 @@ _GetXid(void)
GlobalTotalActiveXid
++
;
if
(
GlobalTotalActiveXid
>
GlobalMaxActiveXid
)
GlobalMaxActiveXid
=
GlobalTotalActiveXid
;
/* keep high water mark for number of simultaneous vfs ops in our filesystem */
if
(
GlobalTotalActiveXid
>
65000
)
cFYI
(
1
,(
"warning: more than 65000 requests active"
));
xid
=
GlobalCurrentXid
++
;
spin_unlock
(
&
GlobalMid_Lock
);
return
xid
;
...
...
@@ -218,6 +218,76 @@ cifs_small_buf_release(void *buf_to_free)
return
;
}
/*
Find a free multiplex id (SMB mid). Otherwise there could be
mid collisions which might cause problems, demultiplexing the
wrong response to this request. Multiplex ids could collide if
one of a series requests takes much longer than the others, or
if a very large number of long lived requests (byte range
locks or FindNotify requests) are pending. No more than
64K-1 requests can be outstanding at one time. If no
mids are available, return zero. A future optimization
could make the combination of mids and uid the key we use
to demultiplex on (rather than mid alone).
In addition to the above check, the cifs demultiplex
code already used the command code as a secondary
check of the frame and if signing is negotiated the
response would be discarded if the mid were the same
but the signature was wrong. Since the mid is not put in the
pending queue until later (when it is about to be dispatched)
we do have to limit the number of outstanding requests
to somewhat less than 64K-1 although it is hard to imagine
so many threads being in the vfs at one time.
*/
__u16
GetNextMid
(
struct
TCP_Server_Info
*
server
)
{
__u16
mid
=
0
;
__u16
last_mid
;
int
collision
;
if
(
server
==
NULL
)
return
mid
;
spin_lock
(
&
GlobalMid_Lock
);
last_mid
=
server
->
CurrentMid
;
/* we do not want to loop forever */
server
->
CurrentMid
++
;
/* This nested loop looks more expensive than it is.
In practice the list of pending requests is short,
fewer than 50, and the mids are likely to be unique
on the first pass through the loop unless some request
takes longer than the 64 thousand requests before it
(and it would also have to have been a request that
did not time out) */
while
(
server
->
CurrentMid
!=
last_mid
)
{
struct
list_head
*
tmp
;
struct
mid_q_entry
*
mid_entry
;
collision
=
0
;
if
(
server
->
CurrentMid
==
0
)
server
->
CurrentMid
++
;
list_for_each
(
tmp
,
&
server
->
pending_mid_q
)
{
mid_entry
=
list_entry
(
tmp
,
struct
mid_q_entry
,
qhead
);
if
((
mid_entry
->
mid
==
server
->
CurrentMid
)
&&
(
mid_entry
->
midState
==
MID_REQUEST_SUBMITTED
))
{
/* This mid is in use, try a different one */
collision
=
1
;
break
;
}
}
if
(
collision
==
0
)
{
mid
=
server
->
CurrentMid
;
break
;
}
server
->
CurrentMid
++
;
}
spin_unlock
(
&
GlobalMid_Lock
);
return
mid
;
}
/* NB: MID can not be set if treeCon not passed in, in that
case it is responsbility of caller to set the mid */
void
header_assemble
(
struct
smb_hdr
*
buffer
,
char
smb_command
/* command */
,
const
struct
cifsTconInfo
*
treeCon
,
int
word_count
...
...
@@ -233,7 +303,8 @@ header_assemble(struct smb_hdr *buffer, char smb_command /* command */ ,
(
2
*
word_count
)
+
sizeof
(
struct
smb_hdr
)
-
4
/* RFC 1001 length field does not count */
+
2
/* for bcc field itself */
;
/* Note that this is the only network field that has to be converted to big endian and it is done just before we send it */
/* Note that this is the only network field that has to be converted
to big endian and it is done just before we send it */
buffer
->
Protocol
[
0
]
=
0xFF
;
buffer
->
Protocol
[
1
]
=
'S'
;
...
...
@@ -245,8 +316,6 @@ header_assemble(struct smb_hdr *buffer, char smb_command /* command */ ,
buffer
->
Pid
=
cpu_to_le16
((
__u16
)
current
->
tgid
);
buffer
->
PidHigh
=
cpu_to_le16
((
__u16
)(
current
->
tgid
>>
16
));
spin_lock
(
&
GlobalMid_Lock
);
GlobalMid
++
;
buffer
->
Mid
=
GlobalMid
;
spin_unlock
(
&
GlobalMid_Lock
);
if
(
treeCon
)
{
buffer
->
Tid
=
treeCon
->
tid
;
...
...
@@ -256,8 +325,9 @@ header_assemble(struct smb_hdr *buffer, char smb_command /* command */ ,
if
(
treeCon
->
ses
->
capabilities
&
CAP_STATUS32
)
{
buffer
->
Flags2
|=
SMBFLG2_ERR_STATUS
;
}
buffer
->
Uid
=
treeCon
->
ses
->
Suid
;
/* always in LE format */
/* Uid is not converted */
buffer
->
Uid
=
treeCon
->
ses
->
Suid
;
buffer
->
Mid
=
GetNextMid
(
treeCon
->
ses
->
server
);
if
(
multiuser_mount
!=
0
)
{
/* For the multiuser case, there are few obvious technically */
/* possible mechanisms to match the local linux user (uid) */
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录