All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v4 0/3] ksmbd: bound smb_check_perm_dacl() ACE walks by DACL size
@ 2026-08-19  3:30 nanx95726
  2026-08-19  3:30 ` [PATCH v4 1/3] ksmbd: add KUnit test for the DACL walk boundary nanx95726
                   ` (3 more replies)
  0 siblings, 4 replies; 5+ messages in thread
From: nanx95726 @ 2026-08-19  3:30 UTC (permalink / raw)
  To: smfrench, linkinjeon, tom, senozhatsky, chenxiaosong; +Cc: linux-cifs, Hang Nan

From: Hang Nan <nanx95726@gmail.com>

Changes in v3:

- Update SMB_SERVER_KUNIT_TESTS help text.
- Moved kunit tests under fs/smb/server/tests/.

The following patch from v2 have already been merged into #ksmbd-for-next-next:
https://lore.kernel.org/linux-cifs/CAKYAXd9XHJSNfrFr+F8thNxFnXqGGcKpS1b1qR4DNuu82+j_VQ@mail.gmail.com/

Hang Nan (3):
  ksmbd: add KUnit test for the DACL walk boundary
  ksmbd: test smb_check_perm_dacl() DACL walk boundary
  ksmbd: test maximal-access DACL walk boundary

 fs/smb/server/Kconfig              |   2 +
 fs/smb/server/Makefile             |   1 +
 fs/smb/server/smbacl.c             |   2 +
 fs/smb/server/tests/Kconfig        |  15 ++
 fs/smb/server/tests/Makefile       |   4 +
 fs/smb/server/tests/smbacl_kunit.c | 301 +++++++++++++++++++++++++++++
 fs/smb/server/vfs.c                |   2 +
 7 files changed, 327 insertions(+)
 create mode 100644 fs/smb/server/tests/Kconfig
 create mode 100644 fs/smb/server/tests/Makefile
 create mode 100644 fs/smb/server/tests/smbacl_kunit.c

-- 
2.55.0


^ permalink raw reply	[flat|nested] 5+ messages in thread

* [PATCH v4 1/3] ksmbd: add KUnit test for the DACL walk boundary
  2026-08-19  3:30 [PATCH v4 0/3] ksmbd: bound smb_check_perm_dacl() ACE walks by DACL size nanx95726
