public inbox for stable@vger.kernel.org
 help / color / mirror / Atom feed
From: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
To: stable@vger.kernel.org
Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>,
	patches@lists.linux.dev, Namjae Jeon <linkinjeon@kernel.org>,
	Steve French <stfrench@microsoft.com>,
	Sasha Levin <sashal@kernel.org>
Subject: [PATCH 6.6 060/102] ksmbd: add support for durable handles v1/v2
Date: Thu, 23 May 2024 15:13:25 +0200	[thread overview]
Message-ID: <20240523130344.733769853@linuxfoundation.org> (raw)
In-Reply-To: <20240523130342.462912131@linuxfoundation.org>

6.6-stable review patch.  If anyone has any objections, please let me know.

------------------

From: Namjae Jeon <linkinjeon@kernel.org>

[ Upstream commit c8efcc786146a951091588e5fa7e3c754850cb3c ]

Durable file handles allow reopening a file preserved on a short
network outage and transparent client reconnection within a timeout.
i.e. Durable handles aren't necessarily cleaned up when the opening
process terminates.

This patch add support for durable handle version 1 and 2.

To prove durable handles work on ksmbd, I have tested this patch with
the following smbtorture tests:

smb2.durable-open.open-oplock
smb2.durable-open.open-lease
smb2.durable-open.reopen1
smb2.durable-open.reopen1a
smb2.durable-open.reopen1a-lease
smb2.durable-open.reopen2
smb2.durable-open.reopen2a
smb2.durable-open.reopen2-lease
smb2.durable-open.reopen2-lease-v2
smb2.durable-open.reopen3
smb2.durable-open.reopen4
smb2.durable-open.delete_on_close2
smb2.durable-open.file-position
smb2.durable-open.lease
smb2.durable-open.alloc-size
smb2.durable-open.read-only
smb2.durable-v2-open.create-blob
smb2.durable-v2-open.open-oplock
smb2.durable-v2-open.open-lease
smb2.durable-v2-open.reopen1
smb2.durable-v2-open.reopen1a
smb2.durable-v2-open.reopen1a-lease
smb2.durable-v2-open.reopen2
smb2.durable-v2-open.reopen2b

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     |   1 +
 fs/smb/server/mgmt/user_session.c |   1 +
 fs/smb/server/oplock.c            |  94 +++++++++--
 fs/smb/server/oplock.h            |   7 +-
 fs/smb/server/smb2ops.c           |   6 +
 fs/smb/server/smb2pdu.c           | 257 +++++++++++++++++++++++++++++-
 fs/smb/server/smb2pdu.h           |  15 ++
 fs/smb/server/vfs_cache.c         | 137 +++++++++++++++-
 fs/smb/server/vfs_cache.h         |   9 ++
 9 files changed, 506 insertions(+), 21 deletions(-)

