ksmbd: add channel rwlock
authorNamjae Jeon <linkinjeon@kernel.org>
Fri, 22 Jul 2022 01:15:57 +0000 (10:15 +0900)
committerSteve French <stfrench@microsoft.com>
Wed, 27 Jul 2022 04:38:05 +0000 (23:38 -0500)
Add missing rwlock for channel list in session.

Signed-off-by: Namjae Jeon <linkinjeon@kernel.org>
Reviewed-by: Hyunchul Lee <hyc.lee@gmail.com>
Signed-off-by: Steve French <stfrench@microsoft.com>
fs/ksmbd/mgmt/user_session.c
fs/ksmbd/mgmt/user_session.h
fs/ksmbd/smb2pdu.c

index 3a44e66..25e9ba3 100644 (file)
@@ -32,11 +32,13 @@ static void free_channel_list(struct ksmbd_session *sess)
 {
        struct channel *chann, *tmp;
 
+       write_lock(&sess->chann_lock);
        list_for_each_entry_safe(chann, tmp, &sess->ksmbd_chann_list,
                                 chann_list) {
                list_del(&chann->chann_list);
                kfree(chann);
        }
+       write_unlock(&sess->chann_lock);
 }
 
 static void __session_rpc_close(struct ksmbd_session *sess,
@@ -303,6 +305,7 @@ static struct ksmbd_session *__session_create(int protocol)
        INIT_LIST_HEAD(&sess->rpc_handle_list);
        sess->sequence_number = 1;
        atomic_set(&sess->refcnt, 1);
+       rwlock_init(&sess->chann_lock);
 
        switch (protocol) {
        case CIFDS_SESSION_FLAG_SMB2:
index 8b08189..1ec659f 100644 (file)
@@ -48,6 +48,7 @@ struct ksmbd_session {
        char                            sess_key[CIFS_KEY_SIZE];
 
        struct hlist_node               hlist;
+       rwlock_t                        chann_lock;
        struct list_head                ksmbd_chann_list;
        struct xarray                   tree_conns;
        struct ida                      tree_conn_ida;
index 7e1620a..02a7df0 100644 (file)
@@ -1512,7 +1512,9 @@ static int ntlm_authenticate(struct ksmbd_work *work)
 
 binding_session:
        if (conn->dialect >= SMB30_PROT_ID) {
+               read_lock(&sess->chann_lock);
                chann = lookup_chann_list(sess, conn);
+               read_unlock(&sess->chann_lock);
                if (!chann) {
                        chann = kmalloc(sizeof(struct channel), GFP_KERNEL);
                        if (!chann)
@@ -1520,7 +1522,9 @@ binding_session:
 
                        chann->conn = conn;
                        INIT_LIST_HEAD(&chann->chann_list);
+                       write_lock(&sess->chann_lock);
                        list_add(&chann->chann_list, &sess->ksmbd_chann_list);
+                       write_unlock(&sess->chann_lock);
                }
        }
 
@@ -1594,7 +1598,9 @@ static int krb5_authenticate(struct ksmbd_work *work)
        }
 
        if (conn->dialect >= SMB30_PROT_ID) {
+               read_lock(&sess->chann_lock);
                chann = lookup_chann_list(sess, conn);
+               read_unlock(&sess->chann_lock);
                if (!chann) {
                        chann = kmalloc(sizeof(struct channel), GFP_KERNEL);
                        if (!chann)
@@ -1602,7 +1608,9 @@ static int krb5_authenticate(struct ksmbd_work *work)
 
                        chann->conn = conn;
                        INIT_LIST_HEAD(&chann->chann_list);
+                       write_lock(&sess->chann_lock);
                        list_add(&chann->chann_list, &sess->ksmbd_chann_list);
+                       write_unlock(&sess->chann_lock);
                }
        }
 
@@ -8361,10 +8369,14 @@ int smb3_check_sign_req(struct ksmbd_work *work)
        if (le16_to_cpu(hdr->Command) == SMB2_SESSION_SETUP_HE) {
                signing_key = work->sess->smb3signingkey;
        } else {
+               read_lock(&work->sess->chann_lock);
                chann = lookup_chann_list(work->sess, conn);
-               if (!chann)
+               if (!chann) {
+                       read_unlock(&work->sess->chann_lock);
                        return 0;
+               }
                signing_key = chann->smb3signingkey;
+               read_unlock(&work->sess->chann_lock);
        }
 
        if (!signing_key) {
@@ -8424,10 +8436,14 @@ void smb3_set_sign_rsp(struct ksmbd_work *work)
            le16_to_cpu(hdr->Command) == SMB2_SESSION_SETUP_HE) {
                signing_key = work->sess->smb3signingkey;
        } else {
+               read_lock(&work->sess->chann_lock);
                chann = lookup_chann_list(work->sess, work->conn);
-               if (!chann)
+               if (!chann) {
+                       read_unlock(&work->sess->chann_lock);
                        return;
+               }
                signing_key = chann->smb3signingkey;
+               read_unlock(&work->sess->chann_lock);
        }
 
        if (!signing_key)