public inbox for ltp@lists.linux.it
 help / color / mirror / Atom feed
* [LTP] [PATCH v2 00/10] setxattrat coverage
@ 2025-10-07  6:46 Andrea Cervesato
  2025-10-07  6:46 ` [LTP] [PATCH v2 01/10] lapi: add struct xattr_args fallback Andrea Cervesato
                   ` (9 more replies)
  0 siblings, 10 replies; 28+ messages in thread
From: Andrea Cervesato @ 2025-10-07  6:46 UTC (permalink / raw)
  To: ltp

This is a patch-set meant to cover setxattrat() syscalls scenarios.
There are two parts:

- cover errors and features which are already tested for setxattr()
  by adding a new setxattrat() test variant to setxattr() testing
  suite

- cover errors which are strictly related to the setxattrat() syscall

Signed-off-by: Andrea Cervesato <andrea.cervesato@suse.com>
---
Changes in v2:
- correctly fallback and import `struct xattr_args`
- fallback setxattrat() only
- Link to v1: https://lore.kernel.org/r/20250127-xattrat-v1-0-c3ee31e2543b@suse.com

---
Andrea Cervesato (10):
      lapi: add struct xattr_args fallback
      lapi: add setxattrat() fallback definition
      setxattr01: add setxattrat variant
      setxattr02: add setxattrat variant
      setxattr03: add setxattrat variant
      lapi: add getxattrat() fallback
      lapi: add removexattrat() fallback
      lapi: add safe *xattrat macros
      Add setxattrat01 test
      Add setxattrat02 test

 configure.ac                                       |   5 +
 include/lapi/xattr.h                               | 156 +++++++++++++++++++++
 testcases/kernel/syscalls/setxattr/setxattr01.c    |  61 ++++++--
 testcases/kernel/syscalls/setxattr/setxattr02.c    |  79 ++++++++---
 testcases/kernel/syscalls/setxattr/setxattr03.c    |  35 +++--
 testcases/kernel/syscalls/setxattrat/.gitignore    |   2 +
 testcases/kernel/syscalls/setxattrat/Makefile      |   8 ++
 .../kernel/syscalls/setxattrat/setxattrat01.c      | 150 ++++++++++++++++++++
 .../kernel/syscalls/setxattrat/setxattrat02.c      | 126 +++++++++++++++++
 9 files changed, 581 insertions(+), 41 deletions(-)
---
base-commit: d2550ffbbcfe163212cd7e9c132db65ae0fa06ed
change-id: 20250121-xattrat-1b1653ccea31

Best regards,
-- 
Andrea Cervesato <andrea.cervesato@suse.com>


-- 
Mailing list info: https://lists.linux.it/listinfo/ltp

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

* [LTP] [PATCH v2 01/10] lapi: add struct xattr_args fallback
  2025-10-07  6:46 [LTP] [PATCH v2 00/10] setxattrat coverage Andrea Cervesato
@ 2025-10-07  6:46 ` Andrea Cervesato
  2025-10-07 11:50   ` Cyril Hrubis
  2025-10-07  6:46 ` [LTP] [PATCH v2 02/10] lapi: add setxattrat() fallback definition Andrea Cervesato
                   ` (8 subsequent siblings)
  9 siblings, 1 reply; 28+ messages in thread
From: Andrea Cervesato @ 2025-10-07  6:46 UTC (permalink / raw)
  To: ltp

From: Andrea Cervesato <andrea.cervesato@suse.com>

Signed-off-by: Andrea Cervesato <andrea.cervesato@suse.com>
---
 configure.ac         |  2 ++
 include/lapi/xattr.h | 32 ++++++++++++++++++++++++++++++++
 2 files changed, 34 insertions(+)