diff --git a/fs/smb/server/ksmbd_netlink.h b/fs/smb/server/ksmbd_netlink.h
index 4464a62228cf3..686b321c5a8bb 100644
--- a/fs/smb/server/ksmbd_netlink.h
+++ b/fs/smb/server/ksmbd_netlink.h
@@ -75,6 +75,7 @@ struct ksmbd_heartbeat {
 #define KSMBD_GLOBAL_FLAG_SMB2_ENCRYPTION	BIT(1)
 #define KSMBD_GLOBAL_FLAG_SMB3_MULTICHANNEL	BIT(2)
 #define KSMBD_GLOBAL_FLAG_SMB2_ENCRYPTION_OFF	BIT(3)
+#define KSMBD_GLOBAL_FLAG_DURABLE_HANDLE	BIT(4)
 
 /*
  * IPC request for ksmbd server startup
diff --git a/fs/smb/server/mgmt/user_session.c b/fs/smb/server/mgmt/user_session.c
index 83074672fe812..aec0a7a124052 100644
--- a/fs/smb/server/mgmt/user_session.c
+++ b/fs/smb/server/mgmt/user_session.c
@@ -324,6 +324,7 @@ void destroy_previous_session(struct ksmbd_conn *conn,
 	    memcmp(user->passkey, prev_user->passkey, user->passkey_sz))
 		goto out;
 
+	ksmbd_destroy_file_table(&prev_sess->file_table);
 	prev_sess->state = SMB2_SESSION_EXPIRED;
 out:
 	up_write(&conn->session_lock);
diff --git a/fs/smb/server/oplock.c b/fs/smb/server/oplock.c
index dc729ab980dc0..7bdae2adad228 100644
--- a/fs/smb/server/oplock.c
+++ b/fs/smb/server/oplock.c
@@ -159,7 +159,8 @@ static struct oplock_info *opinfo_get_list(struct ksmbd_inode *ci)
 	opinfo = list_first_or_null_rcu(&ci->m_op_list, struct oplock_info,
 					op_entry);
 	if (opinfo) {
-		if (!atomic_inc_not_zero(&opinfo->refcount))
+		if (opinfo->conn == NULL ||
+		    !atomic_inc_not_zero(&opinfo->refcount))
 			opinfo = NULL;
 		else {
 			atomic_inc(&opinfo->conn->r_count);
@@ -527,7 +528,7 @@ static struct oplock_info *same_client_has_lease(struct ksmbd_inode *ci,
 	 */
 	read_lock(&ci->m_lock);
 	list_for_each_entry(opinfo, &ci->m_op_list, op_entry) {
-		if (!opinfo->is_lease)
+		if (!opinfo->is_lease || !opinfo->conn)
 			continue;
 		read_unlock(&ci->m_lock);
 		lease = opinfo->o_lease;
@@ -651,7 +652,7 @@ static void __smb2_oplock_break_noti(struct work_struct *wk)
 	struct smb2_hdr *rsp_hdr;
 	struct ksmbd_file *fp;
 
-	fp = ksmbd_lookup_durable_fd(br_info->fid);
+	fp = ksmbd_lookup_global_fd(br_info->fid);
 	if (!fp)
 		goto out;
 
@@ -1115,7 +1116,7 @@ void smb_send_parent_lease_break_noti(struct ksmbd_file *fp,
 
 	read_lock(&p_ci->m_lock);
 	list_for_each_entry(opinfo, &p_ci->m_op_list, op_entry) {
-		if (!opinfo->is_lease)
+		if (opinfo->conn == NULL || !opinfo->is_lease)
 			continue;
 
 		if (opinfo->o_lease->state != SMB2_OPLOCK_LEVEL_NONE &&
@@ -1160,7 +1161,7 @@ void smb_lazy_parent_lease_break_close(struct ksmbd_file *fp)
 
 	read_lock(&p_ci->m_lock);
 	list_for_each_entry(opinfo, &p_ci->m_op_list, op_entry) {
-		if (!opinfo->is_lease)
+		if (opinfo->conn == NULL || !opinfo->is_lease)
 			continue;
 
 		if (opinfo->o_lease->state != SMB2_OPLOCK_LEVEL_NONE) {
@@ -1372,6 +1373,9 @@ void smb_break_all_levII_oplock(struct ksmbd_work *work, struct ksmbd_file *fp,
 
 	rcu_read_lock();
 	list_for_each_entry_rcu(brk_op, &ci->m_op_list, op_entry) {
+		if (brk_op->conn == NULL)
+			continue;
+
 		if (!atomic_inc_not_zero(&brk_op->refcount))
 			continue;
 
@@ -1508,11 +1512,10 @@ void create_lease_buf(u8 *rbuf, struct lease *lease)
 /**
  * parse_lease_state() - parse lease context containted in file open request
  * @open_req:	buffer containing smb2 file open(create) request
- * @is_dir:	whether leasing file is directory
  *
  * Return:  oplock state, -ENOENT if create lease context not found
  */
-struct lease_ctx_info *parse_lease_state(void *open_req, bool is_dir)
+struct lease_ctx_info *parse_lease_state(void *open_req)
 {
 	struct create_context *cc;
 	struct smb2_create_req *req = (struct smb2_create_req *)open_req;
@@ -1530,12 +1533,7 @@ struct lease_ctx_info *parse_lease_state(void *open_req, bool is_dir)
 		struct create_lease_v2 *lc = (struct create_lease_v2 *)cc;
 
 		memcpy(lreq->lease_key, lc->lcontext.LeaseKey, SMB2_LEASE_KEY_SIZE);
-		if (is_dir) {
-			lreq->req_state = lc->lcontext.LeaseState &
-				~SMB2_LEASE_WRITE_CACHING_LE;
-			lreq->is_dir = true;
-		} else
-			lreq->req_state = lc->lcontext.LeaseState;
+		lreq->req_state = lc->lcontext.LeaseState;
 		lreq->flags = lc->lcontext.LeaseFlags;
 		lreq->epoch = lc->lcontext.Epoch;
 		lreq->duration = lc->lcontext.LeaseDuration;
@@ -1659,6 +1657,8 @@ void create_durable_v2_rsp_buf(char *cc, struct ksmbd_file *fp)
 	buf->Name[3] = 'Q';
 
 	buf->Timeout = cpu_to_le32(fp->durable_timeout);
+	if (fp->is_persistent)
+		buf->Flags = cpu_to_le32(SMB2_DHANDLE_FLAG_PERSISTENT);
 }
 
 /**
@@ -1826,3 +1826,71 @@ struct oplock_info *lookup_lease_in_table(struct ksmbd_conn *conn,
 	read_unlock(&lease_list_lock);
 	return ret_op;
 }
+
+int smb2_check_durable_oplock(struct ksmbd_conn *conn,
+			      struct ksmbd_share_config *share,
+			      struct ksmbd_file *fp,
+			      struct lease_ctx_info *lctx,
+			      char *name)
+{
+	struct oplock_info *opinfo = opinfo_get(fp);
+	int ret = 0;
+
+	if (!opinfo)
+		return 0;
+
+	if (opinfo->is_lease == false) {
+		if (lctx) {
+			pr_err("create context include lease\n");
+			ret = -EBADF;
+			goto out;
+		}
+
+		if (opinfo->level != SMB2_OPLOCK_LEVEL_BATCH) {
+			pr_err("oplock level is not equal to SMB2_OPLOCK_LEVEL_BATCH\n");
+			ret = -EBADF;
+		}
+
+		goto out;
+	}
+
+	if (memcmp(conn->ClientGUID, fp->client_guid,
+				SMB2_CLIENT_GUID_SIZE)) {
+		ksmbd_debug(SMB, "Client guid of fp is not equal to the one of connction\n");
+		ret = -EBADF;
+		goto out;
+	}
+
+	if (!lctx) {
+		ksmbd_debug(SMB, "create context does not include lease\n");
+		ret = -EBADF;
+		goto out;
+	}
+
+	if (memcmp(opinfo->o_lease->lease_key, lctx->lease_key,
+				SMB2_LEASE_KEY_SIZE)) {
+		ksmbd_debug(SMB,
+			    "lease key of fp does not match lease key in create context\n");
+		ret = -EBADF;
+		goto out;
+	}
+
+	if (!(opinfo->o_lease->state & SMB2_LEASE_HANDLE_CACHING_LE)) {
+		ksmbd_debug(SMB, "lease state does not contain SMB2_LEASE_HANDLE_CACHING\n");
+		ret = -EBADF;
+		goto out;
+	}
+
+	if (opinfo->o_lease->version != lctx->version) {
+		ksmbd_debug(SMB,
+			    "lease version of fp does not match the one in create context\n");
+		ret = -EBADF;
+		goto out;
+	}
+
+	if (!ksmbd_inode_pending_delete(fp))
+		ret = ksmbd_validate_name_reconnect(share, fp, name);
+out:
+	opinfo_put(opinfo);
+	return ret;
+}
diff --git a/fs/smb/server/oplock.h b/fs/smb/server/oplock.h
index 5b93ea9196c01..e9da63f25b206 100644
--- a/fs/smb/server/oplock.h
+++ b/fs/smb/server/oplock.h
@@ -111,7 +111,7 @@ void opinfo_put(struct oplock_info *opinfo);
 
 /* Lease related functions */
 void create_lease_buf(u8 *rbuf, struct lease *lease);
-struct lease_ctx_info *parse_lease_state(void *open_req, bool is_dir);
+struct lease_ctx_info *parse_lease_state(void *open_req);
 __u8 smb2_map_lease_to_oplock(__le32 lease_state);
 int lease_read_to_write(struct oplock_info *opinfo);
 
@@ -130,4 +130,9 @@ void destroy_lease_table(struct ksmbd_conn *conn);
 void smb_send_parent_lease_break_noti(struct ksmbd_file *fp,
 				      struct lease_ctx_info *lctx);
 void smb_lazy_parent_lease_break_close(struct ksmbd_file *fp);
+int smb2_check_durable_oplock(struct ksmbd_conn *conn,
+			      struct ksmbd_share_config *share,
+			      struct ksmbd_file *fp,
+			      struct lease_ctx_info *lctx,
+			      char *name);
 #endif /* __KSMBD_OPLOCK_H */
diff --git a/fs/smb/server/smb2ops.c b/fs/smb/server/smb2ops.c
index 8600f32c981a1..606aa3c5189a2 100644
--- a/fs/smb/server/smb2ops.c
+++ b/fs/smb/server/smb2ops.c
@@ -261,6 +261,9 @@ void init_smb3_02_server(struct ksmbd_conn *conn)
 
 	if (server_conf.flags & KSMBD_GLOBAL_FLAG_SMB3_MULTICHANNEL)
 		conn->vals->capabilities |= SMB2_GLOBAL_CAP_MULTI_CHANNEL;
+
+	if (server_conf.flags & KSMBD_GLOBAL_FLAG_DURABLE_HANDLE)
+		conn->vals->capabilities |= SMB2_GLOBAL_CAP_PERSISTENT_HANDLES;
 }
 
 /**
@@ -283,6 +286,9 @@ int init_smb3_11_server(struct ksmbd_conn *conn)
 	if (server_conf.flags & KSMBD_GLOBAL_FLAG_SMB3_MULTICHANNEL)
 		conn->vals->capabilities |= SMB2_GLOBAL_CAP_MULTI_CHANNEL;
 
+	if (server_conf.flags & KSMBD_GLOBAL_FLAG_DURABLE_HANDLE)
+		conn->vals->capabilities |= SMB2_GLOBAL_CAP_PERSISTENT_HANDLES;
+
 	INIT_LIST_HEAD(&conn->preauth_sess_table);
 	return 0;
 }
diff --git a/fs/smb/server/smb2pdu.c b/fs/smb/server/smb2pdu.c
index 61717917db765..218adb3c55816 100644
--- a/fs/smb/server/smb2pdu.c
+++ b/fs/smb/server/smb2pdu.c
@@ -2622,6 +2622,165 @@ static void ksmbd_acls_fattr(struct smb_fattr *fattr,
 	}
 }
 
+enum {
+	DURABLE_RECONN_V2 = 1,
+	DURABLE_RECONN,
+	DURABLE_REQ_V2,
+	DURABLE_REQ,
+};
+
+struct durable_info {
+	struct ksmbd_file *fp;
+	unsigned short int type;
+	bool persistent;
+	bool reconnected;
+	unsigned int timeout;
+	char *CreateGuid;
+};
+
+static int parse_durable_handle_context(struct ksmbd_work *work,
+					struct smb2_create_req *req,
+					struct lease_ctx_info *lc,
+					struct durable_info *dh_info)
+{
+	struct ksmbd_conn *conn = work->conn;
+	struct create_context *context;
+	int dh_idx, err = 0;
+	u64 persistent_id = 0;
+	int req_op_level;
+	static const char * const durable_arr[] = {"DH2C", "DHnC", "DH2Q", "DHnQ"};
+
+	req_op_level = req->RequestedOplockLevel;
+	for (dh_idx = DURABLE_RECONN_V2; dh_idx <= ARRAY_SIZE(durable_arr);
+	     dh_idx++) {
+		context = smb2_find_context_vals(req, durable_arr[dh_idx - 1], 4);
+		if (IS_ERR(context)) {
+			err = PTR_ERR(context);
+			goto out;
+		}
+		if (!context)
+			continue;
+
+		switch (dh_idx) {
+		case DURABLE_RECONN_V2:
+		{
+			struct create_durable_reconn_v2_req *recon_v2;
+
+			if (dh_info->type == DURABLE_RECONN ||
+			    dh_info->type == DURABLE_REQ_V2) {
+				err = -EINVAL;
+				goto out;
+			}
+
+			recon_v2 = (struct create_durable_reconn_v2_req *)context;
+			persistent_id = recon_v2->Fid.PersistentFileId;
+			dh_info->fp = ksmbd_lookup_durable_fd(persistent_id);
+			if (!dh_info->fp) {
+				ksmbd_debug(SMB, "Failed to get durable handle state\n");
+				err = -EBADF;
+				goto out;
+			}
+
+			if (memcmp(dh_info->fp->create_guid, recon_v2->CreateGuid,
+				   SMB2_CREATE_GUID_SIZE)) {
+				err = -EBADF;
+				ksmbd_put_durable_fd(dh_info->fp);
+				goto out;
+			}
+
+			dh_info->type = dh_idx;
+			dh_info->reconnected = true;
+			ksmbd_debug(SMB,
+				"reconnect v2 Persistent-id from reconnect = %llu\n",
+					persistent_id);
+			break;
+		}
+		case DURABLE_RECONN:
+		{
+			struct create_durable_reconn_req *recon;
+
+			if (dh_info->type == DURABLE_RECONN_V2 ||
+			    dh_info->type == DURABLE_REQ_V2) {
+				err = -EINVAL;
+				goto out;
+			}
+
+			recon = (struct create_durable_reconn_req *)context;
+			persistent_id = recon->Data.Fid.PersistentFileId;
+			dh_info->fp = ksmbd_lookup_durable_fd(persistent_id);
+			if (!dh_info->fp) {
+				ksmbd_debug(SMB, "Failed to get durable handle state\n");
+				err = -EBADF;
+				goto out;
+			}
+
+			dh_info->type = dh_idx;
+			dh_info->reconnected = true;
+			ksmbd_debug(SMB, "reconnect Persistent-id from reconnect = %llu\n",
+				    persistent_id);
+			break;
+		}
+		case DURABLE_REQ_V2:
+		{
+			struct create_durable_req_v2 *durable_v2_blob;
+
+			if (dh_info->type == DURABLE_RECONN ||
+			    dh_info->type == DURABLE_RECONN_V2) {
+				err = -EINVAL;
+				goto out;
+			}
+
+			durable_v2_blob =
+				(struct create_durable_req_v2 *)context;
+			ksmbd_debug(SMB, "Request for durable v2 open\n");
+			dh_info->fp = ksmbd_lookup_fd_cguid(durable_v2_blob->CreateGuid);
+			if (dh_info->fp) {
+				if (!memcmp(conn->ClientGUID, dh_info->fp->client_guid,
+					    SMB2_CLIENT_GUID_SIZE)) {
+					if (!(req->hdr.Flags & SMB2_FLAGS_REPLAY_OPERATION)) {
+						err = -ENOEXEC;
+						goto out;
+					}
+
+					dh_info->fp->conn = conn;
+					dh_info->reconnected = true;
+					goto out;
+				}
+			}
+
+			if (((lc && (lc->req_state & SMB2_LEASE_HANDLE_CACHING_LE)) ||
+			     req_op_level == SMB2_OPLOCK_LEVEL_BATCH)) {
+				dh_info->CreateGuid =
+					durable_v2_blob->CreateGuid;
+				dh_info->persistent =
+					le32_to_cpu(durable_v2_blob->Flags);
+				dh_info->timeout =
+					le32_to_cpu(durable_v2_blob->Timeout);
+				dh_info->type = dh_idx;
+			}
+			break;
+		}
+		case DURABLE_REQ:
+			if (dh_info->type == DURABLE_RECONN)
+				goto out;
+			if (dh_info->type == DURABLE_RECONN_V2 ||
+			    dh_info->type == DURABLE_REQ_V2) {
+				err = -EINVAL;
+				goto out;
+			}
+
+			if (((lc && (lc->req_state & SMB2_LEASE_HANDLE_CACHING_LE)) ||
+			     req_op_level == SMB2_OPLOCK_LEVEL_BATCH)) {
+				ksmbd_debug(SMB, "Request for durable open\n");
+				dh_info->type = dh_idx;
+			}
+		}
+	}
+
+out:
+	return err;
+}
+
 /**
  * smb2_open() - handler for smb file open request
  * @work:	smb work containing request buffer
@@ -2645,6 +2804,7 @@ int smb2_open(struct ksmbd_work *work)
 	struct lease_ctx_info *lc = NULL;
 	struct create_ea_buf_req *ea_buf = NULL;
 	struct oplock_info *opinfo;
+	struct durable_info dh_info = {0};
 	__le32 *next_ptr = NULL;
 	int req_op_level = 0, open_flags = 0, may_flags = 0, file_info = 0;
 	int rc = 0;
@@ -2725,6 +2885,49 @@ int smb2_open(struct ksmbd_work *work)
 		}
 	}
 
+	req_op_level = req->RequestedOplockLevel;
+
+	if (server_conf.flags & KSMBD_GLOBAL_FLAG_DURABLE_HANDLE &&
+	    req->CreateContextsOffset) {
+		lc = parse_lease_state(req);
+		rc = parse_durable_handle_context(work, req, lc, &dh_info);
+		if (rc) {
+			ksmbd_debug(SMB, "error parsing durable handle context\n");
+			goto err_out2;
+		}
+
+		if (dh_info.reconnected == true) {
+			rc = smb2_check_durable_oplock(conn, share, dh_info.fp, lc, name);
+			if (rc) {
+				ksmbd_put_durable_fd(dh_info.fp);
+				goto err_out2;
+			}
+
+			rc = ksmbd_reopen_durable_fd(work, dh_info.fp);
+			if (rc) {
+				ksmbd_put_durable_fd(dh_info.fp);
+				goto err_out2;
+			}
+
+			if (ksmbd_override_fsids(work)) {
+				rc = -ENOMEM;
+				ksmbd_put_durable_fd(dh_info.fp);
+				goto err_out2;
+			}
+
+			fp = dh_info.fp;
+			file_info = FILE_OPENED;
+
+			rc = ksmbd_vfs_getattr(&fp->filp->f_path, &stat);
+			if (rc)
+				goto err_out2;
+
+			ksmbd_put_durable_fd(fp);
+			goto reconnected_fp;
+		}
+	} else if (req_op_level == SMB2_OPLOCK_LEVEL_LEASE)
+		lc = parse_lease_state(req);
+
 	if (le32_to_cpu(req->ImpersonationLevel) > le32_to_cpu(IL_DELEGATE)) {
 		pr_err("Invalid impersonationlevel : 0x%x\n",
 		       le32_to_cpu(req->ImpersonationLevel));
@@ -3187,10 +3390,6 @@ int smb2_open(struct ksmbd_work *work)
 		need_truncate = 1;
 	}
 
-	req_op_level = req->RequestedOplockLevel;
-	if (req_op_level == SMB2_OPLOCK_LEVEL_LEASE)
-		lc = parse_lease_state(req, S_ISDIR(file_inode(filp)->i_mode));
-
 	share_ret = ksmbd_smb_check_shared_mode(fp->filp, fp);
 	if (!test_share_config_flag(work->tcon->share_conf, KSMBD_SHARE_FLAG_OPLOCKS) ||
 	    (req_op_level == SMB2_OPLOCK_LEVEL_LEASE &&
@@ -3201,6 +3400,11 @@ int smb2_open(struct ksmbd_work *work)
 		}
 	} else {
 		if (req_op_level == SMB2_OPLOCK_LEVEL_LEASE) {
+			if (S_ISDIR(file_inode(filp)->i_mode)) {
+				lc->req_state &= ~SMB2_LEASE_WRITE_CACHING_LE;
+				lc->is_dir = true;
+			}
+
 			/*
 			 * Compare parent lease using parent key. If there is no
 			 * a lease that has same parent key, Send lease break
@@ -3297,6 +3501,24 @@ 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)
+			fp->is_persistent = true;
+		else
+			fp->is_durable = true;
+
+		if (dh_info.type == DURABLE_REQ_V2) {
+			memcpy(fp->create_guid, dh_info.CreateGuid,
+					SMB2_CREATE_GUID_SIZE);
+			if (dh_info.timeout)
+				fp->durable_timeout = min(dh_info.timeout,
+						300000);
+			else
+				fp->durable_timeout = 60;
+		}
+	}
+
+reconnected_fp:
 	rsp->StructureSize = cpu_to_le16(89);
 	rcu_read_lock();
 	opinfo = rcu_dereference(fp->f_opinfo);
@@ -3383,6 +3605,33 @@ int smb2_open(struct ksmbd_work *work)
 		next_off = conn->vals->create_disk_id_size;
 	}
 
+	if (dh_info.type == DURABLE_REQ || dh_info.type == DURABLE_REQ_V2) {
+		struct create_context *durable_ccontext;
+
+		durable_ccontext = (struct create_context *)(rsp->Buffer +
+				le32_to_cpu(rsp->CreateContextsLength));
+		contxt_cnt++;
+		if (dh_info.type == DURABLE_REQ) {
+			create_durable_rsp_buf(rsp->Buffer +
+					le32_to_cpu(rsp->CreateContextsLength));
+			le32_add_cpu(&rsp->CreateContextsLength,
+					conn->vals->create_durable_size);
+			iov_len += conn->vals->create_durable_size;
+		} else {
+			create_durable_v2_rsp_buf(rsp->Buffer +
+					le32_to_cpu(rsp->CreateContextsLength),
+					fp);
+			le32_add_cpu(&rsp->CreateContextsLength,
+					conn->vals->create_durable_v2_size);
+			iov_len += conn->vals->create_durable_v2_size;
+		}
+
+		if (next_ptr)
+			*next_ptr = cpu_to_le32(next_off);
+		next_ptr = &durable_ccontext->Next;
+		next_off = conn->vals->create_durable_size;
+	}
+
 	if (posix_ctxt) {
 		contxt_cnt++;
 		create_posix_rsp_buf(rsp->Buffer +
diff --git a/fs/smb/server/smb2pdu.h b/fs/smb/server/smb2pdu.h
index d12cfd3b09278..bd1d2a0e9203a 100644
--- a/fs/smb/server/smb2pdu.h
+++ b/fs/smb/server/smb2pdu.h
@@ -72,6 +72,18 @@ struct create_durable_req_v2 {
 	__u8 CreateGuid[16];
 } __packed;
 
+struct create_durable_reconn_req {
+	struct create_context ccontext;
+	__u8   Name[8];
+	union {
+		__u8  Reserved[16];
+		struct {
+			__u64 PersistentFileId;
+			__u64 VolatileFileId;
+		} Fid;
+	} Data;
+} __packed;
+
 struct create_durable_reconn_v2_req {
 	struct create_context ccontext;
 	__u8   Name[8];
@@ -98,6 +110,9 @@ struct create_durable_rsp {
 	} Data;
 } __packed;
 
+/* See MS-SMB2 2.2.13.2.11 */
+/* Flags */
+#define SMB2_DHANDLE_FLAG_PERSISTENT	0x00000002
 struct create_durable_v2_rsp {
 	struct create_context ccontext;
 	__u8   Name[8];
diff --git a/fs/smb/server/vfs_cache.c b/fs/smb/server/vfs_cache.c
index 4e82ff627d122..030f70700036c 100644
--- a/fs/smb/server/vfs_cache.c
+++ b/fs/smb/server/vfs_cache.c
@@ -305,7 +305,8 @@ static void __ksmbd_close_fd(struct ksmbd_file_table *ft, struct ksmbd_file *fp)
 
 	fd_limit_close();
 	__ksmbd_remove_durable_fd(fp);
-	__ksmbd_remove_fd(ft, fp);
+	if (ft)
+		__ksmbd_remove_fd(ft, fp);
 
 	close_id_del_oplock(fp);
 	filp = fp->filp;
@@ -465,11 +466,32 @@ struct ksmbd_file *ksmbd_lookup_fd_slow(struct ksmbd_work *work, u64 id,
 	return fp;
 }
 
-struct ksmbd_file *ksmbd_lookup_durable_fd(unsigned long long id)
+struct ksmbd_file *ksmbd_lookup_global_fd(unsigned long long id)
 {
 	return __ksmbd_lookup_fd(&global_ft, id);
 }
 
+struct ksmbd_file *ksmbd_lookup_durable_fd(unsigned long long id)
+{
+	struct ksmbd_file *fp;
+
+	fp = __ksmbd_lookup_fd(&global_ft, id);
+	if (fp && fp->conn) {
+		ksmbd_put_durable_fd(fp);
+		fp = NULL;
+	}
+
+	return fp;
+}
+
+void ksmbd_put_durable_fd(struct ksmbd_file *fp)
+{
+	if (!atomic_dec_and_test(&fp->refcount))
+		return;
+
+	__ksmbd_close_fd(NULL, fp);
+}
+
 struct ksmbd_file *ksmbd_lookup_fd_cguid(char *cguid)
 {
 	struct ksmbd_file	*fp = NULL;
@@ -639,6 +661,32 @@ __close_file_table_ids(struct ksmbd_file_table *ft,
 	return num;
 }
 
+static inline bool is_reconnectable(struct ksmbd_file *fp)
+{
+	struct oplock_info *opinfo = opinfo_get(fp);
+	bool reconn = false;
+
+	if (!opinfo)
+		return false;
+
+	if (opinfo->op_state != OPLOCK_STATE_NONE) {
+		opinfo_put(opinfo);
+		return false;
+	}
+
+	if (fp->is_resilient || fp->is_persistent)
+		reconn = true;
+	else if (fp->is_durable && opinfo->is_lease &&
+		 opinfo->o_lease->state & SMB2_LEASE_HANDLE_CACHING_LE)
+		reconn = true;
+
+	else if (fp->is_durable && opinfo->level == SMB2_OPLOCK_LEVEL_BATCH)
+		reconn = true;
+
+	opinfo_put(opinfo);
+	return reconn;
+}
+
 static bool tree_conn_fd_check(struct ksmbd_tree_connect *tcon,
 			       struct ksmbd_file *fp)
 {
@@ -648,7 +696,28 @@ static bool tree_conn_fd_check(struct ksmbd_tree_connect *tcon,
 static bool session_fd_check(struct ksmbd_tree_connect *tcon,
 			     struct ksmbd_file *fp)
 {
-	return false;
+	struct ksmbd_inode *ci;
+	struct oplock_info *op;
+	struct ksmbd_conn *conn;
+
+	if (!is_reconnectable(fp))
+		return false;
+
+	conn = fp->conn;
+	ci = fp->f_ci;
+	write_lock(&ci->m_lock);
+	list_for_each_entry_rcu(op, &ci->m_op_list, op_entry) {
+		if (op->conn != conn)
+			continue;
+		op->conn = NULL;
+	}
+	write_unlock(&ci->m_lock);
+
+	fp->conn = NULL;
+	fp->tcon = NULL;
+	fp->volatile_id = KSMBD_NO_FID;
+
+	return true;
 }
 
 void ksmbd_close_tree_conn_fds(struct ksmbd_work *work)
@@ -687,6 +756,68 @@ void ksmbd_free_global_file_table(void)
 	ksmbd_destroy_file_table(&global_ft);
 }
 
+int ksmbd_validate_name_reconnect(struct ksmbd_share_config *share,
+				  struct ksmbd_file *fp, char *name)
+{
+	char *pathname, *ab_pathname;
+	int ret = 0;
+
+	pathname = kmalloc(PATH_MAX, GFP_KERNEL);
+	if (!pathname)
+		return -EACCES;
+
+	ab_pathname = d_path(&fp->filp->f_path, pathname, PATH_MAX);
+	if (IS_ERR(ab_pathname)) {
+		kfree(pathname);
+		return -EACCES;
+	}
+
+	if (name && strcmp(&ab_pathname[share->path_sz + 1], name)) {
+		ksmbd_debug(SMB, "invalid name reconnect %s\n", name);
+		ret = -EINVAL;
+	}
+
+	kfree(pathname);
+
+	return ret;
+}
+
+int ksmbd_reopen_durable_fd(struct ksmbd_work *work, struct ksmbd_file *fp)
+{
+	struct ksmbd_inode *ci;
+	struct oplock_info *op;
+
+	if (!fp->is_durable || fp->conn || fp->tcon) {
+		pr_err("Invalid durable fd [%p:%p]\n", fp->conn, fp->tcon);
+		return -EBADF;
+	}
+
+	if (has_file_id(fp->volatile_id)) {
+		pr_err("Still in use durable fd: %llu\n", fp->volatile_id);
+		return -EBADF;
+	}
+
+	fp->conn = work->conn;
+	fp->tcon = work->tcon;
+
+	ci = fp->f_ci;
+	write_lock(&ci->m_lock);
+	list_for_each_entry_rcu(op, &ci->m_op_list, op_entry) {
+		if (op->conn)
+			continue;
+		op->conn = fp->conn;
+	}
+	write_unlock(&ci->m_lock);
+
+	__open_id(&work->sess->file_table, fp, OPEN_ID_TYPE_VOLATILE_ID);
+	if (!has_file_id(fp->volatile_id)) {
+		fp->conn = NULL;
+		fp->tcon = NULL;
+		return -EBADF;
+	}
+	return 0;
+}
+
 int ksmbd_init_file_table(struct ksmbd_file_table *ft)
 {
 	ft->idr = kzalloc(sizeof(struct idr), GFP_KERNEL);
diff --git a/fs/smb/server/vfs_cache.h b/fs/smb/server/vfs_cache.h
index a528f0cc775ae..ed44fb4e18e79 100644
--- a/fs/smb/server/vfs_cache.h
+++ b/fs/smb/server/vfs_cache.h
@@ -14,6 +14,7 @@
 #include <linux/workqueue.h>
 
 #include "vfs.h"
+#include "mgmt/share_config.h"
 
 /* Windows style file permissions for extended response */
 #define	FILE_GENERIC_ALL	0x1F01FF
@@ -106,6 +107,9 @@ struct ksmbd_file {
 	int				dot_dotdot[2];
 	unsigned int			f_state;
 	bool				reserve_lease_break;
+	bool				is_durable;
+	bool				is_persistent;
+	bool				is_resilient;
 };
 
 static inline void set_ctx_actor(struct dir_context *ctx,
@@ -141,7 +145,9 @@ struct ksmbd_file *ksmbd_lookup_fd_slow(struct ksmbd_work *work, u64 id,
 void ksmbd_fd_put(struct ksmbd_work *work, struct ksmbd_file *fp);
 struct ksmbd_inode *ksmbd_inode_lookup_lock(struct dentry *d);
 void ksmbd_inode_put(struct ksmbd_inode *ci);
+struct ksmbd_file *ksmbd_lookup_global_fd(unsigned long long id);
 struct ksmbd_file *ksmbd_lookup_durable_fd(unsigned long long id);
+void ksmbd_put_durable_fd(struct ksmbd_file *fp);
 struct ksmbd_file *ksmbd_lookup_fd_cguid(char *cguid);
 struct ksmbd_file *ksmbd_lookup_fd_inode(struct dentry *dentry);
 unsigned int ksmbd_open_durable_fd(struct ksmbd_file *fp);
@@ -173,6 +179,9 @@ void ksmbd_set_inode_pending_delete(struct ksmbd_file *fp);
 void ksmbd_clear_inode_pending_delete(struct ksmbd_file *fp);
 void ksmbd_fd_set_delete_on_close(struct ksmbd_file *fp,
 				  int file_info);
+int ksmbd_reopen_durable_fd(struct ksmbd_work *work, struct ksmbd_file *fp);
+int ksmbd_validate_name_reconnect(struct ksmbd_share_config *share,
+				  struct ksmbd_file *fp, char *name);
 int ksmbd_init_file_cache(void);
 void ksmbd_exit_file_cache(void);
 #endif /* __VFS_CACHE_H__ */
-- 
2.43.0




  parent reply	other threads:[~2024-05-23 13:25 UTC|newest]

Thread overview: 114+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2024-05-23 13:12 [PATCH 6.6 000/102] 6.6.32-rc1 review Greg Kroah-Hartman
2024-05-23 13:12 ` [PATCH 6.6 001/102] cifs: Add client version details to NTLM authenticate message Greg Kroah-Hartman
2024-05-23 13:12 ` [PATCH 6.6 002/102] SMB3: clarify some of the unused CreateOption flags Greg Kroah-Hartman
2024-05-23 13:12 ` [PATCH 6.6 003/102] Add definition for new smb3.1.1 command type Greg Kroah-Hartman
2024-05-23 13:12 ` [PATCH 6.6 004/102] smb: use crypto_shash_digest() in symlink_hash() Greg Kroah-Hartman
2024-05-23 13:12 ` [PATCH 6.6 005/102] cifs: print server capabilities in DebugData Greg Kroah-Hartman
2024-05-23 13:12 ` [PATCH 6.6 006/102] smb3: minor RDMA cleanup Greg Kroah-Hartman
2024-05-23 13:12 ` [PATCH 6.6 007/102] smb3: more minor cleanups for session handling routines Greg Kroah-Hartman
2024-05-23 13:12 ` [PATCH 6.6 008/102] smb3: minor cleanup of session handling code Greg Kroah-Hartman
2024-05-23 13:12 ` [PATCH 6.6 009/102] Missing field not being returned in ioctl CIFS_IOC_GET_MNT_INFO Greg Kroah-Hartman
2024-05-23 13:12 ` [PATCH 6.6 010/102] cifs: fix use after free for iface while disabling secondary channels Greg Kroah-Hartman
2024-05-23 13:12 ` [PATCH 6.6 011/102] smb: client: introduce cifs_sfu_make_node() Greg Kroah-Hartman
2024-05-23 13:12 ` [PATCH 6.6 012/102] smb: client: Fix minor whitespace errors and warnings Greg Kroah-Hartman
2024-05-23 13:12 ` [PATCH 6.6 013/102] smb: client: extend smb2_compound_op() to accept more commands Greg Kroah-Hartman
2024-05-23 13:12 ` [PATCH 6.6 014/102] smb: client: allow creating special files via reparse points Greg Kroah-Hartman
2024-05-23 13:12 ` [PATCH 6.6 015/102] smb: client: optimise reparse point querying Greg Kroah-Hartman
2024-05-23 13:12 ` [PATCH 6.6 016/102] smb: client: allow creating symlinks via reparse points Greg Kroah-Hartman
2024-05-23 13:12 ` [PATCH 6.6 017/102] smb: client: cleanup smb2_query_reparse_point() Greg Kroah-Hartman
2024-05-23 13:12 ` [PATCH 6.6 018/102] smb: client: handle special files and symlinks in SMB3 POSIX Greg Kroah-Hartman
2024-05-23 13:12 ` [PATCH 6.6 019/102] cifs: fix in logging in cifs_chan_update_iface Greg Kroah-Hartman
2024-05-23 13:12 ` [PATCH 6.6 020/102] smb3: Improve exception handling in allocate_mr_list() Greg Kroah-Hartman
2024-05-23 13:12 ` [PATCH 6.6 021/102] cifs: Pass unbyteswapped eof value into SMB2_set_eof() Greg Kroah-Hartman
2024-05-23 13:12 ` [PATCH 6.6 022/102] cifs: get rid of dup length check in parse_reparse_point() Greg Kroah-Hartman
2024-05-23 13:12 ` [PATCH 6.6 023/102] cifs: remove unneeded return statement Greg Kroah-Hartman
2024-05-23 13:12 ` [PATCH 6.6 024/102] ksmbd: auth: fix most kernel-doc warnings Greg Kroah-Hartman
2024-05-23 13:12 ` [PATCH 6.6 025/102] ksmbd: vfs: fix all " Greg Kroah-Hartman
2024-05-23 13:12 ` [PATCH 6.6 026/102] cifs: remove redundant variable tcon_exist Greg Kroah-Hartman
2024-05-23 13:12 ` [PATCH 6.6 027/102] cifs: minor comment cleanup Greg Kroah-Hartman
2024-05-23 13:12 ` [PATCH 6.6 028/102] cifs: pick channel for tcon and tdis Greg Kroah-Hartman
2024-05-23 13:12 ` [PATCH 6.6 029/102] cifs: new nt status codes from MS-SMB2 Greg Kroah-Hartman
2024-05-23 13:12 ` [PATCH 6.6 030/102] smb: client: dont clobber ->i_rdev from cached reparse points Greg Kroah-Hartman
2024-05-23 13:12 ` [PATCH 6.6 031/102] cifs: new mount option called retrans Greg Kroah-Hartman
2024-05-23 13:12 ` [PATCH 6.6 032/102] smb: Fix some kernel-doc comments Greg Kroah-Hartman
2024-05-23 13:12 ` [PATCH 6.6 033/102] smb: client: delete "true", "false" defines Greg Kroah-Hartman
2024-05-23 13:12 ` [PATCH 6.6 034/102] cifs: commands that are retried should have replay flag set Greg Kroah-Hartman
2024-05-23 13:13 ` [PATCH 6.6 035/102] cifs: set replay flag for retries of write command Greg Kroah-Hartman
2024-05-23 13:13 ` [PATCH 6.6 036/102] ksmbd: Add kernel-doc for ksmbd_extract_sharename() function Greg Kroah-Hartman
2024-05-23 13:13 ` [PATCH 6.6 037/102] cifs: update the same create_guid on replay Greg Kroah-Hartman
2024-05-23 13:13 ` [PATCH 6.6 038/102] smb: client: handle path separator of created SMB symlinks Greg Kroah-Hartman
2024-05-23 13:13 ` [PATCH 6.6 039/102] smb3: update allocation size more accurately on write completion Greg Kroah-Hartman
2024-05-23 13:13 ` [PATCH 6.6 040/102] smb: client: parse owner/group when creating reparse points Greg Kroah-Hartman
2024-05-23 13:13 ` [PATCH 6.6 041/102] smb: client: get rid of smb311_posix_query_path_info() Greg Kroah-Hartman
2024-05-23 13:13 ` [PATCH 6.6 042/102] smb: client: reuse file lease key in compound operations Greg Kroah-Hartman
2024-05-23 13:13 ` [PATCH 6.6 043/102] smb: client: do not defer close open handles to deleted files Greg Kroah-Hartman
2024-05-23 13:13 ` [PATCH 6.6 044/102] smb: client: retry compound request without reusing lease Greg Kroah-Hartman
2024-05-23 13:13 ` [PATCH 6.6 045/102] smb: client: introduce reparse mount option Greg Kroah-Hartman
2024-05-23 13:13 ` [PATCH 6.6 046/102] smb: client: move most of reparse point handling code to common file Greg Kroah-Hartman
2024-05-23 13:13 ` [PATCH 6.6 047/102] smb: client: fix potential broken compound request Greg Kroah-Hartman
2024-05-23 13:13 ` [PATCH 6.6 048/102] smb: client: reduce number of parameters in smb2_compound_op() Greg Kroah-Hartman
2024-05-23 13:13 ` [PATCH 6.6 049/102] smb: client: add support for WSL reparse points Greg Kroah-Hartman
2024-05-23 13:13 ` [PATCH 6.6 050/102] smb: client: Fix a NULL vs IS_ERR() check in wsl_set_xattrs() Greg Kroah-Hartman
2024-05-23 13:13 ` [PATCH 6.6 051/102] smb: client: introduce SMB2_OP_QUERY_WSL_EA Greg Kroah-Hartman
2024-05-23 13:13 ` [PATCH 6.6 052/102] smb: client: parse uid, gid, mode and dev from WSL reparse points Greg Kroah-Hartman
2024-05-23 13:13 ` [PATCH 6.6 053/102] smb: client: set correct d_type for reparse DFS/DFSR and mount point Greg Kroah-Hartman
2024-05-23 13:13 ` [PATCH 6.6 054/102] smb: client: return reparse type in /proc/mounts Greg Kroah-Hartman
2024-05-23 13:13 ` [PATCH 6.6 055/102] smb3: add dynamic trace point for ioctls Greg Kroah-Hartman
2024-05-23 13:13 ` [PATCH 6.6 056/102] smb: client: negotiate compression algorithms Greg Kroah-Hartman
2024-05-23 13:13 ` [PATCH 6.6 057/102] smb: common: fix fields sizes in compression_pattern_payload_v1 Greg Kroah-Hartman
2024-05-23 13:13 ` [PATCH 6.6 058/102] smb: common: simplify compression headers Greg Kroah-Hartman
2024-05-23 13:13 ` [PATCH 6.6 059/102] ksmbd: mark SMB2_SESSION_EXPIRED to session when destroying previous session Greg Kroah-Hartman
2024-05-23 13:13 ` Greg Kroah-Hartman [this message]
2024-05-23 13:13 ` [PATCH 6.6 061/102] cifs: defer close file handles having RH lease Greg Kroah-Hartman
2024-05-23 13:13 ` [PATCH 6.6 062/102] cifs: fixes for get_inode_info Greg Kroah-Hartman
2024-05-23 13:13 ` [PATCH 6.6 063/102] cifs: remove redundant variable assignment Greg Kroah-Hartman
2024-05-23 13:13 ` [PATCH 6.6 064/102] ksmbd: fix possible null-deref in smb_lazy_parent_lease_break_close Greg Kroah-Hartman
2024-05-23 13:13 ` [PATCH 6.6 065/102] ksmbd: Fix spelling mistake "connction" -> "connection" Greg Kroah-Hartman
2024-05-23 13:13 ` [PATCH 6.6 066/102] ksmbd: fix slab-out-of-bounds in smb_strndup_from_utf16() Greg Kroah-Hartman
2024-05-23 13:13 ` [PATCH 6.6 067/102] ksmbd: fix potencial out-of-bounds when buffer offset is invalid Greg Kroah-Hartman
2024-05-23 13:13 ` [PATCH 6.6 068/102] cifs: Move some extern decls from .c files to .h Greg Kroah-Hartman
2024-05-23 13:13 ` [PATCH 6.6 069/102] smb311: correct incorrect offset field in compression header Greg Kroah-Hartman
2024-05-23 13:13 ` [PATCH 6.6 070/102] smb311: additional compression flag defined in updated protocol spec Greg Kroah-Hartman
2024-05-23 13:13 ` [PATCH 6.6 071/102] smb3: add trace event for mknod Greg Kroah-Hartman
2024-05-23 13:13 ` [PATCH 6.6 072/102] smb: client: fix NULL ptr deref in cifs_mark_open_handles_for_deleted_file() Greg Kroah-Hartman
2024-05-23 13:13 ` [PATCH 6.6 073/102] smb: client: instantiate when creating SFU files Greg Kroah-Hartman
2024-05-23 13:13 ` [PATCH 6.6 074/102] cifs: Add tracing for the cifs_tcon struct refcounting Greg Kroah-Hartman
2024-05-23 13:13 ` [PATCH 6.6 075/102] ksmbd: add continuous availability share parameter Greg Kroah-Hartman
2024-05-23 13:13 ` [PATCH 6.6 076/102] smb: smb2pdu.h: Avoid -Wflex-array-member-not-at-end warnings Greg Kroah-Hartman
2024-05-23 13:13 ` [PATCH 6.6 077/102] drm/amd/display: Fix division by zero in setup_dsc_config Greg Kroah-Hartman
2024-05-23 13:13 ` [PATCH 6.6 078/102] net: ks8851: Fix another TX stall caused by wrong ISR flag handling Greg Kroah-Hartman
2024-05-23 13:13 ` [PATCH 6.6 079/102] ice: pass VSI pointer into ice_vc_isvalid_q_id Greg Kroah-Hartman
2024-05-23 13:13 ` [PATCH 6.6 080/102] ice: remove unnecessary duplicate checks for VF VSI ID Greg Kroah-Hartman
2024-05-23 13:13 ` [PATCH 6.6 081/102] Bluetooth: L2CAP: Fix slab-use-after-free in l2cap_connect() Greg Kroah-Hartman
2024-05-23 13:13 ` [PATCH 6.6 082/102] Bluetooth: L2CAP: Fix div-by-zero in l2cap_le_flowctl_init() Greg Kroah-Hartman
2024-05-23 13:13 ` [PATCH 6.6 083/102] KEYS: trusted: Fix memory leak in tpm2_key_encode() Greg Kroah-Hartman
2024-05-23 13:13 ` [PATCH 6.6 084/102] mmc: core: Add HS400 tuning in HS400es initialization Greg Kroah-Hartman
2024-05-23 13:13 ` [PATCH 6.6 085/102] kselftest: Add a ksft_perror() helper Greg Kroah-Hartman
2024-05-23 13:13 ` [PATCH 6.6 086/102] bpf: Add missing BPF_LINK_TYPE invocations Greg Kroah-Hartman
2024-05-23 13:13 ` [PATCH 6.6 087/102] erofs: get rid of erofs_fs_context Greg Kroah-Hartman
2024-05-23 13:13 ` [PATCH 6.6 088/102] erofs: reliably distinguish block based and fscache mode Greg Kroah-Hartman
2024-05-23 13:13 ` [PATCH 6.6 089/102] drm/amdgpu: Fix possible NULL dereference in amdgpu_ras_query_error_status_helper() Greg Kroah-Hartman
2024-05-23 13:13 ` [PATCH 6.6 090/102] binder: fix max_thread type inconsistency Greg Kroah-Hartman
2024-05-23 13:13 ` [PATCH 6.6 091/102] usb: dwc3: Wait unconditionally after issuing EndXfer command Greg Kroah-Hartman
2024-05-23 13:13 ` [PATCH 6.6 092/102] net: usb: ax88179_178a: fix link status when link is set to down/up Greg Kroah-Hartman
2024-05-23 13:13 ` [PATCH 6.6 093/102] usb: typec: ucsi: displayport: Fix potential deadlock Greg Kroah-Hartman
2024-05-23 13:13 ` [PATCH 6.6 094/102] usb: typec: tipd: fix event checking for tps6598x Greg Kroah-Hartman
2024-05-23 13:14 ` [PATCH 6.6 095/102] serial: kgdboc: Fix NMI-safety problems from keyboard reset code Greg Kroah-Hartman
2024-05-23 13:14 ` [PATCH 6.6 096/102] remoteproc: mediatek: Make sure IPI buffer fits in L2TCM Greg Kroah-Hartman
2024-05-23 13:14 ` [PATCH 6.6 097/102] KEYS: trusted: Do not use WARN when encode fails Greg Kroah-Hartman
2024-05-23 13:14 ` [PATCH 6.6 098/102] admin-guide/hw-vuln/core-scheduling: fix return type of PR_SCHED_CORE_GET Greg Kroah-Hartman
2024-05-23 13:14 ` [PATCH 6.6 099/102] docs: kernel_include.py: Cope with docutils 0.21 Greg Kroah-Hartman
2024-05-23 13:14 ` [PATCH 6.6 100/102] Docs/admin-guide/mm/damon/usage: fix wrong example of DAMOS filter matching sysfs file Greg Kroah-Hartman
2024-05-23 13:14 ` [PATCH 6.6 101/102] block: add a disk_has_partscan helper Greg Kroah-Hartman
2024-05-23 13:14 ` [PATCH 6.6 102/102] block: add a partscan sysfs attribute for disks Greg Kroah-Hartman
2024-05-23 17:04 ` [PATCH 6.6 000/102] 6.6.32-rc1 review SeongJae Park
2024-05-23 17:40 ` Mark Brown
2024-05-23 20:39 ` Florian Fainelli
2024-05-23 21:25 ` Takeshi Ogasawara
2024-05-24  6:53 ` Harshit Mogalapalli
2024-05-24 10:00 ` Anders Roxell
2024-05-24 14:35 ` Shuah Khan
2024-05-24 15:19 ` Jon Hunter
2024-05-24 20:36 ` Ron Economos
2024-05-25  1:07 ` Kelsey Steele
2024-05-25 16:25 ` Allen

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20240523130344.733769853@linuxfoundation.org \
    --to=gregkh@linuxfoundation.org \
    --cc=linkinjeon@kernel.org \
    --cc=patches@lists.linux.dev \
    --cc=sashal@kernel.org \
    --cc=stable@vger.kernel.org \
    --cc=stfrench@microsoft.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox