ksmbd: add continuous availability share parameter
authorNamjae Jeon <linkinjeon@kernel.org>
Sat, 20 Apr 2024 00:17:58 +0000 (09:17 +0900)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Sat, 25 May 2024 14:22:52 +0000 (16:22 +0200)
[ Upstream commit e9d8c2f95ab8acaf3f4d4a53682a4afa3c263692 ]

If capabilities of the share is not SMB2_SHARE_CAP_CONTINUOUS_AVAILABILITY,
ksmbd should not grant a persistent handle to the client.
This patch add continuous availability share parameter to control it.

Signed-off-by: Namjae Jeon <linkinjeon@kernel.org>
Signed-off-by: Steve French <stfrench@microsoft.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
fs/smb/server/ksmbd_netlink.h
fs/smb/server/smb2pdu.c

index 686b321c5a8bb5f0a1189023a3311e85aaf84c9e..f4e55199938d58023672fcd3006f7e97502fa6a5 100644 (file)
@@ -340,23 +340,24 @@ enum KSMBD_TREE_CONN_STATUS {
 /*
  * Share config flags.
  */
-#define KSMBD_SHARE_FLAG_INVALID               (0)
-#define KSMBD_SHARE_FLAG_AVAILABLE             BIT(0)
-#define KSMBD_SHARE_FLAG_BROWSEABLE            BIT(1)
-#define KSMBD_SHARE_FLAG_WRITEABLE             BIT(2)
-#define KSMBD_SHARE_FLAG_READONLY              BIT(3)
-#define KSMBD_SHARE_FLAG_GUEST_OK              BIT(4)
-#define KSMBD_SHARE_FLAG_GUEST_ONLY            BIT(5)
-#define KSMBD_SHARE_FLAG_STORE_DOS_ATTRS       BIT(6)
-#define KSMBD_SHARE_FLAG_OPLOCKS               BIT(7)
-#define KSMBD_SHARE_FLAG_PIPE                  BIT(8)
-#define KSMBD_SHARE_FLAG_HIDE_DOT_FILES                BIT(9)
-#define KSMBD_SHARE_FLAG_INHERIT_OWNER         BIT(10)
-#define KSMBD_SHARE_FLAG_STREAMS               BIT(11)
-#define KSMBD_SHARE_FLAG_FOLLOW_SYMLINKS       BIT(12)
-#define KSMBD_SHARE_FLAG_ACL_XATTR             BIT(13)
-#define KSMBD_SHARE_FLAG_UPDATE                        BIT(14)
-#define KSMBD_SHARE_FLAG_CROSSMNT              BIT(15)
+#define KSMBD_SHARE_FLAG_INVALID                       (0)
+#define KSMBD_SHARE_FLAG_AVAILABLE                     BIT(0)
+#define KSMBD_SHARE_FLAG_BROWSEABLE                    BIT(1)
+#define KSMBD_SHARE_FLAG_WRITEABLE                     BIT(2)
+#define KSMBD_SHARE_FLAG_READONLY                      BIT(3)
+#define KSMBD_SHARE_FLAG_GUEST_OK                      BIT(4)
+#define KSMBD_SHARE_FLAG_GUEST_ONLY                    BIT(5)
+#define KSMBD_SHARE_FLAG_STORE_DOS_ATTRS               BIT(6)
+#define KSMBD_SHARE_FLAG_OPLOCKS                       BIT(7)
+#define KSMBD_SHARE_FLAG_PIPE                          BIT(8)
+#define KSMBD_SHARE_FLAG_HIDE_DOT_FILES                        BIT(9)
+#define KSMBD_SHARE_FLAG_INHERIT_OWNER                 BIT(10)
+#define KSMBD_SHARE_FLAG_STREAMS                       BIT(11)
+#define KSMBD_SHARE_FLAG_FOLLOW_SYMLINKS               BIT(12)
+#define KSMBD_SHARE_FLAG_ACL_XATTR                     BIT(13)
+#define KSMBD_SHARE_FLAG_UPDATE                                BIT(14)
+#define KSMBD_SHARE_FLAG_CROSSMNT                      BIT(15)
+#define KSMBD_SHARE_FLAG_CONTINUOUS_AVAILABILITY       BIT(16)
 
 /*
  * Tree connect request flags.
index 75db0e63bcebdcb98ae89deb62a9ec69e4694ec3..1e536ae2776188b11476f9298562b32030bd1451 100644 (file)
@@ -1988,7 +1988,12 @@ int smb2_tree_connect(struct ksmbd_work *work)
        write_unlock(&sess->tree_conns_lock);
        rsp->StructureSize = cpu_to_le16(16);
 out_err1:
-       rsp->Capabilities = 0;
+       if (server_conf.flags & KSMBD_GLOBAL_FLAG_DURABLE_HANDLE &&
+           test_share_config_flag(share,
+                                  KSMBD_SHARE_FLAG_CONTINUOUS_AVAILABILITY))
+               rsp->Capabilities = SMB2_SHARE_CAP_CONTINUOUS_AVAILABILITY;
+       else
+               rsp->Capabilities = 0;
        rsp->Reserved = 0;
        /* default manual caching */
        rsp->ShareFlags = SMB2_SHAREFLAG_MANUAL_CACHING;
@@ -3502,7 +3507,9 @@ int smb2_open(struct ksmbd_work *work)
        memcpy(fp->client_guid, conn->ClientGUID, SMB2_CLIENT_GUID_SIZE);
 
        if (dh_info.type == DURABLE_REQ_V2 || dh_info.type == DURABLE_REQ) {
-               if (dh_info.type == DURABLE_REQ_V2 && dh_info.persistent)
+               if (dh_info.type == DURABLE_REQ_V2 && dh_info.persistent &&
+                   test_share_config_flag(work->tcon->share_conf,
+                                          KSMBD_SHARE_FLAG_CONTINUOUS_AVAILABILITY))
                        fp->is_persistent = true;
                else
                        fp->is_durable = true;