@ 2026-08-19  3:30 ` nanx95726
  2026-08-19  3:30 ` [PATCH v4 2/3] ksmbd: test smb_check_perm_dacl() " nanx95726
                   ` (2 subsequent siblings)
  3 siblings, 0 replies; 5+ messages in thread
From: nanx95726 @ 2026-08-19  3:30 UTC (permalink / raw)
  To: smfrench, linkinjeon, tom, senozhatsky, chenxiaosong; +Cc: linux-cifs, Hang Nan

From: Hang Nan <nanx95726@gmail.com>

smb_check_perm_dacl() must stop walking ACEs at the DACL declared
size instead of using the enclosing security descriptor length.

Add the ksmbd KUnit test configuration and a semantic harness that
verifies a crafted access-granting ACE beyond the declared DACL size is
ignored.

Suggested-by: ChenXiaoSong <chenxiaosong@kylinos.cn>
Suggested-by: Namjae Jeon <linkinjeon@kernel.org>
Signed-off-by: Hang Nan <nanx95726@gmail.com>
Reviewed-by: ChenXiaoSong <chenxiaosong@kylinos.cn>
---
 fs/smb/server/Kconfig              |   2 +
 fs/smb/server/Makefile             |   1 +
 fs/smb/server/tests/Kconfig        |  15 +++
 fs/smb/server/tests/Makefile       |   4 +
 fs/smb/server/tests/smbacl_kunit.c | 170 +++++++++++++++++++++++++++++
 5 files changed, 192 insertions(+)
 create mode 100644 fs/smb/server/tests/Kconfig
 create mode 100644 fs/smb/server/tests/Makefile
 create mode 100644 fs/smb/server/tests/smbacl_kunit.c

diff --git a/fs/smb/server/Kconfig b/fs/smb/server/Kconfig
index 08d8b7a965a6..0d61a27990c6 100644
--- a/fs/smb/server/Kconfig
+++ b/fs/smb/server/Kconfig
@@ -72,3 +72,5 @@ config SMB_SERVER_KERBEROS5
 	bool "Support for Kerberos 5"
 	depends on SMB_SERVER
 	default y
+
+source "fs/smb/server/tests/Kconfig"
diff --git a/fs/smb/server/Makefile b/fs/smb/server/Makefile
index a3e9306055e8..9bc87695a53c 100644
--- a/fs/smb/server/Makefile
+++ b/fs/smb/server/Makefile
@@ -19,3 +19,4 @@ $(obj)/ksmbd_spnego_negtokentarg.asn1.o: $(obj)/ksmbd_spnego_negtokentarg.asn1.c
 
 ksmbd-$(CONFIG_SMB_SERVER_SMBDIRECT) += transport_rdma.o
 ksmbd-$(CONFIG_PROC_FS) += proc.o
+obj-$(CONFIG_SMB_SERVER_KUNIT_TESTS) += tests/
diff --git a/fs/smb/server/tests/Kconfig b/fs/smb/server/tests/Kconfig
new file mode 100644
index 000000000000..ad7a4e94ceaa
--- /dev/null
+++ b/fs/smb/server/tests/Kconfig
@@ -0,0 +1,15 @@
+# SPDX-License-Identifier: GPL-2.0-or-later
+# Copyright (C) 2026 Hang Nan <nanx95726@gmail.com>
+
+config SMB_SERVER_KUNIT_TESTS
+	tristate "KUnit tests for SMB3 server helpers" if !KUNIT_ALL_TESTS
+	depends on SMB_SERVER && SMB_KUNIT_TESTS && TMPFS_XATTR
+	default SMB_KUNIT_TESTS
+	help
+	  This builds the KUnit tests for ksmbd server helpers. The tests
+	  exercise internal server functionality and help detect regressions
+	  in server-side behavior. They are intended for kernel developers
+	  and are not suitable for production systems.
+
+	  For more information on KUnit and unit tests in the kernel,
+	  please read Documentation/dev-tools/kunit/index.rst.
diff --git a/fs/smb/server/tests/Makefile b/fs/smb/server/tests/Makefile
new file mode 100644
index 000000000000..8738ab0b0667
--- /dev/null
+++ b/fs/smb/server/tests/Makefile
@@ -0,0 +1,4 @@
+# SPDX-License-Identifier: GPL-2.0-or-later
+# Copyright (C) 2026 Hang Nan <nanx95726@gmail.com>
+
+obj-$(CONFIG_SMB_SERVER_KUNIT_TESTS) += smbacl_kunit.o
diff --git a/fs/smb/server/tests/smbacl_kunit.c b/fs/smb/server/tests/smbacl_kunit.c
new file mode 100644
index 000000000000..733c2fa92030
--- /dev/null
+++ b/fs/smb/server/tests/smbacl_kunit.c
@@ -0,0 +1,170 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * KUnit tests for ksmbd security descriptor (DACL) handling.
+ *
+ * Copyright (C) 2026 Hang Nan <nanx95726@gmail.com>
+ *
+ * The tests pin the DACL declared-size boundary in smb_check_perm_dacl():
+ *
+ * - ksmbd_dacl_walk_must_stop_at_declared_size: a pure semantic harness
+ *   that models the ACE walk.  Walking to the end of the enclosing
+ *   security descriptor (the pre-fix behaviour) selects an ACE that
+ *   sits beyond struct smb_acl::size; stopping at the declared DACL
+ *   size (the fixed behaviour) rejects it.
+ */
+
+#include <kunit/test.h>
+#include <linux/slab.h>
+
+#include "../smbacl.h"
+#include "../smb_common.h"
+
+struct ksmbd_acl_walk_result {
+	bool found;
+	bool allowed;
+	const struct smb_ace *selected;
+};
+
+static const struct smb_sid test_nonmatching_sid = {
+	1, 5, {0, 0, 0, 0, 0, 5},
+	{ cpu_to_le32(21), cpu_to_le32(1), cpu_to_le32(2),
+	  cpu_to_le32(3), cpu_to_le32(9999) }
+};
+
+/*
+ * S-1-22-1-0: the SID id_to_sid(0, SIDUNIX_USER) resolves to, i.e. what
+ * smb_check_perm_dacl() looks for when called with uid == 0.
+ */
+static const struct smb_sid test_owner_sid = {
+	1, 2, {0, 0, 0, 0, 0, 22},
+	{ cpu_to_le32(1), cpu_to_le32(0) }
+};
+
+static int test_compare_sids(const struct smb_sid *a, const struct smb_sid *b)
+{
+	int i;
+
+	if (a->revision != b->revision || a->num_subauth != b->num_subauth)
+		return 1;
+	for (i = 0; i < NUM_AUTHS; i++) {
+		if (a->authority[i] != b->authority[i])
+			return 1;
+	}
+	for (i = 0; i < a->num_subauth; i++) {
+		if (a->sub_auth[i] != b->sub_auth[i])
+			return 1;
+	}
+	return 0;
+}
+
+static u16 test_ace_size(const struct smb_sid *sid)
+{
+	return offsetof(struct smb_ace, sid) + CIFS_SID_BASE_SIZE +
+	       sid->num_subauth * sizeof(__le32);
+}
+
+static u16 fill_test_ace(struct smb_ace *ace, const struct smb_sid *sid,
+			 u32 access_req)
+{
+	u16 size = test_ace_size(sid);
+
+	ace->type = ACCESS_ALLOWED_ACE_TYPE;
+	ace->flags = 0;
+	ace->size = cpu_to_le16(size);
+	ace->access_req = cpu_to_le32(access_req);
+	memcpy(&ace->sid, sid, size - offsetof(struct smb_ace, sid));
+	return size;
+}
+
+static struct ksmbd_acl_walk_result test_walk_dacl(struct smb_acl *pdacl,
+						    int walk_boundary,
+						    const struct smb_sid *target,
+						    u32 requested)
+{
+	struct ksmbd_acl_walk_result result = {};
+	struct smb_ace *ace;
+	int aces_size;
+	int i;
+
+	ace = (struct smb_ace *)((char *)pdacl + sizeof(struct smb_acl));
+	aces_size = walk_boundary - sizeof(struct smb_acl);
+	for (i = 0; i < le16_to_cpu(pdacl->num_aces); i++) {
+		u16 ace_size;
+
+		if (aces_size < offsetof(struct smb_ace, sid) + CIFS_SID_BASE_SIZE)
+			break;
+		ace_size = le16_to_cpu(ace->size);
+		if (ace_size > aces_size ||
+		    ace_size < offsetof(struct smb_ace, sid) + CIFS_SID_BASE_SIZE)
+			break;
+		aces_size -= ace_size;
+
+		if (ace->sid.num_subauth > SID_MAX_SUB_AUTHORITIES ||
+		    ace_size < offsetof(struct smb_ace, sid) + CIFS_SID_BASE_SIZE +
+			       sizeof(__le32) * ace->sid.num_subauth)
+			break;
+
+		if (!test_compare_sids(target, &ace->sid)) {
+			result.found = true;
+			result.selected = ace;
+			result.allowed = !(requested & ~le32_to_cpu(ace->access_req));
+			return result;
+		}
+
+		ace = (struct smb_ace *)((char *)ace + ace_size);
+	}
+
+	return result;
+}
+
+static void ksmbd_dacl_walk_must_stop_at_declared_size(struct kunit *test)
+{
+	struct ksmbd_acl_walk_result declared, enclosing;
+	struct smb_acl *acl;
+	struct smb_ace *ace1, *fake;
+	u16 ace1_size, fake_size;
+	u16 pdacl_size;
+	u16 acl_size;
+
+	acl = kunit_kzalloc(test, 128, GFP_KERNEL);
+	KUNIT_ASSERT_NOT_NULL(test, acl);
+
+	acl->revision = cpu_to_le16(2);
+	acl->num_aces = cpu_to_le16(2);
+
+	ace1 = (struct smb_ace *)((char *)acl + sizeof(*acl));
+	ace1_size = fill_test_ace(ace1, &test_nonmatching_sid, 0);
+	fake = (struct smb_ace *)((char *)ace1 + ace1_size);
+	fake_size = fill_test_ace(fake, &test_owner_sid, FILE_READ_DATA);
+
+	pdacl_size = sizeof(*acl) + ace1_size;
+	acl_size = pdacl_size + fake_size;
+	acl->size = cpu_to_le16(pdacl_size);
+
+	declared = test_walk_dacl(acl, pdacl_size, &test_owner_sid,
+				  FILE_READ_DATA);
+	enclosing = test_walk_dacl(acl, acl_size, &test_owner_sid,
+				   FILE_READ_DATA);
+
+	KUNIT_EXPECT_FALSE(test, declared.found);
+	KUNIT_EXPECT_FALSE(test, declared.allowed);
+
+	/* Demonstrates that the buggy acl_size boundary selects fake ACE #2. */
+	KUNIT_EXPECT_TRUE(test, enclosing.found);
+	KUNIT_EXPECT_TRUE(test, enclosing.allowed);
+}
+
+static struct kunit_case ksmbd_smbacl_test_cases[] = {
+	KUNIT_CASE(ksmbd_dacl_walk_must_stop_at_declared_size),
+	{}
+};
+
+static struct kunit_suite ksmbd_smbacl_test_suite = {
+	.name = "ksmbd-smbacl",
+	.test_cases = ksmbd_smbacl_test_cases,
+};
+
+kunit_test_suite(ksmbd_smbacl_test_suite);
+
+MODULE_DESCRIPTION("KUnit tests for ksmbd smbacl helpers");
+MODULE_LICENSE("GPL");
-- 
2.55.0


^ permalink raw reply related	[flat|nested] 5+ messages in thread

* [PATCH v4 2/3] ksmbd: test smb_check_perm_dacl() DACL walk boundary
  2026-08-19  3:30 [PATCH v4 0/3] ksmbd: bound smb_check_perm_dacl() ACE walks by DACL size nanx95726
  2026-08-19  3:30 ` [PATCH v4 1/3] ksmbd: add KUnit test for the DACL walk boundary nanx95726
