Skip to content

Commit 90c8ce3

Browse files
committed
Merge tag '6.3-rc3-ksmbd-smb3-server-fixes' of git://git.samba.org/ksmbd
Pull ksmbd server fixes from Steve French: - return less confusing messages on unsupported dialects (STATUS_NOT_SUPPORTED instead of I/O error) - fix for overly frequent inactive session termination - fix refcount leak - fix bounds check problems found by static checkers - fix to advertise named stream support correctly - Fix AES256 signing bug when connected to from MacOS * tag '6.3-rc3-ksmbd-smb3-server-fixes' of git://git.samba.org/ksmbd: ksmbd: return unsupported error on smb1 mount ksmbd: return STATUS_NOT_SUPPORTED on unsupported smb2.0 dialect ksmbd: don't terminate inactive sessions after a few seconds ksmbd: fix possible refcount leak in smb2_open() ksmbd: add low bound validation to FSCTL_QUERY_ALLOCATED_RANGES ksmbd: add low bound validation to FSCTL_SET_ZERO_DATA ksmbd: set FILE_NAMED_STREAMS attribute in FS_ATTRIBUTE_INFORMATION ksmbd: fix wrong signingkey creation when encryption is AES256
2 parents e76db6e + 39b291b commit 90c8ce3

File tree

8 files changed

+78
-55
lines changed

8 files changed

+78
-55
lines changed

fs/ksmbd/auth.c

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -727,8 +727,9 @@ static int generate_key(struct ksmbd_conn *conn, struct ksmbd_session *sess,
727727
goto smb3signkey_ret;
728728
}
729729

730-
if (conn->cipher_type == SMB2_ENCRYPTION_AES256_CCM ||
731-
conn->cipher_type == SMB2_ENCRYPTION_AES256_GCM)
730+
if (key_size == SMB3_ENC_DEC_KEY_SIZE &&
731+
(conn->cipher_type == SMB2_ENCRYPTION_AES256_CCM ||
732+
conn->cipher_type == SMB2_ENCRYPTION_AES256_GCM))
732733
rc = crypto_shash_update(CRYPTO_HMACSHA256(ctx), L256, 4);
733734
else
734735
rc = crypto_shash_update(CRYPTO_HMACSHA256(ctx), L128, 4);

fs/ksmbd/connection.c

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -298,7 +298,7 @@ int ksmbd_conn_handler_loop(void *p)
298298
kvfree(conn->request_buf);
299299
conn->request_buf = NULL;
300300

301-
size = t->ops->read(t, hdr_buf, sizeof(hdr_buf));
301+
size = t->ops->read(t, hdr_buf, sizeof(hdr_buf), -1);
302302
if (size != sizeof(hdr_buf))
303303
break;
304304

@@ -319,13 +319,10 @@ int ksmbd_conn_handler_loop(void *p)
319319
}
320320

321321
/*
322-
* Check if pdu size is valid (min : smb header size,
323-
* max : 0x00FFFFFF).
322+
* Check maximum pdu size(0x00FFFFFF).
324323
*/
325-
if (pdu_size < __SMB2_HEADER_STRUCTURE_SIZE ||
326-
pdu_size > MAX_STREAM_PROT_LEN) {
324+
if (pdu_size > MAX_STREAM_PROT_LEN)
327325
break;
328-
}
329326

