Skip to content

Commit 781802a

Browse files
paliSteve French
authored andcommitted
cifs: Fix establishing NetBIOS session for SMB2+ connection
Function ip_rfc1001_connect() which establish NetBIOS session for SMB connections, currently uses smb_send() function for sending NetBIOS Session Request packet. This function expects that the passed buffer is SMB packet and for SMB2+ connections it mangles packet header, which breaks prepared NetBIOS Session Request packet. Result is that this function send garbage packet for SMB2+ connection, which SMB2+ server cannot parse. That function is not mangling packets for SMB1 connections, so it somehow works for SMB1. Fix this problem and instead of smb_send(), use smb_send_kvec() function which does not mangle prepared packet, this function send them as is. Just API of this function takes struct msghdr (kvec) instead of packet buffer. [MS-SMB2] specification allows SMB2 protocol to use NetBIOS as a transport protocol. NetBIOS can be used over TCP via port 139. So this is a valid configuration, just not so common. And even recent Windows versions (e.g. Windows Server 2022) still supports this configuration: SMB over TCP port 139, including for modern SMB2 and SMB3 dialects. This change fixes SMB2 and SMB3 connections over TCP port 139 which requires establishing of NetBIOS session. Tested that this change fixes establishing of SMB2 and SMB3 connections with Windows Server 2022. Signed-off-by: Pali Rohár <pali@kernel.org> Signed-off-by: Steve French <stfrench@microsoft.com>
1 parent ad9364a commit 781802a

File tree

3 files changed

+19
-6
lines changed

3 files changed

+19
-6
lines changed

fs/smb/client/cifsproto.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,9 @@ extern void cifs_small_buf_release(void *);
3131
extern void free_rsp_buf(int, void *);
3232
extern int smb_send(struct TCP_Server_Info *, struct smb_hdr *,
3333
unsigned int /* length */);
34+
extern int smb_send_kvec(struct TCP_Server_Info *server,
35+
struct msghdr *msg,
36+
size_t *sent);
3437
extern unsigned int _get_xid(void);
3538
extern void _free_xid(unsigned int);
3639
#define get_xid() \

fs/smb/client/connect.c

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3035,8 +3035,10 @@ ip_rfc1001_connect(struct TCP_Server_Info *server)
30353035
* sessinit is sent but no second negprot
30363036
*/
30373037
struct rfc1002_session_packet req = {};
3038-
struct smb_hdr *smb_buf = (struct smb_hdr *)&req;
3038+
struct msghdr msg = {};
3039+
struct kvec iov = {};
30393040
unsigned int len;
3041+
size_t sent;
30403042

30413043
req.trailer.session_req.called_len = sizeof(req.trailer.session_req.called_name);
30423044

@@ -3065,10 +3067,18 @@ ip_rfc1001_connect(struct TCP_Server_Info *server)
30653067
* As per rfc1002, @len must be the number of bytes that follows the
30663068
* length field of a rfc1002 session request payload.
30673069
*/
3068-
len = sizeof(req) - offsetof(struct rfc1002_session_packet, trailer.session_req);
3070+
len = sizeof(req.trailer.session_req);
3071+
req.type = RFC1002_SESSION_REQUEST;
3072+
req.flags = 0;
3073+
req.length = cpu_to_be16(len);
3074+
len += offsetof(typeof(req), trailer.session_req);
3075+
iov.iov_base = &req;
3076+
iov.iov_len = len;
3077+
iov_iter_kvec(&msg.msg_iter, ITER_SOURCE, &iov, 1, len);
3078+
rc = smb_send_kvec(server, &msg, &sent);
3079+
if (rc < 0 || len != sent)
3080+
return (rc == -EINTR || rc == -EAGAIN) ? rc : -ECONNABORTED;
30693081

3070-
smb_buf->smb_buf_length = cpu_to_be32((RFC1002_SESSION_REQUEST << 24) | len);
3071-
rc = smb_send(server, smb_buf, len);
30723082
/*
30733083
* RFC1001 layer in at least one server requires very short break before
30743084
* negprot presumably because not expecting negprot to follow so fast.
@@ -3077,7 +3087,7 @@ ip_rfc1001_connect(struct TCP_Server_Info *server)
30773087
*/
30783088
usleep_range(1000, 2000);
30793089

3080-
return rc;
3090+
return 0;
30813091
}
30823092

30833093
static int

fs/smb/client/transport.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -179,7 +179,7 @@ delete_mid(struct mid_q_entry *mid)
179179
* Our basic "send data to server" function. Should be called with srv_mutex
180180
* held. The caller is responsible for handling the results.
181181
*/
182-
static int
182+
int
183183
smb_send_kvec(struct TCP_Server_Info *server, struct msghdr *smb_msg,
184184
size_t *sent)
185185
{

0 commit comments

Comments
 (0)