@ 2026-08-19  3:30 ` nanx95726
  2026-08-19  3:30 ` [PATCH v4 3/3] ksmbd: test maximal-access " nanx95726
  2026-08-20  0:45 ` [PATCH v4 0/3] ksmbd: bound smb_check_perm_dacl() ACE walks by DACL size Namjae Jeon
  3 siblings, 0 replies; 5+ messages in thread
From: nanx95726 @ 2026-08-19  3:30 UTC (permalink / raw)
  To: smfrench, linkinjeon, tom, senozhatsky, chenxiaosong; +Cc: linux-cifs, Hang Nan

From: Hang Nan <nanx95726@gmail.com>

Drive smb_check_perm_dacl() through ksmbd's NTACL xattr path with a
crafted descriptor whose second ACE is beyond the declared DACL size.

Verify that the out-of-boundary ACE is not selected and access remains
denied.

Suggested-by: ChenXiaoSong <chenxiaosong@kylinos.cn>
Signed-off-by: Hang Nan <nanx95726@gmail.com>
Reviewed-by: ChenXiaoSong <chenxiaosong@kylinos.cn>
---
 fs/smb/server/smbacl.c             |  2 +
 fs/smb/server/tests/smbacl_kunit.c | 90 ++++++++++++++++++++++++++++++
 fs/smb/server/vfs.c                |  2 +
 3 files changed, 94 insertions(+)

diff --git a/fs/smb/server/smbacl.c b/fs/smb/server/smbacl.c
index 8ad2e5a5cca8..5b2d46c09da7 100644
--- a/fs/smb/server/smbacl.c
+++ b/fs/smb/server/smbacl.c
@@ -7,6 +7,7 @@
  */
 
 #include <linux/fs.h>
+#include <kunit/visibility.h>
 #include <linux/slab.h>
 #include <linux/string.h>
 #include <linux/mnt_idmapping.h>
@@ -1652,6 +1653,7 @@ int smb_check_perm_dacl(struct ksmbd_conn *conn, const struct path *path,
 	kfree(pntsd);
 	return rc;
 }
+EXPORT_SYMBOL_IF_KUNIT(smb_check_perm_dacl);
 
 int set_info_sec(struct ksmbd_conn *conn, struct ksmbd_tree_connect *tcon,
 		 const struct path *path, struct smb_ntsd *pntsd, int ntsd_len,
diff --git a/fs/smb/server/tests/smbacl_kunit.c b/fs/smb/server/tests/smbacl_kunit.c
index 733c2fa92030..391b1f5d181c 100644
--- a/fs/smb/server/tests/smbacl_kunit.c
+++ b/fs/smb/server/tests/smbacl_kunit.c
@@ -11,13 +11,22 @@
  *   security descriptor (the pre-fix behaviour) selects an ACE that
  *   sits beyond struct smb_acl::size; stopping at the declared DACL
  *   size (the fixed behaviour) rejects it.
+ *
+ * - ksmbd_smb_check_perm_dacl_boundary: drives the real
+ *   smb_check_perm_dacl() with a descriptor stored through ksmbd's own
+ *   NTACL xattr path on a tmpfs file, and asserts that a post-boundary
+ *   ACE is not selected for a regular access check.
  */
 
 #include <kunit/test.h>
+#include <linux/fs.h>
+#include <linux/mm.h>
+#include <linux/shmem_fs.h>
 #include <linux/slab.h>
 
 #include "../smbacl.h"
 #include "../smb_common.h"
+#include "../vfs.h"
 
 struct ksmbd_acl_walk_result {
 	bool found;
@@ -154,8 +163,88 @@ static void ksmbd_dacl_walk_must_stop_at_declared_size(struct kunit *test)
 	KUNIT_EXPECT_TRUE(test, enclosing.allowed);
 }
 
+/*
+ * Build an NTSD whose DACL declares one ACE (pdacl->size) but actually
+ * contains two: the second ACE sits beyond the declared DACL boundary
+ * yet inside the enclosing security descriptor.  The trailing ACE applies
+ * to S-1-22-1-0, which smb_check_perm_dacl() looks for when uid is zero.
+ */
+static struct smb_ntsd *build_boundary_ntsd(struct kunit *test,
+					    const struct smb_sid *first_sid,
+					    u32 first_access,
+					    u32 trailing_access,
+					    int *ntsd_size)
+{
+	struct smb_ntsd *pntsd;
+	struct smb_acl *pdacl;
+	struct smb_ace *ace;
+	u16 first_size = test_ace_size(first_sid);
+	u16 trailing_size = test_ace_size(&test_owner_sid);
+
+	*ntsd_size = sizeof(struct smb_ntsd) + sizeof(struct smb_acl) +
+		     first_size + trailing_size;
+	pntsd = kunit_kzalloc(test, *ntsd_size, GFP_KERNEL);
+	if (!pntsd)
+		return NULL;
+
+	pntsd->revision = cpu_to_le16(SD_REVISION);
+	pntsd->type = cpu_to_le16(DACL_PRESENT);
+	pntsd->dacloffset = cpu_to_le32(sizeof(struct smb_ntsd));
+
+	pdacl = (struct smb_acl *)((char *)pntsd + sizeof(struct smb_ntsd));
+	pdacl->revision = cpu_to_le16(2);
+	pdacl->num_aces = cpu_to_le16(2);
+	pdacl->size = cpu_to_le16(sizeof(struct smb_acl) + first_size);
+
+	ace = (struct smb_ace *)((char *)pdacl + sizeof(struct smb_acl));
+	fill_test_ace(ace, first_sid, first_access);
+
+	ace = (struct smb_ace *)((char *)ace + first_size);
+	fill_test_ace(ace, &test_owner_sid, trailing_access);
+
+	return pntsd;
+}
+
+static void ksmbd_smb_check_perm_dacl_boundary_test(struct kunit *test)
+{
+	struct file *file;
+	struct smb_ntsd *pntsd;
+	__le32 daccess = cpu_to_le32(FILE_READ_DATA);
+	int ntsd_size, rc;
+
+	pntsd = build_boundary_ntsd(test, &test_nonmatching_sid, 0,
+				     FILE_READ_DATA, &ntsd_size);
+	KUNIT_ASSERT_NOT_NULL(test, pntsd);
+
+	file = shmem_file_setup("ksmbd-kunit-dacl", 0,
+				mk_vma_flags(VMA_NORESERVE_BIT));
+	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, file);
+
+	rc = ksmbd_vfs_set_sd_xattr(NULL, mnt_idmap(file->f_path.mnt),
+				    &file->f_path, pntsd, ntsd_size,
+				    false);
+	KUNIT_EXPECT_EQ(test, 0, rc);
+	if (rc)
+		goto out;
+
+	rc = smb_check_perm_dacl(NULL, &file->f_path, &daccess,
+				 cpu_to_le32(FILE_READ_DATA), 0, false);
+
+	/*
+	 * The post-boundary ACE (ACE #2, beyond pdacl->size) grants
+	 * FILE_READ_DATA to the caller's SID, but it must not be
+	 * selected: the walk stops at the declared DACL size and access
+	 * is denied.  Before the fix the walk used the enclosing
+	 * descriptor length, selected ACE #2 and returned 0.
+	 */
+	KUNIT_EXPECT_EQ(test, -EACCES, rc);
+out:
+	fput(file);
+}
+
 static struct kunit_case ksmbd_smbacl_test_cases[] = {
 	KUNIT_CASE(ksmbd_dacl_walk_must_stop_at_declared_size),
+	KUNIT_CASE(ksmbd_smb_check_perm_dacl_boundary_test),
 	{}
 };
 
@@ -168,3 +257,4 @@ kunit_test_suite(ksmbd_smbacl_test_suite);
 
 MODULE_DESCRIPTION("KUnit tests for ksmbd smbacl helpers");
 MODULE_LICENSE("GPL");
+MODULE_IMPORT_NS("EXPORTED_FOR_KUNIT_TESTING");
diff --git a/fs/smb/server/vfs.c b/fs/smb/server/vfs.c
index 286536f75144..536300f9eb8f 100644
--- a/fs/smb/server/vfs.c
+++ b/fs/smb/server/vfs.c
@@ -5,6 +5,7 @@
  */
 
 #include <crypto/sha2.h>
+#include <kunit/visibility.h>
 #include <linux/kernel.h>
 #include <linux/fs.h>
 #include <linux/filelock.h>
@@ -1668,6 +1669,7 @@ int ksmbd_vfs_set_sd_xattr(struct ksmbd_conn *conn,
 	kfree(def_smb_acl);
 	return rc;
 }
+EXPORT_SYMBOL_IF_KUNIT(ksmbd_vfs_set_sd_xattr);
 
 int ksmbd_vfs_get_sd_xattr(struct ksmbd_conn *conn,
 			   struct mnt_idmap *idmap,
-- 
2.55.0


^ permalink raw reply related	[flat|nested] 5+ messages in thread

* [PATCH v4 3/3] ksmbd: test maximal-access DACL walk boundary
  2026-08-19  3:30 [PATCH v4 0/3] ksmbd: bound smb_check_perm_dacl() ACE walks by DACL size nanx95726
  2026-08-19  3:30 ` [PATCH v4 1/3] ksmbd: add KUnit test for the DACL walk boundary nanx95726
  2026-08-19  3:30 ` [PATCH v4 2/3] ksmbd: test smb_check_perm_dacl() " nanx95726
@ 2026-08-19  3:30 ` nanx95726
  2026-08-20  0:45 ` [PATCH v4 0/3] ksmbd: bound smb_check_perm_dacl() ACE walks by DACL size Namjae Jeon
  3 siblings, 0 replies; 5+ messages in thread
From: nanx95726 @ 2026-08-19  3:30 UTC (permalink / raw)
  To: smfrench, linkinjeon, tom, senozhatsky, chenxiaosong; +Cc: linux-cifs, Hang Nan

From: Hang Nan <nanx95726@gmail.com>

Add a maximal-access variant of the smb_check_perm_dacl() boundary
test.  The in-boundary ACE grants read access, while a trailing ACE
beyond the declared DACL size grants write access.

Verify that maximal-access calculation includes the in-boundary
permission and ignores the trailing permission.

Suggested-by: ChenXiaoSong <chenxiaosong@kylinos.cn>
Signed-off-by: Hang Nan <nanx95726@gmail.com>
Reviewed-by: ChenXiaoSong <chenxiaosong@kylinos.cn>
---
 fs/smb/server/tests/smbacl_kunit.c | 47 ++++++++++++++++++++++++++++--
 1 file changed, 44 insertions(+), 3 deletions(-)

diff --git a/fs/smb/server/tests/smbacl_kunit.c b/fs/smb/server/tests/smbacl_kunit.c
index 391b1f5d181c..33496b4d31a3 100644
--- a/fs/smb/server/tests/smbacl_kunit.c
+++ b/fs/smb/server/tests/smbacl_kunit.c
@@ -12,10 +12,11 @@
  *   sits beyond struct smb_acl::size; stopping at the declared DACL
  *   size (the fixed behaviour) rejects it.
  *
- * - ksmbd_smb_check_perm_dacl_boundary: drives the real
+ * - ksmbd_smb_check_perm_dacl_boundary and
+ *   ksmbd_smb_check_perm_dacl_maximal_boundary: drive the real
  *   smb_check_perm_dacl() with a descriptor stored through ksmbd's own
- *   NTACL xattr path on a tmpfs file, and asserts that a post-boundary
- *   ACE is not selected for a regular access check.
+ *   NTACL xattr path on a tmpfs file, and assert that a post-boundary
+ *   ACE is not selected for either a regular or maximal access check.
  */
 
 #include <kunit/test.h>
@@ -242,9 +243,49 @@ static void ksmbd_smb_check_perm_dacl_boundary_test(struct kunit *test)
 	fput(file);
 }
 
+static void
+ksmbd_smb_check_perm_dacl_maximal_boundary_test(struct kunit *test)
+{
+	struct file *file;
+	struct smb_ntsd *pntsd;
+	__le32 daccess = FILE_MAXIMAL_ACCESS_LE;
+	int ntsd_size, rc;
+
+	/*
+	 * The in-boundary ACE grants read access.  The trailing ACE grants
+	 * write access, which must not be included in the maximal access mask.
+	 */
+	pntsd = build_boundary_ntsd(test, &test_owner_sid, FILE_READ_DATA,
+				     FILE_WRITE_DATA, &ntsd_size);
+	KUNIT_ASSERT_NOT_NULL(test, pntsd);
+
+	file = shmem_file_setup("ksmbd-kunit-dacl-maximal", 0,
+				mk_vma_flags(VMA_NORESERVE_BIT));
+	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, file);
+
+	rc = ksmbd_vfs_set_sd_xattr(NULL, mnt_idmap(file->f_path.mnt),
+				    &file->f_path, pntsd, ntsd_size,
+				    false);
+	KUNIT_EXPECT_EQ(test, 0, rc);
+	if (rc)
+		goto out;
+
+	rc = smb_check_perm_dacl(NULL, &file->f_path, &daccess,
+				 FILE_MAXIMAL_ACCESS_LE, 0, false);
+	KUNIT_EXPECT_EQ(test, 0, rc);
+	if (rc)
+		goto out;
+
+	KUNIT_EXPECT_TRUE(test, le32_to_cpu(daccess) & FILE_READ_DATA);
+	KUNIT_EXPECT_FALSE(test, le32_to_cpu(daccess) & FILE_WRITE_DATA);
+out:
+	fput(file);
+}
+
 static struct kunit_case ksmbd_smbacl_test_cases[] = {
 	KUNIT_CASE(ksmbd_dacl_walk_must_stop_at_declared_size),
 	KUNIT_CASE(ksmbd_smb_check_perm_dacl_boundary_test),
+	KUNIT_CASE(ksmbd_smb_check_perm_dacl_maximal_boundary_test),
 	{}
 };
 
-- 
2.55.0


^ permalink raw reply related	[flat|nested] 5+ messages in thread

* Re: [PATCH v4 0/3] ksmbd: bound smb_check_perm_dacl() ACE walks by DACL size
  2026-08-19  3:30 [PATCH v4 0/3] ksmbd: bound smb_check_perm_dacl() ACE walks by DACL size nanx95726
                   ` (2 preceding siblings ...)
  2026-08-19  3:30 ` [PATCH v4 3/3] ksmbd: test maximal-access " nanx95726
@ 2026-08-20  0:45 ` Namjae Jeon
  3 siblings, 0 replies; 5+ messages in thread
