From patchwork Tue Dec 31 22:35:10 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?q?Pali_Roh=C3=A1r?= X-Patchwork-Id: 13924005 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id C54941B0428; Tue, 31 Dec 2024 22:35:51 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1735684551; cv=none; b=FPslXCIcCtGGIgfQpanp7TDaVpFXYlXAsDosSKQj7ed0rEkKBImrAKRiDrZjsYlXbt7bRHstoJUwb41fqZyfVyxxhd+Gj6LhHLeg7KfWQEC5l+cRa/WsQEydx4UrbEts+m9hj8yJ7jloCMwlUV39Gw7lA6rQwpMY7SYyHUlxsgQ= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1735684551; c=relaxed/simple; bh=W8c5iBpRMEjpMq8Amb2dRFJttRR277+4BAcA8bSbu3A=; h=From:To:Cc:Subject:Date:Message-Id:MIME-Version:Content-Type; b=MZMOW+UjnYF81O5PQjUDvnCIAaYGg6lbAhlQQjd4ra+TjY8oBENwgEL6YFDdq4xPqIhYdV2KqAoAhVBfzjnhhUVZpsJgyzL7Nd3z5+IaW3NrpBkWnoQ8G3fiqVuU7lBUZYUmjq2uf2lSfunJrP4NikbPC0YmeNoHXGNKpDHVBAw= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=HWLvjDcN; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="HWLvjDcN" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 4C385C4CED2; Tue, 31 Dec 2024 22:35:51 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1735684551; bh=W8c5iBpRMEjpMq8Amb2dRFJttRR277+4BAcA8bSbu3A=; h=From:To:Cc:Subject:Date:From; b=HWLvjDcN3s68YRcoPcwSx9m4MdjxaUlYzWMgHuJLKYF/rk3h2FYY38iD9HgYeuxh1 v5y9G65dLu2+aV7432o2onjokC5pxwIF6pVNySQE4XI01ilW2dKR/o/h7SohSYYmdg lFZkfHBcf2mdxYoEAl//G036mrrDu/YU5/bxZtKRYcNQkkhS4A7fQDIRc+ak/CyUg3 kn2m/vn72nP0UQEuGBtzE8O1EDP5FAV06b4fXvH6Fmu4bK2Idv1MjHvt5qPgJY3RDD R/rMv494CeTMpownQtw5TtyTmTzKujGpDNvFk8tKCrdLEgQq9bBcyFhwjpt00225bM 9t0MV86hakzGg== Received: by pali.im (Postfix) id BC23D97E; Tue, 31 Dec 2024 23:35:40 +0100 (CET) From: =?utf-8?q?Pali_Roh=C3=A1r?= To: Steve French , Paulo Alcantara Cc: linux-cifs@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [PATCH 1/5] cifs: Fix access_flags_to_smbopen_mode Date: Tue, 31 Dec 2024 23:35:10 +0100 Message-Id: <20241231223514.15595-1-pali@kernel.org> X-Mailer: git-send-email 2.39.5 Precedence: bulk X-Mailing-List: linux-cifs@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 When converting access_flags to SMBOPEN mode, check for all possible access flags, not only GENERIC_READ and GENERIC_WRITE flags. Signed-off-by: Pali Rohár --- fs/smb/client/cifssmb.c | 32 ++++++++++++++++++++++++-------- 1 file changed, 24 insertions(+), 8 deletions(-) diff --git a/fs/smb/client/cifssmb.c b/fs/smb/client/cifssmb.c index dd71c4c8f776..604e204e3f57 100644 --- a/fs/smb/client/cifssmb.c +++ b/fs/smb/client/cifssmb.c @@ -1024,15 +1024,31 @@ static __u16 convert_disposition(int disposition) static int access_flags_to_smbopen_mode(const int access_flags) { - int masked_flags = access_flags & (GENERIC_READ | GENERIC_WRITE); - - if (masked_flags == GENERIC_READ) - return SMBOPEN_READ; - else if (masked_flags == GENERIC_WRITE) + /* + * SYSTEM_SECURITY grants both read and write access to SACL, treat is as read/write. + * MAXIMUM_ALLOWED grants as many access as possible, so treat it as read/write too. + * SYNCHRONIZE as is does not grant any specific access, so do not check its mask. + * If only SYNCHRONIZE bit is specified then fallback to read access. + */ + bool with_write_flags = access_flags & (FILE_WRITE_DATA | FILE_APPEND_DATA | FILE_WRITE_EA | + FILE_DELETE_CHILD | FILE_WRITE_ATTRIBUTES | DELETE | + WRITE_DAC | WRITE_OWNER | SYSTEM_SECURITY | + MAXIMUM_ALLOWED | GENERIC_WRITE | GENERIC_ALL); + bool with_read_flags = access_flags & (FILE_READ_DATA | FILE_READ_EA | FILE_EXECUTE | + FILE_READ_ATTRIBUTES | READ_CONTROL | + SYSTEM_SECURITY | MAXIMUM_ALLOWED | GENERIC_ALL | + GENERIC_EXECUTE | GENERIC_READ); + bool with_execute_flags = access_flags & (FILE_EXECUTE | MAXIMUM_ALLOWED | GENERIC_ALL | + GENERIC_EXECUTE); + + if (with_write_flags && with_read_flags) + return SMBOPEN_READWRITE; + else if (with_write_flags) return SMBOPEN_WRITE; - - /* just go for read/write */ - return SMBOPEN_READWRITE; + else if (with_execute_flags) + return SMBOPEN_EXECUTE; + else + return SMBOPEN_READ; } int From patchwork Tue Dec 31 22:35:11 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?q?Pali_Roh=C3=A1r?= X-Patchwork-Id: 13924007 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id C53D9170A11; Tue, 31 Dec 2024 22:35:51 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1735684551; cv=none; b=WsdvnakFHObas8qEZ7x6p4+AaTDvtakb0A3PvQ++MK3GGJuMwctF4wiKE8MmDLLX8yeJ/YJr4Te/warzhiSC9QE8sBtX6STFqRfJfFZaPpIQmDKDPkidyiNAEJ9BPoEWVCZ3IHa+9mUxumHtXlLErw4oRYF3q9/gF6k27HQRX3c= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1735684551; c=relaxed/simple; bh=2lN8Yf08Rc70bynorQlGAxZReDCriIUXlHP9bvzS+l0=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version:Content-Type; b=S67urFmL+cdYBbfBERLwty3DxD5Nw8HkikD7cxhKlmkCnbD0As6cBACNw7s88BU7O1Hs5hH2WWUnY0bcoFjWlExoZPqHHtUjrUbvHMil82X3eNqmfpZsGlF9WFnf7oGbgqvVbFZLEe4gydWcJjeDPkWO0vMXxBsAzVbWtyfP73I= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=N3A4xnJa; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="N3A4xnJa" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 5FFB9C4CEDE; Tue, 31 Dec 2024 22:35:51 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1735684551; bh=2lN8Yf08Rc70bynorQlGAxZReDCriIUXlHP9bvzS+l0=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=N3A4xnJa7xBLMk3EfYXeaOBEcaht0HgzjFqXnVnhSPReM4SDF3Vpe2PUj3ukM0xle e8YPVkC/vp5PC1sgq6d3NssSdGzi/PLQbtKlJqQ5MzTasx+3B70d0SL6Vgxs7vL0KJ nZxcBMyehlt69qvXythBVhmxmjbHxPye1KJZt+O/16SALuN61oeiMvHo6/nTHwy+Od K4UEuyi7WvEWXu3SfH7wFPbQm3xJf48/KJlV6etaXHu2P2G6IzcNkp5VxlD++AcfN3 fu/KB4gE5RRi/0GkP+pk77swPUIkWNVrdm04Mm3+ZiVmmU2+dTlg2oPA3MX0pwNvTw Ycp1xNVBe7YNQ== Received: by pali.im (Postfix) id D8B35983; Tue, 31 Dec 2024 23:35:40 +0100 (CET) From: =?utf-8?q?Pali_Roh=C3=A1r?= To: Steve French , Paulo Alcantara Cc: linux-cifs@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [PATCH 2/5] cifs: Do not add FILE_READ_ATTRIBUTES when using GENERIC_READ/EXECUTE/ALL Date: Tue, 31 Dec 2024 23:35:11 +0100 Message-Id: <20241231223514.15595-2-pali@kernel.org> X-Mailer: git-send-email 2.39.5 In-Reply-To: <20241231223514.15595-1-pali@kernel.org> References: <20241231223514.15595-1-pali@kernel.org> Precedence: bulk X-Mailing-List: linux-cifs@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Individual bits GENERIC_READ, GENERIC_EXECUTE and GENERIC_ALL have meaning which includes also access right for FILE_READ_ATTRIBUTES. So specifying FILE_READ_ATTRIBUTES bit together with one of those GENERIC (except GENERIC_WRITE) does not do anything. This change prevents calling additional (fallback) code and sending more requests without FILE_READ_ATTRIBUTES when the primary request fails on -EACCES, as it is not needed at all. Signed-off-by: Pali Rohár --- fs/smb/client/smb2file.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/fs/smb/client/smb2file.c b/fs/smb/client/smb2file.c index 1476cb824ae4..0f3d20b597d6 100644 --- a/fs/smb/client/smb2file.c +++ b/fs/smb/client/smb2file.c @@ -158,7 +158,16 @@ int smb2_open_file(const unsigned int xid, struct cifs_open_parms *oparms, __u32 if (smb2_path == NULL) return -ENOMEM; + /* + * GENERIC_READ, GENERIC_EXECUTE, GENERIC_ALL and MAXIMUM_ALLOWED + * contains also FILE_READ_ATTRIBUTES access right. So do not append + * FILE_READ_ATTRIBUTES when not needed and prevent calling code path + * for retry_without_read_attributes. + */ if (!(oparms->desired_access & FILE_READ_ATTRIBUTES) && + !(oparms->desired_access & GENERIC_READ) && + !(oparms->desired_access & GENERIC_EXECUTE) && + !(oparms->desired_access & GENERIC_ALL) && !(oparms->desired_access & MAXIMUM_ALLOWED)) { oparms->desired_access |= FILE_READ_ATTRIBUTES; retry_without_read_attributes = true; From patchwork Tue Dec 31 22:35:12 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?q?Pali_Roh=C3=A1r?= X-Patchwork-Id: 13924006 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id C54291B0401; Tue, 31 Dec 2024 22:35:51 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1735684551; cv=none; b=lO7o32w/v1tuQcr5WJUDa3HYPJfvXfn6lpYb25ZsetQQtnqVRQUNsoAE128fdw4LiIgrM+Iho6sovnBxKmTRMyLfJgNynXBSVJ5qSg4J01u3AV38csg+pNTB/LHW1TJJMD9qo0BqBw9xxrWeuehnk2Ereig2nWT2EJmgNBwbEOs= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1735684551; c=relaxed/simple; bh=OQK7l6kkrF4aaKofM7nULw1FDL8eDddYk2IX5MvKcV4=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version:Content-Type; b=GoaZxpgdtlT4/9MzPdRD0qkxeh+RnW8VSbyHfcyYXaq4kZkaXsPVOA+eA19rNdQfVwYLK34oV9h6SK42DHqAuCc9bMRR2ZJLviZyG4N5WejDwq0Ua181cqJJzccSTXH7nXOy0JcXM28xYq6exqCqfl/G9T/wUl3Z29hN+ewq28U= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=TsjFUURX; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="TsjFUURX" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 5D0B1C4CED6; Tue, 31 Dec 2024 22:35:51 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1735684551; bh=OQK7l6kkrF4aaKofM7nULw1FDL8eDddYk2IX5MvKcV4=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=TsjFUURX8oUx4N5l1mhHoFQu5/9tyYrn3krg3qaUfUQ4fE96Y7AE5+DXidmfqKIoQ lWmupNw2Th2n9Mn1TmqKoK9plrpq5VcmXpGr+2LY+a/+TjFeGcePhYI6Y1mdmPcrjw 6skJ+VP7rwhtlPP587Z4KviTYaFHhOhjEXz0vclN4Ric6Krcvbaupnvoo5/k9hYPgj t23LyoAtav+gMRg4kAvN8cutTkiLmuZFCuNepLDUyM3VmibJoRUPuadfVCScckXLvi CmvfTr3U/641GbQ5Ut/iA+1Lgd6oULUp/9cqgel4UHDIj5+rN6Yy8mzJENSxMr1BLI qk/Bjjcivj1nw== Received: by pali.im (Postfix) id 186B998C; Tue, 31 Dec 2024 23:35:41 +0100 (CET) From: =?utf-8?q?Pali_Roh=C3=A1r?= To: Steve French , Paulo Alcantara Cc: linux-cifs@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [PATCH 3/5] cifs: Improve SMB2+ stat() to work also on non-present name surrogate reparse points Date: Tue, 31 Dec 2024 23:35:12 +0100 Message-Id: <20241231223514.15595-3-pali@kernel.org> X-Mailer: git-send-email 2.39.5 In-Reply-To: <20241231223514.15595-1-pali@kernel.org> References: <20241231223514.15595-1-pali@kernel.org> Precedence: bulk X-Mailing-List: linux-cifs@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 SMB server returns STATUS_OBJECT_PATH_NOT_FOUND if the path exists, is the reparse point of name surrogate type (e.g. mount point) and surrogate target location does not exist. So if the server returns STATUS_OBJECT_PATH_NOT_FOUND error then it is required to send request again with OPEN_REPARSE_POINT flag. This is needed to distinguish between path does not exist and path exists and points to non-existent surrogate location. Before this change, Linux SMB client returned for non-present name surrogate reparse point -ENOENT error. With this change it correctly returns that the entry exits, it is of directory type with filled stat information. Signed-off-by: Pali Rohár --- fs/smb/client/smb2inode.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/fs/smb/client/smb2inode.c b/fs/smb/client/smb2inode.c index 0b8d6d8f724d..b6342b043073 100644 --- a/fs/smb/client/smb2inode.c +++ b/fs/smb/client/smb2inode.c @@ -958,6 +958,18 @@ int smb2_query_path_info(const unsigned int xid, if (!hdr || out_buftype[0] == CIFS_NO_BUFFER) goto out; + /* + * SMB server returns STATUS_OBJECT_PATH_NOT_FOUND if the path exists, + * is the reparse point of name surrogate type (e.g. mount point) and + * surrogate target location does not exist. + * So if the server returns STATUS_OBJECT_PATH_NOT_FOUND error then it + * is required to send request again with OPEN_REPARSE_POINT flag. + * Re-opening with OPEN_REPARSE_POINT is done in the case when rc is + * -EOPNOTSUPP. + */ + if (hdr->Status == STATUS_OBJECT_PATH_NOT_FOUND) + rc = -EOPNOTSUPP; + switch (rc) { case 0: rc = parse_create_response(data, cifs_sb, full_path, &out_iov[0]); From patchwork Tue Dec 31 22:35:13 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?q?Pali_Roh=C3=A1r?= X-Patchwork-Id: 13924008 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 2D0A01B4236; Tue, 31 Dec 2024 22:35:51 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1735684552; cv=none; b=CCpkj6urdyUO+YV2EmLr0jRsestOK6RcXv6It4FFkoEPqor6RQeWH+ZVA7FijcqdXjOCuatV4Y135rf9Mn/BzYOS5idGHRktKoCLMUbWoRwFaN9bC9pmoG7A8yXCyKKTMgB0HjQ6MBKQeiq/jgTX07acZoh/jAvyBJIVE1oPirE= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1735684552; c=relaxed/simple; bh=ox+e+7YGWz2v0UmWQWMAc9JFxQV71DFh1C6Wg9eekfk=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version:Content-Type; b=A9EO3A/8O5ADw7GkaINVy15gw/km7S9iKq/dkSdTT7MFIZEj+LWmnymUwTL6GPCktf77TMMgqw+Fn0wDC6FoJqS8xYXTYVw+JUF6U1z+OV6VKo/QfpUOC2BtMssgivHsGgtui+JtMNmVb0vUKn7SMdIi/duV1jMkq1dl95qG/xk= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=GfSZ6y9Q; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="GfSZ6y9Q" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 62E09C4CEDF; Tue, 31 Dec 2024 22:35:51 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1735684551; bh=ox+e+7YGWz2v0UmWQWMAc9JFxQV71DFh1C6Wg9eekfk=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=GfSZ6y9Q6zrAq01SItvosH9aNDm1C0ReHOedDEcXPTEyPvnAd4NC3zmmaAMT4m5o/ f/IdKBmNxdh7HpCIkF5G/5YQltHxltb4CbxeofywSPXGQx506rJZLibknCPbRNP+Oy G/RWJhSxgxJ3ezGE1Ixa5qdnyNDh60Hz/stPM+3RGyYXrTnDmAWUuaW8+4fmwIlWEw GdvNEdvkjjHnvc22e+O/D4rwerbThwJ2j/gBi9ffW1x4BLTG1ZMltxnsw/IxNU8c7F lKVL1cnbHfhslLcY2k0PDIpeHhE8jnHyun/Wpf7dhFR23F3xzOo5F7BI8SCbXg4kUW YWHSSfSY2Whmg== Received: by pali.im (Postfix) id 41937C2E; Tue, 31 Dec 2024 23:35:41 +0100 (CET) From: =?utf-8?q?Pali_Roh=C3=A1r?= To: Steve French , Paulo Alcantara Cc: linux-cifs@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [PATCH 4/5] cifs: Improve SMB2+ stat() to work also for paths in DELETE_PENDING state Date: Tue, 31 Dec 2024 23:35:13 +0100 Message-Id: <20241231223514.15595-4-pali@kernel.org> X-Mailer: git-send-email 2.39.5 In-Reply-To: <20241231223514.15595-1-pali@kernel.org> References: <20241231223514.15595-1-pali@kernel.org> Precedence: bulk X-Mailing-List: linux-cifs@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Paths in DELETE_PENDING state cannot be opened at all. So standard way of querying path attributes for this case is not possible. There is an alternative way how to query limited information about file over SMB2+ dialects without opening file itself. It is by opening the parent directory, querying specific child with filled search filer and asking for attributes for that child. Implement this fallback when standard case in smb2_query_path_info fails with STATUS_DELETE_PENDING error and stat was asked for path which is not top level one (because top level does not have parent directory at all). Signed-off-by: Pali Rohár --- fs/smb/client/cifsglob.h | 1 + fs/smb/client/smb2glob.h | 1 + fs/smb/client/smb2inode.c | 171 +++++++++++++++++++++++++++++++++++++- 3 files changed, 170 insertions(+), 3 deletions(-) diff --git a/fs/smb/client/cifsglob.h b/fs/smb/client/cifsglob.h index 06ad727e824b..1338b3473ef3 100644 --- a/fs/smb/client/cifsglob.h +++ b/fs/smb/client/cifsglob.h @@ -2329,6 +2329,7 @@ struct smb2_compound_vars { struct smb_rqst rqst[MAX_COMPOUND]; struct kvec open_iov[SMB2_CREATE_IOV_SIZE]; struct kvec qi_iov; + struct kvec qd_iov[SMB2_QUERY_DIRECTORY_IOV_SIZE]; struct kvec io_iov[SMB2_IOCTL_IOV_SIZE]; struct kvec si_iov[SMB2_SET_INFO_IOV_SIZE]; struct kvec close_iov; diff --git a/fs/smb/client/smb2glob.h b/fs/smb/client/smb2glob.h index 224495322a05..1cb219605e75 100644 --- a/fs/smb/client/smb2glob.h +++ b/fs/smb/client/smb2glob.h @@ -39,6 +39,7 @@ enum smb2_compound_ops { SMB2_OP_GET_REPARSE, SMB2_OP_QUERY_WSL_EA, SMB2_OP_OPEN_QUERY, + SMB2_OP_QUERY_DIRECTORY, }; /* Used when constructing chained read requests. */ diff --git a/fs/smb/client/smb2inode.c b/fs/smb/client/smb2inode.c index b6342b043073..1a8a2f83a3d9 100644 --- a/fs/smb/client/smb2inode.c +++ b/fs/smb/client/smb2inode.c @@ -190,6 +190,8 @@ static int smb2_compound_op(const unsigned int xid, struct cifs_tcon *tcon, int resp_buftype[MAX_COMPOUND]; struct smb2_create_rsp *create_rsp = NULL; struct smb2_query_info_rsp *qi_rsp = NULL; + struct smb2_query_directory_req *qd_rqst = NULL; + struct smb2_query_directory_rsp *qd_rsp = NULL; struct cifs_open_info_data *idata; struct inode *inode = NULL; int flags = 0; @@ -344,6 +346,39 @@ static int smb2_compound_op(const unsigned int xid, struct cifs_tcon *tcon, trace_smb3_posix_query_info_compound_enter(xid, ses->Suid, tcon->tid, full_path); break; + case SMB2_OP_QUERY_DIRECTORY: + rqst[num_rqst].rq_iov = &vars->qd_iov[0]; + rqst[num_rqst].rq_nvec = SMB2_QUERY_DIRECTORY_IOV_SIZE; + + rc = SMB2_query_directory_init(xid, + tcon, + server, + &rqst[num_rqst], + cfile ? cfile->fid.persistent_fid : COMPOUND_FID, + cfile ? cfile->fid.volatile_fid : COMPOUND_FID, + 0, + (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM) ? + SMB_FIND_FILE_ID_FULL_DIR_INFO : + SMB_FIND_FILE_FULL_DIRECTORY_INFO); + if (!rc) { + /* + * Change the default search wildcard pattern '*' + * to the requested file name stored in in_iov[i] + * and request for only one single entry. + */ + qd_rqst = rqst[num_rqst].rq_iov[0].iov_base; + qd_rqst->Flags |= SMB2_RETURN_SINGLE_ENTRY; + qd_rqst->FileNameLength = cpu_to_le16(in_iov[i].iov_len); + rqst[num_rqst].rq_iov[1] = in_iov[i]; + } + if (!rc && (!cfile || num_rqst > 1)) { + smb2_set_next_command(tcon, &rqst[num_rqst]); + smb2_set_related(&rqst[num_rqst]); + } else if (rc) { + goto finished; + } + num_rqst++; + break; case SMB2_OP_DELETE: trace_smb3_delete_enter(xid, ses->Suid, tcon->tid, full_path); break; @@ -716,6 +751,55 @@ static int smb2_compound_op(const unsigned int xid, struct cifs_tcon *tcon, trace_smb3_posix_query_info_compound_done(xid, ses->Suid, tcon->tid); break; + case SMB2_OP_QUERY_DIRECTORY: + if (rc == 0) { + qd_rsp = (struct smb2_query_directory_rsp *) + rsp_iov[i + 1].iov_base; + rc = smb2_validate_iov(le16_to_cpu(qd_rsp->OutputBufferOffset), + le32_to_cpu(qd_rsp->OutputBufferLength), + &rsp_iov[i + 1], + (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM) ? + sizeof(SEARCH_ID_FULL_DIR_INFO) : + sizeof(FILE_FULL_DIRECTORY_INFO)); + } + if (rc == 0) { + /* + * Both SEARCH_ID_FULL_DIR_INFO and FILE_FULL_DIRECTORY_INFO + * have same member offsets except the UniqueId and FileName. + */ + SEARCH_ID_FULL_DIR_INFO *si = (SEARCH_ID_FULL_DIR_INFO *)qd_rsp->Buffer; + idata = in_iov[i + 1].iov_base; + idata->fi.CreationTime = si->CreationTime; + idata->fi.LastAccessTime = si->LastAccessTime; + idata->fi.LastWriteTime = si->LastWriteTime; + idata->fi.ChangeTime = si->ChangeTime; + idata->fi.Attributes = si->ExtFileAttributes; + idata->fi.AllocationSize = si->AllocationSize; + idata->fi.EndOfFile = si->EndOfFile; + idata->fi.EASize = si->EaSize; + /* + * UniqueId is present only in struct SEARCH_ID_FULL_DIR_INFO. + * It is not present in struct FILE_FULL_DIRECTORY_INFO. + * struct SEARCH_ID_FULL_DIR_INFO was requested only when + * CIFS_MOUNT_SERVER_INUM is set. + */ + if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM) + idata->fi.IndexNumber = si->UniqueId; + if (le32_to_cpu(idata->fi.NumberOfLinks) == 0) + idata->fi.NumberOfLinks = cpu_to_le32(1); /* dummy value */ + idata->fi.DeletePending = 0; + idata->fi.Directory = !!(le32_to_cpu(si->ExtFileAttributes) & ATTR_DIRECTORY); + } + SMB2_query_directory_free(&rqst[num_rqst++]); + if (rc) + trace_smb3_query_dir_err(xid, + cfile ? cfile->fid.persistent_fid : COMPOUND_FID, + tcon->tid, ses->Suid, 0, 0, rc); + else + trace_smb3_query_dir_done(xid, + cfile ? cfile->fid.persistent_fid : COMPOUND_FID, + tcon->tid, ses->Suid, 0, 0); + break; case SMB2_OP_DELETE: if (rc) trace_smb3_delete_err(xid, ses->Suid, tcon->tid, rc); @@ -894,6 +978,7 @@ int smb2_query_path_info(const unsigned int xid, struct cifs_open_parms oparms; __u32 create_options = 0; struct cifsFileInfo *cfile; + struct cifsFileInfo *parent_cfile; struct cached_fid *cfid = NULL; struct smb2_hdr *hdr; struct kvec in_iov[3], out_iov[3] = {}; @@ -1085,9 +1170,9 @@ int smb2_query_path_info(const unsigned int xid, break; case -EREMOTE: break; - default: - if (hdr->Status != STATUS_OBJECT_NAME_INVALID) - break; + } + + if (hdr->Status == STATUS_OBJECT_NAME_INVALID) { rc2 = cifs_inval_name_dfs_link_error(xid, tcon, cifs_sb, full_path, &islink); if (rc2) { @@ -1096,6 +1181,86 @@ int smb2_query_path_info(const unsigned int xid, } if (islink) rc = -EREMOTE; + } else if (hdr->Status == STATUS_DELETE_PENDING && full_path[0]) { + /* + * If SMB2 OPEN/CREATE fails with STATUS_DELETE_PENDING error, + * it means that the path is in delete pending state and it is + * not possible to open it until some other client clears delete + * pending state or all other clients close all opened handles + * to that path. + * + * There is an alternative way how to query limited information + * about path which is in delete pending state still suitable + * for the stat() syscall. It is by opening the parent directory, + * querying specific child with filled search filer and asking + * for attributes for that child. + */ + + char *parent_path; + const char *basename; + __le16 *basename_utf16; + int basename_utf16_len; + + basename = strrchr(full_path, CIFS_DIR_SEP(cifs_sb)); + if (basename) { + parent_path = kstrndup(full_path, basename - full_path, GFP_KERNEL); + basename++; + } else { + parent_path = kstrdup("", GFP_KERNEL); + basename = full_path; + } + + if (!parent_path) { + rc = -ENOMEM; + goto out; + } + + basename_utf16 = cifs_convert_path_to_utf16(basename, cifs_sb); + if (!basename_utf16) { + kfree(parent_path); + rc = -ENOMEM; + goto out; + } + + basename_utf16_len = 2 * UniStrnlen((wchar_t *)basename_utf16, PATH_MAX); + +retry_query_directory: + for (i = 0; i < ARRAY_SIZE(out_buftype); i++) { + free_rsp_buf(out_buftype[i], out_iov[i].iov_base); + out_buftype[i] = 0; + out_iov[i].iov_base = NULL; + } + + num_cmds = 1; + cmds[0] = SMB2_OP_QUERY_DIRECTORY; + in_iov[0].iov_base = basename_utf16; + in_iov[0].iov_len = basename_utf16_len; + in_iov[1].iov_base = data; + in_iov[1].iov_len = sizeof(*data); + oparms = CIFS_OPARMS(cifs_sb, tcon, parent_path, FILE_READ_DATA, + FILE_OPEN, CREATE_NOT_FILE, ACL_NO_MODE); + cifs_get_readable_path(tcon, parent_path, &parent_cfile); + rc = smb2_compound_op(xid, tcon, cifs_sb, parent_path, + &oparms, in_iov, cmds, num_cmds, + parent_cfile, out_iov, out_buftype, NULL); + if (rc == -EOPNOTSUPP && (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM)) { + /* + * If querying of server inode numbers is not supported + * but is enabled, then disable it and try again. + */ + cifs_autodisable_serverino(cifs_sb); + goto retry_query_directory; + } + + kfree(parent_path); + kfree(basename_utf16); + + hdr = out_iov[0].iov_base; + if (!hdr || out_buftype[0] == CIFS_NO_BUFFER) + goto out; + + /* As we are in code path for STATUS_DELETE_PENDING, set DeletePending. */ + data->fi.DeletePending = 1; } out: From patchwork Tue Dec 31 22:35:14 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?q?Pali_Roh=C3=A1r?= X-Patchwork-Id: 13924009 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 54D1C1B423F; Tue, 31 Dec 2024 22:35:52 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1735684552; cv=none; b=YFzFJ7Jf1ilYR15/mXYtIi44CzY9FAkw/AjFFGXoWr0KRhQcHk0WTEhhOAKMd8FHLmBCSzZ9Ieqgwv1tRRtkMfC+jqh/0204tHkH95nVussuyhzsx8jV5ntznDFytsx1F21PL18M79Qkc90SQ+UeB4LM6FMXUyXAN/8UsmdK5gA= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1735684552; c=relaxed/simple; bh=5FhqwMpNh+GxOZdVjCIrqXAW5O5GZC6ckTBgwbfr7cQ=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version:Content-Type; b=Visbnz3414R07xcD//9U3fQXVyqokridGWuTrOMZF/X+955sA8PW0q03SIbLz8fhl1UhB2dwAwDZQFjTnfFqy85HERth9G7vANV1a5yCxfhisI1KnYLoC9ul6SxNTZWCszigU/phyRvCWs6ZKm3XZCm3warb0n3AFGJgrSBr2PE= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=V3QUSnri; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="V3QUSnri" Received: by smtp.kernel.org (Postfix) with ESMTPSA id AC3DFC4CEDD; Tue, 31 Dec 2024 22:35:51 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1735684552; bh=5FhqwMpNh+GxOZdVjCIrqXAW5O5GZC6ckTBgwbfr7cQ=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=V3QUSnrioqsKnghsxySA5s/sCe3DPnLFpVqdiwmzF29unI7Mb8STDfnWREgBzxfZP pCxx5/Io4a58SQC8tjeC+E1hetIuCPVtd6KCs2JU/wMsu47qQ4c2ABVSMIR0AzuFc7 aro6vUuMD1B8zeP8+O6fU2xAFa9clj38knV4oMlZGFavS94npQmXOUDclR5p2skJBd V644n3L1Bln4qyEJG3O3aPDDTnhmdyS/dMuXcyluNCqzaPBojXlSfAmBAO0T33gagx M9PL+DvOoJ03t0cd9FrjbkB+JRavr4rhKh8PG3rMQGRWHDbzS7dRYMlZWN8kTaFc/q ytEJEvW9tvc0g== Received: by pali.im (Postfix) id 682F9D12; Tue, 31 Dec 2024 23:35:41 +0100 (CET) From: =?utf-8?q?Pali_Roh=C3=A1r?= To: Steve French , Paulo Alcantara Cc: linux-cifs@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [PATCH 5/5] cifs: Improve detect_directory_symlink_target() function Date: Tue, 31 Dec 2024 23:35:14 +0100 Message-Id: <20241231223514.15595-5-pali@kernel.org> X-Mailer: git-send-email 2.39.5 In-Reply-To: <20241231223514.15595-1-pali@kernel.org> References: <20241231223514.15595-1-pali@kernel.org> Precedence: bulk X-Mailing-List: linux-cifs@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Function detect_directory_symlink_target() is not curruntly able to detect if the target path is directory in case the path is in the DELETE_PENDING state or the user has not granted FILE_READ_ATTRIBUTES permission on the path. This limitation is written in TODO comment. Resolve this problem by replacing code which determinate path type by the query_path_info() callback, which now is able to handle all these cases. Signed-off-by: Pali Rohár --- fs/smb/client/reparse.c | 75 ++++++++++++++--------------------------- 1 file changed, 25 insertions(+), 50 deletions(-) diff --git a/fs/smb/client/reparse.c b/fs/smb/client/reparse.c index 69efbcae6683..ad53b9b4a238 100644 --- a/fs/smb/client/reparse.c +++ b/fs/smb/client/reparse.c @@ -248,18 +248,16 @@ static int detect_directory_symlink_target(struct cifs_sb_info *cifs_sb, bool *directory) { char sep = CIFS_DIR_SEP(cifs_sb); - struct cifs_open_parms oparms; + struct cifs_open_info_data query_info; struct tcon_link *tlink; struct cifs_tcon *tcon; const char *basename; - struct cifs_fid fid; char *resolved_path; int full_path_len; int basename_len; int symname_len; char *path_sep; - __u32 oplock; - int open_rc; + int query_rc; /* * First do some simple check. If the original Linux symlink target ends @@ -282,7 +280,8 @@ static int detect_directory_symlink_target(struct cifs_sb_info *cifs_sb, if (symname[0] == '/') { cifs_dbg(FYI, "%s: cannot determinate if the symlink target path '%s' " - "is directory or not, creating '%s' as file symlink\n", + "is directory or not because path is absolute, " + "creating '%s' as file symlink\n", __func__, symname, full_path); return 0; } @@ -320,58 +319,34 @@ static int detect_directory_symlink_target(struct cifs_sb_info *cifs_sb, if (sep == '\\') convert_delimiter(path_sep, sep); + /* + * Query resolved SMB symlink path and check if it is a directory or not. + * Callback query_path_info() already handles cases when the server does + * not grant FILE_READ_ATTRIBUTES permission for object, or when server + * denies opening the object (e.g. because of DELETE_PENDING state). + */ tcon = tlink_tcon(tlink); - oparms = CIFS_OPARMS(cifs_sb, tcon, resolved_path, - FILE_READ_ATTRIBUTES, FILE_OPEN, 0, ACL_NO_MODE); - oparms.fid = &fid; - - /* Try to open as a directory (NOT_FILE) */ - oplock = 0; - oparms.create_options = cifs_create_options(cifs_sb, - CREATE_NOT_FILE | OPEN_REPARSE_POINT); - open_rc = tcon->ses->server->ops->open(xid, &oparms, &oplock, NULL); - if (open_rc == 0) { - /* Successful open means that the target path is definitely a directory. */ - *directory = true; - tcon->ses->server->ops->close(xid, tcon, &fid); - } else if (open_rc == -ENOTDIR) { - /* -ENOTDIR means that the target path is definitely a file. */ - *directory = false; - } else if (open_rc == -ENOENT) { + query_rc = tcon->ses->server->ops->query_path_info(xid, tcon, cifs_sb, + resolved_path, &query_info); + if (query_rc == 0) { + /* Query on path was successful, so just check for directory attr. */ + *directory = le32_to_cpu(query_info.fi.Attributes) & ATTR_DIRECTORY; + } else if (query_rc == -ENOENT) { /* -ENOENT means that the target path does not exist. */ cifs_dbg(FYI, "%s: symlink target path '%s' does not exist, " "creating '%s' as file symlink\n", __func__, symname, full_path); } else { - /* Try to open as a file (NOT_DIR) */ - oplock = 0; - oparms.create_options = cifs_create_options(cifs_sb, - CREATE_NOT_DIR | OPEN_REPARSE_POINT); - open_rc = tcon->ses->server->ops->open(xid, &oparms, &oplock, NULL); - if (open_rc == 0) { - /* Successful open means that the target path is definitely a file. */ - *directory = false; - tcon->ses->server->ops->close(xid, tcon, &fid); - } else if (open_rc == -EISDIR) { - /* -EISDIR means that the target path is definitely a directory. */ - *directory = true; - } else { - /* - * This code branch is called when we do not have a permission to - * open the resolved_path or some other client/process denied - * opening the resolved_path. - * - * TODO: Try to use ops->query_dir_first on the parent directory - * of resolved_path, search for basename of resolved_path and - * check if the ATTR_DIRECTORY is set in fi.Attributes. In some - * case this could work also when opening of the path is denied. - */ - cifs_dbg(FYI, - "%s: cannot determinate if the symlink target path '%s' " - "is directory or not, creating '%s' as file symlink\n", - __func__, symname, full_path); - } + /* + * This code branch is called when we do not have a permission to + * query the resolved_path or some other error occurred during query. + */ + cifs_dbg(FYI, + "%s: cannot determinate if the symlink target path '%s' " + "is directory or not because query path failed (%d), " + "creating '%s' as file symlink\n", + __func__, symname, query_rc, full_path); } kfree(resolved_path);