330327
/* 4 for rfc1002 length field */
331328
size = pdu_size + 4;
@@ -344,7 +341,7 @@ int ksmbd_conn_handler_loop(void *p)
344341
* We already read 4 bytes to find out PDU size, now
345342
* read in PDU
346343
*/
347-
size = t->ops->read(t, conn->request_buf + 4, pdu_size);
344+
size = t->ops->read(t, conn->request_buf + 4, pdu_size, 2);
348345
if (size < 0) {
349346
pr_err("sock_read failed: %d\n", size);
350347
break;

fs/ksmbd/connection.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -114,7 +114,8 @@ struct ksmbd_transport_ops {
114114
int (*prepare)(struct ksmbd_transport *t);
115115
void (*disconnect)(struct ksmbd_transport *t);
116116
void (*shutdown)(struct ksmbd_transport *t);
117-
int (*read)(struct ksmbd_transport *t, char *buf, unsigned int size);
117+
int (*read)(struct ksmbd_transport *t, char *buf,
118+
unsigned int size, int max_retries);
118119
int (*writev)(struct ksmbd_transport *t, struct kvec *iovs, int niov,
119120
int size, bool need_invalidate_rkey,
120121
unsigned int remote_key);

fs/ksmbd/smb2pdu.c

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2977,8 +2977,11 @@ int smb2_open(struct ksmbd_work *work)
29772977
sizeof(struct smb_acl) +
29782978
sizeof(struct smb_ace) * ace_num * 2,
29792979
GFP_KERNEL);
2980-
if (!pntsd)
2980+
if (!pntsd) {
2981+
posix_acl_release(fattr.cf_acls);
2982+
posix_acl_release(fattr.cf_dacls);
29812983
goto err_out;
2984+
}
29822985

29832986
rc = build_sec_desc(idmap,
29842987
pntsd, NULL, 0,
@@ -4934,6 +4937,10 @@ static int smb2_get_info_filesystem(struct ksmbd_work *work,
49344937

49354938
info->Attributes |= cpu_to_le32(server_conf.share_fake_fscaps);
49364939

4940+
if (test_share_config_flag(work->tcon->share_conf,
4941+
KSMBD_SHARE_FLAG_STREAMS))
4942+
info->Attributes |= cpu_to_le32(FILE_NAMED_STREAMS);
4943+
49374944
info->MaxPathNameComponentLength = cpu_to_le32(stfs.f_namelen);
49384945
len = smbConvertToUTF16((__le16 *)info->FileSystemName,
49394946
"NTFS", PATH_MAX, conn->local_nls, 0);
@@ -7444,13 +7451,16 @@ static int fsctl_query_allocated_ranges(struct ksmbd_work *work, u64 id,
74447451
if (in_count == 0)
74457452
return -EINVAL;
74467453

7454+
start = le64_to_cpu(qar_req->file_offset);
7455+
length = le64_to_cpu(qar_req->length);
7456+
7457+
if (start < 0 || length < 0)
7458+
return -EINVAL;
7459+
74477460
fp = ksmbd_lookup_fd_fast(work, id);
74487461
if (!fp)
74497462
return -ENOENT;
74507463

7451-
start = le64_to_cpu(qar_req->file_offset);
7452-
length = le64_to_cpu(qar_req->length);
7453-
74547464
ret = ksmbd_vfs_fqar_lseek(fp, start, length,
74557465
qar_rsp, in_count, out_count);
74567466
if (ret && ret != -E2BIG)
@@ -7751,7 +7761,7 @@ int smb2_ioctl(struct ksmbd_work *work)
77517761

77527762
off = le64_to_cpu(zero_data->FileOffset);
77537763
bfz = le64_to_cpu(zero_data->BeyondFinalZero);
7754-
if (off > bfz) {
7764+
if (off < 0 || bfz < 0 || off > bfz) {
77557765
ret = -EINVAL;
77567766
goto out;
77577767
}

fs/ksmbd/smb_common.c

Lines changed: 22 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -434,17 +434,34 @@ int ksmbd_extract_shortname(struct ksmbd_conn *conn, const char *longname,
434434

435435
static int __smb2_negotiate(struct ksmbd_conn *conn)
436436
{
437-
return (conn->dialect >= SMB21_PROT_ID &&
437+
return (conn->dialect >= SMB20_PROT_ID &&
438438
conn->dialect <= SMB311_PROT_ID);
439439
}
440440

441441
static int smb_handle_negotiate(struct ksmbd_work *work)
442442
{
443443
struct smb_negotiate_rsp *neg_rsp = work->response_buf;
444444

445-
ksmbd_debug(SMB, "Unsupported SMB protocol\n");
446-
neg_rsp->hdr.Status.CifsError = STATUS_INVALID_LOGON_TYPE;
447-
return -EINVAL;
445+
ksmbd_debug(SMB, "Unsupported SMB1 protocol\n");
446+
447+
/*
448+
* Remove 4 byte direct TCP header, add 2 byte bcc and
449+
* 2 byte DialectIndex.
450+
*/
451+
*(__be32 *)work->response_buf =
452+
cpu_to_be32(sizeof(struct smb_hdr) - 4 + 2 + 2);
453+
neg_rsp->hdr.Status.CifsError = STATUS_SUCCESS;
454+
455+
neg_rsp->hdr.Command = SMB_COM_NEGOTIATE;
456+
*(__le32 *)neg_rsp->hdr.Protocol = SMB1_PROTO_NUMBER;
457+
neg_rsp->hdr.Flags = SMBFLG_RESPONSE;
458+
neg_rsp->hdr.Flags2 = SMBFLG2_UNICODE | SMBFLG2_ERR_STATUS |
459+
SMBFLG2_EXT_SEC | SMBFLG2_IS_LONG_NAME;
460+
461+
neg_rsp->hdr.WordCount = 1;
462+
neg_rsp->DialectIndex = cpu_to_le16(work->conn->dialect);
463+
neg_rsp->ByteCount = 0;
464+
return 0;
448465
}
449466

450467
int ksmbd_smb_negotiate_common(struct ksmbd_work *work, unsigned int command)
@@ -465,7 +482,7 @@ int ksmbd_smb_negotiate_common(struct ksmbd_work *work, unsigned int command)
465482
}
466483
}
467484

468-
if (command == SMB2_NEGOTIATE_HE && __smb2_negotiate(conn)) {
485+
if (command == SMB2_NEGOTIATE_HE) {
469486
ret = smb2_handle_negotiate(work);
470487
init_smb2_neg_rsp(work);
471488
return ret;

fs/ksmbd/smb_common.h

Lines changed: 8 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -158,8 +158,15 @@
158158

159159
#define SMB1_PROTO_NUMBER cpu_to_le32(0x424d53ff)
160160
#define SMB_COM_NEGOTIATE 0x72
161-
162161
#define SMB1_CLIENT_GUID_SIZE (16)
162+
163+
#define SMBFLG_RESPONSE 0x80 /* this PDU is a response from server */
164+
165+
#define SMBFLG2_IS_LONG_NAME cpu_to_le16(0x40)
166+
#define SMBFLG2_EXT_SEC cpu_to_le16(0x800)
167+
#define SMBFLG2_ERR_STATUS cpu_to_le16(0x4000)
168+
#define SMBFLG2_UNICODE cpu_to_le16(0x8000)
169+
163170
struct smb_hdr {
164171
__be32 smb_buf_length;
165172
__u8 Protocol[4];
@@ -199,28 +206,7 @@ struct smb_negotiate_req {
199206
struct smb_negotiate_rsp {
200207
struct smb_hdr hdr; /* wct = 17 */
201208
__le16 DialectIndex; /* 0xFFFF = no dialect acceptable */
202-
__u8 SecurityMode;
203-
__le16 MaxMpxCount;
204-
__le16 MaxNumberVcs;
205-
__le32 MaxBufferSize;
206-
__le32 MaxRawSize;
207-
__le32 SessionKey;
208-
__le32 Capabilities; /* see below */
209-
__le32 SystemTimeLow;
210-
__le32 SystemTimeHigh;
211-
__le16 ServerTimeZone;
212-
__u8 EncryptionKeyLength;
213209
__le16 ByteCount;
214-
union {
215-
unsigned char EncryptionKey[8]; /* cap extended security off */
216-
/* followed by Domain name - if extended security is off */
217-
/* followed by 16 bytes of server GUID */
218-
/* then security blob if cap_extended_security negotiated */
219-
struct {
220-
unsigned char GUID[SMB1_CLIENT_GUID_SIZE];
221-
unsigned char SecurityBlob[1];
222-
} __packed extended_response;
223-
} __packed u;
224210
} __packed;
225211

226212
struct filesystem_attribute_info {

fs/ksmbd/transport_rdma.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -670,7 +670,7 @@ static int smb_direct_post_recv(struct smb_direct_transport *t,
670670
}
671671

672672
static int smb_direct_read(struct ksmbd_transport *t, char *buf,
673-
unsigned int size)
673+
unsigned int size, int unused)
674674
{
675675
struct smb_direct_recvmsg *recvmsg;
676676
struct smb_direct_data_transfer *data_transfer;

fs/ksmbd/transport_tcp.c

Lines changed: 23 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -291,24 +291,25 @@ static int ksmbd_tcp_run_kthread(struct interface *iface)
291291

292292
/**
293293
* ksmbd_tcp_readv() - read data from socket in given iovec
294-
* @t: TCP transport instance
295-
* @iov_orig: base IO vector
296-
* @nr_segs: number of segments in base iov
297-
* @to_read: number of bytes to read from socket
294+
* @t: TCP transport instance
295+
* @iov_orig: base IO vector
296+
* @nr_segs: number of segments in base iov
297+
* @to_read: number of bytes to read from socket
298+
* @max_retries: maximum retry count
298299
*
299300
* Return: on success return number of bytes read from socket,
300301
* otherwise return error number
301302
*/
302303
static int ksmbd_tcp_readv(struct tcp_transport *t, struct kvec *iov_orig,
303-
unsigned int nr_segs, unsigned int to_read)
304+
unsigned int nr_segs, unsigned int to_read,
305+
int max_retries)
304306
{
305307
int length = 0;
306308
int total_read;
307309
unsigned int segs;
308310
struct msghdr ksmbd_msg;
309311
struct kvec *iov;
310312
struct ksmbd_conn *conn = KSMBD_TRANS(t)->conn;
311-
int max_retry = 2;
312313

313314
iov = get_conn_iovec(t, nr_segs);
314315
if (!iov)
@@ -335,14 +336,23 @@ static int ksmbd_tcp_readv(struct tcp_transport *t, struct kvec *iov_orig,
335336
} else if (conn->status == KSMBD_SESS_NEED_RECONNECT) {
336337
total_read = -EAGAIN;
337338
break;
338-
} else if ((length == -ERESTARTSYS || length == -EAGAIN) &&
339-
max_retry) {
339+
} else if (length == -ERESTARTSYS || length == -EAGAIN) {
340+
/*
341+
* If max_retries is negative, Allow unlimited
342+
* retries to keep connection with inactive sessions.
343+
*/
344+
if (max_retries == 0) {
345+
total_read = length;
346+
break;
347+
} else if (max_retries > 0) {
348+
max_retries--;
349+
}
350+
340351
usleep_range(1000, 2000);
341352
length = 0;
342-
max_retry--;
343353
continue;
344354
} else if (length <= 0) {
345-
total_read = -EAGAIN;
355+
total_read = length;
346356
break;
347357
}
348358
}
@@ -358,14 +368,15 @@ static int ksmbd_tcp_readv(struct tcp_transport *t, struct kvec *iov_orig,
358368
* Return: on success return number of bytes read from socket,
359369
* otherwise return error number
360370
*/
361-
static int ksmbd_tcp_read(struct ksmbd_transport *t, char *buf, unsigned int to_read)
371+
static int ksmbd_tcp_read(struct ksmbd_transport *t, char *buf,
372+
unsigned int to_read, int max_retries)
362373
{
363374
struct kvec iov;
364375

365376
iov.iov_base = buf;
366377
iov.iov_len = to_read;
367378

368-
return ksmbd_tcp_readv(TCP_TRANS(t), &iov, 1, to_read);
379+
return ksmbd_tcp_readv(TCP_TRANS(t), &iov, 1, to_read, max_retries);
369380
}
370381

371382
static int ksmbd_tcp_writev(struct ksmbd_transport *t, struct kvec *iov,

0 commit comments

Comments
 (0)