From: Namjae Jeon @ 2026-08-20  0:45 UTC (permalink / raw)
  To: nanx95726; +Cc: smfrench, tom, senozhatsky, chenxiaosong, linux-cifs

On Wed, Aug 19, 2026 at 12:30 PM <nanx95726@gmail.com> wrote:
>
> From: Hang Nan <nanx95726@gmail.com>
>
> Changes in v3:
>
> - Update SMB_SERVER_KUNIT_TESTS help text.
> - Moved kunit tests under fs/smb/server/tests/.
>
> The following patch from v2 have already been merged into #ksmbd-for-next-next:
> https://lore.kernel.org/linux-cifs/CAKYAXd9XHJSNfrFr+F8thNxFnXqGGcKpS1b1qR4DNuu82+j_VQ@mail.gmail.com/
>
> Hang Nan (3):
>   ksmbd: add KUnit test for the DACL walk boundary
>   ksmbd: test smb_check_perm_dacl() DACL walk boundary
>   ksmbd: test maximal-access DACL walk boundary
It’s a bit late to apply this to the 7.3 kernel. I will apply this
patchset to the 7.4 kernel.
Thanks!

^ permalink raw reply	[flat|nested] 5+ messages in thread

end of thread, other threads:[~2026-08-20  0:46 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-08-19  3:30 [PATCH v4 0/3] ksmbd: bound smb_check_perm_dacl() ACE walks by DACL size nanx95726
2026-08-19  3:30 ` [PATCH v4 1/3] ksmbd: add KUnit test for the DACL walk boundary nanx95726
2026-08-19  3:30 ` [PATCH v4 2/3] ksmbd: test smb_check_perm_dacl() " nanx95726
2026-08-19  3:30 ` [PATCH v4 3/3] ksmbd: test maximal-access " nanx95726
2026-08-20  0:45 ` [PATCH v4 0/3] ksmbd: bound smb_check_perm_dacl() ACE walks by DACL size Namjae Jeon

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.