Commit 25ac8c12 authored by Linus Torvalds's avatar Linus Torvalds

Merge tag '6.3-rc-ksmbd-fixes' of git://git.samba.org/ksmbd

Pull ksmbd server updates from Steve French:

 - Fix for memory leak

 - Two important fixes for frame length checks (which are also now
   stricter)

 - four minor cleanup fixes

 - Fix to clarify ksmbd/Kconfig to indent properl

 - Conversion of the channel list and rpc handle list to xarrays

* tag '6.3-rc-ksmbd-fixes' of git://git.samba.org/ksmbd:
  ksmbd: fix possible memory leak in smb2_lock()
  ksmbd: do not allow the actual frame length to be smaller than the rfc1002 length
  ksmbd: fix wrong data area length for smb2 lock request
  ksmbd: Fix parameter name and comment mismatch
  ksmbd: Fix spelling mistake "excceed" -> "exceeded"
  ksmbd: update Kconfig to note Kerberos support and fix indentation
  ksmbd: Remove duplicated codes
  ksmbd: fix typo, syncronous->synchronous
  ksmbd: Implements sess->rpc_handle_list as xarray
  ksmbd: Implements sess->ksmbd_chann_list as xarray
parents 232dd599 d3ca9f7a
...@@ -33,14 +33,16 @@ config SMB_SERVER ...@@ -33,14 +33,16 @@ config SMB_SERVER
in ksmbd-tools, available from in ksmbd-tools, available from
https://github.com/cifsd-team/ksmbd-tools. https://github.com/cifsd-team/ksmbd-tools.
More detail about how to run the ksmbd kernel server is More detail about how to run the ksmbd kernel server is
available via README file available via the README file
(https://github.com/cifsd-team/ksmbd-tools/blob/master/README). (https://github.com/cifsd-team/ksmbd-tools/blob/master/README).
ksmbd kernel server includes support for auto-negotiation, ksmbd kernel server includes support for auto-negotiation,
Secure negotiate, Pre-authentication integrity, oplock/lease, Secure negotiate, Pre-authentication integrity, oplock/lease,
compound requests, multi-credit, packet signing, RDMA(smbdirect), compound requests, multi-credit, packet signing, RDMA(smbdirect),
smb3 encryption, copy-offload, secure per-user session smb3 encryption, copy-offload, secure per-user session
establishment via NTLM or NTLMv2. establishment via Kerberos or NTLMv2.
if SMB_SERVER
config SMB_SERVER_SMBDIRECT config SMB_SERVER_SMBDIRECT
bool "Support for SMB Direct protocol" bool "Support for SMB Direct protocol"
...@@ -54,6 +56,8 @@ config SMB_SERVER_SMBDIRECT ...@@ -54,6 +56,8 @@ config SMB_SERVER_SMBDIRECT
SMB Direct allows transferring SMB packets over RDMA. If unsure, SMB Direct allows transferring SMB packets over RDMA. If unsure,
say N. say N.
endif
config SMB_SERVER_CHECK_CAP_NET_ADMIN config SMB_SERVER_CHECK_CAP_NET_ADMIN
bool "Enable check network administration capability" bool "Enable check network administration capability"
depends on SMB_SERVER depends on SMB_SERVER
......
...@@ -208,9 +208,9 @@ int ksmbd_neg_token_init_mech_type(void *context, size_t hdrlen, ...@@ -208,9 +208,9 @@ int ksmbd_neg_token_init_mech_type(void *context, size_t hdrlen,
return 0; return 0;
} }
int ksmbd_neg_token_init_mech_token(void *context, size_t hdrlen, static int ksmbd_neg_token_alloc(void *context, size_t hdrlen,
unsigned char tag, const void *value, unsigned char tag, const void *value,
size_t vlen) size_t vlen)
{ {
struct ksmbd_conn *conn = context; struct ksmbd_conn *conn = context;
...@@ -223,17 +223,16 @@ int ksmbd_neg_token_init_mech_token(void *context, size_t hdrlen, ...@@ -223,17 +223,16 @@ int ksmbd_neg_token_init_mech_token(void *context, size_t hdrlen,
return 0; return 0;
} }
int ksmbd_neg_token_targ_resp_token(void *context, size_t hdrlen, int ksmbd_neg_token_init_mech_token(void *context, size_t hdrlen,
unsigned char tag, const void *value, unsigned char tag, const void *value,
size_t vlen) size_t vlen)
{ {
struct ksmbd_conn *conn = context; return ksmbd_neg_token_alloc(context, hdrlen, tag, value, vlen);
}
conn->mechToken = kmalloc(vlen + 1, GFP_KERNEL);
if (!conn->mechToken)
return -ENOMEM;
memcpy(conn->mechToken, value, vlen); int ksmbd_neg_token_targ_resp_token(void *context, size_t hdrlen,
conn->mechToken[vlen] = '\0'; unsigned char tag, const void *value,
return 0; size_t vlen)
{
return ksmbd_neg_token_alloc(context, hdrlen, tag, value, vlen);
} }
...@@ -114,7 +114,7 @@ void ksmbd_conn_enqueue_request(struct ksmbd_work *work) ...@@ -114,7 +114,7 @@ void ksmbd_conn_enqueue_request(struct ksmbd_work *work)
if (conn->ops->get_cmd_val(work) != SMB2_CANCEL_HE) { if (conn->ops->get_cmd_val(work) != SMB2_CANCEL_HE) {
requests_queue = &conn->requests; requests_queue = &conn->requests;
work->syncronous = true; work->synchronous = true;
} }
if (requests_queue) { if (requests_queue) {
...@@ -139,7 +139,7 @@ int ksmbd_conn_try_dequeue_request(struct ksmbd_work *work) ...@@ -139,7 +139,7 @@ int ksmbd_conn_try_dequeue_request(struct ksmbd_work *work)
spin_lock(&conn->request_lock); spin_lock(&conn->request_lock);
if (!work->multiRsp) { if (!work->multiRsp) {
list_del_init(&work->request_entry); list_del_init(&work->request_entry);
if (work->syncronous == false) if (!work->synchronous)
list_del_init(&work->async_request_entry); list_del_init(&work->async_request_entry);
ret = 0; ret = 0;
} }
...@@ -312,7 +312,7 @@ int ksmbd_conn_handler_loop(void *p) ...@@ -312,7 +312,7 @@ int ksmbd_conn_handler_loop(void *p)
max_allowed_pdu_size = SMB3_MAX_MSGSIZE; max_allowed_pdu_size = SMB3_MAX_MSGSIZE;
if (pdu_size > max_allowed_pdu_size) { if (pdu_size > max_allowed_pdu_size) {
pr_err_ratelimited("PDU length(%u) excceed maximum allowed pdu size(%u) on connection(%d)\n", pr_err_ratelimited("PDU length(%u) exceeded maximum allowed pdu size(%u) on connection(%d)\n",
pdu_size, max_allowed_pdu_size, pdu_size, max_allowed_pdu_size,
conn->status); conn->status);
break; break;
......
...@@ -68,7 +68,7 @@ struct ksmbd_work { ...@@ -68,7 +68,7 @@ struct ksmbd_work {
/* Request is encrypted */ /* Request is encrypted */
bool encrypted:1; bool encrypted:1;
/* Is this SYNC or ASYNC ksmbd_work */ /* Is this SYNC or ASYNC ksmbd_work */
bool syncronous:1; bool synchronous:1;
bool need_invalidate_rkey:1; bool need_invalidate_rkey:1;
unsigned int remote_key; unsigned int remote_key;
......
...@@ -25,20 +25,19 @@ static DECLARE_RWSEM(sessions_table_lock); ...@@ -25,20 +25,19 @@ static DECLARE_RWSEM(sessions_table_lock);
struct ksmbd_session_rpc { struct ksmbd_session_rpc {
int id; int id;
unsigned int method; unsigned int method;
struct list_head list;
}; };
static void free_channel_list(struct ksmbd_session *sess) static void free_channel_list(struct ksmbd_session *sess)
{ {
struct channel *chann, *tmp; struct channel *chann;
unsigned long index;
write_lock(&sess->chann_lock); xa_for_each(&sess->ksmbd_chann_list, index, chann) {
list_for_each_entry_safe(chann, tmp, &sess->ksmbd_chann_list, xa_erase(&sess->ksmbd_chann_list, index);
chann_list) {
list_del(&chann->chann_list);
kfree(chann); kfree(chann);
} }
write_unlock(&sess->chann_lock);
xa_destroy(&sess->ksmbd_chann_list);
} }
static void __session_rpc_close(struct ksmbd_session *sess, static void __session_rpc_close(struct ksmbd_session *sess,
...@@ -58,15 +57,14 @@ static void __session_rpc_close(struct ksmbd_session *sess, ...@@ -58,15 +57,14 @@ static void __session_rpc_close(struct ksmbd_session *sess,
static void ksmbd_session_rpc_clear_list(struct ksmbd_session *sess) static void ksmbd_session_rpc_clear_list(struct ksmbd_session *sess)
{ {
struct ksmbd_session_rpc *entry; struct ksmbd_session_rpc *entry;
long index;
while (!list_empty(&sess->rpc_handle_list)) { xa_for_each(&sess->rpc_handle_list, index, entry) {
entry = list_entry(sess->rpc_handle_list.next, xa_erase(&sess->rpc_handle_list, index);
struct ksmbd_session_rpc,
list);
list_del(&entry->list);
__session_rpc_close(sess, entry); __session_rpc_close(sess, entry);
} }
xa_destroy(&sess->rpc_handle_list);
} }
static int __rpc_method(char *rpc_name) static int __rpc_method(char *rpc_name)
...@@ -102,13 +100,13 @@ int ksmbd_session_rpc_open(struct ksmbd_session *sess, char *rpc_name) ...@@ -102,13 +100,13 @@ int ksmbd_session_rpc_open(struct ksmbd_session *sess, char *rpc_name)
entry = kzalloc(sizeof(struct ksmbd_session_rpc), GFP_KERNEL); entry = kzalloc(sizeof(struct ksmbd_session_rpc), GFP_KERNEL);
if (!entry) if (!entry)
return -EINVAL; return -ENOMEM;
list_add(&entry->list, &sess->rpc_handle_list);
entry->method = method; entry->method = method;
entry->id = ksmbd_ipc_id_alloc(); entry->id = ksmbd_ipc_id_alloc();
if (entry->id < 0) if (entry->id < 0)
goto free_entry; goto free_entry;
xa_store(&sess->rpc_handle_list, entry->id, entry, GFP_KERNEL);
resp = ksmbd_rpc_open(sess, entry->id); resp = ksmbd_rpc_open(sess, entry->id);
if (!resp) if (!resp)
...@@ -117,9 +115,9 @@ int ksmbd_session_rpc_open(struct ksmbd_session *sess, char *rpc_name) ...@@ -117,9 +115,9 @@ int ksmbd_session_rpc_open(struct ksmbd_session *sess, char *rpc_name)
kvfree(resp); kvfree(resp);
return entry->id; return entry->id;
free_id: free_id:
xa_erase(&sess->rpc_handle_list, entry->id);
ksmbd_rpc_id_free(entry->id); ksmbd_rpc_id_free(entry->id);
free_entry: free_entry:
list_del(&entry->list);
kfree(entry); kfree(entry);
return -EINVAL; return -EINVAL;
} }
...@@ -128,24 +126,17 @@ void ksmbd_session_rpc_close(struct ksmbd_session *sess, int id) ...@@ -128,24 +126,17 @@ void ksmbd_session_rpc_close(struct ksmbd_session *sess, int id)
{ {
struct ksmbd_session_rpc *entry; struct ksmbd_session_rpc *entry;
list_for_each_entry(entry, &sess->rpc_handle_list, list) { entry = xa_erase(&sess->rpc_handle_list, id);
if (entry->id == id) { if (entry)
list_del(&entry->list); __session_rpc_close(sess, entry);
__session_rpc_close(sess, entry);
break;
}
}
} }
int ksmbd_session_rpc_method(struct ksmbd_session *sess, int id) int ksmbd_session_rpc_method(struct ksmbd_session *sess, int id)
{ {
struct ksmbd_session_rpc *entry; struct ksmbd_session_rpc *entry;
list_for_each_entry(entry, &sess->rpc_handle_list, list) { entry = xa_load(&sess->rpc_handle_list, id);
if (entry->id == id) return entry ? entry->method : 0;
return entry->method;
}
return 0;
} }
void ksmbd_session_destroy(struct ksmbd_session *sess) void ksmbd_session_destroy(struct ksmbd_session *sess)
...@@ -190,21 +181,15 @@ int ksmbd_session_register(struct ksmbd_conn *conn, ...@@ -190,21 +181,15 @@ int ksmbd_session_register(struct ksmbd_conn *conn,
static int ksmbd_chann_del(struct ksmbd_conn *conn, struct ksmbd_session *sess) static int ksmbd_chann_del(struct ksmbd_conn *conn, struct ksmbd_session *sess)
{ {
struct channel *chann, *tmp; struct channel *chann;
write_lock(&sess->chann_lock); chann = xa_erase(&sess->ksmbd_chann_list, (long)conn);
list_for_each_entry_safe(chann, tmp, &sess->ksmbd_chann_list, if (!chann)
chann_list) { return -ENOENT;
if (chann->conn == conn) {
list_del(&chann->chann_list);
kfree(chann);
write_unlock(&sess->chann_lock);
return 0;
}
}
write_unlock(&sess->chann_lock);
return -ENOENT; kfree(chann);
return 0;
} }
void ksmbd_sessions_deregister(struct ksmbd_conn *conn) void ksmbd_sessions_deregister(struct ksmbd_conn *conn)
...@@ -234,7 +219,7 @@ void ksmbd_sessions_deregister(struct ksmbd_conn *conn) ...@@ -234,7 +219,7 @@ void ksmbd_sessions_deregister(struct ksmbd_conn *conn)
return; return;
sess_destroy: sess_destroy:
if (list_empty(&sess->ksmbd_chann_list)) { if (xa_empty(&sess->ksmbd_chann_list)) {
xa_erase(&conn->sessions, sess->id); xa_erase(&conn->sessions, sess->id);
ksmbd_session_destroy(sess); ksmbd_session_destroy(sess);
} }
...@@ -320,6 +305,9 @@ static struct ksmbd_session *__session_create(int protocol) ...@@ -320,6 +305,9 @@ static struct ksmbd_session *__session_create(int protocol)
struct ksmbd_session *sess; struct ksmbd_session *sess;
int ret; int ret;
if (protocol != CIFDS_SESSION_FLAG_SMB2)
return NULL;
sess = kzalloc(sizeof(struct ksmbd_session), GFP_KERNEL); sess = kzalloc(sizeof(struct ksmbd_session), GFP_KERNEL);
if (!sess) if (!sess)
return NULL; return NULL;
...@@ -329,30 +317,20 @@ static struct ksmbd_session *__session_create(int protocol) ...@@ -329,30 +317,20 @@ static struct ksmbd_session *__session_create(int protocol)
set_session_flag(sess, protocol); set_session_flag(sess, protocol);
xa_init(&sess->tree_conns); xa_init(&sess->tree_conns);
INIT_LIST_HEAD(&sess->ksmbd_chann_list); xa_init(&sess->ksmbd_chann_list);
INIT_LIST_HEAD(&sess->rpc_handle_list); xa_init(&sess->rpc_handle_list);
sess->sequence_number = 1; sess->sequence_number = 1;
rwlock_init(&sess->chann_lock);
switch (protocol) {
case CIFDS_SESSION_FLAG_SMB2:
ret = __init_smb2_session(sess);
break;
default:
ret = -EINVAL;
break;
}
ret = __init_smb2_session(sess);
if (ret) if (ret)
goto error; goto error;
ida_init(&sess->tree_conn_ida); ida_init(&sess->tree_conn_ida);
if (protocol == CIFDS_SESSION_FLAG_SMB2) { down_write(&sessions_table_lock);
down_write(&sessions_table_lock); hash_add(sessions_table, &sess->hlist, sess->id);
hash_add(sessions_table, &sess->hlist, sess->id); up_write(&sessions_table_lock);
up_write(&sessions_table_lock);
}
return sess; return sess;
error: error:
......
...@@ -21,7 +21,6 @@ struct ksmbd_file_table; ...@@ -21,7 +21,6 @@ struct ksmbd_file_table;
struct channel { struct channel {
__u8 smb3signingkey[SMB3_SIGN_KEY_SIZE]; __u8 smb3signingkey[SMB3_SIGN_KEY_SIZE];
struct ksmbd_conn *conn; struct ksmbd_conn *conn;
struct list_head chann_list;
}; };
struct preauth_session { struct preauth_session {
...@@ -50,11 +49,10 @@ struct ksmbd_session { ...@@ -50,11 +49,10 @@ struct ksmbd_session {
char sess_key[CIFS_KEY_SIZE]; char sess_key[CIFS_KEY_SIZE];
struct hlist_node hlist; struct hlist_node hlist;
rwlock_t chann_lock; struct xarray ksmbd_chann_list;
struct list_head ksmbd_chann_list;
struct xarray tree_conns; struct xarray tree_conns;
struct ida tree_conn_ida; struct ida tree_conn_ida;
struct list_head rpc_handle_list; struct xarray rpc_handle_list;
__u8 smb3encryptionkey[SMB3_ENC_DEC_KEY_SIZE]; __u8 smb3encryptionkey[SMB3_ENC_DEC_KEY_SIZE];
__u8 smb3decryptionkey[SMB3_ENC_DEC_KEY_SIZE]; __u8 smb3decryptionkey[SMB3_ENC_DEC_KEY_SIZE];
......
...@@ -149,15 +149,11 @@ static int smb2_get_data_area_len(unsigned int *off, unsigned int *len, ...@@ -149,15 +149,11 @@ static int smb2_get_data_area_len(unsigned int *off, unsigned int *len,
break; break;
case SMB2_LOCK: case SMB2_LOCK:
{ {
int lock_count; unsigned short lock_count;
/* lock_count = le16_to_cpu(((struct smb2_lock_req *)hdr)->LockCount);
* smb2_lock request size is 48 included single
* smb2_lock_element structure size.
*/
lock_count = le16_to_cpu(((struct smb2_lock_req *)hdr)->LockCount) - 1;
if (lock_count > 0) { if (lock_count > 0) {
*off = __SMB2_HEADER_STRUCTURE_SIZE + 48; *off = offsetof(struct smb2_lock_req, locks);
*len = sizeof(struct smb2_lock_element) * lock_count; *len = sizeof(struct smb2_lock_element) * lock_count;
} }
break; break;
...@@ -412,20 +408,19 @@ int ksmbd_smb2_check_message(struct ksmbd_work *work) ...@@ -412,20 +408,19 @@ int ksmbd_smb2_check_message(struct ksmbd_work *work)
goto validate_credit; goto validate_credit;
/* /*
* windows client also pad up to 8 bytes when compounding. * SMB2 NEGOTIATE request will be validated when message
* If pad is longer than eight bytes, log the server behavior * handling proceeds.
* (once), since may indicate a problem but allow it and
* continue since the frame is parseable.
*/ */
if (clc_len < len) { if (command == SMB2_NEGOTIATE_HE)
ksmbd_debug(SMB, goto validate_credit;
"cli req padded more than expected. Length %d not %d for cmd:%d mid:%llu\n",
len, clc_len, command, /*
le64_to_cpu(hdr->MessageId)); * Allow a message that padded to 8byte boundary.
*/
if (clc_len < len && (len - clc_len) < 8)
goto validate_credit; goto validate_credit;
}
ksmbd_debug(SMB, pr_err_ratelimited(
"cli req too short, len %d not %d. cmd:%d mid:%llu\n", "cli req too short, len %d not %d. cmd:%d mid:%llu\n",
len, clc_len, command, len, clc_len, command,
le64_to_cpu(hdr->MessageId)); le64_to_cpu(hdr->MessageId));
......
...@@ -75,14 +75,7 @@ static inline bool check_session_id(struct ksmbd_conn *conn, u64 id) ...@@ -75,14 +75,7 @@ static inline bool check_session_id(struct ksmbd_conn *conn, u64 id)
struct channel *lookup_chann_list(struct ksmbd_session *sess, struct ksmbd_conn *conn) struct channel *lookup_chann_list(struct ksmbd_session *sess, struct ksmbd_conn *conn)
{ {
struct channel *chann; return xa_load(&sess->ksmbd_chann_list, (long)conn);
list_for_each_entry(chann, &sess->ksmbd_chann_list, chann_list) {
if (chann->conn == conn)
return chann;
}
return NULL;
} }
/** /**
...@@ -506,7 +499,7 @@ int init_smb2_rsp_hdr(struct ksmbd_work *work) ...@@ -506,7 +499,7 @@ int init_smb2_rsp_hdr(struct ksmbd_work *work)
rsp_hdr->SessionId = rcv_hdr->SessionId; rsp_hdr->SessionId = rcv_hdr->SessionId;
memcpy(rsp_hdr->Signature, rcv_hdr->Signature, 16); memcpy(rsp_hdr->Signature, rcv_hdr->Signature, 16);
work->syncronous = true; work->synchronous = true;
if (work->async_id) { if (work->async_id) {
ksmbd_release_id(&conn->async_ida, work->async_id); ksmbd_release_id(&conn->async_ida, work->async_id);
work->async_id = 0; work->async_id = 0;
...@@ -596,6 +589,7 @@ static void destroy_previous_session(struct ksmbd_conn *conn, ...@@ -596,6 +589,7 @@ static void destroy_previous_session(struct ksmbd_conn *conn,
struct ksmbd_session *prev_sess = ksmbd_session_lookup_slowpath(id); struct ksmbd_session *prev_sess = ksmbd_session_lookup_slowpath(id);
struct ksmbd_user *prev_user; struct ksmbd_user *prev_user;
struct channel *chann; struct channel *chann;
long index;
if (!prev_sess) if (!prev_sess)
return; return;
...@@ -609,10 +603,8 @@ static void destroy_previous_session(struct ksmbd_conn *conn, ...@@ -609,10 +603,8 @@ static void destroy_previous_session(struct ksmbd_conn *conn,
return; return;
prev_sess->state = SMB2_SESSION_EXPIRED; prev_sess->state = SMB2_SESSION_EXPIRED;
write_lock(&prev_sess->chann_lock); xa_for_each(&prev_sess->ksmbd_chann_list, index, chann)
list_for_each_entry(chann, &prev_sess->ksmbd_chann_list, chann_list)
chann->conn->status = KSMBD_SESS_EXITING; chann->conn->status = KSMBD_SESS_EXITING;
write_unlock(&prev_sess->chann_lock);
} }
/** /**
...@@ -653,7 +645,7 @@ int setup_async_work(struct ksmbd_work *work, void (*fn)(void **), void **arg) ...@@ -653,7 +645,7 @@ int setup_async_work(struct ksmbd_work *work, void (*fn)(void **), void **arg)
pr_err("Failed to alloc async message id\n"); pr_err("Failed to alloc async message id\n");
return id; return id;
} }
work->syncronous = false; work->synchronous = false;
work->async_id = id; work->async_id = id;
rsp_hdr->Id.AsyncId = cpu_to_le64(id); rsp_hdr->Id.AsyncId = cpu_to_le64(id);
...@@ -1520,19 +1512,14 @@ static int ntlm_authenticate(struct ksmbd_work *work) ...@@ -1520,19 +1512,14 @@ static int ntlm_authenticate(struct ksmbd_work *work)
binding_session: binding_session:
if (conn->dialect >= SMB30_PROT_ID) { if (conn->dialect >= SMB30_PROT_ID) {
read_lock(&sess->chann_lock);
chann = lookup_chann_list(sess, conn); chann = lookup_chann_list(sess, conn);
read_unlock(&sess->chann_lock);
if (!chann) { if (!chann) {
chann = kmalloc(sizeof(struct channel), GFP_KERNEL); chann = kmalloc(sizeof(struct channel), GFP_KERNEL);
if (!chann) if (!chann)
return -ENOMEM; return -ENOMEM;
chann->conn = conn; chann->conn = conn;
INIT_LIST_HEAD(&chann->chann_list); xa_store(&sess->ksmbd_chann_list, (long)conn, chann, GFP_KERNEL);
write_lock(&sess->chann_lock);
list_add(&chann->chann_list, &sess->ksmbd_chann_list);
write_unlock(&sess->chann_lock);
} }
} }
...@@ -1607,19 +1594,14 @@ static int krb5_authenticate(struct ksmbd_work *work) ...@@ -1607,19 +1594,14 @@ static int krb5_authenticate(struct ksmbd_work *work)
} }
if (conn->dialect >= SMB30_PROT_ID) { if (conn->dialect >= SMB30_PROT_ID) {
read_lock(&sess->chann_lock);
chann = lookup_chann_list(sess, conn); chann = lookup_chann_list(sess, conn);
read_unlock(&sess->chann_lock);
if (!chann) { if (!chann) {
chann = kmalloc(sizeof(struct channel), GFP_KERNEL); chann = kmalloc(sizeof(struct channel), GFP_KERNEL);
if (!chann) if (!chann)
return -ENOMEM; return -ENOMEM;
chann->conn = conn; chann->conn = conn;
INIT_LIST_HEAD(&chann->chann_list); xa_store(&sess->ksmbd_chann_list, (long)conn, chann, GFP_KERNEL);
write_lock(&sess->chann_lock);
list_add(&chann->chann_list, &sess->ksmbd_chann_list);
write_unlock(&sess->chann_lock);
} }
} }
...@@ -6645,7 +6627,7 @@ int smb2_cancel(struct ksmbd_work *work) ...@@ -6645,7 +6627,7 @@ int smb2_cancel(struct ksmbd_work *work)
struct ksmbd_conn *conn = work->conn; struct ksmbd_conn *conn = work->conn;
struct smb2_hdr *hdr = smb2_get_msg(work->request_buf); struct smb2_hdr *hdr = smb2_get_msg(work->request_buf);
struct smb2_hdr *chdr; struct smb2_hdr *chdr;
struct ksmbd_work *cancel_work = NULL, *iter; struct ksmbd_work *iter;
struct list_head *command_list; struct list_head *command_list;
ksmbd_debug(SMB, "smb2 cancel called on mid %llu, async flags 0x%x\n", ksmbd_debug(SMB, "smb2 cancel called on mid %llu, async flags 0x%x\n",
...@@ -6667,7 +6649,9 @@ int smb2_cancel(struct ksmbd_work *work) ...@@ -6667,7 +6649,9 @@ int smb2_cancel(struct ksmbd_work *work)
"smb2 with AsyncId %llu cancelled command = 0x%x\n", "smb2 with AsyncId %llu cancelled command = 0x%x\n",
le64_to_cpu(hdr->Id.AsyncId), le64_to_cpu(hdr->Id.AsyncId),
le16_to_cpu(chdr->Command)); le16_to_cpu(chdr->Command));
cancel_work = iter; iter->state = KSMBD_WORK_CANCELLED;
if (iter->cancel_fn)
iter->cancel_fn(iter->cancel_argv);
break; break;
} }
spin_unlock(&conn->request_lock); spin_unlock(&conn->request_lock);
...@@ -6686,18 +6670,12 @@ int smb2_cancel(struct ksmbd_work *work) ...@@ -6686,18 +6670,12 @@ int smb2_cancel(struct ksmbd_work *work)
"smb2 with mid %llu cancelled command = 0x%x\n", "smb2 with mid %llu cancelled command = 0x%x\n",
le64_to_cpu(hdr->MessageId), le64_to_cpu(hdr->MessageId),
le16_to_cpu(chdr->Command)); le16_to_cpu(chdr->Command));
cancel_work = iter; iter->state = KSMBD_WORK_CANCELLED;
break; break;
} }
spin_unlock(&conn->request_lock); spin_unlock(&conn->request_lock);
} }
if (cancel_work) {
cancel_work->state = KSMBD_WORK_CANCELLED;
if (cancel_work->cancel_fn)
cancel_work->cancel_fn(cancel_work->cancel_argv);
}
/* For SMB2_CANCEL command itself send no response*/ /* For SMB2_CANCEL command itself send no response*/
work->send_no_response = 1; work->send_no_response = 1;
return 0; return 0;
...@@ -7062,6 +7040,14 @@ int smb2_lock(struct ksmbd_work *work) ...@@ -7062,6 +7040,14 @@ int smb2_lock(struct ksmbd_work *work)
ksmbd_vfs_posix_lock_wait(flock); ksmbd_vfs_posix_lock_wait(flock);
spin_lock(&work->conn->request_lock);
spin_lock(&fp->f_lock);
list_del(&work->fp_entry);
work->cancel_fn = NULL;
kfree(argv);
spin_unlock(&fp->f_lock);
spin_unlock(&work->conn->request_lock);
if (work->state != KSMBD_WORK_ACTIVE) { if (work->state != KSMBD_WORK_ACTIVE) {
list_del(&smb_lock->llist); list_del(&smb_lock->llist);
spin_lock(&work->conn->llist_lock); spin_lock(&work->conn->llist_lock);
...@@ -7070,9 +7056,6 @@ int smb2_lock(struct ksmbd_work *work) ...@@ -7070,9 +7056,6 @@ int smb2_lock(struct ksmbd_work *work)
locks_free_lock(flock); locks_free_lock(flock);
if (work->state == KSMBD_WORK_CANCELLED) { if (work->state == KSMBD_WORK_CANCELLED) {
spin_lock(&fp->f_lock);
list_del(&work->fp_entry);
spin_unlock(&fp->f_lock);
rsp->hdr.Status = rsp->hdr.Status =
STATUS_CANCELLED; STATUS_CANCELLED;
kfree(smb_lock); kfree(smb_lock);
...@@ -7094,9 +7077,6 @@ int smb2_lock(struct ksmbd_work *work) ...@@ -7094,9 +7077,6 @@ int smb2_lock(struct ksmbd_work *work)
list_del(&smb_lock->clist); list_del(&smb_lock->clist);
spin_unlock(&work->conn->llist_lock); spin_unlock(&work->conn->llist_lock);
spin_lock(&fp->f_lock);
list_del(&work->fp_entry);
spin_unlock(&fp->f_lock);
goto retry; goto retry;
} else if (!rc) { } else if (!rc) {
spin_lock(&work->conn->llist_lock); spin_lock(&work->conn->llist_lock);
...@@ -8410,14 +8390,11 @@ int smb3_check_sign_req(struct ksmbd_work *work) ...@@ -8410,14 +8390,11 @@ int smb3_check_sign_req(struct ksmbd_work *work)
if (le16_to_cpu(hdr->Command) == SMB2_SESSION_SETUP_HE) { if (le16_to_cpu(hdr->Command) == SMB2_SESSION_SETUP_HE) {
signing_key = work->sess->smb3signingkey; signing_key = work->sess->smb3signingkey;
} else { } else {
read_lock(&work->sess->chann_lock);
chann = lookup_chann_list(work->sess, conn); chann = lookup_chann_list(work->sess, conn);
if (!chann) { if (!chann) {
read_unlock(&work->sess->chann_lock);
return 0; return 0;
} }
signing_key = chann->smb3signingkey; signing_key = chann->smb3signingkey;
read_unlock(&work->sess->chann_lock);
} }
if (!signing_key) { if (!signing_key) {
...@@ -8477,14 +8454,11 @@ void smb3_set_sign_rsp(struct ksmbd_work *work) ...@@ -8477,14 +8454,11 @@ void smb3_set_sign_rsp(struct ksmbd_work *work)
le16_to_cpu(hdr->Command) == SMB2_SESSION_SETUP_HE) { le16_to_cpu(hdr->Command) == SMB2_SESSION_SETUP_HE) {
signing_key = work->sess->smb3signingkey; signing_key = work->sess->smb3signingkey;
} else { } else {
read_lock(&work->sess->chann_lock);
chann = lookup_chann_list(work->sess, work->conn); chann = lookup_chann_list(work->sess, work->conn);
if (!chann) { if (!chann) {
read_unlock(&work->sess->chann_lock);
return; return;
} }
signing_key = chann->smb3signingkey; signing_key = chann->smb3signingkey;
read_unlock(&work->sess->chann_lock);
} }
if (!signing_key) if (!signing_key)
......
...@@ -952,9 +952,9 @@ ssize_t ksmbd_vfs_getxattr(struct mnt_idmap *idmap, ...@@ -952,9 +952,9 @@ ssize_t ksmbd_vfs_getxattr(struct mnt_idmap *idmap,
* ksmbd_vfs_setxattr() - vfs helper for smb set extended attributes value * ksmbd_vfs_setxattr() - vfs helper for smb set extended attributes value
* @idmap: idmap of the relevant mount * @idmap: idmap of the relevant mount
* @dentry: dentry to set XATTR at * @dentry: dentry to set XATTR at
* @name: xattr name for setxattr * @attr_name: xattr name for setxattr
* @value: xattr value to set * @attr_value: xattr value to set
* @size: size of xattr value * @attr_size: size of xattr value
* @flags: destination buffer length * @flags: destination buffer length
* *
* Return: 0 on success, otherwise error * Return: 0 on success, otherwise error
......
...@@ -365,12 +365,11 @@ static void __put_fd_final(struct ksmbd_work *work, struct ksmbd_file *fp) ...@@ -365,12 +365,11 @@ static void __put_fd_final(struct ksmbd_work *work, struct ksmbd_file *fp)
static void set_close_state_blocked_works(struct ksmbd_file *fp) static void set_close_state_blocked_works(struct ksmbd_file *fp)
{ {
struct ksmbd_work *cancel_work, *ctmp; struct ksmbd_work *cancel_work;
spin_lock(&fp->f_lock); spin_lock(&fp->f_lock);
list_for_each_entry_safe(cancel_work, ctmp, &fp->blocked_works, list_for_each_entry(cancel_work, &fp->blocked_works,
fp_entry) { fp_entry) {
list_del(&cancel_work->fp_entry);
cancel_work->state = KSMBD_WORK_CLOSED; cancel_work->state = KSMBD_WORK_CLOSED;
cancel_work->cancel_fn(cancel_work->cancel_argv); cancel_work->cancel_fn(cancel_work->cancel_argv);
} }
......
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