* Re: [LTP] fs/acl: Add ACL_USER_OBJ permissions test
2026-05-31 12:45 [LTP] [RFC][PATCH 1/8] " Sachin Sant
@ 2026-06-01 6:48 ` linuxtestproject.agent
0 siblings, 0 replies; 17+ messages in thread
From: linuxtestproject.agent @ 2026-06-01 6:48 UTC (permalink / raw)
To: Sachin Sant; +Cc: ltp
Hi Sachin,
Thank you for this series. Converting the old monolithic tacl_xattr.sh to
modular C tests using the new LTP API is a clear improvement. The code
structure, helper library design, ACL logic, and test coverage are all solid.
I found two commit-message accuracy issues that need to be fixed before the
series can be applied.
---
[PATCH 7/8] fs/acl: Add extended attributes test
The commit subject and body both describe 6 test cases:
Add xattr_test01 test with 6 test cases to validate extended
attribute operations:
1. Set/get xattr on directory
2. Set/get xattr on regular file
3. List xattrs on directory
4. Remove xattr from file
5. Backup and restore xattrs
6. Verify xattr operations follow symlinks to target
But the actual implementation has only 2 sub-tests (.tcnt = 2):
case 0: test_xattr() — covers items 1, 2, 4
case 1: test_xattr_backup_restore() — covers item 5
Items 3 ("List xattrs on directory") and 6 ("Verify xattr operations
follow symlinks to target") are described in the commit message but are
not implemented anywhere in xattr_test01.c. There is no listxattr(2) call
and no symlink creation or xattr-through-symlink test in the file.
The test's own description block is accurate:
* This test validates:
* - Extended attributes set/get/remove operations
* - Extended attributes backup and restore operations
Please update the commit message to match the actual implementation.
Either drop the unimplemented items from the list (and say "2 test cases"),
or implement the missing cases.
---
[PATCH 8/8] fs/acl: Remove old shell-based ACL test
The replacement test summary in this commit is copied from (or refers to)
the inaccurate count above:
- xattr_test01: Extended attributes (6 tests)
xattr_test01 has .tcnt = 2, not 6. Update this line to:
- xattr_test01: Extended attributes (2 tests)
---
Verdict: Needs revision
---
Code review notes (no action required):
- acl_lib.h is clean: the static-inline helper design, SAFE_FORK/
SAFE_WAITPID usage, setgroups(0,NULL)+setgid+setuid ordering, and
_exit(errno) through WEXITSTATUS are all correct.
- All tst_test structs correctly set needs_root=1, mount_device=1,
forks_child=1, and list appropriate ACL-capable filesystems. The
needs_cmds guard for useradd/userdel is a nice touch.
- ACL semantics in every sub-test are correct: ACL_USER_OBJ is unaffected
by ACL_MASK; ACL_OTHER is likewise mask-exempt; ACL_USER/ACL_GROUP/
ACL_GROUP_OBJ are correctly restricted by the mask. The acl_inherit01
umask=0 + mode=0666 → 0444 path matches POSIX ACL inheritance rules.
- The Makefile wildcard build and runtest/fs entries are all consistent.
The old tacl_xattr.sh had no runtest entry, so no runtest removal is
needed.
Thanks,
LTP AI Reviewer
--
Mailing list info: https://lists.linux.it/listinfo/ltp
^ permalink raw reply [flat|nested] 17+ messages in thread
* [LTP] [PATCH v1 0/8] Convert shell-based ACL test (tacl_xattr.sh) to C
@ 2026-06-02 12:19 Sachin Sant
2026-06-02 12:19 ` [LTP] [PATCH v1 1/8] fs/acl: Add ACL_USER_OBJ permissions test Sachin Sant
` (7 more replies)
0 siblings, 8 replies; 17+ messages in thread
From: Sachin Sant @ 2026-06-02 12:19 UTC (permalink / raw)
To: ltp
This patch series converts the existing shell-based ACL
test (tacl_xattr.sh) to C implementation, providing better
integration with the LTP test framework and more precise
control over test execution.
Partially closes(convert tacl_xattr.sh to C)
https://github.com/linux-test-project/ltp/issues/1265
The conversion splits functionality into seven focused test files.
Patch 1/8 adds acl_user_obj01.c
Patch 2/8 adds acl_mask01.c
Patch 3/8 adds acl_other01.c
Patch 4/8 adds acl_inherit01.c
Patch 5/8 adds acl_file_ops01.c
Patch 6/8 adds acl_link01.c
Patch 7/8 adds xattr_test01.c
The code has been successfully tested on SLES (kernel 6.12)
and fedora (kernel 7.0) releases on ppc64le arch.
Test build is clean in various distros. CI build report at
https://github.com/sacsant/ltp/actions/runs/26816761775
Running the test in a distro missing acl development package
or acl library comes out clean with TCONF
root@linux:/opt/ltp# ./testcases/bin/acl_user_obj01
tst_test.c:1414: TCONF: libacl or ACL headers are not available
root@linux:/opt/ltp#
Sachin Sant (8):
fs/acl: Add ACL_USER_OBJ permissions test
fs/acl: Add ACL mask interaction tests
fs/acl: Add ACL_OTHER permissions test
fs/acl: Add default ACL inheritance test
fs/acl: Add chmod/chown ACL interaction tests
fs/acl: Add symlink ACL operations test
fs/acl: Add extended attributes test
fs/acl: Remove old shell-based ACL test
runtest/fs | 8 +
testcases/kernel/fs/acl/.gitignore | 7 +
testcases/kernel/fs/acl/Makefile | 10 +
testcases/kernel/fs/acl/acl_file_ops01.c | 302 +++++++++
testcases/kernel/fs/acl/acl_inherit01.c | 118 ++++
testcases/kernel/fs/acl/acl_lib.h | 348 ++++++++++
testcases/kernel/fs/acl/acl_link01.c | 130 ++++
testcases/kernel/fs/acl/acl_mask01.c | 283 ++++++++
testcases/kernel/fs/acl/acl_other01.c | 107 +++
testcases/kernel/fs/acl/acl_user_obj01.c | 115 ++++
testcases/kernel/fs/acl/tacl_xattr.sh | 807 -----------------------
testcases/kernel/fs/acl/xattr_test01.c | 349 ++++++++++
12 files changed, 1777 insertions(+), 807 deletions(-)
create mode 100644 testcases/kernel/fs/acl/.gitignore
create mode 100644 testcases/kernel/fs/acl/Makefile
create mode 100644 testcases/kernel/fs/acl/acl_file_ops01.c
create mode 100644 testcases/kernel/fs/acl/acl_inherit01.c
create mode 100644 testcases/kernel/fs/acl/acl_lib.h
create mode 100644 testcases/kernel/fs/acl/acl_link01.c
create mode 100644 testcases/kernel/fs/acl/acl_mask01.c
create mode 100644 testcases/kernel/fs/acl/acl_other01.c
create mode 100644 testcases/kernel/fs/acl/acl_user_obj01.c
delete mode 100755 testcases/kernel/fs/acl/tacl_xattr.sh
create mode 100644 testcases/kernel/fs/acl/xattr_test01.c
--
2.39.1
--
Mailing list info: https://lists.linux.it/listinfo/ltp
^ permalink raw reply [flat|nested] 17+ messages in thread
* [LTP] [PATCH v1 1/8] fs/acl: Add ACL_USER_OBJ permissions test
2026-06-02 12:19 [LTP] [PATCH v1 0/8] Convert shell-based ACL test (tacl_xattr.sh) to C Sachin Sant
@ 2026-06-02 12:19 ` Sachin Sant
2026-06-02 12:52 ` [LTP] " linuxtestproject.agent
2026-06-02 12:19 ` [LTP] [PATCH v1 2/8] fs/acl: Add ACL mask interaction tests Sachin Sant
` (6 subsequent siblings)
7 siblings, 1 reply; 17+ messages in thread
From: Sachin Sant @ 2026-06-02 12:19 UTC (permalink / raw)
To: ltp
Add acl_user_obj01 test to validate ACL_USER_OBJ (owner) permissions.
This test verifies that:
- Traditional permission bits restrict owner access
- ACL_USER_OBJ entries override permission bits
- Owner permissions work correctly with ACL entries
The test creates a directory with restrictive permissions, verifies
that file creation is denied, then sets ACL_USER_OBJ with write
permissions and confirms that file creation succeeds.
The patch also adds acl_lib.h containing shared helper functions
and definitions for ACL and extended attribute tests. This
library provides:
- Test user management (ltpuser1, ltpuser2, ltpuser3)
- ACL entry creation and manipulation helpers
- File operation helpers with different uid/gid
- Test path management and cleanup functions
- Extended attribute test definitions
Signed-off-by: Sachin Sant <sachinp@linux.ibm.com>
---
V1 changes:
- Use ACL_LIBS variable instead of hardcoded -lacl in Makefile
- Move ACL header includes inside feature guards in acl_lib.h
- Use HAVE_LIBACL guards in .c code
- Report TCONF when libacl is not available
- rfc link https://lore.kernel.org/ltp/477836fd-80c8-4168-bfe6-00b374bb2534@linux.ibm.com/T/#t
---
runtest/fs | 2 +
testcases/kernel/fs/acl/.gitignore | 1 +
testcases/kernel/fs/acl/Makefile | 10 +
testcases/kernel/fs/acl/acl_lib.h | 348 +++++++++++++++++++++++
testcases/kernel/fs/acl/acl_user_obj01.c | 115 ++++++++
5 files changed, 476 insertions(+)
create mode 100644 testcases/kernel/fs/acl/.gitignore
create mode 100644 testcases/kernel/fs/acl/Makefile
create mode 100644 testcases/kernel/fs/acl/acl_lib.h
create mode 100644 testcases/kernel/fs/acl/acl_user_obj01.c
diff --git a/runtest/fs b/runtest/fs
index 1d753e0dd..debedb9ae 100644
--- a/runtest/fs
+++ b/runtest/fs
@@ -87,3 +87,5 @@ binfmt_misc01 binfmt_misc01.sh
binfmt_misc02 binfmt_misc02.sh
squashfs01 squashfs01
+
+acl_user_obj01 acl_user_obj01
diff --git a/testcases/kernel/fs/acl/.gitignore b/testcases/kernel/fs/acl/.gitignore
new file mode 100644
index 000000000..d9c46db11
--- /dev/null
+++ b/testcases/kernel/fs/acl/.gitignore
@@ -0,0 +1 @@
+/acl_user_obj01
diff --git a/testcases/kernel/fs/acl/Makefile b/testcases/kernel/fs/acl/Makefile
new file mode 100644
index 000000000..e094549a7
--- /dev/null
+++ b/testcases/kernel/fs/acl/Makefile
@@ -0,0 +1,10 @@
+# SPDX-License-Identifier: GPL-2.0-or-later
+# Copyright (c) 2026 IBM
+
+top_srcdir ?= ../../../..
+
+include $(top_srcdir)/include/mk/testcases.mk
+
+LDLIBS += $(ACL_LIBS)
+
+include $(top_srcdir)/include/mk/generic_leaf_target.mk
diff --git a/testcases/kernel/fs/acl/acl_lib.h b/testcases/kernel/fs/acl/acl_lib.h
new file mode 100644
index 000000000..5044ce02e
--- /dev/null
+++ b/testcases/kernel/fs/acl/acl_lib.h
@@ -0,0 +1,348 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * Copyright (c) IBM, 2026
+ * Original shell test by Kai Zhao (ltcd3@cn.ibm.com)
+ * Converted to C by Sachin Sant <sachinp@linux.ibm.com>
+ *
+ * Common library for ACL and extended attribute tests
+ */
+
+#ifndef ACL_LIB_H
+#define ACL_LIB_H
+
+#include <pwd.h>
+#include <grp.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <string.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <sys/xattr.h>
+
+#include "config.h"
+#include "tst_test.h"
+#include "tst_safe_stdio.h"
+
+#ifdef HAVE_LIBACL
+#include <sys/acl.h>
+#include <acl/libacl.h>
+#endif
+
+#define MNTPOINT "mntpoint"
+#define TESTDIR MNTPOINT "/testdir"
+#define TESTFILE TESTDIR "/testfile"
+#define TESTSYMLINK TESTDIR "/testsymlink"
+#define XATTR_BACKUP_FILE MNTPOINT "/xattr_backup.txt"
+#define TEST_USER1 "ltpuser1"
+#define TEST_USER2 "ltpuser2"
+#define TEST_USER3 "ltpuser3"
+
+#define USER1_CREATED (1 << 0)
+#define USER2_CREATED (1 << 1)
+#define USER3_CREATED (1 << 2)
+
+/* Extended attribute test values */
+#define XATTR_TEST_DIR_NAME "user.test_attr"
+#define XATTR_TEST_DIR_VALUE "test_value"
+#define XATTR_TEST_DIR_SIZE 10
+#define XATTR_TEST_FILE_NAME "user.file_attr"
+#define XATTR_TEST_FILE_VALUE "file_val"
+#define XATTR_TEST_FILE_SIZE 8
+#define XATTR_TEST1_NAME "user.test1"
+#define XATTR_TEST1_VALUE "value1"
+#define XATTR_TEST1_SIZE 6
+#define XATTR_TEST2_NAME "user.test2"
+#define XATTR_TEST2_VALUE "value2"
+#define XATTR_TEST2_SIZE 6
+
+/* Global variables for test users */
+extern uid_t user1_uid, user2_uid, user3_uid;
+extern gid_t user1_gid, user2_gid, user3_gid;
+extern int users_created;
+
+/* Helper functions */
+static inline void reset_test_path(void)
+{
+ if (unlink(TESTSYMLINK) == -1 && errno != ENOENT)
+ tst_res(TWARN | TERRNO, "unlink(%s) failed", TESTSYMLINK);
+
+ if (unlink(TESTFILE) == -1 && errno != ENOENT)
+ tst_res(TWARN | TERRNO, "unlink(%s) failed", TESTFILE);
+
+ if (rmdir(TESTDIR) == -1 && errno != ENOENT)
+ tst_res(TWARN | TERRNO, "rmdir(%s) failed", TESTDIR);
+
+ SAFE_MKDIR(TESTDIR, 0755);
+ SAFE_CHOWN(TESTDIR, user1_uid, user1_gid);
+}
+
+static inline void cleanup_testfile(void)
+{
+ if (unlink(TESTFILE) == -1 && errno != ENOENT)
+ tst_res(TWARN | TERRNO, "unlink(%s) failed", TESTFILE);
+}
+
+#ifdef HAVE_LIBACL
+static inline void safe_acl_free(void *ptr)
+{
+ if (ptr && acl_free(ptr) == -1)
+ tst_res(TWARN | TERRNO, "acl_free failed");
+}
+
+static inline void safe_add_perm(acl_permset_t permset, acl_perm_t perm)
+{
+ if (acl_add_perm(permset, perm) == -1)
+ tst_brk(TBROK | TERRNO, "acl_add_perm failed");
+}
+
+static inline void safe_fill_permset(acl_permset_t permset, int perms)
+{
+ if (acl_clear_perms(permset) == -1)
+ tst_brk(TBROK | TERRNO, "acl_clear_perms failed");
+
+ if (perms & ACL_READ)
+ safe_add_perm(permset, ACL_READ);
+
+ if (perms & ACL_WRITE)
+ safe_add_perm(permset, ACL_WRITE);
+
+ if (perms & ACL_EXECUTE)
+ safe_add_perm(permset, ACL_EXECUTE);
+}
+
+/*
+ * Helper to clear ACL mask permissions.
+ * Finds the ACL_MASK entry in the given ACL and sets its permissions to 0.
+ */
+static inline void clear_acl_mask_perms(acl_t acl)
+{
+ acl_entry_t entry;
+ acl_permset_t permset;
+ acl_tag_t tag;
+ int i;
+
+ for (i = ACL_FIRST_ENTRY; ; i = ACL_NEXT_ENTRY) {
+ int ret = acl_get_entry(acl, i, &entry);
+
+ if (ret == -1)
+ tst_brk(TBROK | TERRNO, "acl_get_entry failed");
+
+ if (ret != 1)
+ break;
+
+ if (acl_get_tag_type(entry, &tag) == -1)
+ tst_brk(TBROK | TERRNO, "acl_get_tag_type failed");
+
+ if (tag != ACL_MASK)
+ continue;
+
+ if (acl_get_permset(entry, &permset) == -1)
+ tst_brk(TBROK | TERRNO, "acl_get_permset failed");
+
+ safe_fill_permset(permset, 0);
+
+ if (acl_set_permset(entry, permset) == -1)
+ tst_brk(TBROK | TERRNO, "acl_set_permset failed");
+
+ break;
+ }
+}
+
+/*
+ * Helper to add an ACL entry with optional qualifier.
+ * For ACL_USER and ACL_GROUP tags, qualifier must be provided.
+ * For other tags (ACL_USER_OBJ, ACL_GROUP_OBJ, ACL_OTHER, ACL_MASK),
+ * qualifier should be NULL.
+ */
+static inline void add_acl_entry_with_qualifier(acl_t acl, acl_tag_t tag,
+ const void *qualifier,
+ int perms)
+{
+ acl_entry_t entry;
+ acl_permset_t permset;
+
+ if (acl_create_entry(&acl, &entry) == -1)
+ tst_brk(TBROK | TERRNO, "acl_create_entry failed");
+
+ if (acl_set_tag_type(entry, tag) == -1)
+ tst_brk(TBROK | TERRNO, "acl_set_tag_type failed");
+
+ /* Set qualifier for ACL_USER and ACL_GROUP entries */
+ if (qualifier && acl_set_qualifier(entry, qualifier) == -1)
+ tst_brk(TBROK | TERRNO, "acl_set_qualifier failed");
+
+ if (acl_get_permset(entry, &permset) == -1)
+ tst_brk(TBROK | TERRNO, "acl_get_permset failed");
+
+ safe_fill_permset(permset, perms);
+
+ if (acl_set_permset(entry, permset) == -1)
+ tst_brk(TBROK | TERRNO, "acl_set_permset failed");
+}
+
+/* Convenience wrapper for entries without qualifiers */
+static inline void add_acl_entry(acl_t acl, acl_tag_t tag, int perms)
+{
+ add_acl_entry_with_qualifier(acl, tag, NULL, perms);
+}
+
+/* Convenience wrapper for named user entries */
+static inline void add_named_user_acl_entry(acl_t acl, uid_t uid, int perms)
+{
+ add_acl_entry_with_qualifier(acl, ACL_USER, &uid, perms);
+}
+
+/* Convenience wrapper for named group entries */
+static inline void add_named_group_acl_entry(acl_t acl, gid_t gid, int perms)
+{
+ add_acl_entry_with_qualifier(acl, ACL_GROUP, &gid, perms);
+}
+
+static inline void add_empty_acl_entry(acl_t acl, acl_tag_t tag)
+{
+ add_acl_entry(acl, tag, 0);
+}
+
+static inline void set_acl_file(const char *path, acl_type_t type, acl_t acl)
+{
+ if (acl_valid(acl) == -1)
+ tst_brk(TBROK | TERRNO, "acl_valid failed");
+
+ if (acl_set_file(path, type, acl) == -1)
+ tst_brk(TBROK | TERRNO, "acl_set_file(%s) failed", path);
+}
+#endif
+
+static inline int create_file_as(uid_t uid, gid_t gid, mode_t mode,
+ int use_umask, mode_t mask)
+{
+ pid_t pid;
+ int status;
+
+ pid = SAFE_FORK();
+ if (!pid) {
+ int fd, err;
+
+ if (setgroups(0, NULL) == -1) {
+ err = errno;
+ _exit(err);
+ }
+
+ if (setgid(gid) == -1) {
+ err = errno;
+ _exit(err);
+ }
+
+ if (setuid(uid) == -1) {
+ err = errno;
+ _exit(err);
+ }
+
+ if (use_umask)
+ umask(mask);
+
+ fd = open(TESTFILE, O_CREAT | O_WRONLY, mode);
+ if (fd >= 0) {
+ close(fd);
+ _exit(0);
+ }
+
+ err = errno;
+ _exit(err);
+ }
+
+ SAFE_WAITPID(pid, &status, 0);
+
+ if (!WIFEXITED(status))
+ tst_brk(TBROK, "Child terminated abnormally");
+
+ return WEXITSTATUS(status);
+}
+
+static inline int try_create_as(uid_t uid, gid_t gid, mode_t mode)
+{
+ return create_file_as(uid, gid, mode, 0, 0);
+}
+
+static inline int create_with_umask_as(uid_t uid, gid_t gid, mode_t mode,
+ mode_t mask)
+{
+ return create_file_as(uid, gid, mode, 1, mask);
+}
+
+static inline void create_user_if_needed(const char *username, int flag)
+{
+ struct passwd *pw;
+
+ errno = 0;
+ pw = getpwnam(username);
+ if (!pw && errno != 0)
+ tst_brk(TBROK | TERRNO, "getpwnam(%s) failed", username);
+
+ if (!pw) {
+ if (tst_cmd((const char *[]){"useradd", "-M", username, NULL},
+ NULL, NULL, TST_CMD_PASS_RETVAL) != 0)
+ tst_brk(TCONF, "Failed to create user %s", username);
+ users_created |= flag;
+ }
+}
+
+static inline void create_test_users(void)
+{
+ create_user_if_needed(TEST_USER1, USER1_CREATED);
+ create_user_if_needed(TEST_USER2, USER2_CREATED);
+ create_user_if_needed(TEST_USER3, USER3_CREATED);
+}
+
+static inline void init_test_users(void)
+{
+ struct passwd *pw;
+
+ create_test_users();
+
+ pw = SAFE_GETPWNAM(TEST_USER1);
+ user1_uid = pw->pw_uid;
+ user1_gid = pw->pw_gid;
+
+ pw = SAFE_GETPWNAM(TEST_USER2);
+ user2_uid = pw->pw_uid;
+ user2_gid = pw->pw_gid;
+
+ pw = SAFE_GETPWNAM(TEST_USER3);
+ user3_uid = pw->pw_uid;
+ user3_gid = pw->pw_gid;
+}
+
+static inline void cleanup_test_users(void)
+{
+ if (users_created & USER1_CREATED)
+ tst_cmd((const char *[]){"userdel", TEST_USER1, NULL},
+ NULL, NULL, TST_CMD_PASS_RETVAL);
+
+ if (users_created & USER2_CREATED)
+ tst_cmd((const char *[]){"userdel", TEST_USER2, NULL},
+ NULL, NULL, TST_CMD_PASS_RETVAL);
+
+ if (users_created & USER3_CREATED)
+ tst_cmd((const char *[]){"userdel", TEST_USER3, NULL},
+ NULL, NULL, TST_CMD_PASS_RETVAL);
+}
+
+static inline void cleanup_test_paths(void)
+{
+ if (unlink(TESTSYMLINK) == -1 && errno != ENOENT)
+ tst_res(TWARN | TERRNO, "unlink(%s) failed", TESTSYMLINK);
+
+ if (unlink(TESTFILE) == -1 && errno != ENOENT)
+ tst_res(TWARN | TERRNO, "unlink(%s) failed", TESTFILE);
+
+ if (unlink(XATTR_BACKUP_FILE) == -1 && errno != ENOENT)
+ tst_res(TWARN | TERRNO, "unlink(%s) failed",
+ XATTR_BACKUP_FILE);
+
+ if (rmdir(TESTDIR) == -1 && errno != ENOENT)
+ tst_res(TWARN | TERRNO, "rmdir(%s) failed", TESTDIR);
+}
+
+#endif /* ACL_LIB_H */
diff --git a/testcases/kernel/fs/acl/acl_user_obj01.c b/testcases/kernel/fs/acl/acl_user_obj01.c
new file mode 100644
index 000000000..4f34085e8
--- /dev/null
+++ b/testcases/kernel/fs/acl/acl_user_obj01.c
@@ -0,0 +1,115 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright (c) IBM, 2026
+ *
+ * Original shell test by Kai Zhao (ltcd3@cn.ibm.com)
+ * Converted to C by Sachin Sant <sachinp@linux.ibm.com>
+ */
+
+/*\
+ * Test ACL_USER_OBJ permissions.
+ *
+ * Verify that owner permissions (ACL_USER_OBJ) correctly control access
+ * to files and directories. The test validates that:
+ * - Traditional permission bits deny access when restrictive
+ * - ACL_USER_OBJ entries can grant access beyond permission bits
+ * - Owner permissions work independently of group and other permissions
+ */
+
+#include "acl_lib.h"
+
+uid_t user1_uid, user2_uid, user3_uid;
+gid_t user1_gid, user2_gid, user3_gid;
+int users_created = 0;
+
+#ifdef HAVE_LIBACL
+
+static void run(void)
+{
+ acl_t acl;
+ int err;
+
+ tst_res(TINFO, "Testing ACL_USER_OBJ permissions");
+ reset_test_path();
+
+ /* Test 1: Verify permission bits deny access */
+ SAFE_CHMOD(TESTDIR, 0500);
+
+ err = try_create_as(user1_uid, user1_gid, 0644);
+ if (!err) {
+ cleanup_testfile();
+ tst_res(TFAIL, "Created file without write permission");
+ return;
+ }
+
+ if (err != EACCES) {
+ errno = err;
+ tst_res(TFAIL | TERRNO, "Expected EACCES from owner create");
+ return;
+ }
+
+ tst_res(TPASS, "File creation denied by permission bits");
+
+ /* Test 2: Verify ACL_USER_OBJ grants access */
+ acl = acl_init(3);
+ if (!acl)
+ tst_brk(TBROK | TERRNO, "acl_init failed");
+
+ add_acl_entry(acl, ACL_USER_OBJ,
+ ACL_READ | ACL_WRITE | ACL_EXECUTE);
+ add_empty_acl_entry(acl, ACL_GROUP_OBJ);
+ add_empty_acl_entry(acl, ACL_OTHER);
+
+ set_acl_file(TESTDIR, ACL_TYPE_ACCESS, acl);
+ safe_acl_free(acl);
+
+ err = try_create_as(user1_uid, user1_gid, 0644);
+ if (err) {
+ errno = err;
+ tst_res(TFAIL | TERRNO,
+ "Failed to create file with ACL_USER_OBJ rwx");
+ return;
+ }
+
+ cleanup_testfile();
+ tst_res(TPASS, "ACL_USER_OBJ permissions work correctly");
+}
+
+static void setup(void)
+{
+ init_test_users();
+ reset_test_path();
+}
+
+static void cleanup(void)
+{
+ cleanup_test_paths();
+ cleanup_test_users();
+}
+
+static struct tst_test test = {
+ .test_all = run,
+ .setup = setup,
+ .cleanup = cleanup,
+ .needs_root = 1,
+ .mount_device = 1,
+ .mntpoint = MNTPOINT,
+ .forks_child = 1,
+ .filesystems = (struct tst_fs[]) {
+ {.type = "ext2", .mnt_data = "acl"},
+ {.type = "ext3", .mnt_data = "acl"},
+ {.type = "ext4", .mnt_data = "acl"},
+ {.type = "xfs"},
+ {.type = "btrfs"},
+ {}
+ },
+ .needs_cmds = (struct tst_cmd[]) {
+ {.cmd = "useradd"},
+ {.cmd = "userdel"},
+ {}
+ }
+};
+
+#else
+TST_TEST_TCONF("libacl or ACL headers are not available");
+#endif
--
2.39.1
--
Mailing list info: https://lists.linux.it/listinfo/ltp
^ permalink raw reply related [flat|nested] 17+ messages in thread
* [LTP] [PATCH v1 2/8] fs/acl: Add ACL mask interaction tests
2026-06-02 12:19 [LTP] [PATCH v1 0/8] Convert shell-based ACL test (tacl_xattr.sh) to C Sachin Sant
2026-06-02 12:19 ` [LTP] [PATCH v1 1/8] fs/acl: Add ACL_USER_OBJ permissions test Sachin Sant
@ 2026-06-02 12:19 ` Sachin Sant
2026-06-02 12:19 ` [LTP] [PATCH v1 3/8] fs/acl: Add ACL_OTHER permissions test Sachin Sant
` (5 subsequent siblings)
7 siblings, 0 replies; 17+ messages in thread
From: Sachin Sant @ 2026-06-02 12:19 UTC (permalink / raw)
To: ltp
Add acl_mask01 test with 3 test cases to validate ACL_MASK
interaction with named user and group entries:
1. ACL_USER with mask - Named user permissions restricted by mask
2. ACL_GROUP with mask - Named group permissions restricted by mask
3. ACL_GROUP_OBJ with mask - Group owner permissions restricted by mask
Each test verifies that:
- With mask set to rwx, access is granted
- With mask cleared (---), access is denied with EACCES
This validates that ACL_MASK correctly restricts permissions for
ACL_USER, ACL_GROUP, and ACL_GROUP_OBJ entries.
Signed-off-by: Sachin Sant <sachinp@linux.ibm.com>
---
V1 changes:
- Use HAVE_LIBACL guards in .c code
- Report TCONF when libacl is not available
- rfc link https://lore.kernel.org/ltp/477836fd-80c8-4168-bfe6-00b374bb2534@linux.ibm.com/T/#t
---
runtest/fs | 1 +
testcases/kernel/fs/acl/.gitignore | 1 +
testcases/kernel/fs/acl/acl_mask01.c | 283 +++++++++++++++++++++++++++
3 files changed, 285 insertions(+)
create mode 100644 testcases/kernel/fs/acl/acl_mask01.c
diff --git a/runtest/fs b/runtest/fs
index debedb9ae..b1202dc03 100644
--- a/runtest/fs
+++ b/runtest/fs
@@ -89,3 +89,4 @@ binfmt_misc02 binfmt_misc02.sh
squashfs01 squashfs01
acl_user_obj01 acl_user_obj01
+acl_mask01 acl_mask01
diff --git a/testcases/kernel/fs/acl/.gitignore b/testcases/kernel/fs/acl/.gitignore
index d9c46db11..bfcdee93d 100644
--- a/testcases/kernel/fs/acl/.gitignore
+++ b/testcases/kernel/fs/acl/.gitignore
@@ -1 +1,2 @@
/acl_user_obj01
+/acl_mask01
diff --git a/testcases/kernel/fs/acl/acl_mask01.c b/testcases/kernel/fs/acl/acl_mask01.c
new file mode 100644
index 000000000..bfcd4c285
--- /dev/null
+++ b/testcases/kernel/fs/acl/acl_mask01.c
@@ -0,0 +1,283 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright (c) IBM, 2026
+ *
+ * Original shell test by Kai Zhao (ltcd3@cn.ibm.com)
+ * Converted to C by Sachin Sant <sachinp@linux.ibm.com>
+ */
+
+/*\
+ * Test ACL mask interaction with named users and groups.
+ *
+ * Verify that ACL_MASK correctly restricts permissions for:
+ * - ACL_USER (named user) entries
+ * - ACL_GROUP (named group) entries
+ * - ACL_GROUP_OBJ (group owner) entries
+ *
+ * The mask acts as an upper bound on permissions for these entry types.
+ * Even if an entry grants full permissions, the mask can restrict them.
+ * ACL_USER_OBJ and ACL_OTHER are not affected by the mask.
+ *
+ * [Algorithm]
+ *
+ * For each entry type (ACL_USER, ACL_GROUP, ACL_GROUP_OBJ):
+ * 1. Set up ACL with full permissions for the entry
+ * 2. Set mask to allow full permissions (rwx)
+ * 3. Verify access is granted
+ * 4. Clear mask permissions (---)
+ * 5. Verify access is denied despite entry having full permissions
+ */
+
+#include "acl_lib.h"
+
+uid_t user1_uid, user2_uid, user3_uid;
+gid_t user1_gid, user2_gid, user3_gid;
+int users_created = 0;
+
+#ifdef HAVE_LIBACL
+
+/*
+ * Test ACL_USER permissions with mask.
+ * Named user permissions should be restricted by ACL_MASK.
+ */
+static void test_acl_user_with_mask(void)
+{
+ acl_t acl;
+ int err;
+
+ tst_res(TINFO, "Testing ACL_USER with mask");
+ reset_test_path();
+
+ acl = acl_init(5);
+ if (!acl)
+ tst_brk(TBROK | TERRNO, "acl_init failed");
+
+ add_acl_entry(acl, ACL_USER_OBJ,
+ ACL_READ | ACL_WRITE | ACL_EXECUTE);
+ add_named_user_acl_entry(acl, user3_uid,
+ ACL_READ | ACL_WRITE | ACL_EXECUTE);
+ add_empty_acl_entry(acl, ACL_GROUP_OBJ);
+ add_acl_entry(acl, ACL_MASK,
+ ACL_READ | ACL_WRITE | ACL_EXECUTE);
+ add_empty_acl_entry(acl, ACL_OTHER);
+
+ set_acl_file(TESTDIR, ACL_TYPE_ACCESS, acl);
+ safe_acl_free(acl);
+
+ err = try_create_as(user3_uid, user3_gid, 0644);
+ if (err) {
+ errno = err;
+ tst_res(TFAIL | TERRNO,
+ "ACL_USER with mask rwx should allow access");
+ return;
+ }
+
+ cleanup_testfile();
+
+ acl = acl_get_file(TESTDIR, ACL_TYPE_ACCESS);
+ if (!acl)
+ tst_brk(TBROK | TERRNO, "acl_get_file failed");
+
+ clear_acl_mask_perms(acl);
+ set_acl_file(TESTDIR, ACL_TYPE_ACCESS, acl);
+ safe_acl_free(acl);
+
+ err = try_create_as(user3_uid, user3_gid, 0644);
+ if (!err) {
+ cleanup_testfile();
+ tst_res(TFAIL, "ACL_USER with mask --- should deny access");
+ return;
+ }
+
+ if (err != EACCES) {
+ errno = err;
+ tst_res(TFAIL | TERRNO, "Expected EACCES from named user");
+ return;
+ }
+
+ tst_res(TPASS, "ACL_USER with mask works correctly");
+}
+
+/*
+ * Test ACL_GROUP permissions with mask.
+ * Named group permissions should be restricted by ACL_MASK.
+ */
+static void test_acl_group_with_mask(void)
+{
+ acl_t acl;
+ int err;
+
+ tst_res(TINFO, "Testing ACL_GROUP with mask");
+ reset_test_path();
+
+ acl = acl_init(5);
+ if (!acl)
+ tst_brk(TBROK | TERRNO, "acl_init failed");
+
+ add_acl_entry(acl, ACL_USER_OBJ,
+ ACL_READ | ACL_WRITE | ACL_EXECUTE);
+ add_empty_acl_entry(acl, ACL_GROUP_OBJ);
+ add_named_group_acl_entry(acl, user2_gid,
+ ACL_READ | ACL_WRITE | ACL_EXECUTE);
+ add_acl_entry(acl, ACL_MASK,
+ ACL_READ | ACL_WRITE | ACL_EXECUTE);
+ add_empty_acl_entry(acl, ACL_OTHER);
+
+ set_acl_file(TESTDIR, ACL_TYPE_ACCESS, acl);
+ safe_acl_free(acl);
+
+ err = try_create_as(user2_uid, user2_gid, 0644);
+ if (err) {
+ errno = err;
+ tst_res(TFAIL | TERRNO,
+ "ACL_GROUP with mask rwx should allow access");
+ return;
+ }
+
+ cleanup_testfile();
+
+ acl = acl_get_file(TESTDIR, ACL_TYPE_ACCESS);
+ if (!acl)
+ tst_brk(TBROK | TERRNO, "acl_get_file failed");
+
+ clear_acl_mask_perms(acl);
+ set_acl_file(TESTDIR, ACL_TYPE_ACCESS, acl);
+ safe_acl_free(acl);
+
+ err = try_create_as(user2_uid, user2_gid, 0644);
+ if (!err) {
+ cleanup_testfile();
+ tst_res(TFAIL, "ACL_GROUP with mask --- should deny access");
+ return;
+ }
+
+ if (err != EACCES) {
+ errno = err;
+ tst_res(TFAIL | TERRNO, "Expected EACCES from named group");
+ return;
+ }
+
+ tst_res(TPASS, "ACL_GROUP with mask works correctly");
+}
+
+/*
+ * Test ACL_GROUP_OBJ permissions with mask.
+ * Group owner permissions should be restricted by ACL_MASK.
+ */
+static void test_acl_group_obj_with_mask(void)
+{
+ acl_t acl;
+ int err;
+
+ tst_res(TINFO, "Testing ACL_GROUP_OBJ with mask");
+ reset_test_path();
+
+ SAFE_CHOWN(TESTDIR, user1_uid, user2_gid);
+
+ acl = acl_init(4);
+ if (!acl)
+ tst_brk(TBROK | TERRNO, "acl_init failed");
+
+ add_acl_entry(acl, ACL_USER_OBJ,
+ ACL_READ | ACL_WRITE | ACL_EXECUTE);
+ add_acl_entry(acl, ACL_GROUP_OBJ,
+ ACL_READ | ACL_WRITE | ACL_EXECUTE);
+ add_acl_entry(acl, ACL_MASK,
+ ACL_READ | ACL_WRITE | ACL_EXECUTE);
+ add_empty_acl_entry(acl, ACL_OTHER);
+
+ set_acl_file(TESTDIR, ACL_TYPE_ACCESS, acl);
+ safe_acl_free(acl);
+
+ err = try_create_as(user2_uid, user2_gid, 0644);
+ if (err) {
+ errno = err;
+ tst_res(TFAIL | TERRNO,
+ "ACL_GROUP_OBJ with mask rwx should allow access");
+ return;
+ }
+
+ cleanup_testfile();
+
+ acl = acl_get_file(TESTDIR, ACL_TYPE_ACCESS);
+ if (!acl)
+ tst_brk(TBROK | TERRNO, "acl_get_file failed");
+
+ clear_acl_mask_perms(acl);
+ set_acl_file(TESTDIR, ACL_TYPE_ACCESS, acl);
+ safe_acl_free(acl);
+
+ err = try_create_as(user2_uid, user2_gid, 0644);
+ if (!err) {
+ cleanup_testfile();
+ SAFE_CHOWN(TESTDIR, user1_uid, user1_gid);
+ tst_res(TFAIL,
+ "ACL_GROUP_OBJ with mask --- should deny access");
+ return;
+ }
+
+ if (err != EACCES) {
+ SAFE_CHOWN(TESTDIR, user1_uid, user1_gid);
+ errno = err;
+ tst_res(TFAIL | TERRNO, "Expected EACCES from group owner");
+ return;
+ }
+
+ SAFE_CHOWN(TESTDIR, user1_uid, user1_gid);
+ tst_res(TPASS, "ACL_GROUP_OBJ with mask works correctly");
+}
+
+static void setup(void)
+{
+ init_test_users();
+ reset_test_path();
+}
+
+static void cleanup(void)
+{
+ cleanup_test_paths();
+ cleanup_test_users();
+}
+
+static void run(unsigned int n)
+{
+ switch (n) {
+ case 0:
+ test_acl_user_with_mask();
+ break;
+ case 1:
+ test_acl_group_with_mask();
+ break;
+ case 2:
+ test_acl_group_obj_with_mask();
+ break;
+ }
+}
+
+static struct tst_test test = {
+ .test = run,
+ .tcnt = 3,
+ .setup = setup,
+ .cleanup = cleanup,
+ .needs_root = 1,
+ .mount_device = 1,
+ .mntpoint = MNTPOINT,
+ .forks_child = 1,
+ .filesystems = (struct tst_fs[]) {
+ {.type = "ext2", .mnt_data = "acl"},
+ {.type = "ext3", .mnt_data = "acl"},
+ {.type = "ext4", .mnt_data = "acl"},
+ {.type = "xfs"},
+ {.type = "btrfs"},
+ {}
+ },
+ .needs_cmds = (struct tst_cmd[]) {
+ {.cmd = "useradd"},
+ {.cmd = "userdel"},
+ {}
+ }
+};
+
+#else
+TST_TEST_TCONF("libacl or ACL headers are not available");
+#endif
--
2.39.1
--
Mailing list info: https://lists.linux.it/listinfo/ltp
^ permalink raw reply related [flat|nested] 17+ messages in thread
* [LTP] [PATCH v1 3/8] fs/acl: Add ACL_OTHER permissions test
2026-06-02 12:19 [LTP] [PATCH v1 0/8] Convert shell-based ACL test (tacl_xattr.sh) to C Sachin Sant
2026-06-02 12:19 ` [LTP] [PATCH v1 1/8] fs/acl: Add ACL_USER_OBJ permissions test Sachin Sant
2026-06-02 12:19 ` [LTP] [PATCH v1 2/8] fs/acl: Add ACL mask interaction tests Sachin Sant
@ 2026-06-02 12:19 ` Sachin Sant
2026-06-02 12:19 ` [LTP] [PATCH v1 4/8] fs/acl: Add default ACL inheritance test Sachin Sant
` (4 subsequent siblings)
7 siblings, 0 replies; 17+ messages in thread
From: Sachin Sant @ 2026-06-02 12:19 UTC (permalink / raw)
To: ltp
Add acl_other01 test to validate that ACL_OTHER permissions are
not affected by ACL_MASK.
The test verifies that:
- ACL_OTHER entry with rwx permissions allows access
- ACL_MASK set to --- does not restrict ACL_OTHER
- Users not matching owner, named users, or groups use ACL_OTHER
This confirms that ACL_MASK only affects ACL_USER, ACL_GROUP_OBJ,
and ACL_GROUP entries, but not ACL_OTHER.
Signed-off-by: Sachin Sant <sachinp@linux.ibm.com>
---
V1 changes:
- Use HAVE_LIBACL guards in .c code
- Report TCONF when libacl is not available
- rfc link https://lore.kernel.org/ltp/477836fd-80c8-4168-bfe6-00b374bb2534@linux.ibm.com/T/#t
---
runtest/fs | 1 +
testcases/kernel/fs/acl/.gitignore | 1 +
testcases/kernel/fs/acl/acl_other01.c | 107 ++++++++++++++++++++++++++
3 files changed, 109 insertions(+)
create mode 100644 testcases/kernel/fs/acl/acl_other01.c
diff --git a/runtest/fs b/runtest/fs
index b1202dc03..4a528e08e 100644
--- a/runtest/fs
+++ b/runtest/fs
@@ -90,3 +90,4 @@ squashfs01 squashfs01
acl_user_obj01 acl_user_obj01
acl_mask01 acl_mask01
+acl_other01 acl_other01
diff --git a/testcases/kernel/fs/acl/.gitignore b/testcases/kernel/fs/acl/.gitignore
index bfcdee93d..c3ec0fad3 100644
--- a/testcases/kernel/fs/acl/.gitignore
+++ b/testcases/kernel/fs/acl/.gitignore
@@ -1,2 +1,3 @@
/acl_user_obj01
/acl_mask01
+/acl_other01
diff --git a/testcases/kernel/fs/acl/acl_other01.c b/testcases/kernel/fs/acl/acl_other01.c
new file mode 100644
index 000000000..e16c9ac66
--- /dev/null
+++ b/testcases/kernel/fs/acl/acl_other01.c
@@ -0,0 +1,107 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright (c) IBM, 2026
+ *
+ * Original shell test by Kai Zhao (ltcd3@cn.ibm.com)
+ * Converted to C by Sachin Sant <sachinp@linux.ibm.com>
+ */
+
+/*\
+ * Test ACL_OTHER permissions.
+ *
+ * Verify that ACL_OTHER permissions work correctly and are not affected
+ * by ACL_MASK. The ACL_OTHER entry controls access for users who don't
+ * match any other ACL entry (not the owner, not in any named user entry,
+ * not in the owning group, and not in any named group entry).
+ *
+ * Unlike ACL_USER, ACL_GROUP, and ACL_GROUP_OBJ entries, ACL_OTHER
+ * permissions are not restricted by the ACL_MASK.
+ *
+ * [Algorithm]
+ *
+ * 1. Set up ACL with rwx permissions for ACL_OTHER
+ * 2. Set ACL_MASK to --- (no permissions)
+ * 3. Attempt file creation as a user matching ACL_OTHER
+ * 4. Verify access is granted despite restrictive mask
+ */
+
+#include "acl_lib.h"
+
+uid_t user1_uid, user2_uid, user3_uid;
+gid_t user1_gid, user2_gid, user3_gid;
+int users_created = 0;
+
+#ifdef HAVE_LIBACL
+
+static void run(void)
+{
+ acl_t acl;
+ int err;
+
+ tst_res(TINFO, "Testing ACL_OTHER permissions");
+ reset_test_path();
+
+ acl = acl_init(4);
+ if (!acl)
+ tst_brk(TBROK | TERRNO, "acl_init failed");
+
+ add_acl_entry(acl, ACL_USER_OBJ,
+ ACL_READ | ACL_WRITE | ACL_EXECUTE);
+ add_empty_acl_entry(acl, ACL_GROUP_OBJ);
+ add_empty_acl_entry(acl, ACL_MASK);
+ add_acl_entry(acl, ACL_OTHER,
+ ACL_READ | ACL_WRITE | ACL_EXECUTE);
+
+ set_acl_file(TESTDIR, ACL_TYPE_ACCESS, acl);
+ safe_acl_free(acl);
+
+ err = try_create_as(user2_uid, user2_gid, 0644);
+ if (err) {
+ errno = err;
+ tst_res(TFAIL | TERRNO,
+ "ACL_OTHER rwx should allow access despite mask");
+ return;
+ }
+
+ cleanup_testfile();
+ tst_res(TPASS, "ACL_OTHER not affected by mask");
+}
+
+static void setup(void)
+{
+ init_test_users();
+ reset_test_path();
+}
+
+static void cleanup(void)
+{
+ cleanup_test_paths();
+ cleanup_test_users();
+}
+
+static struct tst_test test = {
+ .test_all = run,
+ .setup = setup,
+ .cleanup = cleanup,
+ .needs_root = 1,
+ .mount_device = 1,
+ .mntpoint = MNTPOINT,
+ .forks_child = 1,
+ .filesystems = (struct tst_fs[]) {
+ {.type = "ext2", .mnt_data = "acl"},
+ {.type = "ext3", .mnt_data = "acl"},
+ {.type = "ext4", .mnt_data = "acl"},
+ {.type = "xfs"},
+ {.type = "btrfs"},
+ {}
+ },
+ .needs_cmds = (struct tst_cmd[]) {
+ {.cmd = "useradd"},
+ {.cmd = "userdel"},
+ {}
+ }
+};
+
+#else
+TST_TEST_TCONF("libacl or ACL headers are not available");
+#endif
--
2.39.1
--
Mailing list info: https://lists.linux.it/listinfo/ltp
^ permalink raw reply related [flat|nested] 17+ messages in thread
* [LTP] [PATCH v1 4/8] fs/acl: Add default ACL inheritance test
2026-06-02 12:19 [LTP] [PATCH v1 0/8] Convert shell-based ACL test (tacl_xattr.sh) to C Sachin Sant
` (2 preceding siblings ...)
2026-06-02 12:19 ` [LTP] [PATCH v1 3/8] fs/acl: Add ACL_OTHER permissions test Sachin Sant
@ 2026-06-02 12:19 ` Sachin Sant
2026-06-02 12:19 ` [LTP] [PATCH v1 5/8] fs/acl: Add chmod/chown ACL interaction tests Sachin Sant
` (3 subsequent siblings)
7 siblings, 0 replies; 17+ messages in thread
From: Sachin Sant @ 2026-06-02 12:19 UTC (permalink / raw)
To: ltp
Add acl_inherit01 test to validate default ACL inheritance from
parent directory to newly created files.
The test verifies that:
- Default ACLs set on a directory are inherited by new files
- New file permissions reflect the default ACL entries
- File created with umask 0 gets permissions from default ACL
This test sets default ACL with read-only permissions (r--r--r--)
on the parent directory, creates a new file with umask 0, and
verifies the file has 0444 permissions inherited from the default ACL.
Signed-off-by: Sachin Sant <sachinp@linux.ibm.com>
---
V1 changes:
- Use HAVE_LIBACL guards in .c code
- Report TCONF when libacl is not available
- rfc link https://lore.kernel.org/ltp/477836fd-80c8-4168-bfe6-00b374bb2534@linux.ibm.com/T/#t
---
runtest/fs | 1 +
testcases/kernel/fs/acl/.gitignore | 1 +
testcases/kernel/fs/acl/acl_inherit01.c | 118 ++++++++++++++++++++++++
3 files changed, 120 insertions(+)
create mode 100644 testcases/kernel/fs/acl/acl_inherit01.c
diff --git a/runtest/fs b/runtest/fs
index 4a528e08e..47a7f4104 100644
--- a/runtest/fs
+++ b/runtest/fs
@@ -91,3 +91,4 @@ squashfs01 squashfs01
acl_user_obj01 acl_user_obj01
acl_mask01 acl_mask01
acl_other01 acl_other01
+acl_inherit01 acl_inherit01
diff --git a/testcases/kernel/fs/acl/.gitignore b/testcases/kernel/fs/acl/.gitignore
index c3ec0fad3..bc03ba1fd 100644
--- a/testcases/kernel/fs/acl/.gitignore
+++ b/testcases/kernel/fs/acl/.gitignore
@@ -1,3 +1,4 @@
/acl_user_obj01
/acl_mask01
/acl_other01
+/acl_inherit01
diff --git a/testcases/kernel/fs/acl/acl_inherit01.c b/testcases/kernel/fs/acl/acl_inherit01.c
new file mode 100644
index 000000000..b9cf51525
--- /dev/null
+++ b/testcases/kernel/fs/acl/acl_inherit01.c
@@ -0,0 +1,118 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright (c) IBM, 2026
+ *
+ * Original shell test by Kai Zhao (ltcd3@cn.ibm.com)
+ * Converted to C by Sachin Sant <sachinp@linux.ibm.com>
+ */
+
+/*\
+ * Test default ACL inheritance.
+ *
+ * Verify that files created in a directory with default ACLs inherit
+ * those ACLs as their access ACLs. Default ACLs are only applicable
+ * to directories and define the access ACLs that files and subdirectories
+ * created within that directory will inherit.
+ *
+ * [Algorithm]
+ *
+ * 1. Set default ACL on parent directory with read-only permissions
+ * 2. Create a new file in that directory with umask 0
+ * 3. Verify the file inherits the default ACL as its access ACL
+ * 4. Check that file permissions match the inherited ACL (0444)
+ */
+
+#include "acl_lib.h"
+
+uid_t user1_uid, user2_uid, user3_uid;
+gid_t user1_gid, user2_gid, user3_gid;
+int users_created = 0;
+
+#ifdef HAVE_LIBACL
+
+static void run(void)
+{
+ acl_t acl, file_acl;
+ struct stat st;
+ int err;
+
+ tst_res(TINFO, "Testing default ACL inheritance");
+ reset_test_path();
+
+ acl = acl_init(3);
+ if (!acl)
+ tst_brk(TBROK | TERRNO, "acl_init failed");
+
+ add_acl_entry(acl, ACL_USER_OBJ, ACL_READ);
+ add_acl_entry(acl, ACL_GROUP_OBJ, ACL_READ);
+ add_acl_entry(acl, ACL_OTHER, ACL_READ);
+
+ set_acl_file(TESTDIR, ACL_TYPE_DEFAULT, acl);
+ safe_acl_free(acl);
+
+ err = create_with_umask_as(user1_uid, user1_gid, 0666, 0);
+ if (err) {
+ errno = err;
+ tst_res(TFAIL | TERRNO, "Failed to create test file");
+ return;
+ }
+
+ SAFE_STAT(TESTFILE, &st);
+
+ if ((st.st_mode & 0777) != 0444) {
+ tst_res(TFAIL,
+ "File permissions 0%o, expected 0444 from default ACL",
+ st.st_mode & 0777);
+ cleanup_testfile();
+ return;
+ }
+
+ file_acl = acl_get_file(TESTFILE, ACL_TYPE_ACCESS);
+ if (!file_acl) {
+ cleanup_testfile();
+ tst_brk(TBROK | TERRNO, "acl_get_file failed");
+ }
+
+ safe_acl_free(file_acl);
+ cleanup_testfile();
+ tst_res(TPASS, "Default ACL inheritance works correctly");
+}
+
+static void setup(void)
+{
+ init_test_users();
+ reset_test_path();
+}
+
+static void cleanup(void)
+{
+ cleanup_test_paths();
+ cleanup_test_users();
+}
+
+static struct tst_test test = {
+ .test_all = run,
+ .setup = setup,
+ .cleanup = cleanup,
+ .needs_root = 1,
+ .mount_device = 1,
+ .mntpoint = MNTPOINT,
+ .forks_child = 1,
+ .filesystems = (struct tst_fs[]) {
+ {.type = "ext2", .mnt_data = "acl"},
+ {.type = "ext3", .mnt_data = "acl"},
+ {.type = "ext4", .mnt_data = "acl"},
+ {.type = "xfs"},
+ {.type = "btrfs"},
+ {}
+ },
+ .needs_cmds = (struct tst_cmd[]) {
+ {.cmd = "useradd"},
+ {.cmd = "userdel"},
+ {}
+ }
+};
+
+#else
+TST_TEST_TCONF("libacl or ACL headers are not available");
+#endif
--
2.39.1
--
Mailing list info: https://lists.linux.it/listinfo/ltp
^ permalink raw reply related [flat|nested] 17+ messages in thread
* [LTP] [PATCH v1 5/8] fs/acl: Add chmod/chown ACL interaction tests
2026-06-02 12:19 [LTP] [PATCH v1 0/8] Convert shell-based ACL test (tacl_xattr.sh) to C Sachin Sant
` (3 preceding siblings ...)
2026-06-02 12:19 ` [LTP] [PATCH v1 4/8] fs/acl: Add default ACL inheritance test Sachin Sant
@ 2026-06-02 12:19 ` Sachin Sant
2026-06-02 12:19 ` [LTP] [PATCH v1 6/8] fs/acl: Add symlink ACL operations test Sachin Sant
` (2 subsequent siblings)
7 siblings, 0 replies; 17+ messages in thread
From: Sachin Sant @ 2026-06-02 12:19 UTC (permalink / raw)
To: ltp
Add acl_file_ops01 test with 2 test cases to validate chmod and
chown interaction with ACL entries:
1. chmod interaction - Verifies that chmod updates ACL_USER_OBJ,
ACL_GROUP_OBJ, and ACL_OTHER entries to match new permission bits.
Sets ACL with read-only, then chmod 0777, and confirms all three
ACL entries now have rwx permissions.
2. chown interaction - Verifies that chown changes file owner and
group without modifying ACL entry permissions. Sets ACL entries,
performs chown, and confirms ACL permissions are preserved.
These tests ensure chmod and chown work correctly with ACL-enabled files.
Signed-off-by: Sachin Sant <sachinp@linux.ibm.com>
---
V1 changes:
- Use HAVE_LIBACL guards in .c code
- Report TCONF when libacl is not available
- rfc link https://lore.kernel.org/ltp/477836fd-80c8-4168-bfe6-00b374bb2534@linux.ibm.com/T/#t
---
runtest/fs | 1 +
testcases/kernel/fs/acl/.gitignore | 1 +
testcases/kernel/fs/acl/acl_file_ops01.c | 302 +++++++++++++++++++++++
3 files changed, 304 insertions(+)
create mode 100644 testcases/kernel/fs/acl/acl_file_ops01.c
diff --git a/runtest/fs b/runtest/fs
index 47a7f4104..2364a8564 100644
--- a/runtest/fs
+++ b/runtest/fs
@@ -92,3 +92,4 @@ acl_user_obj01 acl_user_obj01
acl_mask01 acl_mask01
acl_other01 acl_other01
acl_inherit01 acl_inherit01
+acl_file_ops01 acl_file_ops01
diff --git a/testcases/kernel/fs/acl/.gitignore b/testcases/kernel/fs/acl/.gitignore
index bc03ba1fd..eb4b4a227 100644
--- a/testcases/kernel/fs/acl/.gitignore
+++ b/testcases/kernel/fs/acl/.gitignore
@@ -2,3 +2,4 @@
/acl_mask01
/acl_other01
/acl_inherit01
+/acl_file_ops01
diff --git a/testcases/kernel/fs/acl/acl_file_ops01.c b/testcases/kernel/fs/acl/acl_file_ops01.c
new file mode 100644
index 000000000..5caa6e536
--- /dev/null
+++ b/testcases/kernel/fs/acl/acl_file_ops01.c
@@ -0,0 +1,302 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright (c) IBM, 2026
+ *
+ * Original shell test by Kai Zhao (ltcd3@cn.ibm.com)
+ * Converted to C by Sachin Sant <sachinp@linux.ibm.com>
+ */
+
+/*\
+ * Test chmod and chown interaction with ACLs.
+ *
+ * Verify that standard file operations (chmod, chown) interact correctly
+ * with ACLs:
+ * - chmod should update ACL_USER_OBJ, ACL_GROUP_OBJ, and ACL_OTHER entries
+ * - chown should change file owner/group without affecting ACL entries
+ * - ACL permissions should be preserved after ownership changes
+ *
+ * [Algorithm]
+ *
+ * Test 1 - chmod interaction:
+ * 1. Create file with read-only ACL entries
+ * 2. Use chmod to set permissions to 0777
+ * 3. Verify ACL entries are updated to rwx for user, group, and other
+ *
+ * Test 2 - chown interaction:
+ * 1. Create file with specific ACL entries (rw for user, r for group/other)
+ * 2. Use chown to change owner and group
+ * 3. Verify ownership changed correctly
+ * 4. Verify ACL entries preserved their permissions after chown
+ */
+
+#include "acl_lib.h"
+
+uid_t user1_uid, user2_uid, user3_uid;
+gid_t user1_gid, user2_gid, user3_gid;
+int users_created = 0;
+
+#ifdef HAVE_LIBACL
+
+/*
+ * Test chmod interaction with ACLs.
+ * chmod should update ACL_USER_OBJ, ACL_GROUP_OBJ, and ACL_OTHER.
+ */
+static void test_chmod_acl(void)
+{
+ acl_t acl;
+ acl_entry_t entry;
+ acl_permset_t permset;
+ acl_tag_t tag;
+ int fd = -1;
+ int i;
+ int user_ok = 0, group_ok = 0, other_ok = 0;
+
+ tst_res(TINFO, "Testing chmod interaction with ACLs");
+ reset_test_path();
+
+ fd = SAFE_OPEN(TESTFILE, O_CREAT | O_WRONLY, 0644);
+ SAFE_CLOSE(fd);
+
+ acl = acl_init(3);
+ if (!acl) {
+ cleanup_testfile();
+ tst_brk(TBROK | TERRNO, "acl_init failed");
+ }
+
+ add_acl_entry(acl, ACL_USER_OBJ, ACL_READ);
+ add_acl_entry(acl, ACL_GROUP_OBJ, ACL_READ);
+ add_acl_entry(acl, ACL_OTHER, ACL_READ);
+ set_acl_file(TESTFILE, ACL_TYPE_ACCESS, acl);
+ safe_acl_free(acl);
+
+ SAFE_CHMOD(TESTFILE, 0777);
+
+ acl = acl_get_file(TESTFILE, ACL_TYPE_ACCESS);
+ if (!acl) {
+ cleanup_testfile();
+ tst_brk(TBROK | TERRNO, "acl_get_file failed");
+ }
+
+ for (i = ACL_FIRST_ENTRY; ; i = ACL_NEXT_ENTRY) {
+ int ret;
+
+ ret = acl_get_entry(acl, i, &entry);
+ if (ret == -1) {
+ safe_acl_free(acl);
+ cleanup_testfile();
+ tst_brk(TBROK | TERRNO, "acl_get_entry failed");
+ }
+
+ if (ret != 1)
+ break;
+
+ if (acl_get_tag_type(entry, &tag) == -1) {
+ safe_acl_free(acl);
+ cleanup_testfile();
+ tst_brk(TBROK | TERRNO,
+ "acl_get_tag_type failed");
+ }
+
+ if (acl_get_permset(entry, &permset) == -1) {
+ safe_acl_free(acl);
+ cleanup_testfile();
+ tst_brk(TBROK | TERRNO,
+ "acl_get_permset failed");
+ }
+
+ if (tag == ACL_USER_OBJ) {
+ if (acl_get_perm(permset, ACL_READ) == 1 &&
+ acl_get_perm(permset, ACL_WRITE) == 1 &&
+ acl_get_perm(permset, ACL_EXECUTE) == 1)
+ user_ok = 1;
+ } else if (tag == ACL_GROUP_OBJ) {
+ if (acl_get_perm(permset, ACL_READ) == 1 &&
+ acl_get_perm(permset, ACL_WRITE) == 1 &&
+ acl_get_perm(permset, ACL_EXECUTE) == 1)
+ group_ok = 1;
+ } else if (tag == ACL_OTHER) {
+ if (acl_get_perm(permset, ACL_READ) == 1 &&
+ acl_get_perm(permset, ACL_WRITE) == 1 &&
+ acl_get_perm(permset, ACL_EXECUTE) == 1)
+ other_ok = 1;
+ }
+ }
+
+ safe_acl_free(acl);
+ cleanup_testfile();
+
+ if (user_ok && group_ok && other_ok)
+ tst_res(TPASS, "chmod correctly updated ACL entries");
+ else
+ tst_res(TFAIL, "chmod did not update ACL entries correctly");
+}
+
+/*
+ * Test chown interaction with ACLs.
+ * chown should change file owner and group without affecting ACL entries.
+ */
+static void test_chown_acl(void)
+{
+ acl_t acl;
+ acl_entry_t entry;
+ acl_tag_t tag;
+ acl_permset_t permset;
+ struct stat st;
+ int fd = -1;
+ int i, found_user_obj = 0, found_group_obj = 0, found_other = 0;
+
+ tst_res(TINFO, "Testing chown interaction with ACLs");
+ reset_test_path();
+
+ fd = SAFE_OPEN(TESTFILE, O_CREAT | O_WRONLY, 0644);
+ SAFE_CLOSE(fd);
+
+ acl = acl_init(3);
+ if (!acl) {
+ cleanup_testfile();
+ tst_brk(TBROK | TERRNO, "acl_init failed");
+ }
+
+ add_acl_entry(acl, ACL_USER_OBJ, ACL_READ | ACL_WRITE);
+ add_acl_entry(acl, ACL_GROUP_OBJ, ACL_READ);
+ add_acl_entry(acl, ACL_OTHER, ACL_READ);
+ set_acl_file(TESTFILE, ACL_TYPE_ACCESS, acl);
+ safe_acl_free(acl);
+
+ SAFE_CHOWN(TESTFILE, user2_uid, user2_gid);
+
+ SAFE_STAT(TESTFILE, &st);
+
+ if (st.st_uid != user2_uid || st.st_gid != user2_gid) {
+ cleanup_testfile();
+ tst_res(TFAIL, "chown did not change owner/group correctly");
+ return;
+ }
+
+ /* Verify ACL entries are preserved after chown */
+ acl = acl_get_file(TESTFILE, ACL_TYPE_ACCESS);
+ if (!acl) {
+ cleanup_testfile();
+ tst_brk(TBROK | TERRNO, "acl_get_file failed");
+ }
+
+ for (i = ACL_FIRST_ENTRY; ; i = ACL_NEXT_ENTRY) {
+ int ret = acl_get_entry(acl, i, &entry);
+
+ if (ret == -1) {
+ safe_acl_free(acl);
+ cleanup_testfile();
+ tst_brk(TBROK | TERRNO, "acl_get_entry failed");
+ }
+
+ if (ret != 1)
+ break;
+
+ if (acl_get_tag_type(entry, &tag) == -1) {
+ safe_acl_free(acl);
+ cleanup_testfile();
+ tst_brk(TBROK | TERRNO, "acl_get_tag_type failed");
+ }
+
+ if (acl_get_permset(entry, &permset) == -1) {
+ safe_acl_free(acl);
+ cleanup_testfile();
+ tst_brk(TBROK | TERRNO, "acl_get_permset failed");
+ }
+
+ if (tag == ACL_USER_OBJ) {
+ found_user_obj = 1;
+ if (!acl_get_perm(permset, ACL_READ) ||
+ !acl_get_perm(permset, ACL_WRITE)) {
+ safe_acl_free(acl);
+ cleanup_testfile();
+ tst_res(TFAIL,
+ "ACL_USER_OBJ perms changed after chown");
+ return;
+ }
+ } else if (tag == ACL_GROUP_OBJ) {
+ found_group_obj = 1;
+ if (!acl_get_perm(permset, ACL_READ) ||
+ acl_get_perm(permset, ACL_WRITE)) {
+ safe_acl_free(acl);
+ cleanup_testfile();
+ tst_res(TFAIL,
+ "ACL_GROUP_OBJ perms changed after chown");
+ return;
+ }
+ } else if (tag == ACL_OTHER) {
+ found_other = 1;
+ if (!acl_get_perm(permset, ACL_READ) ||
+ acl_get_perm(permset, ACL_WRITE)) {
+ safe_acl_free(acl);
+ cleanup_testfile();
+ tst_res(TFAIL,
+ "ACL_OTHER perms changed after chown");
+ return;
+ }
+ }
+ }
+
+ safe_acl_free(acl);
+
+ if (!found_user_obj || !found_group_obj || !found_other) {
+ cleanup_testfile();
+ tst_res(TFAIL, "ACL entries missing after chown");
+ return;
+ }
+
+ cleanup_testfile();
+ tst_res(TPASS, "chown preserved ACL entries correctly");
+}
+
+static void setup(void)
+{
+ init_test_users();
+ reset_test_path();
+}
+
+static void cleanup(void)
+{
+ cleanup_test_paths();
+ cleanup_test_users();
+}
+
+static void run(unsigned int n)
+{
+ switch (n) {
+ case 0:
+ test_chmod_acl();
+ break;
+ case 1:
+ test_chown_acl();
+ break;
+ }
+}
+
+static struct tst_test test = {
+ .test = run,
+ .tcnt = 2,
+ .setup = setup,
+ .cleanup = cleanup,
+ .needs_root = 1,
+ .mount_device = 1,
+ .mntpoint = MNTPOINT,
+ .forks_child = 1,
+ .filesystems = (struct tst_fs[]) {
+ {.type = "ext2", .mnt_data = "acl"},
+ {.type = "ext3", .mnt_data = "acl"},
+ {.type = "ext4", .mnt_data = "acl"},
+ {.type = "xfs"},
+ {.type = "btrfs"},
+ {}
+ },
+ .needs_cmds = (struct tst_cmd[]) {
+ {.cmd = "useradd"},
+ {.cmd = "userdel"},
+ {}
+ }
+};
+
+#else
+TST_TEST_TCONF("libacl or ACL headers are not available");
+#endif
--
2.39.1
--
Mailing list info: https://lists.linux.it/listinfo/ltp
^ permalink raw reply related [flat|nested] 17+ messages in thread
* [LTP] [PATCH v1 6/8] fs/acl: Add symlink ACL operations test
2026-06-02 12:19 [LTP] [PATCH v1 0/8] Convert shell-based ACL test (tacl_xattr.sh) to C Sachin Sant
` (4 preceding siblings ...)
2026-06-02 12:19 ` [LTP] [PATCH v1 5/8] fs/acl: Add chmod/chown ACL interaction tests Sachin Sant
@ 2026-06-02 12:19 ` Sachin Sant
2026-06-02 12:19 ` [LTP] [PATCH v1 7/8] fs/acl: Add extended attributes test Sachin Sant
2026-06-02 12:19 ` [LTP] [PATCH v1 8/8] fs/acl: Remove old shell-based ACL test Sachin Sant
7 siblings, 0 replies; 17+ messages in thread
From: Sachin Sant @ 2026-06-02 12:19 UTC (permalink / raw)
To: ltp
Add acl_link01 test to validate that ACL operations on symlinks
follow the symlink to the target file.
The test verifies that:
- acl_set_file() on a symlink sets ACL on the target file
- acl_get_file() on a symlink retrieves ACL from the target file
- ACL operations follow symlinks rather than operating on the link itself
This test creates a file and symlink, sets ACL via the symlink path,
and retrieves ACL via the symlink path to confirm both operations
work on the target file. Returns TCONF if ACL on symlinks is not
supported by the filesystem.
Signed-off-by: Sachin Sant <sachinp@linux.ibm.com>
---
V1 changes:
- Use HAVE_LIBACL guards in .c code
- Report TCONF when libacl is not available
- rfc link https://lore.kernel.org/ltp/477836fd-80c8-4168-bfe6-00b374bb2534@linux.ibm.com/T/#t
---
runtest/fs | 1 +
testcases/kernel/fs/acl/.gitignore | 1 +
testcases/kernel/fs/acl/acl_link01.c | 130 +++++++++++++++++++++++++++
3 files changed, 132 insertions(+)
create mode 100644 testcases/kernel/fs/acl/acl_link01.c
diff --git a/runtest/fs b/runtest/fs
index 2364a8564..89d26e086 100644
--- a/runtest/fs
+++ b/runtest/fs
@@ -93,3 +93,4 @@ acl_mask01 acl_mask01
acl_other01 acl_other01
acl_inherit01 acl_inherit01
acl_file_ops01 acl_file_ops01
+acl_link01 acl_link01
diff --git a/testcases/kernel/fs/acl/.gitignore b/testcases/kernel/fs/acl/.gitignore
index eb4b4a227..4a071d516 100644
--- a/testcases/kernel/fs/acl/.gitignore
+++ b/testcases/kernel/fs/acl/.gitignore
@@ -3,3 +3,4 @@
/acl_other01
/acl_inherit01
/acl_file_ops01
+/acl_link01
diff --git a/testcases/kernel/fs/acl/acl_link01.c b/testcases/kernel/fs/acl/acl_link01.c
new file mode 100644
index 000000000..ff8a71ec7
--- /dev/null
+++ b/testcases/kernel/fs/acl/acl_link01.c
@@ -0,0 +1,130 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright (c) IBM, 2026
+ *
+ * Original shell test by Kai Zhao (ltcd3@cn.ibm.com)
+ * Converted to C by Sachin Sant <sachinp@linux.ibm.com>
+ */
+
+/*\
+ * Test ACL operations on symlinks.
+ *
+ * Verify that ACL operations on symlinks follow the symlink to the target
+ * file. When setting or getting ACLs through a symlink path, the operation
+ * should affect the target file, not the symlink itself.
+ *
+ * Note: Some filesystems may not support ACLs on symlinks and will return
+ * EOPNOTSUPP, which is treated as TCONF (test not applicable).
+ *
+ * [Algorithm]
+ *
+ * 1. Create a regular file
+ * 2. Create a symlink pointing to the file
+ * 3. Set ACL through the symlink path
+ * 4. Verify the ACL was set on the target file
+ * 5. Get ACL through the symlink path
+ * 6. Verify we can read the ACL through the symlink
+ */
+
+#include "acl_lib.h"
+
+uid_t user1_uid, user2_uid, user3_uid;
+gid_t user1_gid, user2_gid, user3_gid;
+int users_created = 0;
+
+#ifdef HAVE_LIBACL
+
+static void run(void)
+{
+ acl_t acl;
+ int fd = -1;
+ int err;
+
+ tst_res(TINFO, "Testing ACL operations on symlinks");
+ reset_test_path();
+
+ fd = SAFE_OPEN(TESTFILE, O_CREAT | O_WRONLY, 0644);
+ SAFE_CLOSE(fd);
+
+ SAFE_SYMLINK("testfile", TESTSYMLINK);
+
+ acl = acl_init(3);
+ if (!acl) {
+ cleanup_testfile();
+ tst_brk(TBROK | TERRNO, "acl_init failed");
+ }
+
+ add_acl_entry(acl, ACL_USER_OBJ, ACL_READ | ACL_WRITE);
+ add_acl_entry(acl, ACL_GROUP_OBJ, ACL_READ);
+ add_acl_entry(acl, ACL_OTHER, ACL_READ);
+
+ err = acl_set_file(TESTSYMLINK, ACL_TYPE_ACCESS, acl);
+ if (err == -1) {
+ safe_acl_free(acl);
+ if (unlink(TESTSYMLINK) == -1)
+ tst_res(TWARN | TERRNO, "unlink symlink failed");
+ cleanup_testfile();
+ if (errno == EOPNOTSUPP) {
+ tst_res(TCONF,
+ "ACL on symlinks not supported");
+ return;
+ }
+ tst_brk(TBROK | TERRNO, "acl_set_file on symlink failed");
+ }
+
+ safe_acl_free(acl);
+
+ acl = acl_get_file(TESTSYMLINK, ACL_TYPE_ACCESS);
+ if (!acl) {
+ if (unlink(TESTSYMLINK) == -1)
+ tst_res(TWARN | TERRNO, "unlink symlink failed");
+ cleanup_testfile();
+ tst_brk(TBROK | TERRNO, "acl_get_file on symlink failed");
+ }
+
+ safe_acl_free(acl);
+
+ if (unlink(TESTSYMLINK) == -1)
+ tst_res(TWARN | TERRNO, "unlink symlink failed");
+ cleanup_testfile();
+ tst_res(TPASS, "Symlink ACL operations work correctly");
+}
+
+static void setup(void)
+{
+ init_test_users();
+ reset_test_path();
+}
+
+static void cleanup(void)
+{
+ cleanup_test_paths();
+ cleanup_test_users();
+}
+
+static struct tst_test test = {
+ .test_all = run,
+ .setup = setup,
+ .cleanup = cleanup,
+ .needs_root = 1,
+ .mount_device = 1,
+ .mntpoint = MNTPOINT,
+ .forks_child = 1,
+ .filesystems = (struct tst_fs[]) {
+ {.type = "ext2", .mnt_data = "acl"},
+ {.type = "ext3", .mnt_data = "acl"},
+ {.type = "ext4", .mnt_data = "acl"},
+ {.type = "xfs"},
+ {.type = "btrfs"},
+ {}
+ },
+ .needs_cmds = (struct tst_cmd[]) {
+ {.cmd = "useradd"},
+ {.cmd = "userdel"},
+ {}
+ }
+};
+
+#else
+TST_TEST_TCONF("libacl or ACL headers are not available");
+#endif
--
2.39.1
--
Mailing list info: https://lists.linux.it/listinfo/ltp
^ permalink raw reply related [flat|nested] 17+ messages in thread
* [LTP] [PATCH v1 7/8] fs/acl: Add extended attributes test
2026-06-02 12:19 [LTP] [PATCH v1 0/8] Convert shell-based ACL test (tacl_xattr.sh) to C Sachin Sant
` (5 preceding siblings ...)
2026-06-02 12:19 ` [LTP] [PATCH v1 6/8] fs/acl: Add symlink ACL operations test Sachin Sant
@ 2026-06-02 12:19 ` Sachin Sant
2026-06-02 12:19 ` [LTP] [PATCH v1 8/8] fs/acl: Remove old shell-based ACL test Sachin Sant
7 siblings, 0 replies; 17+ messages in thread
From: Sachin Sant @ 2026-06-02 12:19 UTC (permalink / raw)
To: ltp
Add xattr_test01 implementing extended attributes testing
- Test xattr set/get/remove operations on files and directories
- Test xattr backup and restore functionality
- Support multiple filesystems (ext2/3/4, xfs, btrfs)
- Update runtest/fs to include xattr_test01
- Update .gitignore for new test binary
Signed-off-by: Sachin Sant <sachinp@linux.ibm.com>
---
V1 changes:
- Updated commit message to reflect the actual implementation.
- rfc link https://lore.kernel.org/ltp/477836fd-80c8-4168-bfe6-00b374bb2534@linux.ibm.com/T/#t
---
runtest/fs | 1 +
testcases/kernel/fs/acl/.gitignore | 1 +
testcases/kernel/fs/acl/xattr_test01.c | 349 +++++++++++++++++++++++++
3 files changed, 351 insertions(+)
create mode 100644 testcases/kernel/fs/acl/xattr_test01.c
diff --git a/runtest/fs b/runtest/fs
index 89d26e086..6787b099d 100644
--- a/runtest/fs
+++ b/runtest/fs
@@ -94,3 +94,4 @@ acl_other01 acl_other01
acl_inherit01 acl_inherit01
acl_file_ops01 acl_file_ops01
acl_link01 acl_link01
+xattr_test01 xattr_test01
diff --git a/testcases/kernel/fs/acl/.gitignore b/testcases/kernel/fs/acl/.gitignore
index 4a071d516..62ccd0457 100644
--- a/testcases/kernel/fs/acl/.gitignore
+++ b/testcases/kernel/fs/acl/.gitignore
@@ -4,3 +4,4 @@
/acl_inherit01
/acl_file_ops01
/acl_link01
+/xattr_test01
diff --git a/testcases/kernel/fs/acl/xattr_test01.c b/testcases/kernel/fs/acl/xattr_test01.c
new file mode 100644
index 000000000..e3a0684e5
--- /dev/null
+++ b/testcases/kernel/fs/acl/xattr_test01.c
@@ -0,0 +1,349 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright (c) IBM, 2026
+ *
+ * Original shell test by Kai Zhao (ltcd3@cn.ibm.com)
+ * Converted to C by Sachin Sant <sachinp@linux.ibm.com>
+ */
+
+/*\
+ * Test Extended Attributes (xattr).
+ *
+ * Some filesystems require explicit user_xattr mount options,
+ * while others (e.g. xfs and btrfs) provide these features without
+ * mount options.
+ *
+ * This test validates:
+ * - Extended attributes set/get/remove operations
+ * - Extended attributes backup and restore operations
+ *
+ * The test creates test users to validate xattr behavior across
+ * different user contexts.
+ *
+ * [Algorithm]
+ *
+ * 1. Set extended attributes on directories and files
+ * 2. Verify attributes can be retrieved correctly
+ * 3. Test attribute removal
+ * 4. Create backup of extended attributes to a file
+ * 5. Remove original attributes
+ * 6. Restore attributes from backup file
+ * 7. Verify restored attributes match original values
+ */
+
+#include "acl_lib.h"
+
+uid_t user1_uid, user2_uid, user3_uid;
+gid_t user1_gid, user2_gid, user3_gid;
+int users_created = 0;
+
+/*
+ * Test extended attributes.
+ * Set, get, and remove extended attributes on files and directories.
+ */
+static void test_xattr(void)
+{
+ char value[256];
+ ssize_t size;
+ int fd = -1;
+ int file_created = 0;
+
+ tst_res(TINFO, "Testing extended attributes");
+ reset_test_path();
+
+ TST_EXP_PASS_SILENT(setxattr(TESTDIR, XATTR_TEST_DIR_NAME, XATTR_TEST_DIR_VALUE,
+ XATTR_TEST_DIR_SIZE, 0));
+ if (!TST_PASS) {
+ if (TST_ERR == EOPNOTSUPP) {
+ tst_res(TCONF, "Extended attributes not supported");
+ return;
+ }
+ tst_res(TFAIL, "setxattr on directory failed");
+ return;
+ }
+
+ TST_EXP_POSITIVE(getxattr(TESTDIR, XATTR_TEST_DIR_NAME, value, sizeof(value)));
+ if (!TST_PASS)
+ goto cleanup_dir_xattr;
+
+ size = TST_RET;
+
+ if (size != XATTR_TEST_DIR_SIZE ||
+ memcmp(value, XATTR_TEST_DIR_VALUE, XATTR_TEST_DIR_SIZE) != 0) {
+ tst_res(TFAIL, "getxattr returned wrong directory value");
+ goto cleanup_dir_xattr;
+ }
+
+ fd = SAFE_OPEN(TESTFILE, O_CREAT | O_WRONLY, 0644);
+ SAFE_CLOSE(fd);
+ file_created = 1;
+
+ TST_EXP_PASS_SILENT(setxattr(TESTFILE, XATTR_TEST_FILE_NAME, XATTR_TEST_FILE_VALUE,
+ XATTR_TEST_FILE_SIZE, 0));
+ if (!TST_PASS) {
+ if (TST_ERR == EOPNOTSUPP) {
+ tst_res(TCONF, "Extended attributes not supported");
+ goto cleanup_file_and_dir;
+ }
+ tst_res(TFAIL, "setxattr on file failed");
+ goto cleanup_file_and_dir;
+ }
+
+ TST_EXP_POSITIVE(getxattr(TESTFILE, XATTR_TEST_FILE_NAME, value, sizeof(value)));
+ if (!TST_PASS)
+ goto cleanup_file_and_dir;
+
+ size = TST_RET;
+
+ if (size != XATTR_TEST_FILE_SIZE ||
+ memcmp(value, XATTR_TEST_FILE_VALUE, XATTR_TEST_FILE_SIZE) != 0) {
+ tst_res(TFAIL, "getxattr returned wrong file value");
+ goto cleanup_file_and_dir;
+ }
+
+ TST_EXP_PASS(removexattr(TESTFILE, XATTR_TEST_FILE_NAME));
+ if (!TST_PASS)
+ goto cleanup_file_and_dir;
+
+ TST_EXP_FAIL(getxattr(TESTFILE, XATTR_TEST_FILE_NAME, value, sizeof(value)),
+ ENODATA, "getxattr after removal");
+ if (!TST_PASS)
+ goto cleanup_file_and_dir;
+
+ tst_res(TPASS, "Extended attributes work correctly");
+
+cleanup_file_and_dir:
+ if (file_created)
+ cleanup_testfile();
+cleanup_dir_xattr:
+ if (removexattr(TESTDIR, XATTR_TEST_DIR_NAME) == -1 &&
+ errno != ENODATA)
+ tst_res(TWARN | TERRNO, "removexattr failed");
+}
+
+#define XATTR_BACKUP_TEST_COUNT 2
+
+/*
+ * Helper function to cleanup test xattrs.
+ */
+static inline void cleanup_test_xattrs(void)
+{
+ if (removexattr(TESTFILE, XATTR_TEST1_NAME) == -1 &&
+ errno != ENODATA)
+ tst_res(TWARN | TERRNO, "removexattr XATTR_TEST1_NAME failed");
+ if (removexattr(TESTFILE, XATTR_TEST2_NAME) == -1 &&
+ errno != ENODATA)
+ tst_res(TWARN | TERRNO, "removexattr XATTR_TEST2_NAME failed");
+}
+
+/*
+ * Test extended attributes backup and restore.
+ * Extended attributes should be preserved through backup/restore.
+ */
+static void test_xattr_backup_restore(void)
+{
+ char value[256];
+ char line[512];
+ char attr_name[256];
+ char attr_value[256];
+ ssize_t size;
+ size_t name_len, value_len;
+ int fd = -1;
+ FILE *fp = NULL;
+ int restored_count = 0;
+ int backup_created = 0;
+
+ tst_res(TINFO, "Testing extended attributes backup and restore");
+ reset_test_path();
+
+ fd = SAFE_OPEN(TESTFILE, O_CREAT | O_WRONLY, 0644);
+ SAFE_CLOSE(fd);
+
+ TST_EXP_PASS_SILENT(setxattr(TESTFILE, XATTR_TEST1_NAME, XATTR_TEST1_VALUE,
+ XATTR_TEST1_SIZE, 0));
+ if (!TST_PASS) {
+ cleanup_testfile();
+ if (TST_ERR == EOPNOTSUPP) {
+ tst_res(TCONF, "Extended attributes not supported");
+ return;
+ }
+ tst_res(TFAIL, "setxattr failed");
+ return;
+ }
+
+ TST_EXP_PASS(setxattr(TESTFILE, XATTR_TEST2_NAME, XATTR_TEST2_VALUE,
+ XATTR_TEST2_SIZE, 0));
+ if (!TST_PASS)
+ goto cleanup_xattrs;
+
+ fp = SAFE_FOPEN(XATTR_BACKUP_FILE, "w");
+ backup_created = 1;
+
+ if (fprintf(fp, "# file: %s\n", TESTFILE) < 0) {
+ tst_res(TFAIL | TERRNO, "fprintf failed");
+ goto cleanup_backup;
+ }
+ if (fprintf(fp, "%s=\"%s\"\n", XATTR_TEST1_NAME,
+ XATTR_TEST1_VALUE) < 0) {
+ tst_res(TFAIL | TERRNO, "fprintf failed");
+ goto cleanup_backup;
+ }
+ if (fprintf(fp, "%s=\"%s\"\n", XATTR_TEST2_NAME,
+ XATTR_TEST2_VALUE) < 0) {
+ tst_res(TFAIL | TERRNO, "fprintf failed");
+ goto cleanup_backup;
+ }
+ SAFE_FCLOSE(fp);
+ fp = NULL;
+
+ /* Remove xattrs to simulate loss */
+ cleanup_test_xattrs();
+
+ /* Restore from backup file */
+ fp = SAFE_FOPEN(XATTR_BACKUP_FILE, "r");
+ while (fgets(line, sizeof(line), fp)) {
+ char *p, *q;
+
+ if (line[0] == '#' || line[0] == '\n')
+ continue;
+
+ /* Parse: attr_name="attr_value" */
+ p = strchr(line, '=');
+ if (!p)
+ continue;
+
+ /* Safe copy of attribute name with length check */
+ name_len = p - line;
+
+ if (name_len >= sizeof(attr_name)) {
+ tst_res(TWARN, "Attribute name too long, skipping");
+ continue;
+ }
+ memcpy(attr_name, line, name_len);
+ attr_name[name_len] = '\0';
+
+ p++;
+ if (*p != '"')
+ continue;
+ p++;
+
+ q = strchr(p, '"');
+ if (!q)
+ continue;
+
+ /* Safe copy of attribute value with length check */
+ value_len = q - p;
+
+ if (value_len >= sizeof(attr_value)) {
+ tst_res(TWARN, "Attribute value too long, skipping");
+ continue;
+ }
+ memcpy(attr_value, p, value_len);
+ attr_value[value_len] = '\0';
+
+ /* Restore the xattr */
+ TST_EXP_PASS_SILENT(setxattr(TESTFILE, attr_name, attr_value,
+ value_len, 0));
+ if (!TST_PASS) {
+ tst_res(TFAIL, "setxattr restore failed for %s", attr_name);
+ goto cleanup_backup;
+ }
+ restored_count++;
+ }
+ SAFE_FCLOSE(fp);
+ fp = NULL;
+
+ if (restored_count != XATTR_BACKUP_TEST_COUNT) {
+ tst_res(TFAIL, "Expected %d xattrs restored, got %d",
+ XATTR_BACKUP_TEST_COUNT, restored_count);
+ goto cleanup_backup;
+ }
+
+ /* Verify restored xattrs */
+ TST_EXP_POSITIVE(getxattr(TESTFILE, XATTR_TEST1_NAME, value, sizeof(value)));
+ if (!TST_PASS)
+ goto cleanup_backup;
+
+ size = TST_RET;
+ if (size != XATTR_TEST1_SIZE ||
+ memcmp(value, XATTR_TEST1_VALUE, XATTR_TEST1_SIZE) != 0) {
+ tst_res(TFAIL,
+ "Extended attribute %s restore verification failed",
+ XATTR_TEST1_NAME);
+ goto cleanup_backup;
+ }
+
+ TST_EXP_POSITIVE(getxattr(TESTFILE, XATTR_TEST2_NAME, value, sizeof(value)));
+ if (!TST_PASS)
+ goto cleanup_backup;
+
+ size = TST_RET;
+ if (size != XATTR_TEST2_SIZE ||
+ memcmp(value, XATTR_TEST2_VALUE, XATTR_TEST2_SIZE) != 0) {
+ tst_res(TFAIL,
+ "Extended attribute %s restore verification failed",
+ XATTR_TEST2_NAME);
+ goto cleanup_backup;
+ }
+
+ tst_res(TPASS, "Extended attributes backup/restore work correctly");
+
+cleanup_backup:
+ if (fp)
+ SAFE_FCLOSE(fp);
+ if (backup_created) {
+ if (unlink(XATTR_BACKUP_FILE) == -1)
+ tst_res(TWARN | TERRNO, "unlink backup file failed");
+ }
+cleanup_xattrs:
+ cleanup_test_xattrs();
+ cleanup_testfile();
+}
+
+static void setup(void)
+{
+ init_test_users();
+ reset_test_path();
+}
+
+static void cleanup(void)
+{
+ cleanup_test_paths();
+ cleanup_test_users();
+}
+
+static void run(unsigned int n)
+{
+ switch (n) {
+ case 0:
+ test_xattr();
+ break;
+ case 1:
+ test_xattr_backup_restore();
+ break;
+ }
+}
+
+static struct tst_test test = {
+ .test = run,
+ .tcnt = 2,
+ .setup = setup,
+ .cleanup = cleanup,
+ .needs_root = 1,
+ .mount_device = 1,
+ .mntpoint = MNTPOINT,
+ .forks_child = 1,
+ .filesystems = (struct tst_fs[]) {
+ {.type = "ext2", .mnt_data = "user_xattr"},
+ {.type = "ext3", .mnt_data = "user_xattr"},
+ {.type = "ext4", .mnt_data = "user_xattr"},
+ {.type = "xfs"},
+ {.type = "btrfs"},
+ {}
+ },
+ .needs_cmds = (struct tst_cmd[]) {
+ {.cmd = "useradd"},
+ {.cmd = "userdel"},
+ {}
+ }
+};
--
2.39.1
--
Mailing list info: https://lists.linux.it/listinfo/ltp
^ permalink raw reply related [flat|nested] 17+ messages in thread
* [LTP] [PATCH v1 8/8] fs/acl: Remove old shell-based ACL test
2026-06-02 12:19 [LTP] [PATCH v1 0/8] Convert shell-based ACL test (tacl_xattr.sh) to C Sachin Sant
` (6 preceding siblings ...)
2026-06-02 12:19 ` [LTP] [PATCH v1 7/8] fs/acl: Add extended attributes test Sachin Sant
@ 2026-06-02 12:19 ` Sachin Sant
7 siblings, 0 replies; 17+ messages in thread
From: Sachin Sant @ 2026-06-02 12:19 UTC (permalink / raw)
To: ltp
Remove tacl_xattr.sh, the old shell-based ACL and extended attribute
test script. This test has been replaced by the new modular C-based
test suite:
- acl_user_obj01: ACL_USER_OBJ permissions
- acl_mask01: ACL mask interactions (3 tests)
- acl_other01: ACL_OTHER permissions
- acl_inherit01: Default ACL inheritance
- acl_file_ops01: chmod/chown interactions (2 tests)
- acl_link01: Symlink ACL operations
- xattr_test01: Extended attributes (2 tests)
Signed-off-by: Sachin Sant <sachinp@linux.ibm.com>
---
V1 changes:
- Updated commit message to reflect correct number of
test scenario in xattr_test01
- rfc link https://lore.kernel.org/ltp/477836fd-80c8-4168-bfe6-00b374bb2534@linux.ibm.com/T/#t
---
testcases/kernel/fs/acl/tacl_xattr.sh | 807 --------------------------
1 file changed, 807 deletions(-)
delete mode 100755 testcases/kernel/fs/acl/tacl_xattr.sh
diff --git a/testcases/kernel/fs/acl/tacl_xattr.sh b/testcases/kernel/fs/acl/tacl_xattr.sh
deleted file mode 100755
index c2383fdd9..000000000
--- a/testcases/kernel/fs/acl/tacl_xattr.sh
+++ /dev/null
@@ -1,807 +0,0 @@
-#!/bin/bash
-##############################################################
-#
-# Copyright (c) International Business Machines Corp., 2003
-#
-# This program is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation; either version 2 of the License, or
-# (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
-# the GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation,
-#
-# FILE : tacl_xattr.sh
-# USAGE : ./tacl_xattr.sh
-#
-# DESCRIPTION : A script that will test ACL and Extend Attribute on Linux system.
-# REQUIREMENTS:
-# 1) Kernel with loop device support
-# 2) A spare (scratch) disk partition of 100MB or larger.
-# 3) Kernel with ACL and Extend Attribute function support
-#
-# HISTORY :
-# 10/23/2003 Kai Zhao (ltcd3@cn.ibm.com)
-# 07/06/2004 Jacky Malcles enable ext3 & clean users home dir.
-#
-# CODE COVERAGE:
-# 76.3% - fs/posix_acl.c
-# 80.9% - xattr_acl.c
-# 73.0% - xattr.c
-#
-##############################################################
-
-CUR_PATH=""
-CONTENT=""
-RES=""
-USER_PERMISSION=""
-GROUP_PERMISSION=""
-OTHER_PERMISSION=""
-ITEM_OWNER=""
-ITEM_GROUP=""
-
-################################################################
-#
-# Make sure that uid=root is running this script.
-# Make sure that loop device is built into the kernel
-# Make sure that ACL(Access Control List) and Extended Attribute are
-# built into the kernel
-#
-################################################################
-
-if [ $UID != 0 ]
-then
- echo "FAILED: Must have root access to execute this script"
- exit 1
-fi
-
-#################################################################
-#
-# Prepare Ext2 file system for ACL and Extended Attribute test
-# Make some directory , file and symlink for the test
-# Add three users for the test
-#
-#################################################################
-
-if [ ! -e tacl ]
-then
- mkdir -m 777 tacl
-else
- echo "FAILED: Directory tacl are exist"
- exit 1
-fi
-
-dd if=/dev/zero of=tacl/blkext2 bs=1k count=10240
-chmod 777 tacl/blkext2
-
-losetup /dev/loop0 tacl/blkext2 >/dev/null 2>&1
-if [ $? != 0 ]
-then
- printf "\nFAILED: [ losetup ] Must have loop device support by kernel\n"
- printf "\t to execute this script\n"
- exit 1
-fi
-
-mount | grep ext2
-if [ $? != 0 ]
-then
- mkfs -t ext3 /dev/loop0
- mkdir -m 777 tacl/mount-ext2
- mount -t ext3 -o defaults,acl,user_xattr /dev/loop0 tacl/mount-ext2
- if [ $? != 0 ]
- then
- printf "\nFAILED: [ mount ] Make sure that ACL (Access Control List)\n"
- printf "\t and Extended Attribute are built into the kernel\n"
- printf "\t Can not mount ext2 file system with acl and user_xattr options\n"
- exit 1
- fi
-
-else
- mkfs -t ext2 /dev/loop0
- mkdir -m 777 tacl/mount-ext2
- mount -t ext2 -o defaults,acl,user_xattr /dev/loop0 tacl/mount-ext2
- if [ $? != 0 ]
- then
- printf "\nFAILED: [ mount ] Make sure that ACL (Access Control List)\n"
- printf "\t and Extended Attribute are built into the kernel\n"
- printf "\t Can not mount ext2 file system with acl and user_xattr options\n"
- exit 1
- fi
-fi
-
-chmod 777 tacl/mount-ext2
-
-useradd -d `pwd`/tacl/tacluser1 tacluser1
-useradd -d `pwd`/tacl/tacluser2 tacluser2
-useradd -d `pwd`/tacl/tacluser3 tacluser3
-useradd -d `pwd`/tacl/tacluser4 tacluser4
-
-if [ ! -e tacl/mount-ext2/shared ]
-then
- mkdir -p -m 777 tacl/mount-ext2/shared
-fi
-
-CUR_PATH=`pwd`
-
-su - tacluser1 << TACL_USER1
-
- mkdir $CUR_PATH/tacl/mount-ext2/shared/team1
- touch $CUR_PATH/tacl/mount-ext2/shared/team1/file1
-
- cd $CUR_PATH/tacl/mount-ext2/shared/team1
- ln -sf file1 symlinkfile1
- cd $CUR_PATH
-
- cd $CUR_PATH/tacl/mount-ext2/shared
- ln -sf team1 symlinkdir1
- cd $CUR_PATH
-
-TACL_USER1
-
-su - tacluser2 << TACL_USER2
-
- mkdir $CUR_PATH/tacl/mount-ext2/shared/team2
- touch $CUR_PATH/tacl/mount-ext2/shared/team2/file1
-
- cd $CUR_PATH/tacl/mount-ext2/shared/team2
- ln -sf file1 symlinkfile1
- cd $CUR_PATH
-
- cd $CUR_PATH/tacl/mount-ext2/shared
- ln -sf team2 symlinkdir2
- cd $CUR_PATH
-
-TACL_USER2
-
-#############################################################################################
-#
-# The permissions bit limit user's act
-# lrwxrwxrwx 1 tacluser1 tacluser1 5 Jun 23 13:39 symlinkdir1 -> team1
-# lrwxrwxrwx 1 tacluser2 tacluser2 5 Jun 23 13:39 symlinkdir2 -> team2
-# dr-x------ 2 tacluser1 tacluser1 1024 Jun 23 13:39 team1
-# drwxrwxr-x 2 tacluser2 tacluser2 1024 Jun 23 13:39 team2
-#
-#############################################################################################
-
-chmod 500 tacl/mount-ext2/shared/team1
-
-su - tacluser1 << TACL_USER1
-
- touch $CUR_PATH/tacl/mount-ext2/shared/team1/newfil1 2> /dev/null
- if [ -e $CUR_PATH/tacl/mount-ext2/shared/team1/newfile1 ]
- then
- printf "\nFAILED: [ touch ] Create file must be denied by file permission bits\n"
- printf "\t [ Physical Directory ]\n"
- else
- printf "\nSUCCESS: Create file denied by file permission bits [ Physical directory ]\n"
- fi
-
- touch $CUR_PATH/tacl/mount-ext2/shared/symlinkdir1/newfil2 2> /dev/null
- if [ -e $CUR_PATH/tacl/mount-ext2/shared/team1/newfile2 ]
- then
- printf "\nFAILED: [ touch ] Create file must be denied by file permission bits\n"
- printf "\t [ Symlink Directory ]\n"
- else
- printf "\nSUCCESS: Create file denied by file permission bits [ Symlink directory ]\n"
- fi
-
-TACL_USER1
-
-#################################################################
-#
-# ACL_USER_OBJ are a superset of the permissions specified
-# by the file permission bits.
-# The effective user ID of the process matches the user ID of
-# the file object owner.
-# Owner's act are based ACL_USER_OBJ
-#
-#################################################################
-
-setfacl -m u::rx tacl/mount-ext2/shared/team1
-su - tacluser1 << TACL_USER1
-
- cd $CUR_PATH/tacl/mount-ext2/shared/team1/ 2> /dev/null
- if [ $? != 0 ]
- then
- printf "\nFAILED: [ touch ] ACL_USER_OBJ entry already contains the owner execute\n"
- printf "\t permissions, but operation failed [ Physical Directory ]\n"
- else
- printf "\nSUCCESS: ACL_USER_OBJ entry contains the owner execute permissions,\n"
- printf "\t operation success [ Physical Directory ]\n"
- fi
-
- cd $CUR_PATH/tacl/mount-ext2/shared/symlinkdir1/ 2> /dev/null
- if [ $? != 0 ]
- then
- printf "\nFAILED: [ touch ] ACL_USER_OBJ entry already contains the owner execute\n"
- printf "\t permissions, but operation failed [ Symlink Directory ]\n"
- else
- printf "\nSUCCESS: ACL_USER_OBJ entry contains the owner execute permissions,\n"
- printf "\t operation success [ Symlink Directory ]\n"
- fi
-
-TACL_USER1
-
-setfacl -m u::rwx tacl/mount-ext2/shared/team1
-
-su - tacluser1 << TACL_USER1
-
- touch $CUR_PATH/tacl/mount-ext2/shared/team1/newfil1 2> /dev/null
- if [ -e $CUR_PATH/tacl/mount-ext2/shared/team1/newfile1 ]
- then
- printf "\nFAILED: [ touch ] ACL_USER_OBJ entry already contains the owner write \n"
- printf "\t permissions, but operation failed [ Physical Directory ]\n"
- else
- printf "\nSUCCESS: ACL_USER_OBJ entry contains the owner write permissions,\n"
- printf "\t operation success [ Physical Directory ]\n"
- fi
-
- touch $CUR_PATH/tacl/mount-ext2/shared/symlinkdir1/newfil2 2> /dev/null
- if [ -e $CUR_PATH/tacl/mount-ext2/shared/team1/newfile2 ]
- then
- printf "\nFAILED: [ touch ] ACL_USER_OBJ entry already contains the owner write \n"
- printf "\t permissions, but operation failed [ Symlink Directory ]\n"
- else
- printf "\nSUCCESS: ACL_USER_OBJ entry contains the owner write permissions,\n"
- printf "\t operation success [ Symlink Directory ]\n"
- fi
-
-TACL_USER1
-
-#################################################################
-#
-# The effective user ID of the process matches the qualifier of
-# any entry of type ACL_USER
-# IF the matching ACL_USER entry and the ACL_MASK
-# entry contain the requested permissions,# access is granted,
-# ELSE access is denied.
-#
-#################################################################
-
-setfacl -m u:tacluser3:rwx tacl/mount-ext2/shared/team1
-
-su - tacluser3 << TACL_USER3
-
- touch $CUR_PATH/tacl/mount-ext2/shared/team1/newfile3 2> /dev/null
- if [ -e $CUR_PATH/tacl/mount-ext2/shared/team1/newfile3 ]
- then
- printf "\nSUCCESS: ACL_USER entry contains the user permissions,\n"
- printf "\t operation success [ Physical Directory ]\n"
- else
- printf "\nFAILED: ACL_USER entry contains the user permissions,\n"
- printf "\t but operation denied [ Physical Directory ]\n"
- fi
-
- touch $CUR_PATH/tacl/mount-ext2/shared/symlinkdir1/newfile4 2> /dev/null
- if [ -e $CUR_PATH/tacl/mount-ext2/shared/symlinkdir1/newfile4 ]
- then
- printf "\nSUCCESS: ACL_USER entry contains the user permissions,\n"
- printf "\t operation success [ Symlink Directory ]\n"
- else
- printf "\nFAILED: ACL_USER entry contains the user permissions,\n"
- printf "\t but operation denied [ Symlink Directory ]\n"
- fi
-
-TACL_USER3
-
-setfacl -m mask:--- tacl/mount-ext2/shared/team1
-
-su - tacluser3 << TACL_USER3
-
- touch $CUR_PATH/tacl/mount-ext2/shared/team1/newfile5 2> /dev/null
- if [ -e $CUR_PATH/tacl/mount-ext2/shared/team1/newfile5 ]
- then
- printf "\nFAILED: [ touch ] ACL_USER entry contains the user permissions\n"
- printf "\t but ACL_MASK are set --- ,\n"
- printf "\t operation must be denied [ Physical Directory ]\n"
- else
- printf "\nSUCCESS: ACL_USER entry contains the user permissions,\n"
- printf "\t but ACL_MASK are set ___ ,\n"
- printf "\t operation success [ Physical Directory ]\n"
- fi
-
- touch $CUR_PATH/tacl/mount-ext2/shared/symlinkdir1/newfile6 2> /dev/null
- if [ -e $CUR_PATH/tacl/mount-ext2/shared/symlinkdir1/newfile6 ]
- then
- printf "\nFAILED: [ touch ] ACL_USER entry contains the user permissions\n"
- printf "\t but ACL_MASK are set --- ,\n"
- printf "\t operation must be denied [ Symlink Directory ]\n"
- else
- printf "\nSUCCESS: ACL_USER entry contains the user permissions,\n"
- printf "\t but ACL_MASK are set ___ ,\n"
- printf "\t operation success [ Symlink Directory ]\n"
- fi
-
-TACL_USER3
-
-###########################################################################################
-#
-# The effective group ID or any of the supplementary group IDs of the process match the
-# qualifier of the entry of type ACL_GROUP_OBJ, or the qualifier of any entry of type
-# ACL_GROUP
-#
-# IF the ACL contains an ACL_MASK entry, THEN
-# if the ACL_MASK entry and any of the matching ACL_GROUP_OBJ
-# or ACL_GROUP entries contain the requested permissions,
-# access is granted,
-#
-# else access is denied.
-#
-# ELSE (note that there can be no ACL_GROUP entries without an ACL_MASK entry)
-# if the ACL_GROUP_OBJ entry contains the requested permis-
-# sions, access is granted,
-#
-# else access is denied.
-#
-###########################################################################################
-
-setfacl -m g:tacluser2:rwx tacl/mount-ext2/shared/team1
-
-su - tacluser2 << TACL_USER2
- touch $CUR_PATH/tacl/mount-ext2/shared/team1/newfile7 2> /dev/null
- if [ -e $CUR_PATH/tacl/mount-ext2/shared/team1/newfile7 ]
- then
- printf "\nSUCCESS: ACL_GROUP entry contains the group permissions,\n"
- printf "\t option success [ Physical Directory ]\n"
- else
- printf "\nFAILED: [ touch ] ACL_GROUP entry already contains the group permissions,\n"
- printf "\t but option success [ Physical Directory ]\n"
- fi
-
- touch $CUR_PATH/tacl/mount-ext2/shared/symlinkdir1/newfile8 2> /dev/null
- if [ -e $CUR_PATH/tacl/mount-ext2/shared/symlinkdir1/newfile8 ]
- then
- printf "\nSUCCESS: ACL_GROUP entry contains the group permissions,\n"
- printf "\t option success [ Symlink Directory ]\n"
- else
- printf "\nFAILED: [ touch ] ACL_GROUP entry already contains the group permissions,\n"
- printf "\t but option success [ Symlink Directory ]\n"
- fi
-
-TACL_USER2
-
-setfacl -m mask:--- tacl/mount-ext2/shared/team1
-
-su - tacluser2 << TACL_USER2
- touch $CUR_PATH/tacl/mount-ext2/shared/team1/newfile9 2> /dev/null
- if [ -e $CUR_PATH/tacl/mount-ext2/shared/team1/newfile9 ]
- then
- printf "\nFAILED: [ touch ] ACL_GROUP entry contains the group permissions\n"
- printf "\t and ACL_MASK entry are set ---,\n"
- printf "\t option must no be success [ Physical Directory ]\n"
- else
- printf "\nSUCCESS: ACL_GROUP entry already contains the group permissions\n"
- printf "\t and ACL_MASK entry are set ---,\n"
- printf "\t option success [ Physical Directory ]\n"
- fi
-
- touch $CUR_PATH/tacl/mount-ext2/shared/symlinkdir1/newfile10 2> /dev/null
- if [ -e $CUR_PATH/tacl/mount-ext2/shared/symlinkdir1/newfile10 ]
- then
- printf "\nFAILED: [ touch ] ACL_GROUP entry contains the group permissions\n"
- printf "\t and ACL_MASK entry are set ---,\n"
- printf "\t option must no be success [ Symlink Directory ]\n"
- else
- printf "\nSUCCESS: ACL_GROUP entry already contains the group permissions\n"
- printf "\t and ACL_MASK entry are set ---,\n"
- printf "\t option success [ Symlink Directory ]\n"
- fi
-
-TACL_USER2
-
-setfacl -m g::rwx tacl/mount-ext2/shared/team1
-usermod -g tacluser1 tacluser2
-
-su - tacluser2 << TACL_USER2
-
- touch $CUR_PATH/tacl/mount-ext2/shared/team1/newfile11 2> /dev/null
- if [ -e $CUR_PATH/tacl/mount-ext2/shared/team1/newfile11 ]
- then
- printf "\nSUCCESS: ACL_GROUP_OBJ entry contains the group owner permissions,\n"
- printf "\t option success [ Physical Directory ]\n"
- else
- printf "\nFAILED: [ touch ] ACL_GROUP_OBJ entry already contains the group owner,\n"
- printf "\t but option denied [ Physical Directory ]\n"
- fi
-
- touch $CUR_PATH/tacl/mount-ext2/shared/symlinkdir1/newfile12 2> /dev/null
- if [ -e $CUR_PATH/tacl/mount-ext2/shared/symlinkdir1/newfile12 ]
- then
- printf "\nSUCCESS: ACL_GROUP_OBJ entry contains the group owner permissions,\n"
- printf "\t option success [ Symlink Directory ]\n"
- else
- printf "\nFAILED: [ touch ] ACL_GROUP_OBJ entry already contains the group owner,\n"
- printf "\t but option denied [ Symlink Directory ]\n"
- fi
-
-TACL_USER2
-
-setfacl -m mask:--- tacl/mount-ext2/shared/team1
-
-su - tacluser2 << TACL_USER2
- touch $CUR_PATH/tacl/mount-ext2/shared/team1/newfile13 2> /dev/null
- if [ -e $CUR_PATH/tacl/mount-ext2/shared/team1/newfile13 ]
- then
- printf "\nFAILED: [ touch ] ACL_GROUP_OBJ entry contains the group owner permissions\n"
- printf "\t and ACL_MASK entry are set ---,\n"
- printf "\t option must no be success [ Physical Directory ]\n"
- else
- printf "\nSUCCESS: ACL_GROUP_OBJ entry already contains the group owner permissions\n"
- printf "\t and ACL_MASK entry are set ---,\n"
- printf "\t option success [ Physical Directory ]\n"
- fi
-
- touch $CUR_PATH/tacl/mount-ext2/shared/symlinkdir1/newfile14 2> /dev/null
- if [ -e $CUR_PATH/tacl/mount-ext2/shared/symlinkdir1/newfile14 ]
- then
- printf "\nFAILED: [ touch ] ACL_GROUP_OBJ entry contains the group owner permissions\n"
- printf "\t and ACL_MASK entry are set ---,\n"
- printf "\t option must no be success [ Symlink Directory ]\n"
- else
- printf "\nSUCCESS: ACL_GROUP_OBJ entry already contains the group owner permissions\n"
- printf "\t and ACL_MASK entry are set ---,\n"
- printf "\t option success [ Symlink Directory ]\n"
- fi
-
-TACL_USER2
-
-usermod -g tacluser2 tacluser2
-
-###################################################################################
-#
-# IF the ACL_OTHER entry contains the requested permissions, access is granted
-#
-###################################################################################
-
-setfacl -m o::rwx tacl/mount-ext2/shared/team1
-
-su - tacluser4 << TACL_USER4
-
- touch $CUR_PATH/tacl/mount-ext2/shared/team1/newfile15 2> /dev/null
- if [ -e $CUR_PATH/tacl/mount-ext2/shared/team1/newfile15 ]
- then
- printf "\nSUCCESS: ACL_OTHER entry contains the user permissions,\n"
- printf "\t operation success [ Physical Directory ]\n"
- else
- printf "\nFAILED: ACL_OTHER entry contains the user permissions,\n"
- printf "\t but operation denied [ Physical Directory ]\n"
- fi
-
- touch $CUR_PATH/tacl/mount-ext2/shared/symlinkdir1/newfile16 2> /dev/null
- if [ -e $CUR_PATH/tacl/mount-ext2/shared/symlinkdir1/newfile16 ]
- then
- printf "\nSUCCESS: ACL_OTHER entry contains the user permissions,\n"
- printf "\t operation success [ Symlink Directory ]\n"
- else
- printf "\nFAILED: ACL_OTHER entry contains the user permissions,\n"
- printf "\t but operation denied [ Symlink Directory ]\n"
- fi
-
-TACL_USER4
-
-setfacl -m mask:--- tacl/mount-ext2/shared/team1
-
-su - tacluser4 << TACL_USER4
-
- touch $CUR_PATH/tacl/mount-ext2/shared/team1/newfile17 2> /dev/null
- if [ -e $CUR_PATH/tacl/mount-ext2/shared/team1/newfile17 ]
- then
- printf "\nSUCCESS: [ touch ] ACL_OTHER do not strick by ACL_MASK [ Physical Directory ]\n"
- else
- printf "\nFAILED: ACL_OTHER do not strick by ACL_MASK [ Physical Directory ]\n"
- fi
-
- touch $CUR_PATH/tacl/mount-ext2/shared/symlinkdir1/newfile18 2> /dev/null
- if [ -e $CUR_PATH/tacl/mount-ext2/shared/symlinkdir1/newfile18 ]
- then
- printf "\nSUCCESS: [ touch ] ACL_OTHER do not strick by ACL_MASK [ Symlink Directory ]\n"
- else
- printf "\nFAILED: ACL_OTHER do not strick by ACL_MASK [ Symlink Directory ]\n"
- fi
-
-TACL_USER4
-
-############################################################################
-#
-# OBJECT CREATION AND DEFAULT ACLs
-# The new object inherits the default ACL of the containing directory as its access ACL.
-#
-############################################################################
-
-rm -f tacl/mount-ext2/shared/team1/newfil*
-
-#
-# Test ACL_USER_OBJ default ACLs
-#
-setfacl -m d:u::r -m d:g::r -m d:o::r tacl/mount-ext2/shared/team1
-
-su - tacluser1 << TACL_USER1
-
- MASK=`umask`
- umask 0
- touch $CUR_PATH/tacl/mount-ext2/shared/team1/newfile1
- umask $MASK > /dev/null
-
-TACL_USER1
-
-CONTENT=""
-CONTENT=`ls -l tacl/mount-ext2/shared/team1/newfile1`
-RES=`echo $CONTENT | grep ".r--r--r--" | awk '{print $1}'`
-
-if [ $RES != "" ]
-then
- printf "\nSUCCESS: With default ACLs set, new file permission set correct.\n"
-else
- printf "\nFAILED: With default ACLs set, new file permission set not correct\n"
-fi
-
-
-
-#
-# Test ACL_USER and ACL_GROUP defaults ACLs
-#
-setfacl -m d:u:tacluser3:rw -m d:g:tacluser3:rw tacl/mount-ext2/shared/team1
-su - tacluser3 << TACL_USER3
-
- MASK=`umask`
- umask 0
- touch $CUR_PATH/tacl/mount-ext2/shared/team1/newfile2
- umask $MASK > /dev/null
-
-TACL_USER3
-
-CONTENT=""
-CONTENT=`ls -l tacl/mount-ext2/shared/team1/newfile2`
-RES=`echo $CONTENT | grep ".r--rw-r--" | awk '{print $1}'`
-
-if [ $RES != "" ]
-then
- printf "\nSUCCESS: With default ACLs set, new file permission set correct.\n"
-else
- printf "\nFAILED: With default ACLs set, new file permission set not correct\n"
-fi
-
-#
-# Test ACL_GROUP default ACLs
-#
-
-setfacl -m d:u::rwx -m d:g::rwx -m d:o::rwx tacl/mount-ext2/shared/team1
-su - tacluser3 << TACL_USER3
-
- MASK=`umask`
- umask 0
- touch $CUR_PATH/tacl/mount-ext2/shared/team1/newfile3
- umask $MASK > /dev/null
-
-TACL_USER3
-
-CONTENT=""
-CONTENT=`ls -l tacl/mount-ext2/shared/team1/newfile3`
-RES=`echo $CONTENT | grep ".rw-rw-rw-" | awk '{print \$1}'`
-
-if [ $RES != "" ]
-then
- printf "\nSUCCESS: With default ACLs set, new file permission set correct.\n"
-else
- printf "\nFAILED: With default ACLs set, new file permission set not correct\n"
-fi
-
-
-#################################################################################
-#
-# Chmod also change ACL_USER_OBJ ACL_GROUP_OBJ and ACL_OTHER permissions
-#
-#################################################################################
-su - tacluser3 << TACL_USER3
- MASK=`umask`
- umask 0
-
- chmod 777 $CUR_PATH/tacl/mount-ext2/shared/team1/newfile3
- umask $MASK > /dev/null
-TACL_USER3
-
-CONTENT=""
-CONTENT=`getfacl tacl/mount-ext2/shared/team1/newfile3`
-
-USER_PERMISSION=`echo $CONTENT | awk '{print \$10}'`
-
-GROUP_PERMISSION=`echo $CONTENT | awk '{print \$12}'`
-OTHER_PERMISSION=`echo $CONTENT | awk '{print \$15}'`
-
-if [ $USER_PERMISSION = "user::rwx" ]
-then
- if [ $GROUP_PERMISSION = "group::rwx" ]
- then
- if [ $OTHER_PERMISSION = "other::rwx" ]
- then
- printf "\nSUCCESS: Chmod with ACL_USER_OBJ ACL_GROUP_OBJ and ACL_OTHER are correct\n"
- else
- printf "\nFAILED: Chmod with ACL_USER_OBJ ACL_GROUP_OBJ and ACL_OTHER are not correct\n"
- fi
- else
- printf "\nFAILED: Chmod with ACL_USER_OBJ ACL_GROUP_OBJ and ACL_OTHER are not correct\n"
- fi
-else
- printf "\nFAILED: Chmod with ACL_USER_OBJ ACL_GROUP_OBJ and ACL_OTHER are not correct\n"
-fi
-
-
-#####################################################################################
-#
-# Chown only change object owner and group
-#
-#####################################################################################
-
-chown tacluser2.tacluser2 tacl/mount-ext2/shared/team1/newfile2
-CONTENT=""
-CONTENT=`getfacl tacl/mount-ext2/shared/team1/newfile2`
-
-ITEM_OWNER=`echo $CONTENT | awk '{print \$6}'`
-ITEM_GROUP=`echo $CONTENT | awk '{print \$9}'`
-
-if [ $ITEM_OWNER = "tacluser2" ]
-then
- if [ $ITEM_GROUP = "tacluser2" ]
- then
- printf "\nSUCCESS: Chown correct\n"
- else
- printf "\nFAILED: Chown are not correct\n"
- fi
-else
- echo "FAILED: Chown are not correct"
-fi
-
-#####################################################
-#
-# Test ACLs backup and restore
-#
-#####################################################
-
-getfacl -RL tacl/mount-ext2/ > tacl/tmp1
-setfacl -m u::--- -m g::--- -m o::--- tacl/mount-ext2/shared/team1
-setfacl --restore tacl/tmp1
-getfacl -RL tacl/mount-ext2/ > tacl/tmp2
-
-if [ `diff tacl/tmp1 tacl/tmp2` ]
-then
- printf "\nFAILED: ACLs backup and restore are not correct\n"
-else
- printf "\nSUCCESS: ACLs backup and restore are correct\n"
-fi
-
-printf "\n\tEnd ACLs Test\n"
-
-#####################################################
-#
-# Now begin Extend Attribute test
-#
-#####################################################
-
-printf "\nNow begin Extend Attribute Test\n"
-
-# dir
-printf "\nAttach name:value pair to object dir\n\n"
-attr -s attrname1 -V attrvalue1 tacl/mount-ext2/shared/team2
-if [ $? != 0 ]
-then
- echo "FAILED: Attach name:value pair to object dir"
-fi
-
-#file
-echo
-echo "Attach name:value pair to object file "
-echo ""
-attr -s attrname2 -V attrvalue2 tacl/mount-ext2/shared/team2/file1
-if [ $? != 0 ]
-then
- echo "FAILED: Attach name:value pair to object file"
-fi
-
-#symlink file
-echo
-echo "Attach name:value pair to object symlink file"
-echo ""
-attr -s attrname3 -V attrvalue3 tacl/mount-ext2/shared/team2/symlinkfile1
-if [ $? != 0 ]
-then
- echo "INFO: Can't attach name:value pair to object symlink file"
-fi
-
-echo ""
-ls -lRt tacl/mount-ext2/shared/team2
-
-echo
-echo "get extended attributes of filesystem objects"
-echo ""
-
-echo "Dump the values"
-getfattr -d tacl/mount-ext2/shared/team2
-if [ $? != 0 ]
-then
- echo "FAILED: getfattr: Dump the values"
-fi
-
-echo "Recursively dump the values"
-getfattr -dR tacl/mount-ext2/*
-if [ $? != 0 ]
-then
- echo "FAILED: getfattr: Recursively Dump the values"
-fi
-
-echo "Do not follow symlinks."
-echo "but extended user attributes are disallowed for symbolic links"
-getfattr -h --no-dereference tacl/mount-ext2/shared/team2/symlinkfile1
-if [ $? != 0 ]
-then
- echo "FAILED: getfattr: Do not follow symlinks."
-fi
-echo
-
-echo "Logical walk, follow symbolic links"
-getfattr -L tacl/mount-ext2/shared/team2/*
-if [ $? != 0 ]
-then
- echo "FAILED: getfattr: Logical walk"
-fi
-
-echo "Physical walk, skip all symbolic links"
-getfattr -P tacl/mount-ext2/shared/team2/*
-if [ $? != 0 ]
-then
- echo "FAILED: getfattr: Physical walk"
-fi
-
-echo "attr -g to search the named object"
-attr -g attrname1 tacl/mount-ext2/shared/team2
-if [ $? != 0 ]
-then
- echo "FAILED: attr: to search the named object"
-fi
-echo
-
-echo "attr -r to remove the named object"
-attr -r attrname2 tacl/mount-ext2/shared/team2/file1
-if [ $? != 0 ]
-then
- echo "FAILED: attr: to remove the named object"
-fi
-
-
-#################################
-#
-# Backup and Restore
-#
-#################################
-getfattr -dhR -m- -e hex tacl/mount-ext2 > tacl/backup.ea
-setfattr -h --restore=tacl/backup.ea
-
-getfattr -dhR -m- -e hex tacl/mount-ext2 > tacl/backup.ea1
-if [ `diff tacl/backup.ea1 tacl/backup.ea` ]
-then
- printf "\nFAILED: EAs backup and restore are not correct\n"
-else
- printf "\nSUCCESS: EAs backup and restore are correct\n"
-fi
-
-printf "\n\tEnd EAs Test\n"
-
-
-
-#####################################################
-#
-# Clean up
-#
-#####################################################
-
-userdel tacluser1
-userdel tacluser2
-userdel tacluser3
-userdel tacluser4
-umount -d tacl/mount-ext2
-rm -rf tacl
--
2.39.1
--
Mailing list info: https://lists.linux.it/listinfo/ltp
^ permalink raw reply related [flat|nested] 17+ messages in thread
* Re: [LTP] fs/acl: Add ACL_USER_OBJ permissions test
2026-06-02 12:19 ` [LTP] [PATCH v1 1/8] fs/acl: Add ACL_USER_OBJ permissions test Sachin Sant
@ 2026-06-02 12:52 ` linuxtestproject.agent
2026-06-05 9:20 ` Andrea Cervesato via ltp
0 siblings, 1 reply; 17+ messages in thread
From: linuxtestproject.agent @ 2026-06-02 12:52 UTC (permalink / raw)
To: Sachin Sant; +Cc: ltp
Hi Sachin,
Thanks for the patch series. The approach — converting tacl_xattr.sh to
a modular C test suite — is a good improvement. I have some issues to
address before this can be merged.
Kernel version note: checked against stable 7.1. POSIX ACLs and xattrs
have been in-tree for many kernel generations; no .min_kver concerns.
---
[PATCH 1/8] fs/acl: Add ACL_USER_OBJ permissions test
> /*\
> * Test ACL_USER_OBJ permissions.
> *
> * Verify that owner permissions (ACL_USER_OBJ) correctly control access
> * to files and directories. The test validates that:
> * - Traditional permission bits deny access when restrictive
> * - ACL_USER_OBJ entries can grant access beyond permission bits
"ACL_USER_OBJ entries can grant access beyond permission bits" is
incorrect. ACL_USER_OBJ IS the owner permission bits — they are the same
inode field. When you call acl_set_file() with ACL_USER_OBJ=rwx, the
kernel updates the inode owner permission bits to rwx. There is nothing
"beyond" the permission bits happening.
The test logic itself is correct: after chmod(0500) denies write, calling
acl_set_file() with ACL_USER_OBJ=rwx grants write access because the
inode owner bits are overwritten. Please fix the description to reflect
that accurately, for example:
- ACL_USER_OBJ permissions are applied directly as the owner bits
- Setting ACL_USER_OBJ=rwx via acl_set_file() overrides a previous
chmod restriction
---
[PATCH 6/8] fs/acl: Add symlink ACL operations test
> /*
> * Note: Some filesystems may not support ACLs on symlinks and will
> * return EOPNOTSUPP, which is treated as TCONF (test not applicable).
> */
This note is wrong, and it propagates into the TCONF message below.
acl_set_file() is implemented on top of setxattr(2), which follows
symlinks. The test is not "setting ACLs on a symlink" — it is setting
ACLs on the *target* through a symlink path. Symlinks themselves never
hold ACLs on Linux.
EOPNOTSUPP from acl_set_file() means the *target* filesystem does not
support ACLs, not that "ACLs on symlinks are unsupported".
> if (errno == EOPNOTSUPP) {
> tst_res(TCONF,
> "ACL on symlinks not supported");
The message "ACL on symlinks not supported" repeats the same incorrect
framing. It should say something like:
tst_res(TCONF, "ACL not supported by this filesystem");
Please fix both the block comment and the TCONF string.
The commit body has the same issue:
> Returns TCONF if ACL on symlinks is not supported by the filesystem.
Should be:
Returns TCONF if ACL is not supported by the filesystem.
---
[PATCH 6/8] fs/acl: Add symlink ACL operations test
[PATCH 7/8] fs/acl: Add extended attributes test
Both acl_link01.c and xattr_test01.c call init_test_users() in setup()
and cleanup_test_users() in cleanup(), and both have:
.needs_cmds = (struct tst_cmd[]) {
{.cmd = "useradd"},
{.cmd = "userdel"},
{}
}
Neither test uses test user UIDs/GIDs for its actual test operations.
The user creation happens only because reset_test_path() calls
SAFE_CHOWN(TESTDIR, user1_uid, user1_gid). For these two tests:
- acl_link01: creates file + symlink as root, sets/gets ACL as root;
the ownership of TESTDIR is irrelevant to whether symlink ACL
operations work.
- xattr_test01: sets/gets/removes xattrs as root; TESTDIR ownership
is irrelevant to xattr operations.
The needs_cmds dependency will cause TCONF on environments without
useradd/userdel (some containers, embedded targets) even though the
tests do not actually require those users. Please either:
a) Avoid calling reset_test_path() in these two tests and use a
simpler path setup that does not chown (e.g. SAFE_MKDIR only), or
b) Add a variant of reset_test_path() that skips the chown step.
---
Pre-existing issues (informational only, do not affect verdict):
None found.
---
Verdict: Needs revision
Issues requiring fixes before merge:
1. acl_user_obj01.c: incorrect description "beyond permission bits"
2. acl_link01.c: incorrect TCONF message and block comment re symlinks
3. Commit 1bdd453 body: incorrect "on symlinks" wording
4. acl_link01.c + xattr_test01.c: unnecessary test user creation and
needs_cmds adding useradd/userdel dependency
LTP AI Reviewer
--
Mailing list info: https://lists.linux.it/listinfo/ltp
^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: [LTP] fs/acl: Add ACL_USER_OBJ permissions test
2026-06-03 6:57 [LTP] [PATCH v2 1/8] " Sachin Sant
@ 2026-06-03 9:43 ` linuxtestproject.agent
2026-06-03 12:49 ` Sachin Sant
0 siblings, 1 reply; 17+ messages in thread
From: linuxtestproject.agent @ 2026-06-03 9:43 UTC (permalink / raw)
To: Sachin Sant; +Cc: ltp
Hi Sachin,
Thank you for the patches. This is a welcome addition — replacing the old
unmaintained bash script with a proper set of modular C tests with full LTP
framework integration. Below are my review comments.
---
[PATCH 1/8] fs/acl: Add ACL_USER_OBJ permissions test
acl_lib.h: Copyright header
The .c and .h files all carry:
* Copyright (c) IBM, 2026
The correct LTP convention is:
* Copyright (c) 2026 IBM
(year first, then author, no comma). Same applies to all .c/.h files
in the series.
acl_user_obj01.c: The test logic is correct.
SAFE_CHMOD(TESTDIR, 0500) followed by try_create_as() expecting EACCES
is sound. Setting a minimal ACL (USER_OBJ, GROUP_OBJ, OTHER) via
acl_set_file() updates the inode mode bits, so USER_OBJ=rwx makes the
subsequent creation succeed. No issues here.
---
[PATCH 3/8] fs/acl: Add symlink ACL operations test
acl_link01.c: Test does not verify what it claims
The commit message says:
"acl_set_file() on a symlink sets ACL on the target file"
But the test only checks the return value of acl_set_file() and
acl_get_file() through the symlink — it never verifies that the ACL
was actually set on TESTFILE (the symlink target).
The retrieved ACL is read through the symlink and then immediately
freed without inspecting its contents or comparing it with what was
set. So the claim that "ACL operations follow symlinks rather than
operating on the link itself" is not actually proven.
To properly verify this, also call acl_get_file(TESTFILE, ...) and
confirm the expected entries are present, or at minimum compare the
ACL retrieved via the symlink against the ACL retrieved via the
direct file path.
---
[PATCH 7/8] fs/acl: Add extended attributes test
Commit message body contains file-change bullets:
The last two bullet points in the commit body are:
- Update runtest/fs to include xattr_test01
- Update .gitignore for new test binary
These describe file modifications rather than the test's purpose or
rationale. The diff already shows what files were modified. Remove
these bullets from the commit message body; keep only the description
of what the test validates.
---
Pre-existing issues (informational, not blocking):
None identified.
---
Verdict: Needs revision
Regards,
LTP AI Reviewer
--
Mailing list info: https://lists.linux.it/listinfo/ltp
^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: [LTP] fs/acl: Add ACL_USER_OBJ permissions test
2026-06-03 9:43 ` [LTP] " linuxtestproject.agent
@ 2026-06-03 12:49 ` Sachin Sant
0 siblings, 0 replies; 17+ messages in thread
From: Sachin Sant @ 2026-06-03 12:49 UTC (permalink / raw)
To: ltp
On 03/06/26 3:13 pm, linuxtestproject.agent@gmail.com wrote:
> [PATCH 3/8] fs/acl: Add symlink ACL operations test
This should be PATCH 6/8 in the series. The review comments
are correct.
The current test only proves that acl_set_file() and acl_get_file()
succeed through the symlink path, but it does not verify that the
ACL was actually applied to the target file. I’ll update it to read the
ACL from both TESTSYMLINK and TESTFILE, and verify the expected
entries/permissions match.”
> acl_link01.c: Test does not verify what it claims
>
> The commit message says:
> "acl_set_file() on a symlink sets ACL on the target file"
>
> But the test only checks the return value of acl_set_file() and
> acl_get_file() through the symlink — it never verifies that the ACL
> was actually set on TESTFILE (the symlink target).
>
> The retrieved ACL is read through the symlink and then immediately
> freed without inspecting its contents or comparing it with what was
> set. So the claim that "ACL operations follow symlinks rather than
> operating on the link itself" is not actually proven.
>
> To properly verify this, also call acl_get_file(TESTFILE, ...) and
> confirm the expected entries are present, or at minimum compare the
> ACL retrieved via the symlink against the ACL retrieved via the
> direct file path.
>
> ---
--
Thanks
- Sachin
--
Mailing list info: https://lists.linux.it/listinfo/ltp
^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: [LTP] fs/acl: Add ACL_USER_OBJ permissions test
2026-06-03 14:01 [LTP] [PATCH 1/8] " Sachin Sant
@ 2026-06-03 14:52 ` linuxtestproject.agent
0 siblings, 0 replies; 17+ messages in thread
From: linuxtestproject.agent @ 2026-06-03 14:52 UTC (permalink / raw)
To: Sachin Sant; +Cc: ltp
On Wed, 3 Jun 2026 19:31:40 +0530, Sachin Sant wrote:
> fs/acl: Add ACL_USER_OBJ permissions test
> fs/acl: Add ACL mask interaction tests
> fs/acl: Add ACL_OTHER permissions test
> fs/acl: Add default ACL inheritance test
> fs/acl: Add chmod/chown ACL interaction tests
> fs/acl: Add symlink ACL operations test
> fs/acl: Add extended attributes test
> fs/acl: Remove old shell-based ACL test
The overall approach is sound — replacing the old monolithic shell script
with focused C tests is the right direction, and the shared acl_lib.h is
well-structured. However there are a few issues that need addressing before
this is ready.
---
BLOCKING
---
[1] acl_link01.c: test is vacuous and does not verify symlink-following
The test creates TESTFILE with mode 0644, then sets:
ACL_USER_OBJ = rw-
ACL_GROUP_OBJ = r--
ACL_OTHER = r--
via TESTSYMLINK. That ACL is bit-for-bit identical to the minimal ACL
already implied by mode 0644, so acl_set_file() changes nothing. Then
acl_get_file() is called on both TESTFILE and TESTSYMLINK; since both
resolve to the same inode, acl_cmp() is trivially 0 regardless of whether
the symlink was followed during the set call.
The test would pass even if acl_set_file() on a symlink were a no-op.
Fix: set a deliberately distinct ACL through the symlink — one that is
different from the file's initial state — and then verify the target file's
ACL reflects that change. For example:
SAFE_OPEN(TESTFILE, O_CREAT | O_WRONLY, 0600);
acl = acl_init(3);
add_acl_entry(acl, ACL_USER_OBJ, ACL_READ | ACL_WRITE | ACL_EXECUTE);
add_acl_entry(acl, ACL_GROUP_OBJ, ACL_READ | ACL_WRITE);
add_acl_entry(acl, ACL_OTHER, 0);
/* Set the new ACL through the symlink */
acl_set_file(TESTSYMLINK, ACL_TYPE_ACCESS, acl);
/* Now read from the target and from the symlink */
target_acl = acl_get_file(TESTFILE, ACL_TYPE_ACCESS);
symlink_acl = acl_get_file(TESTSYMLINK, ACL_TYPE_ACCESS);
/* Both must match the ACL we set, and the target must differ from 0600 */
With a distinct ACL, a failure to follow the symlink during the set call
would be caught because the target file's mode/ACL would remain at 0600.
---
[2] acl_other01.c: correctness depends on distro-specific useradd behaviour
The test relies on user2_gid != user1_gid so that user2 falls through to
ACL_OTHER rather than matching ACL_GROUP_OBJ (the directory's owning
group is user1_gid). Whether useradd creates a private group per user is
controlled by USERGROUPS_ENAB in /etc/login.defs. On many distributions
this defaults to "yes", but it is not universal. On a system where
USERGROUPS_ENAB=no, both users would share the same primary GID and user2
would match ACL_GROUP_OBJ (masked to --- by ACL_MASK), causing EACCES and
a false test failure.
Fix: explicitly request a user-private group:
tst_cmd((const char *[]){"useradd", "-M", "-U", username, NULL}, ...);
The "-U" flag creates a group with the same name as the user, guaranteeing
a distinct GID even when USERGROUPS_ENAB=no. Check that your target
useradd supports -U (it is part of shadow-utils and available on all
mainstream distros).
The same concern applies to acl_mask01.c which tests ACL_GROUP and
ACL_GROUP_OBJ interactions depending on user/group separation.
---
NON-BLOCKING
---
[3] acl_lib.h: create_user_if_needed() uses TCONF when TBROK is correct
if (tst_cmd((const char *[]){"useradd", "-M", username, NULL},
NULL, NULL, TST_CMD_PASS_RETVAL) != 0)
tst_brk(TCONF, "Failed to create user %s", username);
The needs_cmds field already handles the "useradd not installed" case
with TCONF. Once useradd is present but returns non-zero (e.g. PAM
policy, container user-namespace restrictions, nss failures), the test
cannot be set up — that is TBROK, not TCONF. Using TCONF here silently
skips the test instead of surfacing the setup failure.
tst_brk(TBROK, "Failed to create user %s", username);
---
[4] acl_lib.h: set_acl_file() should treat EOPNOTSUPP as TCONF
static inline void set_acl_file(const char *path, acl_type_t type, acl_t acl)
{
...
if (acl_set_file(path, type, acl) == -1)
tst_brk(TBROK | TERRNO, "acl_set_file(%s) failed", path);
}
If POSIX ACL support is missing at the kernel level (CONFIG_FS_POSIX_ACL
not set) and the filesystem returns EOPNOTSUPP, all tests that go through
set_acl_file() will report TBROK instead of TCONF. acl_link01.c already
handles this correctly inline; the same treatment should be in the shared
helper:
if (acl_set_file(path, type, acl) == -1) {
if (errno == EOPNOTSUPP)
tst_brk(TCONF | TERRNO, "ACL not supported on %s", path);
tst_brk(TBROK | TERRNO, "acl_set_file(%s) failed", path);
}
---
[5] acl_inherit01.c: acl_get_file() result is never inspected
file_acl = acl_get_file(TESTFILE, ACL_TYPE_ACCESS);
if (!file_acl) {
cleanup_testfile();
tst_brk(TBROK | TERRNO, "acl_get_file failed");
}
safe_acl_free(file_acl);
The test states it verifies that "the file inherits the default ACL as
its access ACL" but the retrieved ACL object is freed immediately without
any content check. The mode-bit verification (0444) is sufficient to
confirm the inherited ACL was applied for a minimal ACL, so either:
(a) Remove the acl_get_file() block and add a comment explaining that
for a minimal inherited ACL the mode bits are the canonical check, or
(b) Iterate file_acl and verify that each entry matches the expected
inherited permissions.
As written the block misleads the reader into thinking the ACL content
is being validated when it is not.
---
Sachin Sant <sachinp@linux.ibm.com>
--
Mailing list info: https://lists.linux.it/listinfo/ltp
^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: [LTP] fs/acl: Add ACL_USER_OBJ permissions test
2026-06-04 6:54 [LTP] [PATCH v4 1/8] fs/acl: Add ACL_USER_OBJ permissions test Sachin Sant
@ 2026-06-04 7:20 ` linuxtestproject.agent
2026-06-05 9:31 ` linuxtestproject.agent
1 sibling, 0 replies; 17+ messages in thread
From: linuxtestproject.agent @ 2026-06-04 7:20 UTC (permalink / raw)
To: Sachin Sant; +Cc: ltp
On Thu, Jun 04, 2026 at 12:24:10 +0530, Sachin Sant wrote:
> fs/acl: Add ACL_USER_OBJ permissions test
> fs/acl: Add ACL mask interaction tests
> fs/acl: Add ACL_OTHER permissions test
> fs/acl: Add default ACL inheritance test
> fs/acl: Add chmod/chown ACL interaction tests
> fs/acl: Add symlink ACL operations test
> fs/acl: Add extended attributes test
> fs/acl: Remove old shell-based ACL test
Hi Sachin,
Thanks for the patch series. The overall direction is good — replacing the
old bash-based tacl_xattr.sh with modular C tests is the right move. I have
a few issues below that need addressing before this can be merged.
---
[PATCH 1/8] fs/acl: Add ACL_USER_OBJ permissions test (acl_user_obj01.c)
The run() function contains two independent test cases — deny-by-mode and
grant-by-ACL — both calling tst_res(TPASS/TFAIL,...) and with the second
depending on no shared mutable state from the first. Using .test_all for
two distinct cases means a failure of the first silently skips the second,
and both results appear under the same test counter. Change this to:
.test = run,
.tcnt = 2,
and dispatch on n inside run():
static void run(unsigned int n)
{
switch (n) {
case 0: test_deny_by_mode(); break;
case 1: test_grant_by_acl(); break;
}
}
This matches the pattern used in acl_mask01.c and acl_file_ops01.c.
---
[PATCH 6/8] fs/acl: Add symlink ACL operations test (acl_link01.c)
The test verifies that acl_get_file() via a symlink returns the same result
as acl_get_file() on the target file directly. It does NOT verify that the
ACL was actually set to the intended value.
Consider the failure mode: if acl_set_file(TESTSYMLINK, ...) silently acted
on the symlink's own metadata rather than following it to the target, the
call would still return 0 (or EOPNOTSUPP), then both acl_get_file(TESTFILE)
and acl_get_file(TESTSYMLINK) would still agree with each other (both
reflecting the original 0600 permission), and the test would TPASS even
though the ACL was never applied to the target.
The commit message and the TPASS string both claim "ACL set via symlink was
applied to target file (rwxrw----)" but the code never checks that the
actual ACL content is rwxrw----.
After the set-via-symlink step, read back the ACL from the target file
directly and verify it matches the expected entries
(ACL_USER_OBJ=rwx, ACL_GROUP_OBJ=rw, ACL_OTHER=---) before proceeding to
the symlink-vs-direct comparison.
---
[PATCH 7/8] fs/acl: Add extended attributes test (xattr_test01.c)
Two issues:
1. test_xattr_backup_restore() does not test backup/restore
The backup step hard-codes the attribute values into the file using the
same compile-time constants (XATTR_TEST1_VALUE, XATTR_TEST2_VALUE) that
were used to set the xattrs:
fprintf(fp, "%s=\"%s\"\n", XATTR_TEST1_NAME, XATTR_TEST1_VALUE);
fprintf(fp, "%s=\"%s\"\n", XATTR_TEST2_NAME, XATTR_TEST2_VALUE);
This means the backup file is written from constants, not read from the
filesystem. The test exercises the restore-and-verify path, but not the
backup path (reading live xattrs from the filesystem and saving them).
A genuine backup/restore test must generate the backup by reading the
attributes off the file (e.g., via getxattr/listxattr) and saving the
actual runtime values. As written, the test would pass even if the
previous setxattr calls had silently written wrong values or nothing at
all, because the backup never actually reads from the filesystem state.
Either rename the test to reflect what it actually tests
("xattr_set_restore" or similar) or fix the backup step to genuinely
read live xattr values before removing them.
2. Mixed use of TST_EXP_PASS / TST_EXP_PASS_SILENT inflates the TPASS count
test_xattr() on a clean run emits five TPASS results:
- TST_EXP_POSITIVE(getxattr TESTDIR) → TPASS
- TST_EXP_POSITIVE(getxattr TESTFILE) → TPASS
- TST_EXP_PASS(removexattr) → TPASS
- TST_EXP_FAIL(getxattr after removal) → TPASS
- tst_res(TPASS, "Extended attributes...") → TPASS
Likewise test_xattr_backup_restore() emits four. Each function is run
as a single test slot (.tcnt = 2), so each slot should produce exactly
one TPASS on success. Use TST_EXP_PASS_SILENT (and
TST_EXP_POSITIVE_SILENT / manual errno checks) for all intermediate
operations, and emit one tst_res(TPASS, ...) per function at the end.
Or conversely, remove the final tst_res(TPASS, ...) and keep only the
individual macro results — but then be consistent throughout.
---
Minor nits (not blocking, fix at discretion):
* acl_lib.h: The extern declarations for user1_uid, user2_uid, etc. must
be matched by a definition in every translation unit that actually
references them. Tests that don't use the user infrastructure
(acl_link01.c, xattr_test01.c) include the header but provide no
definition. This happens to be harmless today because none of the
static-inline helpers that use those variables are instantiated in those
binaries. However it is fragile: adding a single call to any user-aware
helper in those files would cause a link error. Consider moving the
globals (and their initializers) to an acl_lib.c file so the header
only needs the extern declarations, or at minimum add a comment
documenting the requirement.
* acl_lib.h: cleanup_test_paths() unconditionally tries to unlink
XATTR_BACKUP_FILE. Tests that never create that file (acl_link01.c,
acl_mask01.c, etc.) silently get an ENOENT, which is harmless, but the
cleanup function is carrying responsibility for a resource it cannot
know was created. Consider splitting out cleanup_xattr_backup() or
handling the backup file inside xattr_test01.c's own cleanup.
Thanks,
Copilot
--
Mailing list info: https://lists.linux.it/listinfo/ltp
^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: [LTP] fs/acl: Add ACL_USER_OBJ permissions test
2026-06-02 12:52 ` [LTP] " linuxtestproject.agent
@ 2026-06-05 9:20 ` Andrea Cervesato via ltp
0 siblings, 0 replies; 17+ messages in thread
From: Andrea Cervesato via ltp @ 2026-06-05 9:20 UTC (permalink / raw)
To: Sachin Sant; +Cc: ltp
Hi Sachin Sant,
please consider the agent review bugged. We had some issues with it
and now it's finally fixed. You will receive a proper review soon,
I triggered it in the CI.
Regards,
--
Andrea Cervesato
SUSE QE Automation Engineer Linux
andrea.cervesato@suse.com
--
Mailing list info: https://lists.linux.it/listinfo/ltp
^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: [LTP] fs/acl: Add ACL_USER_OBJ permissions test
2026-06-04 6:54 [LTP] [PATCH v4 1/8] fs/acl: Add ACL_USER_OBJ permissions test Sachin Sant
2026-06-04 7:20 ` [LTP] " linuxtestproject.agent
@ 2026-06-05 9:31 ` linuxtestproject.agent
1 sibling, 0 replies; 17+ messages in thread
From: linuxtestproject.agent @ 2026-06-05 9:31 UTC (permalink / raw)
To: Sachin Sant; +Cc: ltp
Hi Sachin,
On Thu, 4 Jun 2026 12:24:10 +0530, Sachin Sant
<sachinp@linux.ibm.com> wrote:
> fs/acl: Add ACL_USER_OBJ permissions test
--- [PATCH 1/8] ---
> The patch also adds acl_lib.h containing shared helper functions
> and definitions for ACL and extended attribute tests.
The commit adds two distinct things: the shared helper library
acl_lib.h, and the first test acl_user_obj01.c. Per Ground Rule 7,
each patch must contain exactly one logical change. acl_lib.h should
be introduced in a preparatory commit before the tests that use it.
> then sets ACL_USER_OBJ with write permissions and confirms that
> file creation succeeds.
> + add_acl_entry(acl, ACL_USER_OBJ,
> + ACL_READ | ACL_WRITE | ACL_EXECUTE);
The body says "sets ACL_USER_OBJ with write permissions" but the
code grants read, write, and execute (rwx). The description should
say "full permissions (rwx)" or "rwx".
> +uid_t user1_uid, user2_uid, user3_uid;
> +gid_t user1_gid, user2_gid, user3_gid;
> +int users_created = 0;
> +
> +#ifdef HAVE_LIBACL
These variable definitions are outside the #ifdef HAVE_LIBACL guard
but are only used inside it. Per c-tests.md Rule 16, all test code
must be wrapped by the feature guard. Move these three lines inside
the #ifdef block.
The same pattern appears in acl_mask01.c (patch 2/8), acl_other01.c
(patch 3/8), acl_inherit01.c (patch 4/8), and acl_file_ops01.c
(patch 5/8).
> +LDLIBS += $(ACL_LIBS)
This applies the ACL library link flag to every binary in the
directory, including xattr_test01, which uses only xattr syscalls and
does not call any libacl functions. Per the build-system rules,
per-target flags are preferred when not every test truly needs them.
Verdict: Needs revision
---
Note:
The agent can sometimes produce false positives although often its
findings are genuine. If you find issues with the review, please
comment this email or ignore the suggestions.
Regards,
LTP AI Reviewer
--
Mailing list info: https://lists.linux.it/listinfo/ltp
^ permalink raw reply [flat|nested] 17+ messages in thread
end of thread, other threads:[~2026-06-05 9:31 UTC | newest]
Thread overview: 17+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-06-02 12:19 [LTP] [PATCH v1 0/8] Convert shell-based ACL test (tacl_xattr.sh) to C Sachin Sant
2026-06-02 12:19 ` [LTP] [PATCH v1 1/8] fs/acl: Add ACL_USER_OBJ permissions test Sachin Sant
2026-06-02 12:52 ` [LTP] " linuxtestproject.agent
2026-06-05 9:20 ` Andrea Cervesato via ltp
2026-06-02 12:19 ` [LTP] [PATCH v1 2/8] fs/acl: Add ACL mask interaction tests Sachin Sant
2026-06-02 12:19 ` [LTP] [PATCH v1 3/8] fs/acl: Add ACL_OTHER permissions test Sachin Sant
2026-06-02 12:19 ` [LTP] [PATCH v1 4/8] fs/acl: Add default ACL inheritance test Sachin Sant
2026-06-02 12:19 ` [LTP] [PATCH v1 5/8] fs/acl: Add chmod/chown ACL interaction tests Sachin Sant
2026-06-02 12:19 ` [LTP] [PATCH v1 6/8] fs/acl: Add symlink ACL operations test Sachin Sant
2026-06-02 12:19 ` [LTP] [PATCH v1 7/8] fs/acl: Add extended attributes test Sachin Sant
2026-06-02 12:19 ` [LTP] [PATCH v1 8/8] fs/acl: Remove old shell-based ACL test Sachin Sant
-- strict thread matches above, loose matches on Subject: below --
2026-06-04 6:54 [LTP] [PATCH v4 1/8] fs/acl: Add ACL_USER_OBJ permissions test Sachin Sant
2026-06-04 7:20 ` [LTP] " linuxtestproject.agent
2026-06-05 9:31 ` linuxtestproject.agent
2026-06-03 14:01 [LTP] [PATCH 1/8] " Sachin Sant
2026-06-03 14:52 ` [LTP] " linuxtestproject.agent
2026-06-03 6:57 [LTP] [PATCH v2 1/8] " Sachin Sant
2026-06-03 9:43 ` [LTP] " linuxtestproject.agent
2026-06-03 12:49 ` Sachin Sant
2026-05-31 12:45 [LTP] [RFC][PATCH 1/8] " Sachin Sant
2026-06-01 6:48 ` [LTP] " linuxtestproject.agent
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.