diff --git a/configure.ac b/configure.ac
index 0480f46ca..c32d9992c 100644
--- a/configure.ac
+++ b/configure.ac
@@ -83,6 +83,7 @@ AC_CHECK_HEADERS_ONCE([ \
     linux/tty.h \
     linux/types.h \
     linux/userfaultfd.h \
+    linux/xattr.h \
     netinet/sctp.h \
     pthread.h \
     sys/epoll.h \
@@ -266,6 +267,7 @@ AC_CHECK_TYPES([struct mnt_id_req],,,[#include <sys/mount.h>])
 AC_CHECK_TYPES([struct statmount],,,[#include <sys/mount.h>])
 AC_CHECK_MEMBERS([struct statmount.mnt_ns_id],,,[#include <unistd.h>
 #include <linux/mount.h>])
+AC_CHECK_TYPES([struct xattr_args],,,[#include <linux/xattr.h>])
 
 AC_CHECK_TYPES([struct pidfd_info],,,[#include <sys/pidfd.h>])
 AC_CHECK_TYPES([struct file_attr],,,[#include <linux/fs.h>])
diff --git a/include/lapi/xattr.h b/include/lapi/xattr.h
new file mode 100644
index 000000000..8bd2d45e4
--- /dev/null
+++ b/include/lapi/xattr.h
@@ -0,0 +1,32 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * Copyright (c) 2025 Linux Test Project
+ */
+
+#ifndef LAPI_XATTR_H__
+#define LAPI_XATTR_H__
+
+#include <stdint.h>
+#include "config.h"
+
+#ifdef HAVE_LINUX_XATTR_H
+# include <linux/xattr.h>
+#endif
+
+#ifndef XATTR_CREATE
+# define XATTR_CREATE	0x1	/* set value, fail if attr already exists */
+#endif
+
+#ifndef XATTR_REPLACE
+# define XATTR_REPLACE	0x2	/* set value, fail if attr does not exist */
+#endif
+
+#ifndef HAVE_STRUCT_XATTR_ARGS
+struct xattr_args {
+	uint64_t value;
+	uint32_t size;
+	uint32_t flags;
+};
+#endif
+
+#endif /* LAPI_XATTR_H__ */

-- 
2.51.0


-- 
Mailing list info: https://lists.linux.it/listinfo/ltp

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

* [LTP] [PATCH v2 02/10] lapi: add setxattrat() fallback definition
  2025-10-07  6:46 [LTP] [PATCH v2 00/10] setxattrat coverage Andrea Cervesato
  2025-10-07  6:46 ` [LTP] [PATCH v2 01/10] lapi: add struct xattr_args fallback Andrea Cervesato
@ 2025-10-07  6:46 ` Andrea Cervesato
  2025-10-07 12:05   ` Cyril Hrubis
  2025-10-07 15:16   ` Cyril Hrubis
  2025-10-07  6:46 ` [LTP] [PATCH v2 03/10] setxattr01: add setxattrat variant Andrea Cervesato
                   ` (7 subsequent siblings)
  9 siblings, 2 replies; 28+ messages in thread
From: Andrea Cervesato @ 2025-10-07  6:46 UTC (permalink / raw)
  To: ltp

From: Andrea Cervesato <andrea.cervesato@suse.com>

Signed-off-by: Andrea Cervesato <andrea.cervesato@suse.com>
---
 configure.ac         |  1 +
 include/lapi/xattr.h | 12 ++++++++++++
 2 files changed, 13 insertions(+)

diff --git a/configure.ac b/configure.ac
index c32d9992c..827a8e6eb 100644
--- a/configure.ac
+++ b/configure.ac
@@ -157,6 +157,7 @@ AC_CHECK_FUNCS_ONCE([ \
     sendmmsg \
     sethostid \
     setns \
+    setxattrat \
     sigpending \
     splice \
     statx \
diff --git a/include/lapi/xattr.h b/include/lapi/xattr.h
index 8bd2d45e4..8ab7e51d5 100644
--- a/include/lapi/xattr.h
+++ b/include/lapi/xattr.h
@@ -7,7 +7,9 @@
 #define LAPI_XATTR_H__
 
 #include <stdint.h>
+#include <stddef.h>
 #include "config.h"
+#include "lapi/syscalls.h"
 
 #ifdef HAVE_LINUX_XATTR_H
 # include <linux/xattr.h>
@@ -29,4 +31,14 @@ struct xattr_args {
 };
 #endif
 
+#ifndef HAVE_FUNC_SETXATTRAT
+static inline int setxattrat(int dfd, const char *pathname,
+			     unsigned int at_flags, const char *name,
+			     const struct xattr_args *uargs, size_t usize)
+{
+	return tst_syscall(__NR_setxattrat, dfd, pathname, at_flags, name,
+		    uargs, usize);
+}
+#endif
+
 #endif /* LAPI_XATTR_H__ */

-- 
2.51.0


-- 
Mailing list info: https://lists.linux.it/listinfo/ltp

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

* [LTP] [PATCH v2 03/10] setxattr01: add setxattrat variant
  2025-10-07  6:46 [LTP] [PATCH v2 00/10] setxattrat coverage Andrea Cervesato
  2025-10-07  6:46 ` [LTP] [PATCH v2 01/10] lapi: add struct xattr_args fallback Andrea Cervesato
  2025-10-07  6:46 ` [LTP] [PATCH v2 02/10] lapi: add setxattrat() fallback definition Andrea Cervesato
@ 2025-10-07  6:46 ` Andrea Cervesato
  2025-10-07 12:29   ` Cyril Hrubis
  2025-10-07  6:46 ` [LTP] [PATCH v2 04/10] setxattr02: " Andrea Cervesato
                   ` (6 subsequent siblings)
  9 siblings, 1 reply; 28+ messages in thread
From: Andrea Cervesato @ 2025-10-07  6:46 UTC (permalink / raw)
  To: ltp

From: Andrea Cervesato <andrea.cervesato@suse.com>

Signed-off-by: Andrea Cervesato <andrea.cervesato@suse.com>
---
 testcases/kernel/syscalls/setxattr/setxattr01.c | 61 +++++++++++++++++++------
 1 file changed, 47 insertions(+), 14 deletions(-)

diff --git a/testcases/kernel/syscalls/setxattr/setxattr01.c b/testcases/kernel/syscalls/setxattr/setxattr01.c
index a405bf42e..ade405f37 100644
--- a/testcases/kernel/syscalls/setxattr/setxattr01.c
+++ b/testcases/kernel/syscalls/setxattr/setxattr01.c
@@ -20,6 +20,10 @@
  */
 
 #include "config.h"
+#include "tst_test.h"
+
+#ifdef HAVE_SYS_XATTR_H
+
 #include <sys/types.h>
 #include <sys/stat.h>
 #include <sys/wait.h>
@@ -30,12 +34,9 @@
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
-#ifdef HAVE_SYS_XATTR_H
-# include <sys/xattr.h>
-#endif
-#include "tst_test.h"
+#include "lapi/xattr.h"
+#include <sys/xattr.h>
 
-#ifdef HAVE_SYS_XATTR_H
 #define XATTR_NAME_MAX 255
 #define XATTR_NAME_LEN (XATTR_NAME_MAX + 2)
 #define XATTR_SIZE_MAX 65536
@@ -43,11 +44,13 @@
 #define XATTR_TEST_VALUE "this is a test value"
 #define XATTR_TEST_VALUE_SIZE 20
 #define MNTPOINT "mntpoint"
-#define FNAME MNTPOINT"/setxattr01testfile"
+#define FNAME_REL "setxattr01testfile"
+#define FNAME MNTPOINT"/"FNAME_REL
 
 static char long_key[XATTR_NAME_LEN];
 static char *long_value;
 static char *xattr_value = XATTR_TEST_VALUE;
+static int mnt_fd = -1;
 
 struct test_case {
 	char *key;
@@ -126,44 +129,64 @@ struct test_case tc[] = {
 
 static void verify_setxattr(unsigned int i)
 {
+	char *sysname;
+
 	/* some tests might require existing keys for each iteration */
 	if (tc[i].keyneeded) {
 		SAFE_SETXATTR(FNAME, tc[i].key, *tc[i].value, tc[i].size,
 				XATTR_CREATE);
 	}
 
-	TEST(setxattr(FNAME, tc[i].key, *tc[i].value, tc[i].size, tc[i].flags));
+	if (tst_variant) {
+		sysname = "setxattrat";
+
+		struct xattr_args args = {
+			.value = (uint64_t)tc[i].value,
+			.size = tc[i].size,
+			.flags = tc[i].flags,
+		};
+
+		TEST(setxattrat(mnt_fd, FNAME_REL, AT_SYMLINK_NOFOLLOW,
+			tc[i].key, &args, sizeof(args)));
+	} else {
+		sysname = "setxattr";
+
+		TEST(setxattr(
+			FNAME,
+			tc[i].key, *tc[i].value, tc[i].size,
+			tc[i].flags));
+	}
 
 	if (TST_RET == -1 && TST_ERR == EOPNOTSUPP)
-		tst_brk(TCONF, "setxattr(2) not supported");
+		tst_brk(TCONF, "%s(2) not supported", sysname);
 
 	/* success */
 
 	if (!tc[i].exp_err) {
 		if (TST_RET) {
 			tst_res(TFAIL | TTERRNO,
-				"setxattr(2) failed with %li", TST_RET);
+				"%s(2) failed with %li", sysname, TST_RET);
 			return;
 		}
 
 		/* this is needed for subsequent iterations */
 		SAFE_REMOVEXATTR(FNAME, tc[i].key);
 
-		tst_res(TPASS, "setxattr(2) passed");
+		tst_res(TPASS, "%s(2) passed", sysname);
 
 		return;
 	}
 
 	if (TST_RET == 0) {
-		tst_res(TFAIL, "setxattr(2) passed unexpectedly");
+		tst_res(TFAIL, "%s(2) passed unexpectedly", sysname);
 		return;
 	}
 
 	/* error */
 
 	if (tc[i].exp_err != TST_ERR) {
-		tst_res(TFAIL | TTERRNO, "setxattr(2) should fail with %s",
-			tst_strerrno(tc[i].exp_err));
+		tst_res(TFAIL | TTERRNO, "%s(2) should fail with %s",
+			sysname, tst_strerrno(tc[i].exp_err));
 		return;
 	}
 
@@ -171,7 +194,7 @@ static void verify_setxattr(unsigned int i)
 	if (tc[i].keyneeded)
 		SAFE_REMOVEXATTR(FNAME, tc[i].key);
 
-	tst_res(TPASS | TTERRNO, "setxattr(2) failed");
+	tst_res(TPASS | TTERRNO, "%s(2) failed", sysname);
 }
 
 static void setup(void)
@@ -192,12 +215,22 @@ static void setup(void)
 		if (!tc[i].key)
 			tc[i].key = tst_get_bad_addr(NULL);
 	}
+
+	mnt_fd = SAFE_OPEN(MNTPOINT, O_DIRECTORY);
+}
+
+static void cleanup(void)
+{
+	if (mnt_fd != -1)
+		SAFE_CLOSE(mnt_fd);
 }
 
 static struct tst_test test = {
 	.setup = setup,
+	.cleanup = cleanup,
 	.test = verify_setxattr,
 	.tcnt = ARRAY_SIZE(tc),
+	.test_variants = 2,
 	.mntpoint = MNTPOINT,
 	.mount_device = 1,
 	.all_filesystems = 1,

-- 
2.51.0


-- 
Mailing list info: https://lists.linux.it/listinfo/ltp

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

* [LTP] [PATCH v2 04/10] setxattr02: add setxattrat variant
  2025-10-07  6:46 [LTP] [PATCH v2 00/10] setxattrat coverage Andrea Cervesato
                   ` (2 preceding siblings ...)
  2025-10-07  6:46 ` [LTP] [PATCH v2 03/10] setxattr01: add setxattrat variant Andrea Cervesato
@ 2025-10-07  6:46 ` Andrea Cervesato
  2025-10-07 12:40   ` Cyril Hrubis
  2025-10-07  6:46 ` [LTP] [PATCH v2 05/10] setxattr03: " Andrea Cervesato
                   ` (5 subsequent siblings)
  9 siblings, 1 reply; 28+ messages in thread
From: Andrea Cervesato @ 2025-10-07  6:46 UTC (permalink / raw)
  To: ltp

From: Andrea Cervesato <andrea.cervesato@suse.com>

Signed-off-by: Andrea Cervesato <andrea.cervesato@suse.com>
---
 testcases/kernel/syscalls/setxattr/setxattr02.c | 79 +++++++++++++++++++------
 1 file changed, 60 insertions(+), 19 deletions(-)

diff --git a/testcases/kernel/syscalls/setxattr/setxattr02.c b/testcases/kernel/syscalls/setxattr/setxattr02.c
index 9f5f998da..b5042a0df 100644
--- a/testcases/kernel/syscalls/setxattr/setxattr02.c
+++ b/testcases/kernel/syscalls/setxattr/setxattr02.c
@@ -19,6 +19,10 @@
  */
 
 #include "config.h"
+#include "tst_test.h"
+
+#ifdef HAVE_SYS_XATTR_H
+
 #include <sys/types.h>
 #include <sys/stat.h>
 #include <sys/sysmacros.h>
@@ -30,12 +34,10 @@
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
-#ifdef HAVE_SYS_XATTR_H
-# include <sys/xattr.h>
-#endif
-#include "tst_test.h"
+#include "lapi/xattr.h"
+#include "lapi/fcntl.h"
+#include <sys/xattr.h>
 
-#ifdef HAVE_SYS_XATTR_H
 #define XATTR_TEST_KEY "user.testkey"
 #define XATTR_TEST_VALUE "this is a test value"
 #define XATTR_TEST_VALUE_SIZE 20
@@ -49,6 +51,8 @@
 #define BLK      "setxattr02blk"
 #define SOCK     "setxattr02sock"
 
+static int tmpdir_fd = -1;
+
 struct test_case {
 	char *fname;
 	char *key;
@@ -120,39 +124,58 @@ static struct test_case tc[] = {
 
 static void verify_setxattr(unsigned int i)
 {
+	char *sysname;
+
 	/* some tests might require existing keys for each iteration */
 	if (tc[i].needskeyset) {
 		SAFE_SETXATTR(tc[i].fname, tc[i].key, tc[i].value, tc[i].size,
-				XATTR_CREATE);
+			XATTR_CREATE);
 	}
 
-	TEST(setxattr(tc[i].fname, tc[i].key, tc[i].value, tc[i].size,
-			tc[i].flags));
+	if (tst_variant) {
+		sysname = "setxattrat";
+
+		struct xattr_args args = {
+			.value = (uint64_t)tc[i].value,
+			.size = tc[i].size,
+			.flags = tc[i].flags,
+		};
+
+		int at_flags = tc[i].needskeyset ? 0 : AT_SYMLINK_NOFOLLOW;
+
+		TEST(setxattrat(tmpdir_fd, tc[i].fname, at_flags,
+			tc[i].key, &args, sizeof(args)));
+	} else {
+		sysname = "setxattr";
+
+		TEST(setxattr(tc[i].fname, tc[i].key, tc[i].value, tc[i].size,
+				tc[i].flags));
+	}
 
 	if (TST_RET == -1 && TST_ERR == EOPNOTSUPP)
-		tst_brk(TCONF, "setxattr(2) not supported");
+		tst_brk(TCONF, "%s(2) not supported", sysname);
 
 	/* success */
 
 	if (!tc[i].exp_err) {
 		if (TST_RET) {
 			tst_res(TFAIL | TTERRNO,
-				"setxattr(2) on %s failed with %li",
-				tc[i].fname + OFFSET, TST_RET);
+				"%s(2) on %s failed with %li",
+				sysname, tc[i].fname + OFFSET, TST_RET);
 			return;
 		}
 
 		/* this is needed for subsequent iterations */
 		SAFE_REMOVEXATTR(tc[i].fname, tc[i].key);
 
-		tst_res(TPASS, "setxattr(2) on %s passed",
-				tc[i].fname + OFFSET);
+		tst_res(TPASS, "%s(2) on %s passed",
+				sysname, tc[i].fname + OFFSET);
 		return;
 	}
 
 	if (TST_RET == 0) {
-		tst_res(TFAIL, "setxattr(2) on %s passed unexpectedly",
-				tc[i].fname + OFFSET);
+		tst_res(TFAIL, "%s(2) on %s passed unexpectedly",
+				sysname, tc[i].fname + OFFSET);
 		return;
 	}
 
@@ -160,8 +183,8 @@ static void verify_setxattr(unsigned int i)
 
 	if (tc[i].exp_err != TST_ERR) {
 		tst_res(TFAIL | TTERRNO,
-				"setxattr(2) on %s should have failed with %s",
-				tc[i].fname + OFFSET,
+				"%s(2) on %s should have failed with %s",
+				sysname, tc[i].fname + OFFSET,
 				tst_strerrno(tc[i].exp_err));
 		return;
 	}
@@ -170,8 +193,8 @@ static void verify_setxattr(unsigned int i)
 	if (tc[i].needskeyset)
 		SAFE_REMOVEXATTR(tc[i].fname, tc[i].key);
 
-	tst_res(TPASS | TTERRNO, "setxattr(2) on %s failed",
-			tc[i].fname + OFFSET);
+	tst_res(TPASS | TTERRNO, "%s(2) on %s failed",
+			sysname, tc[i].fname + OFFSET);
 }
 
 static void setup(void)
@@ -185,12 +208,30 @@ static void setup(void)
 	SAFE_MKNOD(CHR, S_IFCHR | 0777, dev);
 	SAFE_MKNOD(BLK, S_IFBLK | 0777, 0);
 	SAFE_MKNOD(SOCK, S_IFSOCK | 0777, 0);
+
+	tmpdir_fd = SAFE_OPEN(tst_tmpdir_path(), O_DIRECTORY);
+}
+
+static void cleanup(void)
+{
+	if (tmpdir_fd != -1)
+		SAFE_CLOSE(tmpdir_fd);
+
+	SAFE_UNLINK(FILENAME);
+	SAFE_RMDIR(DIRNAME);
+	SAFE_UNLINK(SYMLINK);
+	SAFE_UNLINK(FIFO);
+	SAFE_UNLINK(CHR);
+	SAFE_UNLINK(BLK);
+	SAFE_UNLINK(SOCK);
 }
 
 static struct tst_test test = {
 	.setup = setup,
+	.cleanup = cleanup,
 	.test = verify_setxattr,
 	.tcnt = ARRAY_SIZE(tc),
+	.test_variants = 2,
 	.needs_tmpdir = 1,
 	.needs_root = 1,
 };

-- 
2.51.0


-- 
Mailing list info: https://lists.linux.it/listinfo/ltp

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

* [LTP] [PATCH v2 05/10] setxattr03: add setxattrat variant
  2025-10-07  6:46 [LTP] [PATCH v2 00/10] setxattrat coverage Andrea Cervesato
                   ` (3 preceding siblings ...)
  2025-10-07  6:46 ` [LTP] [PATCH v2 04/10] setxattr02: " Andrea Cervesato
@ 2025-10-07  6:46 ` Andrea Cervesato
  2025-10-07 15:11   ` Cyril Hrubis
  2025-10-07  6:46 ` [LTP] [PATCH v2 06/10] lapi: add getxattrat() fallback Andrea Cervesato
                   ` (4 subsequent siblings)
  9 siblings, 1 reply; 28+ messages in thread
From: Andrea Cervesato @ 2025-10-07  6:46 UTC (permalink / raw)
  To: ltp

From: Andrea Cervesato <andrea.cervesato@suse.com>

Signed-off-by: Andrea Cervesato <andrea.cervesato@suse.com>
---
 testcases/kernel/syscalls/setxattr/setxattr03.c | 35 +++++++++++++++++++------
 1 file changed, 27 insertions(+), 8 deletions(-)

diff --git a/testcases/kernel/syscalls/setxattr/setxattr03.c b/testcases/kernel/syscalls/setxattr/setxattr03.c
index 0b5b48a55..2465edd69 100644
--- a/testcases/kernel/syscalls/setxattr/setxattr03.c
+++ b/testcases/kernel/syscalls/setxattr/setxattr03.c
@@ -12,7 +12,12 @@
  */
 
 #define _GNU_SOURCE
+
 #include "config.h"
+#include "tst_test.h"
+
+#ifdef HAVE_SYS_XATTR_H
+
 #include <sys/ioctl.h>
 #include <sys/types.h>
 #include <sys/stat.h>
@@ -24,14 +29,10 @@
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
-#ifdef HAVE_SYS_XATTR_H
-# include <sys/xattr.h>
-#endif
 #include "lapi/fs.h"
+#include "lapi/xattr.h"
+#include <sys/xattr.h>
 
-#include "tst_test.h"
-
-#if defined HAVE_SYS_XATTR_H
 #define XATTR_TEST_KEY "user.testkey"
 #define XATTR_TEST_VALUE "this is a test value"
 #define XATTR_TEST_VALUE_SIZE (sizeof(XATTR_TEST_VALUE) - 1)
@@ -76,11 +77,23 @@ static struct test_case tc[] = {
 
 static int immu_fd;
 static int append_fd;
+static int tmpdir_fd = -1;
 
 static void verify_setxattr(unsigned int i)
 {
-	TEST(setxattr(tc[i].fname, tc[i].key, tc[i].value, tc[i].size,
-			tc[i].flags));
+	if (tst_variant) {
+		struct xattr_args args = {
+			.value = (uint64_t)tc[i].value,
+			.size = tc[i].size,
+			.flags = tc[i].flags,
+		};
+
+		TEST(setxattrat(tmpdir_fd, tc[i].fname, AT_SYMLINK_NOFOLLOW,
+			tc[i].key, &args, sizeof(args)));
+	} else {
+		TEST(setxattr(tc[i].fname, tc[i].key, tc[i].value, tc[i].size,
+				tc[i].flags));
+	}
 
 	if (!TST_RET) {
 		tst_res(TFAIL, "%s succeeded unexpectedly", tc[i].desc);
@@ -143,10 +156,15 @@ static void setup(void)
 	if (set_append_on(append_fd))
 		tst_brk(TBROK | TERRNO, "Set %s append-only failed",
 			APPEND_FILE);
+
+	tmpdir_fd = SAFE_OPEN(tst_tmpdir_path(), O_DIRECTORY);
 }
 
 static void cleanup(void)
 {
+	if (tmpdir_fd != -1)
+		SAFE_CLOSE(tmpdir_fd);
+
 	if ((immu_fd > 0) && set_immutable_off(immu_fd))
 		tst_res(TWARN | TERRNO, "Unset %s immutable failed",
 			 IMMU_FILE);
@@ -167,6 +185,7 @@ static struct tst_test test = {
 	.cleanup = cleanup,
 	.test = verify_setxattr,
 	.tcnt = ARRAY_SIZE(tc),
+	.test_variants = 2,
 	.needs_tmpdir = 1,
 	.needs_root = 1,
 };

-- 
2.51.0


-- 
Mailing list info: https://lists.linux.it/listinfo/ltp

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

* [LTP] [PATCH v2 06/10] lapi: add getxattrat() fallback
  2025-10-07  6:46 [LTP] [PATCH v2 00/10] setxattrat coverage Andrea Cervesato
                   ` (4 preceding siblings ...)
  2025-10-07  6:46 ` [LTP] [PATCH v2 05/10] setxattr03: " Andrea Cervesato
@ 2025-10-07  6:46 ` Andrea Cervesato
  2025-10-07 15:21   ` Cyril Hrubis
  2025-10-07  6:46 ` [LTP] [PATCH v2 07/10] lapi: add removexattrat() fallback Andrea Cervesato
                   ` (3 subsequent siblings)
  9 siblings, 1 reply; 28+ messages in thread
From: Andrea Cervesato @ 2025-10-07  6:46 UTC (permalink / raw)
  To: ltp

From: Andrea Cervesato <andrea.cervesato@suse.com>

Signed-off-by: Andrea Cervesato <andrea.cervesato@suse.com>
---
 configure.ac         |  1 +
 include/lapi/xattr.h | 10 ++++++++++
 2 files changed, 11 insertions(+)

diff --git a/configure.ac b/configure.ac
index 827a8e6eb..e43e631ab 100644
--- a/configure.ac
+++ b/configure.ac
@@ -125,6 +125,7 @@ AC_CHECK_FUNCS_ONCE([ \
     getcpu \
     getdents \
     getdents64 \
+    getxattrat \
     io_pgetevents \
     io_uring_setup \
     io_uring_register \
diff --git a/include/lapi/xattr.h b/include/lapi/xattr.h
index 8ab7e51d5..3b664e4e6 100644
--- a/include/lapi/xattr.h
+++ b/include/lapi/xattr.h
@@ -41,4 +41,14 @@ static inline int setxattrat(int dfd, const char *pathname,
 }
 #endif
 
+#ifndef HAVE_FUNC_GETXATTRAT
+static inline int getxattrat(int dfd, const char *pathname,
+			     unsigned int at_flags, const char *name,
+			     void *value, size_t size)
+{
+	return tst_syscall(__NR_getxattrat, dfd, pathname, at_flags, name,
+		    value, size);
+}
+#endif
+
 #endif /* LAPI_XATTR_H__ */

-- 
2.51.0


-- 
Mailing list info: https://lists.linux.it/listinfo/ltp

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

* [LTP] [PATCH v2 07/10] lapi: add removexattrat() fallback
  2025-10-07  6:46 [LTP] [PATCH v2 00/10] setxattrat coverage Andrea Cervesato
                   ` (5 preceding siblings ...)
  2025-10-07  6:46 ` [LTP] [PATCH v2 06/10] lapi: add getxattrat() fallback Andrea Cervesato
@ 2025-10-07  6:46 ` Andrea Cervesato
  2025-10-07 15:26   ` Cyril Hrubis
  2025-10-07  6:47 ` [LTP] [PATCH v2 08/10] lapi: add safe *xattrat macros Andrea Cervesato
                   ` (2 subsequent siblings)
  9 siblings, 1 reply; 28+ messages in thread
From: Andrea Cervesato @ 2025-10-07  6:46 UTC (permalink / raw)
  To: ltp

From: Andrea Cervesato <andrea.cervesato@suse.com>

Signed-off-by: Andrea Cervesato <andrea.cervesato@suse.com>
---
 configure.ac         | 1 +
 include/lapi/xattr.h | 8 ++++++++
 2 files changed, 9 insertions(+)

diff --git a/configure.ac b/configure.ac
index e43e631ab..e77377a60 100644
--- a/configure.ac
+++ b/configure.ac
@@ -153,6 +153,7 @@ AC_CHECK_FUNCS_ONCE([ \
     quotactl_fd \
     rand_r \
     recvmmsg \
+    removexattrat \
     renameat2 \
     sched_getcpu \
     sendmmsg \
diff --git a/include/lapi/xattr.h b/include/lapi/xattr.h
index 3b664e4e6..2ca05c787 100644
--- a/include/lapi/xattr.h
+++ b/include/lapi/xattr.h
@@ -51,4 +51,12 @@ static inline int getxattrat(int dfd, const char *pathname,
 }
 #endif
 
+#ifndef HAVE_FUNC_REMOVEXATTRAT
+static inline int removexattrat(int dfd, const char *pathname,
+			     unsigned int at_flags, const char *name)
+{
+	return tst_syscall(__NR_removexattrat, dfd, pathname, at_flags, name);
+}
+#endif
+
 #endif /* LAPI_XATTR_H__ */

-- 
2.51.0


-- 
Mailing list info: https://lists.linux.it/listinfo/ltp

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

* [LTP] [PATCH v2 08/10] lapi: add safe *xattrat macros
  2025-10-07  6:46 [LTP] [PATCH v2 00/10] setxattrat coverage Andrea Cervesato
                   ` (6 preceding siblings ...)
  2025-10-07  6:46 ` [LTP] [PATCH v2 07/10] lapi: add removexattrat() fallback Andrea Cervesato
@ 2025-10-07  6:47 ` Andrea Cervesato
  2025-10-08  9:36   ` Cyril Hrubis
  2025-10-07  6:47 ` [LTP] [PATCH v2 09/10] Add setxattrat01 test Andrea Cervesato
  2025-10-07  6:47 ` [LTP] [PATCH v2 10/10] Add setxattrat02 test Andrea Cervesato
  9 siblings, 1 reply; 28+ messages in thread
From: Andrea Cervesato @ 2025-10-07  6:47 UTC (permalink / raw)
  To: ltp

From: Andrea Cervesato <andrea.cervesato@suse.com>

Introduce the following new safe macros:

- SAFE_SETXATTRAT
- SAFE_GETXATTRAT
- SAFE_REMOVEXATTRAT

Signed-off-by: Andrea Cervesato <andrea.cervesato@suse.com>
---
 include/lapi/xattr.h | 94 ++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 94 insertions(+)

diff --git a/include/lapi/xattr.h b/include/lapi/xattr.h
index 2ca05c787..cfd1cca40 100644
--- a/include/lapi/xattr.h
+++ b/include/lapi/xattr.h
@@ -59,4 +59,98 @@ static inline int removexattrat(int dfd, const char *pathname,
 }
 #endif
 
+int safe_setxattrat(const char *file, const int lineno,
+		int dfd, const char *path, int at_flags,
+		const char *key, struct xattr_args *args, size_t size)
+{
+	int rval;
+
+	rval = setxattrat(dfd, path, at_flags, key, args, size);
+
+	if (rval == -1) {
+		if (errno == ENOTSUP) {
+			tst_brk_(file, lineno, TCONF,
+				"no xattr support in fs, mounted without user_xattr option "
+				"or invalid namespace/name format");
+			return rval;
+		}
+
+		tst_brk_(file, lineno, TBROK | TERRNO,
+			"setxattrat(%d, %s, %d, %s, %p, %zu) failed",
+			dfd, path, at_flags, key, args, size);
+	} else if (rval) {
+		tst_brk_(file, lineno, TBROK | TERRNO,
+			"Invalid setxattrat(%d, %s, %d, %s, %p, %zu) return value %d",
+			dfd, path, at_flags, key, args, size, rval);
+	}
+
+	return rval;
+}
+
+#define SAFE_SETXATTRAT(dfd, path, at_flags, key, args, size) \
+	safe_setxattrat(__FILE__, __LINE__, \
+		 (dfd), (path), (at_flags), (key), (args), (size))
+
+int safe_getxattrat(const char *file, const int lineno,
+		int dfd, const char *path, int at_flags,
+		const char *key, struct xattr_args *args, size_t size)
+{
+	int rval;
+
+	rval = getxattrat(dfd, path, at_flags, key, args, size);
+
+	if (rval == -1) {
+		if (errno == ENOTSUP) {
+			tst_brk_(file, lineno, TCONF,
+				"no xattr support in fs, mounted without user_xattr option "
+				"or invalid namespace/name format");
+			return rval;
+		}
+
+		tst_brk_(file, lineno, TBROK | TERRNO,
+			"getxattrat(%d, %s, %d, %s, %p, %zu) failed",
+			dfd, path, at_flags, key, args, size);
+	} else if (rval < 0) {
+		tst_brk_(file, lineno, TBROK | TERRNO,
+			"Invalid getxattrat(%d, %s, %d, %s, %p, %zu) return value %d",
+			dfd, path, at_flags, key, args, size, rval);
+	}
+
+	return rval;
+}
+
+#define SAFE_GETXATTRAT(dfd, path, at_flags, key, args, size) \
+	safe_getxattrat(__FILE__, __LINE__, \
+		 (dfd), (path), (at_flags), (key), (args), (size))
+
+int safe_removexattrat(const char *file, const int lineno,
+		int dfd, const char *path, int at_flags, const char *name)
+{
+	int rval;
+
+	rval = removexattrat(dfd, path, at_flags, name);
+
+	if (rval == -1) {
+		if (errno == ENOTSUP) {
+			tst_brk_(file, lineno, TCONF,
+				"no xattr support in fs or mounted without user_xattr option");
+			return rval;
+		}
+
+		tst_brk_(file, lineno, TBROK | TERRNO,
+			"removexattrat(%d, %s, %d, %s) failed",
+			dfd, path, at_flags, name);
+	} else if (rval) {
+		tst_brk_(file, lineno, TBROK | TERRNO,
+			"Invalid removexattrat(%d, %s, %d, %s) return value %d",
+			dfd, path, at_flags, name, rval);
+	}
+
+	return rval;
+}
+
+#define SAFE_REMOVEXATTRAT(dfd, path, at_flags, name) \
+	safe_removexattrat(__FILE__, __LINE__, \
+		 (dfd), (path), (at_flags), (name))
+
 #endif /* LAPI_XATTR_H__ */

-- 
2.51.0


-- 
Mailing list info: https://lists.linux.it/listinfo/ltp

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

* [LTP] [PATCH v2 09/10] Add setxattrat01 test
  2025-10-07  6:46 [LTP] [PATCH v2 00/10] setxattrat coverage Andrea Cervesato
                   ` (7 preceding siblings ...)
  2025-10-07  6:47 ` [LTP] [PATCH v2 08/10] lapi: add safe *xattrat macros Andrea Cervesato
@ 2025-10-07  6:47 ` Andrea Cervesato
  2025-10-08  9:44   ` Cyril Hrubis
  2025-10-07  6:47 ` [LTP] [PATCH v2 10/10] Add setxattrat02 test Andrea Cervesato
  9 siblings, 1 reply; 28+ messages in thread
From: Andrea Cervesato @ 2025-10-07  6:47 UTC (permalink / raw)
  To: ltp

From: Andrea Cervesato <andrea.cervesato@suse.com>

Test if setxattrat() syscall is correctly following symlink, setting
a xattr on a file.

Signed-off-by: Andrea Cervesato <andrea.cervesato@suse.com>
---
 testcases/kernel/syscalls/setxattrat/.gitignore    |   1 +
 testcases/kernel/syscalls/setxattrat/Makefile      |   8 ++
 .../kernel/syscalls/setxattrat/setxattrat01.c      | 150 +++++++++++++++++++++
 3 files changed, 159 insertions(+)

diff --git a/testcases/kernel/syscalls/setxattrat/.gitignore b/testcases/kernel/syscalls/setxattrat/.gitignore
new file mode 100644
index 000000000..e636401d7
--- /dev/null
+++ b/testcases/kernel/syscalls/setxattrat/.gitignore
@@ -0,0 +1 @@
+setxattrat01
diff --git a/testcases/kernel/syscalls/setxattrat/Makefile b/testcases/kernel/syscalls/setxattrat/Makefile
new file mode 100644
index 000000000..e582f727d
--- /dev/null
+++ b/testcases/kernel/syscalls/setxattrat/Makefile
@@ -0,0 +1,8 @@
+# SPDX-License-Identifier: GPL-2.0-or-later
+# Copyright (C) 2025 SUSE LLC
+
+top_srcdir		?= ../../../..
+
+include $(top_srcdir)/include/mk/testcases.mk
+
+include $(top_srcdir)/include/mk/generic_leaf_target.mk
diff --git a/testcases/kernel/syscalls/setxattrat/setxattrat01.c b/testcases/kernel/syscalls/setxattrat/setxattrat01.c
new file mode 100644
index 000000000..86ad7503f
--- /dev/null
+++ b/testcases/kernel/syscalls/setxattrat/setxattrat01.c
@@ -0,0 +1,150 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright (C) 2025 SUSE LLC Andrea Cervesato <andrea.cervesato@suse.com>
+ */
+
+/*\
+ * [Description]
+ *
+ * Test if setxattrat() syscall is correctly following symlink, setting a
+ * xattr on a file.
+ *
+ * [Algorithm]
+ *
+ * - create a file and the symlink pointing to it
+ * - run setxattrat() on the symlink following the pointing file
+ * - verify that file xattr has been set
+ * - verify that symlink xattr has not been set
+ * - run setxattrat() on the symlink with AT_SYMLINK_NOFOLLOW
+ * - verify that file xattr has not been set
+ * - verify that symlink xattr has been set
+ */
+
+#include "tst_test.h"
+#include "lapi/xattr.h"
+
+#include <sys/xattr.h>
+
+#define FNAME "ltp_file"
+#define SNAME "ltp_symbolic_file"
+#define XATTR_TEST_KEY "trusted.ltptestkey"
+#define XATTR_TEST_VALUE "ltprulez"
+#define XATTR_TEST_VALUE_SIZE 8
+
+static struct xattr_args *args;
+static int tmpdir_fd = -1;
+
+static struct tcase {
+	char *dst_set;
+	char *dst_noset;
+	int at_flags;
+} tcases[] = {
+	{
+		.dst_set = FNAME,
+		.dst_noset = SNAME,
+		.at_flags = 0,
+	},
+	{
+		.dst_set = SNAME,
+		.dst_noset = FNAME,
+		.at_flags = AT_SYMLINK_NOFOLLOW,
+	}
+};
+
+static void expect_xattr(const char *fname)
+{
+	int ret;
+	char buff[XATTR_TEST_VALUE_SIZE];
+
+	tst_res(TINFO, "Check if %s has xattr", fname);
+
+	memset(args, 0, sizeof(*args));
+	memset(buff, 0, XATTR_TEST_VALUE_SIZE);
+
+	args->value = (uint64_t)buff;
+	args->size = XATTR_TEST_VALUE_SIZE;
+
+	ret = SAFE_GETXATTRAT(tmpdir_fd, fname, AT_SYMLINK_NOFOLLOW,
+		XATTR_TEST_KEY, args, sizeof(*args));
+
+	TST_EXP_EQ_LI(ret, XATTR_TEST_VALUE_SIZE);
+	TST_EXP_EQ_LI(args->size, XATTR_TEST_VALUE_SIZE);
+	TST_EXP_EQ_LI(args->flags, 0);
+	TST_EXP_EQ_STRN((char *)args->value, XATTR_TEST_VALUE, XATTR_TEST_VALUE_SIZE);
+}
+
+static void expect_no_xattr(const char *fname)
+{
+	char buff[XATTR_TEST_VALUE_SIZE];
+
+	tst_res(TINFO, "Check if %s has no xattr", fname);
+
+	memset(args, 0, sizeof(*args));
+	memset(buff, 0, XATTR_TEST_VALUE_SIZE);
+
+	args->value = (uint64_t)buff;
+	args->size = 0;
+
+	TST_EXP_FAIL(tst_syscall(__NR_getxattrat, tmpdir_fd, fname,
+		AT_SYMLINK_NOFOLLOW, XATTR_TEST_KEY, args, sizeof(*args)),
+		ENODATA);
+
+	TST_EXP_EQ_LI(args->size, 0);
+	TST_EXP_EQ_LI(args->flags, 0);
+	TST_EXP_EQ_STRN((char *)args->value, "\0", 1);
+}
+
+static void run(unsigned int i)
+{
+	struct tcase *tc = &tcases[i];
+
+	args->value = (uint64_t)XATTR_TEST_VALUE;
+	args->size = XATTR_TEST_VALUE_SIZE;
+	args->flags = XATTR_CREATE;
+
+	tst_res(TINFO, "Setting xattr '%s' in %s (flags=%s)",
+		XATTR_TEST_KEY, SNAME,
+		!tc->at_flags ? "0" : "AT_SYMLINK_NOFOLLOW");
+
+	SAFE_SETXATTRAT(tmpdir_fd, SNAME, tc->at_flags, XATTR_TEST_KEY,
+		 args, sizeof(*args));
+
+	expect_xattr(tc->dst_set);
+	expect_no_xattr(tc->dst_noset);
+
+	SAFE_REMOVEXATTRAT(tmpdir_fd, tc->dst_set, tc->at_flags,
+		XATTR_TEST_KEY);
+}
+
+static void setup(void)
+{
+	char *tmpdir;
+
+	tmpdir = tst_tmpdir_path();
+	tmpdir_fd = SAFE_OPEN(tmpdir, O_DIRECTORY);
+
+	SAFE_TOUCH(FNAME, 0777, NULL);
+	SAFE_SYMLINK(FNAME, SNAME);
+}
+
+static void cleanup(void)
+{
+	if (tmpdir_fd != -1)
+		SAFE_CLOSE(tmpdir_fd);
+
+	SAFE_UNLINK(SNAME);
+	SAFE_UNLINK(FNAME);
+}
+
+static struct tst_test test = {
+	.test = run,
+	.setup = setup,
+	.cleanup = cleanup,
+	.needs_tmpdir = 1,
+	.needs_root = 1,
+	.tcnt = ARRAY_SIZE(tcases),
+	.bufs = (struct tst_buffers []) {
+		{&args, .size = sizeof(struct xattr_args)},
+		{},
+	}
+};

-- 
2.51.0


-- 
Mailing list info: https://lists.linux.it/listinfo/ltp

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

* [LTP] [PATCH v2 10/10] Add setxattrat02 test
  2025-10-07  6:46 [LTP] [PATCH v2 00/10] setxattrat coverage Andrea Cervesato
                   ` (8 preceding siblings ...)
  2025-10-07  6:47 ` [LTP] [PATCH v2 09/10] Add setxattrat01 test Andrea Cervesato
@ 2025-10-07  6:47 ` Andrea Cervesato
  2025-10-08 10:02   ` Cyril Hrubis
  9 siblings, 1 reply; 28+ messages in thread
From: Andrea Cervesato @ 2025-10-07  6:47 UTC (permalink / raw)
  To: ltp

From: Andrea Cervesato <andrea.cervesato@suse.com>

Test if setxattrat() syscall is correctly raising errors when giving
invalid inputs.

Signed-off-by: Andrea Cervesato <andrea.cervesato@suse.com>
---
 testcases/kernel/syscalls/setxattrat/.gitignore    |   1 +
 .../kernel/syscalls/setxattrat/setxattrat02.c      | 126 +++++++++++++++++++++
 2 files changed, 127 insertions(+)

diff --git a/testcases/kernel/syscalls/setxattrat/.gitignore b/testcases/kernel/syscalls/setxattrat/.gitignore
index e636401d7..9d007a44d 100644
--- a/testcases/kernel/syscalls/setxattrat/.gitignore
+++ b/testcases/kernel/syscalls/setxattrat/.gitignore
@@ -1 +1,2 @@
 setxattrat01
+setxattrat02
diff --git a/testcases/kernel/syscalls/setxattrat/setxattrat02.c b/testcases/kernel/syscalls/setxattrat/setxattrat02.c
new file mode 100644
index 000000000..8092fef26
--- /dev/null
+++ b/testcases/kernel/syscalls/setxattrat/setxattrat02.c
@@ -0,0 +1,126 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright (C) 2025 SUSE LLC Andrea Cervesato <andrea.cervesato@suse.com>
+ */
+
+/*\
+ * [Description]
+ *
+ * Test if setxattrat() syscall is correctly raising errors when giving invalid
+ * inputs.
+ */
+
+#include "tst_test.h"
+#include "lapi/xattr.h"
+#include "lapi/syscalls.h"
+
+#include <sys/xattr.h>
+
+#define FNAME "ltp_file"
+#define XATTR_TEST_KEY "trusted.ltptestkey"
+#define XATTR_TEST_VALUE "ltprulez"
+#define XATTR_TEST_VALUE_SIZE 8
+
+static struct xattr_args *args;
+static struct xattr_args *null_args;
+static int invalid_fd = -1;
+static int tmpdir_fd = -1;
+
+static struct tcase {
+	int *dfd;
+	int at_flags;
+	struct xattr_args **args;
+	size_t args_size;
+	int exp_errno;
+	char *reason;
+} tcases[] = {
+	{
+		.dfd = &invalid_fd,
+		.args = &args,
+		.args_size = sizeof(struct xattr_args),
+		.exp_errno = EBADF,
+		.reason = "Invalid directory file descriptor",
+	},
+	{
+		.dfd = &tmpdir_fd,
+		.at_flags = -1,
+		.args = &args,
+		.args_size = sizeof(struct xattr_args),
+		.exp_errno = EINVAL,
+		.reason = "Invalid AT flags",
+	},
+	{
+		.dfd = &tmpdir_fd,
+		.at_flags = AT_SYMLINK_NOFOLLOW + 1,
+		.args = &args,
+		.args_size = sizeof(struct xattr_args),
+		.exp_errno = EINVAL,
+		.reason = "Out of bound AT flags",
+	},
+	{
+		.dfd = &tmpdir_fd,
+		.args = &null_args,
+		.args_size = sizeof(struct xattr_args),
+		.exp_errno = EINVAL,
+		.reason = "Invalid arguments",
+	},
+	{
+		.dfd = &tmpdir_fd,
+		.args = &args,
+		.args_size = SIZE_MAX,
+		.exp_errno = E2BIG,
+		.reason = "Arguments size is too big",
+	},
+	{
+		.dfd = &tmpdir_fd,
+		.args = &args,
+		.args_size = sizeof(struct xattr_args) - 1,
+		.exp_errno = EINVAL,
+		.reason = "Invalid arguments size",
+	},
+};
+
+static void run(unsigned int i)
+{
+	struct tcase *tc = &tcases[i];
+
+	args->flags = XATTR_CREATE;
+	args->value = (uint64_t)XATTR_TEST_VALUE;
+	args->size = XATTR_TEST_VALUE_SIZE;
+
+	TST_EXP_FAIL(tst_syscall(__NR_setxattrat,
+		tc->dfd, FNAME, tc->at_flags, XATTR_TEST_KEY,
+		tc->args, tc->args_size),
+		tc->exp_errno, "%s", tc->reason);
+}
+
+static void setup(void)
+{
+	char *tmpdir;
+
+	tmpdir = tst_tmpdir_path();
+	tmpdir_fd = SAFE_OPEN(tmpdir, O_DIRECTORY);
+
+	SAFE_TOUCH(FNAME, 0777, NULL);
+}
+
+static void cleanup(void)
+{
+	if (tmpdir_fd != -1)
+		SAFE_CLOSE(tmpdir_fd);
+
+	SAFE_UNLINK(FNAME);
+}
+
+static struct tst_test test = {
+	.test = run,
+	.setup = setup,
+	.cleanup = cleanup,
+	.tcnt = ARRAY_SIZE(tcases),
+	.needs_root = 1,
+	.needs_tmpdir = 1,
+	.bufs = (struct tst_buffers []) {
+		{&args, .size = sizeof(struct xattr_args)},
+		{},
+	}
+};

-- 
2.51.0


-- 
Mailing list info: https://lists.linux.it/listinfo/ltp

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

* Re: [LTP] [PATCH v2 01/10] lapi: add struct xattr_args fallback
  2025-10-07  6:46 ` [LTP] [PATCH v2 01/10] lapi: add struct xattr_args fallback Andrea Cervesato
@ 2025-10-07 11:50   ` Cyril Hrubis
  0 siblings, 0 replies; 28+ messages in thread
From: Cyril Hrubis @ 2025-10-07 11:50 UTC (permalink / raw)
  To: Andrea Cervesato; +Cc: ltp

Hi!
Reviewed-by: Cyril Hrubis <chrubis@suse.cz>

-- 
Cyril Hrubis
chrubis@suse.cz

-- 
Mailing list info: https://lists.linux.it/listinfo/ltp

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

* Re: [LTP] [PATCH v2 02/10] lapi: add setxattrat() fallback definition
  2025-10-07  6:46 ` [LTP] [PATCH v2 02/10] lapi: add setxattrat() fallback definition Andrea Cervesato
@ 2025-10-07 12:05   ` Cyril Hrubis
  2025-10-07 15:16   ` Cyril Hrubis
  1 sibling, 0 replies; 28+ messages in thread
From: Cyril Hrubis @ 2025-10-07 12:05 UTC (permalink / raw)
  To: Andrea Cervesato; +Cc: ltp

Hi!
Reviewed-by: Cyril Hrubis <chrubis@suse.cz>

-- 
Cyril Hrubis
chrubis@suse.cz

-- 
Mailing list info: https://lists.linux.it/listinfo/ltp

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

* Re: [LTP] [PATCH v2 03/10] setxattr01: add setxattrat variant
  2025-10-07  6:46 ` [LTP] [PATCH v2 03/10] setxattr01: add setxattrat variant Andrea Cervesato
@ 2025-10-07 12:29   ` Cyril Hrubis
  2025-10-07 13:16     ` Andrea Cervesato via ltp
  0 siblings, 1 reply; 28+ messages in thread
From: Cyril Hrubis @ 2025-10-07 12:29 UTC (permalink / raw)
  To: Andrea Cervesato; +Cc: ltp

Hi!
Looks good to me:

Reviewed-by: Cyril Hrubis <chrubis@suse.cz>

...

>  	if (TST_RET == -1 && TST_ERR == EOPNOTSUPP)
> -		tst_brk(TCONF, "setxattr(2) not supported");
> +		tst_brk(TCONF, "%s(2) not supported", sysname);

Can we please, in a subsequent patch, convert this part to our standard
approach where we check for the availability in the test setup and
expect the syscalls to be present if kernel is new enough?

-- 
Cyril Hrubis
chrubis@suse.cz

-- 
Mailing list info: https://lists.linux.it/listinfo/ltp

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

* Re: [LTP] [PATCH v2 04/10] setxattr02: add setxattrat variant
  2025-10-07  6:46 ` [LTP] [PATCH v2 04/10] setxattr02: " Andrea Cervesato
@ 2025-10-07 12:40   ` Cyril Hrubis
  0 siblings, 0 replies; 28+ messages in thread
From: Cyril Hrubis @ 2025-10-07 12:40 UTC (permalink / raw)
  To: Andrea Cervesato; +Cc: ltp

On Tue, Oct 07, 2025 at 08:46:56AM +0200, Andrea Cervesato wrote:
> From: Andrea Cervesato <andrea.cervesato@suse.com>
> 
> Signed-off-by: Andrea Cervesato <andrea.cervesato@suse.com>
> ---
>  testcases/kernel/syscalls/setxattr/setxattr02.c | 79 +++++++++++++++++++------
>  1 file changed, 60 insertions(+), 19 deletions(-)
> 
> diff --git a/testcases/kernel/syscalls/setxattr/setxattr02.c b/testcases/kernel/syscalls/setxattr/setxattr02.c
> index 9f5f998da..b5042a0df 100644
> --- a/testcases/kernel/syscalls/setxattr/setxattr02.c
> +++ b/testcases/kernel/syscalls/setxattr/setxattr02.c
> @@ -19,6 +19,10 @@
>   */
>  
>  #include "config.h"
> +#include "tst_test.h"
> +
> +#ifdef HAVE_SYS_XATTR_H
> +
>  #include <sys/types.h>
>  #include <sys/stat.h>
>  #include <sys/sysmacros.h>
> @@ -30,12 +34,10 @@
>  #include <stdio.h>
>  #include <stdlib.h>
>  #include <string.h>
> -#ifdef HAVE_SYS_XATTR_H
> -# include <sys/xattr.h>
> -#endif
> -#include "tst_test.h"
> +#include "lapi/xattr.h"
> +#include "lapi/fcntl.h"
> +#include <sys/xattr.h>
>  
> -#ifdef HAVE_SYS_XATTR_H
>  #define XATTR_TEST_KEY "user.testkey"
>  #define XATTR_TEST_VALUE "this is a test value"
>  #define XATTR_TEST_VALUE_SIZE 20
> @@ -49,6 +51,8 @@
>  #define BLK      "setxattr02blk"
>  #define SOCK     "setxattr02sock"
>  
> +static int tmpdir_fd = -1;
> +
>  struct test_case {
>  	char *fname;
>  	char *key;
> @@ -120,39 +124,58 @@ static struct test_case tc[] = {
>  
>  static void verify_setxattr(unsigned int i)
>  {
> +	char *sysname;
> +
>  	/* some tests might require existing keys for each iteration */
>  	if (tc[i].needskeyset) {
>  		SAFE_SETXATTR(tc[i].fname, tc[i].key, tc[i].value, tc[i].size,
> -				XATTR_CREATE);
> +			XATTR_CREATE);
>  	}
>  
> -	TEST(setxattr(tc[i].fname, tc[i].key, tc[i].value, tc[i].size,
> -			tc[i].flags));
> +	if (tst_variant) {
> +		sysname = "setxattrat";
> +
> +		struct xattr_args args = {
> +			.value = (uint64_t)tc[i].value,
> +			.size = tc[i].size,
> +			.flags = tc[i].flags,
> +		};
> +
> +		int at_flags = tc[i].needskeyset ? 0 : AT_SYMLINK_NOFOLLOW;


I do not get why this is needed.

In kernel:

SYSCALL_DEFINE5(setxattr, const char __user *, pathname,
                const char __user *, name, const void __user *, value,
                size_t, size, int, flags)
{
        return path_setxattrat(AT_FDCWD, pathname, 0, name, value, size, flags);
	                                           ^
						   the setxattr() the
						   always sets the
						   at_flags to 0
}


So shouldn't setxattrat() just work the same if we pass 0 there?

It's the lsetxattr() syscall that passes AT_SYMLINK_NOFOLLOW:

SYSCALL_DEFINE5(lsetxattr, const char __user *, pathname,
                const char __user *, name, const void __user *, value,
                size_t, size, int, flags)
{
        return path_setxattrat(AT_FDCWD, pathname, AT_SYMLINK_NOFOLLOW, name,
                               value, size, flags);
}

>  static void setup(void)
> @@ -185,12 +208,30 @@ static void setup(void)
>  	SAFE_MKNOD(CHR, S_IFCHR | 0777, dev);
>  	SAFE_MKNOD(BLK, S_IFBLK | 0777, 0);
>  	SAFE_MKNOD(SOCK, S_IFSOCK | 0777, 0);
> +
> +	tmpdir_fd = SAFE_OPEN(tst_tmpdir_path(), O_DIRECTORY);

This is memleak, on the top of that can't we just use the AT_FDCWD
instead? Or if you want to make sure that the syscall works with a real
fd we can do SAFE_OPEN(".", O_DIRECTORY) instead....


-- 
Cyril Hrubis
chrubis@suse.cz

-- 
Mailing list info: https://lists.linux.it/listinfo/ltp

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

* Re: [LTP] [PATCH v2 03/10] setxattr01: add setxattrat variant
  2025-10-07 12:29   ` Cyril Hrubis
@ 2025-10-07 13:16     ` Andrea Cervesato via ltp
  2025-10-07 14:35       ` Cyril Hrubis
  0 siblings, 1 reply; 28+ messages in thread
From: Andrea Cervesato via ltp @ 2025-10-07 13:16 UTC (permalink / raw)
  To: Cyril Hrubis, Andrea Cervesato; +Cc: ltp

On Tue Oct 7, 2025 at 2:29 PM CEST, Cyril Hrubis wrote:
> Can we please, in a subsequent patch, convert this part to our standard
> approach where we check for the availability in the test setup and
> expect the syscalls to be present if kernel is new enough?

What do you think it's the best way? Some of these tests have multiple
syscalls related to *xattrat and in this test in particular we are
testing 2 syscalls. Maybe the best way would be to check for HAVE_FUNC_*
declarations in this case, but then fallback function would fail anyway.

-- 
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] 28+ messages in thread

* Re: [LTP] [PATCH v2 03/10] setxattr01: add setxattrat variant
  2025-10-07 13:16     ` Andrea Cervesato via ltp
@ 2025-10-07 14:35       ` Cyril Hrubis
  2025-10-08 10:40         ` Andrea Cervesato via ltp
  0 siblings, 1 reply; 28+ messages in thread
From: Cyril Hrubis @ 2025-10-07 14:35 UTC (permalink / raw)
  To: Andrea Cervesato; +Cc: ltp

Hi!
> > Can we please, in a subsequent patch, convert this part to our standard
> > approach where we check for the availability in the test setup and
> > expect the syscalls to be present if kernel is new enough?
> 
> What do you think it's the best way? Some of these tests have multiple
> syscalls related to *xattrat and in this test in particular we are
> testing 2 syscalls.

The same what we do for the rest of the syscalls, introduce a
setxattrat_supported() helper into a shared header that would call
tst_brk(TCONF, "") if kernel is older than the version the syscall was
added to and we got ENOSYS.

We actually have to handle a few cases here:

For setxattrat:
  - ENOSYS -> kernel too old
  - EOPNOTSUPP -> filesystem does not support extended attributes
                  (e.g. vfat)

And as for filesystem support, it looks like TMPFS has
CONFIG_TMPFS_XATTR option so it could be enabled or disabled, however
they should be supported for native Linux filesystems such as ext, btrfs
or xfs.

And we have to handle EOPNOTSUPP for setxattr() as well, so the test
setup would look like:

	if (tst_variant)
		setxattrat_supported();
	else
		setxattr_supported();

At the moment the ENOSYS branch would be covered by the fallback
function since it calls tst_syscall() but once the function gets added
to libc the check would no longer happen, so we need to eventually
handle the ENOSYS in the foo_supported() function as well.

> Maybe the best way would be to check for HAVE_FUNC_* declarations in
> this case, but then fallback function would fail anyway.

No this does not work, the only way how to find out if a syscall is
supported is to call it and check the return value.

-- 
Cyril Hrubis
chrubis@suse.cz

-- 
Mailing list info: https://lists.linux.it/listinfo/ltp

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

* Re: [LTP] [PATCH v2 05/10] setxattr03: add setxattrat variant
  2025-10-07  6:46 ` [LTP] [PATCH v2 05/10] setxattr03: " Andrea Cervesato
@ 2025-10-07 15:11   ` Cyril Hrubis
  0 siblings, 0 replies; 28+ messages in thread
From: Cyril Hrubis @ 2025-10-07 15:11 UTC (permalink / raw)
  To: Andrea Cervesato; +Cc: ltp

Hi!
>  	if (!TST_RET) {
>  		tst_res(TFAIL, "%s succeeded unexpectedly", tc[i].desc);
> @@ -143,10 +156,15 @@ static void setup(void)
>  	if (set_append_on(append_fd))
>  		tst_brk(TBROK | TERRNO, "Set %s append-only failed",
>  			APPEND_FILE);
> +
> +	tmpdir_fd = SAFE_OPEN(tst_tmpdir_path(), O_DIRECTORY);

Here as well. Maybe we should use AT_FDCWD in one test and return value
from SAFE_OPEN(".", O_DIRECTORY) in the other, so that we test different
codepaths in the kernel.

-- 
Cyril Hrubis
chrubis@suse.cz

-- 
Mailing list info: https://lists.linux.it/listinfo/ltp

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

* Re: [LTP] [PATCH v2 02/10] lapi: add setxattrat() fallback definition
  2025-10-07  6:46 ` [LTP] [PATCH v2 02/10] lapi: add setxattrat() fallback definition Andrea Cervesato
  2025-10-07 12:05   ` Cyril Hrubis
@ 2025-10-07 15:16   ` Cyril Hrubis
  1 sibling, 0 replies; 28+ messages in thread
From: Cyril Hrubis @ 2025-10-07 15:16 UTC (permalink / raw)
  To: Andrea Cervesato; +Cc: ltp

On Tue, Oct 07, 2025 at 08:46:54AM +0200, Andrea Cervesato wrote:
> From: Andrea Cervesato <andrea.cervesato@suse.com>
> 
> Signed-off-by: Andrea Cervesato <andrea.cervesato@suse.com>
> ---
>  configure.ac         |  1 +
>  include/lapi/xattr.h | 12 ++++++++++++
>  2 files changed, 13 insertions(+)
> 
> diff --git a/configure.ac b/configure.ac
> index c32d9992c..827a8e6eb 100644
> --- a/configure.ac
> +++ b/configure.ac
> @@ -157,6 +157,7 @@ AC_CHECK_FUNCS_ONCE([ \
>      sendmmsg \
>      sethostid \
>      setns \
> +    setxattrat \
>      sigpending \
>      splice \
>      statx \
> diff --git a/include/lapi/xattr.h b/include/lapi/xattr.h
> index 8bd2d45e4..8ab7e51d5 100644
> --- a/include/lapi/xattr.h
> +++ b/include/lapi/xattr.h
> @@ -7,7 +7,9 @@
>  #define LAPI_XATTR_H__
>  
>  #include <stdint.h>
> +#include <stddef.h>
>  #include "config.h"
> +#include "lapi/syscalls.h"
>  
>  #ifdef HAVE_LINUX_XATTR_H
>  # include <linux/xattr.h>
> @@ -29,4 +31,14 @@ struct xattr_args {
>  };
>  #endif
>  
> +#ifndef HAVE_FUNC_SETXATTRAT
                  ^
		  Actually that FUNC shouldn't be there, it's just
		  HAVE_SETXATTRAT

> +static inline int setxattrat(int dfd, const char *pathname,
> +			     unsigned int at_flags, const char *name,
> +			     const struct xattr_args *uargs, size_t usize)
> +{
> +	return tst_syscall(__NR_setxattrat, dfd, pathname, at_flags, name,
> +		    uargs, usize);
> +}
> +#endif
> +
>  #endif /* LAPI_XATTR_H__ */
> 
> -- 
> 2.51.0
> 
> 
> -- 
> Mailing list info: https://lists.linux.it/listinfo/ltp

-- 
Cyril Hrubis
chrubis@suse.cz

-- 
Mailing list info: https://lists.linux.it/listinfo/ltp

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

* Re: [LTP] [PATCH v2 06/10] lapi: add getxattrat() fallback
  2025-10-07  6:46 ` [LTP] [PATCH v2 06/10] lapi: add getxattrat() fallback Andrea Cervesato
@ 2025-10-07 15:21   ` Cyril Hrubis
  0 siblings, 0 replies; 28+ messages in thread
From: Cyril Hrubis @ 2025-10-07 15:21 UTC (permalink / raw)
  To: Andrea Cervesato; +Cc: ltp

Hi!
> +#ifndef HAVE_FUNC_GETXATTRAT
                ^
		Here as well no FUNC

Otherwise:

Reviewed-by: Cyril Hrubis <chrubis@suse.cz>

> +static inline int getxattrat(int dfd, const char *pathname,
> +			     unsigned int at_flags, const char *name,
> +			     void *value, size_t size)
> +{
> +	return tst_syscall(__NR_getxattrat, dfd, pathname, at_flags, name,
> +		    value, size);
> +}
> +#endif
> +
>  #endif /* LAPI_XATTR_H__ */
> 
> -- 
> 2.51.0
> 
> 
> -- 
> Mailing list info: https://lists.linux.it/listinfo/ltp

-- 
Cyril Hrubis
chrubis@suse.cz

-- 
Mailing list info: https://lists.linux.it/listinfo/ltp

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

* Re: [LTP] [PATCH v2 07/10] lapi: add removexattrat() fallback
  2025-10-07  6:46 ` [LTP] [PATCH v2 07/10] lapi: add removexattrat() fallback Andrea Cervesato
@ 2025-10-07 15:26   ` Cyril Hrubis
  0 siblings, 0 replies; 28+ messages in thread
From: Cyril Hrubis @ 2025-10-07 15:26 UTC (permalink / raw)
  To: Andrea Cervesato; +Cc: ltp

Hi!
> +#ifndef HAVE_FUNC_REMOVEXATTRAT
                ^
		And here as well, otherwise:

Reviewed-by: Cyril Hrubis <chrubis@suse.cz>

> +static inline int removexattrat(int dfd, const char *pathname,
> +			     unsigned int at_flags, const char *name)
> +{
> +	return tst_syscall(__NR_removexattrat, dfd, pathname, at_flags, name);
> +}
> +#endif
> +
>  #endif /* LAPI_XATTR_H__ */
> 
> -- 
> 2.51.0
> 
> 
> -- 
> Mailing list info: https://lists.linux.it/listinfo/ltp

-- 
Cyril Hrubis
chrubis@suse.cz

-- 
Mailing list info: https://lists.linux.it/listinfo/ltp

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

* Re: [LTP] [PATCH v2 08/10] lapi: add safe *xattrat macros
  2025-10-07  6:47 ` [LTP] [PATCH v2 08/10] lapi: add safe *xattrat macros Andrea Cervesato
@ 2025-10-08  9:36   ` Cyril Hrubis
  0 siblings, 0 replies; 28+ messages in thread
From: Cyril Hrubis @ 2025-10-08  9:36 UTC (permalink / raw)
  To: Andrea Cervesato; +Cc: ltp

Hi!
Reviewed-by: Cyril Hrubis <chrubis@suse.cz>

-- 
Cyril Hrubis
chrubis@suse.cz

-- 
Mailing list info: https://lists.linux.it/listinfo/ltp

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

* Re: [LTP] [PATCH v2 09/10] Add setxattrat01 test
  2025-10-07  6:47 ` [LTP] [PATCH v2 09/10] Add setxattrat01 test Andrea Cervesato
@ 2025-10-08  9:44   ` Cyril Hrubis
  2025-10-13  7:54     ` Andrea Cervesato via ltp
  0 siblings, 1 reply; 28+ messages in thread
From: Cyril Hrubis @ 2025-10-08  9:44 UTC (permalink / raw)
  To: Andrea Cervesato; +Cc: ltp

Hi!
> +/*\
> + * [Description]
> + *
> + * Test if setxattrat() syscall is correctly following symlink, setting a
> + * xattr on a file.
> + *
> + * [Algorithm]
> + *
> + * - create a file and the symlink pointing to it
> + * - run setxattrat() on the symlink following the pointing file
> + * - verify that file xattr has been set
> + * - verify that symlink xattr has not been set

Shouldn't this be a variant of a setxattr() test?

> + * - run setxattrat() on the symlink with AT_SYMLINK_NOFOLLOW
> + * - verify that file xattr has not been set
> + * - verify that symlink xattr has been set
> + */

And this a variant of lsetxattr() test?

-- 
Cyril Hrubis
chrubis@suse.cz

-- 
Mailing list info: https://lists.linux.it/listinfo/ltp

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

* Re: [LTP] [PATCH v2 10/10] Add setxattrat02 test
  2025-10-07  6:47 ` [LTP] [PATCH v2 10/10] Add setxattrat02 test Andrea Cervesato
@ 2025-10-08 10:02   ` Cyril Hrubis
  2025-10-10 11:05     ` Andrea Cervesato via ltp
  0 siblings, 1 reply; 28+ messages in thread
From: Cyril Hrubis @ 2025-10-08 10:02 UTC (permalink / raw)
  To: Andrea Cervesato; +Cc: ltp

Hi!
> +} tcases[] = {
> +	{
> +		.dfd = &invalid_fd,
> +		.args = &args,
> +		.args_size = sizeof(struct xattr_args),
> +		.exp_errno = EBADF,
> +		.reason = "Invalid directory file descriptor",
> +	},

Maybe it would make sense to use tst_fd to hammer the syscall with all
kinds of strange file descriptors.

> +	{
> +		.dfd = &tmpdir_fd,
> +		.at_flags = -1,
> +		.args = &args,
> +		.args_size = sizeof(struct xattr_args),
> +		.exp_errno = EINVAL,
> +		.reason = "Invalid AT flags",
> +	},
> +	{
> +		.dfd = &tmpdir_fd,
> +		.at_flags = AT_SYMLINK_NOFOLLOW + 1,
> +		.args = &args,
> +		.args_size = sizeof(struct xattr_args),
> +		.exp_errno = EINVAL,
> +		.reason = "Out of bound AT flags",
> +	},
> +	{
> +		.dfd = &tmpdir_fd,
> +		.args = &null_args,
> +		.args_size = sizeof(struct xattr_args),
> +		.exp_errno = EINVAL,
> +		.reason = "Invalid arguments",
> +	},
> +	{
> +		.dfd = &tmpdir_fd,
> +		.args = &args,
> +		.args_size = SIZE_MAX,
> +		.exp_errno = E2BIG,
> +		.reason = "Arguments size is too big",
> +	},
> +	{
> +		.dfd = &tmpdir_fd,
> +		.args = &args,
> +		.args_size = sizeof(struct xattr_args) - 1,
> +		.exp_errno = EINVAL,
> +		.reason = "Invalid arguments size",
> +	},
> +};
> +
> +static void run(unsigned int i)
> +{
> +	struct tcase *tc = &tcases[i];
> +
> +	args->flags = XATTR_CREATE;
> +	args->value = (uint64_t)XATTR_TEST_VALUE;
> +	args->size = XATTR_TEST_VALUE_SIZE;
> +
> +	TST_EXP_FAIL(tst_syscall(__NR_setxattrat,
> +		tc->dfd, FNAME, tc->at_flags, XATTR_TEST_KEY,
> +		tc->args, tc->args_size),
> +		tc->exp_errno, "%s", tc->reason);
> +}
> +
> +static void setup(void)
> +{
> +	char *tmpdir;
> +
> +	tmpdir = tst_tmpdir_path();
> +	tmpdir_fd = SAFE_OPEN(tmpdir, O_DIRECTORY);

Here as well, just use AT_FDCWD.

> +	SAFE_TOUCH(FNAME, 0777, NULL);
> +}
> +
> +static void cleanup(void)
> +{
> +	if (tmpdir_fd != -1)
> +		SAFE_CLOSE(tmpdir_fd);
> +
> +	SAFE_UNLINK(FNAME);
> +}
> +
> +static struct tst_test test = {
> +	.test = run,
> +	.setup = setup,
> +	.cleanup = cleanup,
> +	.tcnt = ARRAY_SIZE(tcases),
> +	.needs_root = 1,
> +	.needs_tmpdir = 1,
> +	.bufs = (struct tst_buffers []) {
> +		{&args, .size = sizeof(struct xattr_args)},
> +		{},
> +	}
> +};
> 
> -- 
> 2.51.0
> 
> 
> -- 
> Mailing list info: https://lists.linux.it/listinfo/ltp

-- 
Cyril Hrubis
chrubis@suse.cz

-- 
Mailing list info: https://lists.linux.it/listinfo/ltp

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

* Re: [LTP] [PATCH v2 03/10] setxattr01: add setxattrat variant
  2025-10-07 14:35       ` Cyril Hrubis
@ 2025-10-08 10:40         ` Andrea Cervesato via ltp
  2025-10-08 12:16           ` Cyril Hrubis
  0 siblings, 1 reply; 28+ messages in thread
From: Andrea Cervesato via ltp @ 2025-10-08 10:40 UTC (permalink / raw)
  To: Cyril Hrubis, Andrea Cervesato; +Cc: ltp

Hi,

On Tue Oct 7, 2025 at 4:35 PM CEST, Cyril Hrubis wrote:
> Hi!
>> > Can we please, in a subsequent patch, convert this part to our standard
>> > approach where we check for the availability in the test setup and
>> > expect the syscalls to be present if kernel is new enough?
>> 
>> What do you think it's the best way? Some of these tests have multiple
>> syscalls related to *xattrat and in this test in particular we are
>> testing 2 syscalls.
>
> The same what we do for the rest of the syscalls, introduce a
> setxattrat_supported() helper into a shared header that would call
> tst_brk(TCONF, "") if kernel is older than the version the syscall was
> added to and we got ENOSYS.
>
> We actually have to handle a few cases here:
>
> For setxattrat:
>   - ENOSYS -> kernel too old
>   - EOPNOTSUPP -> filesystem does not support extended attributes
>                   (e.g. vfat)
>
> And as for filesystem support, it looks like TMPFS has
> CONFIG_TMPFS_XATTR option so it could be enabled or disabled, however
> they should be supported for native Linux filesystems such as ext, btrfs
> or xfs.
>
> And we have to handle EOPNOTSUPP for setxattr() as well, so the test
> setup would look like:
>
> 	if (tst_variant)
> 		setxattrat_supported();
> 	else
> 		setxattr_supported();

The problem I have with this approach is that the whole kernel
implementation of setxattr() is based on setxattrat() and this test is
just moving through the same code. I would like to give a bare minimum
attention. At the same time, we need to test a syscall by calling it
with the right data, on files, that is something we are already doing
during the test. For instance, we don't have a "foo" run and we are just
going around setup() which is really slow only for filesystems testing.
In general, letting the syscall to fail inside test won't get much time.

>
> At the moment the ENOSYS branch would be covered by the fallback
> function since it calls tst_syscall() but once the function gets added
> to libc the check would no longer happen, so we need to eventually
> handle the ENOSYS in the foo_supported() function as well.
>
>> Maybe the best way would be to check for HAVE_FUNC_* declarations in
>> this case, but then fallback function would fail anyway.
>
> No this does not work, the only way how to find out if a syscall is
> supported is to call it and check the return value.




-- 
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] 28+ messages in thread

* Re: [LTP] [PATCH v2 03/10] setxattr01: add setxattrat variant
  2025-10-08 10:40         ` Andrea Cervesato via ltp
@ 2025-10-08 12:16           ` Cyril Hrubis
  0 siblings, 0 replies; 28+ messages in thread
From: Cyril Hrubis @ 2025-10-08 12:16 UTC (permalink / raw)
  To: Andrea Cervesato; +Cc: ltp

Hi!
> > And as for filesystem support, it looks like TMPFS has
> > CONFIG_TMPFS_XATTR option so it could be enabled or disabled, however
> > they should be supported for native Linux filesystems such as ext, btrfs
> > or xfs.
> >
> > And we have to handle EOPNOTSUPP for setxattr() as well, so the test
> > setup would look like:
> >
> > 	if (tst_variant)
> > 		setxattrat_supported();
> > 	else
> > 		setxattr_supported();
> 
> The problem I have with this approach is that the whole kernel
> implementation of setxattr() is based on setxattrat() and this test is
> just moving through the same code.

The problem at hand is that the *attrat() syscalls were added to 6.13,
we are going to be stuck for a decade with kernels that does not support
these. Which means that we have to make sure to check for ENOSYS for
the at family of the xattr syscalls somewhere anyways and we have to
make sure that the coverage for the older syscalls is sufficient too.

> I would like to give a bare minimum attention. At the same time, we
> need to test a syscall by calling it with the right data, on files,
> that is something we are already doing during the test. For instance,
> we don't have a "foo" run and we are just going around setup() which
> is really slow only for filesystems testing.  In general, letting the
> syscall to fail inside test won't get much time.

Technically you can call the setxattrat() with a dummy parameters, they
does not even have to be correct, because if the syscall is not
supported in the kernel you will get ENOSYS as soon as the kernel
attempts to fetch the handler form the syscall table.

-- 
Cyril Hrubis
chrubis@suse.cz

-- 
Mailing list info: https://lists.linux.it/listinfo/ltp

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

* Re: [LTP] [PATCH v2 10/10] Add setxattrat02 test
  2025-10-08 10:02   ` Cyril Hrubis
@ 2025-10-10 11:05     ` Andrea Cervesato via ltp
  0 siblings, 0 replies; 28+ messages in thread
From: Andrea Cervesato via ltp @ 2025-10-10 11:05 UTC (permalink / raw)
  To: Cyril Hrubis, Andrea Cervesato; +Cc: ltp

Hi,

On Wed Oct 8, 2025 at 12:02 PM CEST, Cyril Hrubis wrote:
> Hi!
>> +} tcases[] = {
>> +	{
>> +		.dfd = &invalid_fd,
>> +		.args = &args,
>> +		.args_size = sizeof(struct xattr_args),
>> +		.exp_errno = EBADF,
>> +		.reason = "Invalid directory file descriptor",
>> +	},
>
> Maybe it would make sense to use tst_fd to hammer the syscall with all
> kinds of strange file descriptors.
>

This makes sense for a new test, in this test it's better to keep this
approach.

>> +	{
>> +		.dfd = &tmpdir_fd,
>> +		.at_flags = -1,
>> +		.args = &args,
>> +		.args_size = sizeof(struct xattr_args),
>> +		.exp_errno = EINVAL,
>> +		.reason = "Invalid AT flags",
>> +	},
>> +	{
>> +		.dfd = &tmpdir_fd,
>> +		.at_flags = AT_SYMLINK_NOFOLLOW + 1,
>> +		.args = &args,
>> +		.args_size = sizeof(struct xattr_args),
>> +		.exp_errno = EINVAL,
>> +		.reason = "Out of bound AT flags",
>> +	},
>> +	{
>> +		.dfd = &tmpdir_fd,
>> +		.args = &null_args,
>> +		.args_size = sizeof(struct xattr_args),
>> +		.exp_errno = EINVAL,
>> +		.reason = "Invalid arguments",
>> +	},
>> +	{
>> +		.dfd = &tmpdir_fd,
>> +		.args = &args,
>> +		.args_size = SIZE_MAX,
>> +		.exp_errno = E2BIG,
>> +		.reason = "Arguments size is too big",
>> +	},
>> +	{
>> +		.dfd = &tmpdir_fd,
>> +		.args = &args,
>> +		.args_size = sizeof(struct xattr_args) - 1,
>> +		.exp_errno = EINVAL,
>> +		.reason = "Invalid arguments size",
>> +	},
>> +};
>> +
>> +static void run(unsigned int i)
>> +{
>> +	struct tcase *tc = &tcases[i];
>> +
>> +	args->flags = XATTR_CREATE;
>> +	args->value = (uint64_t)XATTR_TEST_VALUE;
>> +	args->size = XATTR_TEST_VALUE_SIZE;
>> +
>> +	TST_EXP_FAIL(tst_syscall(__NR_setxattrat,
>> +		tc->dfd, FNAME, tc->at_flags, XATTR_TEST_KEY,
>> +		tc->args, tc->args_size),
>> +		tc->exp_errno, "%s", tc->reason);
>> +}
>> +
>> +static void setup(void)
>> +{
>> +	char *tmpdir;
>> +
>> +	tmpdir = tst_tmpdir_path();
>> +	tmpdir_fd = SAFE_OPEN(tmpdir, O_DIRECTORY);
>
> Here as well, just use AT_FDCWD.
>

Ok.

>> +	SAFE_TOUCH(FNAME, 0777, NULL);
>> +}
>> +
>> +static void cleanup(void)
>> +{
>> +	if (tmpdir_fd != -1)
>> +		SAFE_CLOSE(tmpdir_fd);
>> +
>> +	SAFE_UNLINK(FNAME);
>> +}
>> +
>> +static struct tst_test test = {
>> +	.test = run,
>> +	.setup = setup,
>> +	.cleanup = cleanup,
>> +	.tcnt = ARRAY_SIZE(tcases),
>> +	.needs_root = 1,
>> +	.needs_tmpdir = 1,
>> +	.bufs = (struct tst_buffers []) {
>> +		{&args, .size = sizeof(struct xattr_args)},
>> +		{},
>> +	}
>> +};
>> 
>> -- 
>> 2.51.0
>> 
>> 
>> -- 
>> Mailing list info: https://lists.linux.it/listinfo/ltp




-- 
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] 28+ messages in thread

* Re: [LTP] [PATCH v2 09/10] Add setxattrat01 test
  2025-10-08  9:44   ` Cyril Hrubis
@ 2025-10-13  7:54     ` Andrea Cervesato via ltp
  0 siblings, 0 replies; 28+ messages in thread
From: Andrea Cervesato via ltp @ 2025-10-13  7:54 UTC (permalink / raw)
  To: Cyril Hrubis, Andrea Cervesato; +Cc: ltp

Hi!

On Wed Oct 8, 2025 at 11:44 AM CEST, Cyril Hrubis wrote:
> Hi!
>> +/*\
>> + * [Description]
>> + *
>> + * Test if setxattrat() syscall is correctly following symlink, setting a
>> + * xattr on a file.
>> + *
>> + * [Algorithm]
>> + *
>> + * - create a file and the symlink pointing to it
>> + * - run setxattrat() on the symlink following the pointing file
>> + * - verify that file xattr has been set
>> + * - verify that symlink xattr has not been set
>
> Shouldn't this be a variant of a setxattr() test?
>
>> + * - run setxattrat() on the symlink with AT_SYMLINK_NOFOLLOW
>> + * - verify that file xattr has not been set
>> + * - verify that symlink xattr has been set
>> + */
>
> And this a variant of lsetxattr() test?

This is the exact reason why I'm not yet 100% sure about coverage for
setxattrat, since most of the tests can be just variants of other
existing tests and most of the time we have code duplication.

After thinking carefully about this patch-set, I'm not sure to proceed
anymore, since the kernel itself is using setxattrat() to implement
setxattr() and lsetxattr().

-- 
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] 28+ messages in thread

end of thread, other threads:[~2025-10-13  7:55 UTC | newest]

Thread overview: 28+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-10-07  6:46 [LTP] [PATCH v2 00/10] setxattrat coverage Andrea Cervesato
2025-10-07  6:46 ` [LTP] [PATCH v2 01/10] lapi: add struct xattr_args fallback Andrea Cervesato
2025-10-07 11:50   ` Cyril Hrubis
2025-10-07  6:46 ` [LTP] [PATCH v2 02/10] lapi: add setxattrat() fallback definition Andrea Cervesato
2025-10-07 12:05   ` Cyril Hrubis
2025-10-07 15:16   ` Cyril Hrubis
2025-10-07  6:46 ` [LTP] [PATCH v2 03/10] setxattr01: add setxattrat variant Andrea Cervesato
2025-10-07 12:29   ` Cyril Hrubis
2025-10-07 13:16     ` Andrea Cervesato via ltp
2025-10-07 14:35       ` Cyril Hrubis
2025-10-08 10:40         ` Andrea Cervesato via ltp
2025-10-08 12:16           ` Cyril Hrubis
2025-10-07  6:46 ` [LTP] [PATCH v2 04/10] setxattr02: " Andrea Cervesato
2025-10-07 12:40   ` Cyril Hrubis
2025-10-07  6:46 ` [LTP] [PATCH v2 05/10] setxattr03: " Andrea Cervesato
2025-10-07 15:11   ` Cyril Hrubis
2025-10-07  6:46 ` [LTP] [PATCH v2 06/10] lapi: add getxattrat() fallback Andrea Cervesato
2025-10-07 15:21   ` Cyril Hrubis
2025-10-07  6:46 ` [LTP] [PATCH v2 07/10] lapi: add removexattrat() fallback Andrea Cervesato
2025-10-07 15:26   ` Cyril Hrubis
2025-10-07  6:47 ` [LTP] [PATCH v2 08/10] lapi: add safe *xattrat macros Andrea Cervesato
2025-10-08  9:36   ` Cyril Hrubis
2025-10-07  6:47 ` [LTP] [PATCH v2 09/10] Add setxattrat01 test Andrea Cervesato
2025-10-08  9:44   ` Cyril Hrubis
2025-10-13  7:54     ` Andrea Cervesato via ltp
2025-10-07  6:47 ` [LTP] [PATCH v2 10/10] Add setxattrat02 test Andrea Cervesato
2025-10-08 10:02   ` Cyril Hrubis
2025-10-10 11:05     ` Andrea Cervesato via ltp

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox