Commit 8cb1bb17 authored by Linus Torvalds's avatar Linus Torvalds

Merge tag '6.8-rc-smb-server-fixes-part2' of git://git.samba.org/ksmbd

Pull more smb server updates from Steve French:

 - Fix for incorrect oplock break on directories when leases disabled

 - UAF fix for race between create and destroy of tcp connection

 - Important session setup SPNEGO fix

 - Update ksmbd feature status summary

* tag '6.8-rc-smb-server-fixes-part2' of git://git.samba.org/ksmbd:
  ksmbd: only v2 leases handle the directory
  ksmbd: fix UAF issue in ksmbd_tcp_new_connection()
  ksmbd: validate mech token in session setup
  ksmbd: update feature status in documentation
parents 16df6e07 77bebd18
...@@ -73,15 +73,14 @@ Auto Negotiation Supported. ...@@ -73,15 +73,14 @@ Auto Negotiation Supported.
Compound Request Supported. Compound Request Supported.
Oplock Cache Mechanism Supported. Oplock Cache Mechanism Supported.
SMB2 leases(v1 lease) Supported. SMB2 leases(v1 lease) Supported.
Directory leases(v2 lease) Planned for future. Directory leases(v2 lease) Supported.
Multi-credits Supported. Multi-credits Supported.
NTLM/NTLMv2 Supported. NTLM/NTLMv2 Supported.
HMAC-SHA256 Signing Supported. HMAC-SHA256 Signing Supported.
Secure negotiate Supported. Secure negotiate Supported.
Signing Update Supported. Signing Update Supported.
Pre-authentication integrity Supported. Pre-authentication integrity Supported.
SMB3 encryption(CCM, GCM) Supported. (CCM and GCM128 supported, GCM256 in SMB3 encryption(CCM, GCM) Supported. (CCM/GCM128 and CCM/GCM256 supported)
progress)
SMB direct(RDMA) Supported. SMB direct(RDMA) Supported.
SMB3 Multi-channel Partially Supported. Planned to implement SMB3 Multi-channel Partially Supported. Planned to implement
replay/retry mechanisms for future. replay/retry mechanisms for future.
...@@ -112,6 +111,10 @@ DCE/RPC support Partially Supported. a few calls(NetShareEnumAll, ...@@ -112,6 +111,10 @@ DCE/RPC support Partially Supported. a few calls(NetShareEnumAll,
for Witness protocol e.g.) for Witness protocol e.g.)
ksmbd/nfsd interoperability Planned for future. The features that ksmbd ksmbd/nfsd interoperability Planned for future. The features that ksmbd
support are Leases, Notify, ACLs and Share modes. support are Leases, Notify, ACLs and Share modes.
SMB3.1.1 Compression Planned for future.
SMB3.1.1 over QUIC Planned for future.
Signing/Encryption over RDMA Planned for future.
SMB3.1.1 GMAC signing support Planned for future.
============================== ================================================= ============================== =================================================
......
...@@ -214,10 +214,15 @@ static int ksmbd_neg_token_alloc(void *context, size_t hdrlen, ...@@ -214,10 +214,15 @@ static int ksmbd_neg_token_alloc(void *context, size_t hdrlen,
{ {
struct ksmbd_conn *conn = context; struct ksmbd_conn *conn = context;
if (!vlen)
return -EINVAL;
conn->mechToken = kmemdup_nul(value, vlen, GFP_KERNEL); conn->mechToken = kmemdup_nul(value, vlen, GFP_KERNEL);
if (!conn->mechToken) if (!conn->mechToken)
return -ENOMEM; return -ENOMEM;
conn->mechTokenLen = (unsigned int)vlen;
return 0; return 0;
} }
......
...@@ -416,13 +416,7 @@ static void stop_sessions(void) ...@@ -416,13 +416,7 @@ static void stop_sessions(void)
again: again:
down_read(&conn_list_lock); down_read(&conn_list_lock);
list_for_each_entry(conn, &conn_list, conns_list) { list_for_each_entry(conn, &conn_list, conns_list) {
struct task_struct *task;
t = conn->transport; t = conn->transport;
task = t->handler;
if (task)
ksmbd_debug(CONN, "Stop session handler %s/%d\n",
task->comm, task_pid_nr(task));
ksmbd_conn_set_exiting(conn); ksmbd_conn_set_exiting(conn);
if (t->ops->shutdown) { if (t->ops->shutdown) {
up_read(&conn_list_lock); up_read(&conn_list_lock);
......
...@@ -88,6 +88,7 @@ struct ksmbd_conn { ...@@ -88,6 +88,7 @@ struct ksmbd_conn {
__u16 dialect; __u16 dialect;
char *mechToken; char *mechToken;
unsigned int mechTokenLen;
struct ksmbd_conn_ops *conn_ops; struct ksmbd_conn_ops *conn_ops;
...@@ -134,7 +135,6 @@ struct ksmbd_transport_ops { ...@@ -134,7 +135,6 @@ struct ksmbd_transport_ops {
struct ksmbd_transport { struct ksmbd_transport {
struct ksmbd_conn *conn; struct ksmbd_conn *conn;
struct ksmbd_transport_ops *ops; struct ksmbd_transport_ops *ops;
struct task_struct *handler;
}; };
#define KSMBD_TCP_RECV_TIMEOUT (7 * HZ) #define KSMBD_TCP_RECV_TIMEOUT (7 * HZ)
......
...@@ -1197,6 +1197,12 @@ int smb_grant_oplock(struct ksmbd_work *work, int req_op_level, u64 pid, ...@@ -1197,6 +1197,12 @@ int smb_grant_oplock(struct ksmbd_work *work, int req_op_level, u64 pid,
bool prev_op_has_lease; bool prev_op_has_lease;
__le32 prev_op_state = 0; __le32 prev_op_state = 0;
/* Only v2 leases handle the directory */
if (S_ISDIR(file_inode(fp->filp)->i_mode)) {
if (!lctx || lctx->version != 2)
return 0;
}
opinfo = alloc_opinfo(work, pid, tid); opinfo = alloc_opinfo(work, pid, tid);
if (!opinfo) if (!opinfo)
return -ENOMEM; return -ENOMEM;
......
...@@ -1414,6 +1414,9 @@ static struct ksmbd_user *session_user(struct ksmbd_conn *conn, ...@@ -1414,6 +1414,9 @@ static struct ksmbd_user *session_user(struct ksmbd_conn *conn,
char *name; char *name;
unsigned int name_off, name_len, secbuf_len; unsigned int name_off, name_len, secbuf_len;
if (conn->use_spnego && conn->mechToken)
secbuf_len = conn->mechTokenLen;
else
secbuf_len = le16_to_cpu(req->SecurityBufferLength); secbuf_len = le16_to_cpu(req->SecurityBufferLength);
if (secbuf_len < sizeof(struct authenticate_message)) { if (secbuf_len < sizeof(struct authenticate_message)) {
ksmbd_debug(SMB, "blob len %d too small\n", secbuf_len); ksmbd_debug(SMB, "blob len %d too small\n", secbuf_len);
...@@ -1505,6 +1508,9 @@ static int ntlm_authenticate(struct ksmbd_work *work, ...@@ -1505,6 +1508,9 @@ static int ntlm_authenticate(struct ksmbd_work *work,
struct authenticate_message *authblob; struct authenticate_message *authblob;
authblob = user_authblob(conn, req); authblob = user_authblob(conn, req);
if (conn->use_spnego && conn->mechToken)
sz = conn->mechTokenLen;
else
sz = le16_to_cpu(req->SecurityBufferLength); sz = le16_to_cpu(req->SecurityBufferLength);
rc = ksmbd_decode_ntlmssp_auth_blob(authblob, sz, conn, sess); rc = ksmbd_decode_ntlmssp_auth_blob(authblob, sz, conn, sess);
if (rc) { if (rc) {
...@@ -1778,8 +1784,7 @@ int smb2_sess_setup(struct ksmbd_work *work) ...@@ -1778,8 +1784,7 @@ int smb2_sess_setup(struct ksmbd_work *work)
negblob_off = le16_to_cpu(req->SecurityBufferOffset); negblob_off = le16_to_cpu(req->SecurityBufferOffset);
negblob_len = le16_to_cpu(req->SecurityBufferLength); negblob_len = le16_to_cpu(req->SecurityBufferLength);
if (negblob_off < offsetof(struct smb2_sess_setup_req, Buffer) || if (negblob_off < offsetof(struct smb2_sess_setup_req, Buffer)) {
negblob_len < offsetof(struct negotiate_message, NegotiateFlags)) {
rc = -EINVAL; rc = -EINVAL;
goto out_err; goto out_err;
} }
...@@ -1788,8 +1793,15 @@ int smb2_sess_setup(struct ksmbd_work *work) ...@@ -1788,8 +1793,15 @@ int smb2_sess_setup(struct ksmbd_work *work)
negblob_off); negblob_off);
if (decode_negotiation_token(conn, negblob, negblob_len) == 0) { if (decode_negotiation_token(conn, negblob, negblob_len) == 0) {
if (conn->mechToken) if (conn->mechToken) {
negblob = (struct negotiate_message *)conn->mechToken; negblob = (struct negotiate_message *)conn->mechToken;
negblob_len = conn->mechTokenLen;
}
}
if (negblob_len < offsetof(struct negotiate_message, NegotiateFlags)) {
rc = -EINVAL;
goto out_err;
} }
if (server_conf.auth_mechs & conn->auth_mechs) { if (server_conf.auth_mechs & conn->auth_mechs) {
......
...@@ -2039,6 +2039,7 @@ static bool rdma_frwr_is_supported(struct ib_device_attr *attrs) ...@@ -2039,6 +2039,7 @@ static bool rdma_frwr_is_supported(struct ib_device_attr *attrs)
static int smb_direct_handle_connect_request(struct rdma_cm_id *new_cm_id) static int smb_direct_handle_connect_request(struct rdma_cm_id *new_cm_id)
{ {
struct smb_direct_transport *t; struct smb_direct_transport *t;
struct task_struct *handler;
int ret; int ret;
if (!rdma_frwr_is_supported(&new_cm_id->device->attrs)) { if (!rdma_frwr_is_supported(&new_cm_id->device->attrs)) {
...@@ -2056,11 +2057,11 @@ static int smb_direct_handle_connect_request(struct rdma_cm_id *new_cm_id) ...@@ -2056,11 +2057,11 @@ static int smb_direct_handle_connect_request(struct rdma_cm_id *new_cm_id)
if (ret) if (ret)
goto out_err; goto out_err;
KSMBD_TRANS(t)->handler = kthread_run(ksmbd_conn_handler_loop, handler = kthread_run(ksmbd_conn_handler_loop,
KSMBD_TRANS(t)->conn, "ksmbd:r%u", KSMBD_TRANS(t)->conn, "ksmbd:r%u",
smb_direct_port); smb_direct_port);
if (IS_ERR(KSMBD_TRANS(t)->handler)) { if (IS_ERR(handler)) {
ret = PTR_ERR(KSMBD_TRANS(t)->handler); ret = PTR_ERR(handler);
pr_err("Can't start thread\n"); pr_err("Can't start thread\n");
goto out_err; goto out_err;
} }
......
...@@ -185,6 +185,7 @@ static int ksmbd_tcp_new_connection(struct socket *client_sk) ...@@ -185,6 +185,7 @@ static int ksmbd_tcp_new_connection(struct socket *client_sk)
struct sockaddr *csin; struct sockaddr *csin;
int rc = 0; int rc = 0;
struct tcp_transport *t; struct tcp_transport *t;
struct task_struct *handler;
t = alloc_transport(client_sk); t = alloc_transport(client_sk);
if (!t) { if (!t) {
...@@ -199,13 +200,13 @@ static int ksmbd_tcp_new_connection(struct socket *client_sk) ...@@ -199,13 +200,13 @@ static int ksmbd_tcp_new_connection(struct socket *client_sk)
goto out_error; goto out_error;
} }
KSMBD_TRANS(t)->handler = kthread_run(ksmbd_conn_handler_loop, handler = kthread_run(ksmbd_conn_handler_loop,
KSMBD_TRANS(t)->conn, KSMBD_TRANS(t)->conn,
"ksmbd:%u", "ksmbd:%u",
ksmbd_tcp_get_port(csin)); ksmbd_tcp_get_port(csin));
if (IS_ERR(KSMBD_TRANS(t)->handler)) { if (IS_ERR(handler)) {
pr_err("cannot start conn thread\n"); pr_err("cannot start conn thread\n");
rc = PTR_ERR(KSMBD_TRANS(t)->handler); rc = PTR_ERR(handler);
free_transport(t); free_transport(t);
} }
return rc; return rc;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment