* [LTP] [PATCH v10 0/2] open16: allow restricted O_CREAT of FIFOs and regular files
[not found] <https://patchwork.ozlabs.org/project/ltp/patch/20260707022959.24088-2-wegao@suse.com/>
@ 2026-07-07 5:47 ` Wei Gao via ltp
2026-07-07 5:47 ` [LTP] [PATCH v10 1/2] lib: New library function tst_get_free_uid Wei Gao via ltp
2026-07-07 5:47 ` [LTP] [PATCH v10 2/2] " Wei Gao via ltp
0 siblings, 2 replies; 15+ messages in thread
From: Wei Gao via ltp @ 2026-07-07 5:47 UTC (permalink / raw)
To: ltp
v9->v10:
- Update comments for tst_get_free_uid
- Update logic of tst_get_free_uid
Wei Gao (2):
lib: New library function tst_get_free_uid
open16: allow restricted O_CREAT of FIFOs and regular files
include/tst_uid.h | 27 ++++-
lib/tst_uid.c | 28 +++++
runtest/syscalls | 1 +
testcases/kernel/syscalls/open/.gitignore | 1 +
testcases/kernel/syscalls/open/open16.c | 134 ++++++++++++++++++++++
5 files changed, 187 insertions(+), 4 deletions(-)
create mode 100644 testcases/kernel/syscalls/open/open16.c
--
2.54.0
--
Mailing list info: https://lists.linux.it/listinfo/ltp
^ permalink raw reply [flat|nested] 15+ messages in thread* [LTP] [PATCH v10 1/2] lib: New library function tst_get_free_uid
2026-07-07 5:47 ` [LTP] [PATCH v10 0/2] open16: allow restricted O_CREAT of FIFOs and regular files Wei Gao via ltp
@ 2026-07-07 5:47 ` Wei Gao via ltp
2026-07-07 7:48 ` [LTP] " linuxtestproject.agent
2026-07-21 7:41 ` [LTP] [PATCH v11 0/2] open16: allow restricted O_CREAT of FIFOs and regular files Wei Gao via ltp
2026-07-07 5:47 ` [LTP] [PATCH v10 2/2] " Wei Gao via ltp
1 sibling, 2 replies; 15+ messages in thread
From: Wei Gao via ltp @ 2026-07-07 5:47 UTC (permalink / raw)
To: ltp
Add tst_get_free_uid() to dynamically find unused UIDs for tests.
Some tests need a completely unassigned, unused UID. This is used by
open16 to verify restricted O_CREAT in sticky directories by running
as a sandboxed user with no file ownership or privileges.
Signed-off-by: Wei Gao <wegao@suse.com>
---
include/tst_uid.h | 27 +++++++++++++++++++++++----
lib/tst_uid.c | 28 ++++++++++++++++++++++++++++
2 files changed, 51 insertions(+), 4 deletions(-)
diff --git a/include/tst_uid.h b/include/tst_uid.h
index 2237ddcbf..2ffe84613 100644
--- a/include/tst_uid.h
+++ b/include/tst_uid.h
@@ -7,10 +7,29 @@
#include <sys/types.h>
-/*
- * Find unassigned gid. The skip argument can be used to ignore e.g. the main
- * group of a specific user in case it's not listed in the group file. If you
- * do not need to skip any specific gid, simply set it to 0.
+/**
+ * tst_get_free_uid() - Find a UID not assigned to any user.
+ * @skip: UID value to skip (pass 0 to skip none).
+ *
+ * Scans the password database for the first unused UID starting
+ * from 1, skipping @skip. Calls tst_brk(TBROK) if no free UID
+ * is found or a lookup error occurs.
+ *
+ * Return: An unused uid_t value.
+ */
+uid_t tst_get_free_uid_(const char *file, const int lineno, uid_t skip);
+#define tst_get_free_uid(skip) tst_get_free_uid_(__FILE__, __LINE__, (skip))
+
+/**
+ * tst_get_free_gid() - Find a GID not assigned to any group.
+ * @skip: GID value to skip (pass 0 to skip none).
+ *
+ * Scans the group database for the first unused GID starting from 1,
+ * skipping @skip. The @skip argument can be used to ignore e.g. the main
+ * group of a specific user in case it's not listed in the group file.
+ * Calls tst_brk(TBROK) if no free GID is found or a lookup error occurs.
+ *
+ * Return: An unused gid_t value.
*/
gid_t tst_get_free_gid_(const char *file, const int lineno, gid_t skip);
#define tst_get_free_gid(skip) tst_get_free_gid_(__FILE__, __LINE__, (skip))
diff --git a/lib/tst_uid.c b/lib/tst_uid.c
index af4ef8cf7..93c9b83d2 100644
--- a/lib/tst_uid.c
+++ b/lib/tst_uid.c
@@ -5,6 +5,7 @@
#include <sys/types.h>
#include <grp.h>
+#include <pwd.h>
#include <errno.h>
#define TST_NO_DEFAULT_MAIN
@@ -12,6 +13,33 @@
#include "tst_uid.h"
#define MAX_GID 32767
+#define MAX_UID 32767
+
+uid_t tst_get_free_uid_(const char *file, const int lineno, uid_t skip)
+{
+ uid_t ret;
+
+ for (ret = 1; ret < MAX_UID; ret++) {
+ if (ret == skip)
+ continue;
+
+ errno = 0;
+ if (getpwuid(ret))
+ continue;
+
+ if (errno == 0 || errno == ENOENT || errno == ESRCH) {
+ tst_res_(file, lineno, TINFO | TERRNO,
+ "Found unused UID %d", (int)ret);
+ return ret;
+ }
+
+ tst_brk_(file, lineno, TBROK | TERRNO, "User ID lookup failed");
+ return (uid_t)-1;
+ }
+
+ tst_brk_(file, lineno, TBROK, "No free user ID found");
+ return (uid_t)-1;
+}
gid_t tst_get_free_gid_(const char *file, const int lineno, gid_t skip)
{
--
2.54.0
--
Mailing list info: https://lists.linux.it/listinfo/ltp
^ permalink raw reply related [flat|nested] 15+ messages in thread* Re: [LTP] lib: New library function tst_get_free_uid
2026-07-07 5:47 ` [LTP] [PATCH v10 1/2] lib: New library function tst_get_free_uid Wei Gao via ltp
@ 2026-07-07 7:48 ` linuxtestproject.agent
2026-07-21 7:41 ` [LTP] [PATCH v11 0/2] open16: allow restricted O_CREAT of FIFOs and regular files Wei Gao via ltp
1 sibling, 0 replies; 15+ messages in thread
From: linuxtestproject.agent @ 2026-07-07 7:48 UTC (permalink / raw)
To: Wei Gao; +Cc: ltp
Hi Wei,
On Tue, 7 Jul 2026 05:47:53 +0000, Wei Gao wrote:
> lib: New library function tst_get_free_uid
--- [PATCH 1/2] ---
> +/**
> + * tst_get_free_uid() - Find a UID not assigned to any user.
> + * @skip: UID value to skip (pass 0 to skip none).
The summary line says tst_get_free_uid() but the symbol being declared
is tst_get_free_uid_(). linuxdoc requires the summary name to match the
symbol exactly, so it would fail to associate this /** block with the
implementation.
Should this be "tst_get_free_uid_() - ..." to match the symbol, or is
the intent to document the macro tst_get_free_uid() instead?
Same issue applies to the modified tst_get_free_gid() summary below.
> +uid_t tst_get_free_uid_(const char *file, const int lineno, uid_t skip);
The function has three parameters but the kernel-doc block only documents
@skip. linuxdoc expects an @name: entry for every parameter in declaration
order. @file and @lineno are missing.
Same gap in the modified tst_get_free_gid_() block.
> + if (errno == 0 || errno == ENOENT || errno == ESRCH) {
> + tst_res_(file, lineno, TINFO | TERRNO,
> + "Found unused UID %d", (int)ret);
> + return ret;
When getpwuid() returns NULL with errno set to ENOENT or ESRCH, TERRNO
appends the errno string to the message, producing output like:
"Found unused UID 5: No such file or directory". The function succeeded,
so the error string is misleading. Should TERRNO be dropped here, or
should it be conditionally omitted when errno indicates "not found"?
--- [PATCH 2/2] ---
> +Add LTP coverage for kernel commit 30aba6656f61 (Linux 4.19), which
> +introduced protection against spoofing attacks via O_CREAT of FIFOs and
> +regular files in world-writable sticky directories.
> +
> +This commit adds test cases to verify these security restrictions for
> +opening FIFOs and regular files in world-writable sticky directories.
tcase[2] uses dir_mode=0030|SVTX (group-writable sticky, level 2), which
the commit body doesn't mention. The test's own doc block describes both
"world-writable (level 1) or group-writable (level 2)" correctly — does
the body need updating to match?
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] 15+ messages in thread* [LTP] [PATCH v11 0/2] open16: allow restricted O_CREAT of FIFOs and regular files
2026-07-07 5:47 ` [LTP] [PATCH v10 1/2] lib: New library function tst_get_free_uid Wei Gao via ltp
2026-07-07 7:48 ` [LTP] " linuxtestproject.agent
@ 2026-07-21 7:41 ` Wei Gao via ltp
2026-07-21 7:41 ` [LTP] [PATCH v11 1/2] lib: New library function tst_get_free_uid Wei Gao via ltp
` (2 more replies)
1 sibling, 3 replies; 15+ messages in thread
From: Wei Gao via ltp @ 2026-07-21 7:41 UTC (permalink / raw)
To: ltp
v10->v11:
* tst_uid.h: Moved kernel-doc comments above the macros to fix parser warnings.
* tst_uid.c: Removed TERRNO from tst_get_free_gid_ success path to avoid misleading output.
* open16: Added group-writable sticky directories to the commit message to match the test.
Wei Gao (2):
lib: New library function tst_get_free_uid
open16: allow restricted O_CREAT of FIFOs and regular files
include/tst_uid.h | 29 ++++-
lib/tst_uid.c | 30 ++++-
runtest/syscalls | 1 +
testcases/kernel/syscalls/open/.gitignore | 1 +
testcases/kernel/syscalls/open/open16.c | 135 ++++++++++++++++++++++
5 files changed, 191 insertions(+), 5 deletions(-)
create mode 100644 testcases/kernel/syscalls/open/open16.c
--
2.54.0
--
Mailing list info: https://lists.linux.it/listinfo/ltp
^ permalink raw reply [flat|nested] 15+ messages in thread* [LTP] [PATCH v11 1/2] lib: New library function tst_get_free_uid
2026-07-21 7:41 ` [LTP] [PATCH v11 0/2] open16: allow restricted O_CREAT of FIFOs and regular files Wei Gao via ltp
@ 2026-07-21 7:41 ` Wei Gao via ltp
2026-07-21 8:38 ` [LTP] " linuxtestproject.agent
2026-07-21 7:41 ` [LTP] [PATCH v11 2/2] open16: allow restricted O_CREAT of FIFOs and regular files Wei Gao via ltp
2026-07-21 8:22 ` [LTP] [PATCH v11 0/2] " Andrea Cervesato via ltp
2 siblings, 1 reply; 15+ messages in thread
From: Wei Gao via ltp @ 2026-07-21 7:41 UTC (permalink / raw)
To: ltp
Add tst_get_free_uid() to dynamically find unused UIDs for tests.
Some tests need a completely unassigned, unused UID. This is used by
open16 to verify restricted O_CREAT in sticky directories by running
as a sandboxed user with no file ownership or privileges.
Signed-off-by: Wei Gao <wegao@suse.com>
---
include/tst_uid.h | 29 +++++++++++++++++++++++++----
lib/tst_uid.c | 30 +++++++++++++++++++++++++++++-
2 files changed, 54 insertions(+), 5 deletions(-)
diff --git a/include/tst_uid.h b/include/tst_uid.h
index 2237ddcbf..c73450956 100644
--- a/include/tst_uid.h
+++ b/include/tst_uid.h
@@ -7,12 +7,33 @@
#include <sys/types.h>
-/*
- * Find unassigned gid. The skip argument can be used to ignore e.g. the main
- * group of a specific user in case it's not listed in the group file. If you
- * do not need to skip any specific gid, simply set it to 0.
+uid_t tst_get_free_uid_(const char *file, const int lineno, uid_t skip);
+
+/**
+ * tst_get_free_uid() - Find a UID not assigned to any user.
+ * @skip: UID value to skip (pass 0 to skip none).
+ *
+ * Scans the password database for the first unused UID starting
+ * from 1, skipping @skip. Calls tst_brk(TBROK) if no free UID
+ * is found or a lookup error occurs.
+ *
+ * Return: An unused uid_t value.
*/
+#define tst_get_free_uid(skip) tst_get_free_uid_(__FILE__, __LINE__, (skip))
+
gid_t tst_get_free_gid_(const char *file, const int lineno, gid_t skip);
+
+/**
+ * tst_get_free_gid() - Find a GID not assigned to any group.
+ * @skip: GID value to skip (pass 0 to skip none).
+ *
+ * Scans the group database for the first unused GID starting from 1,
+ * skipping @skip. The @skip argument can be used to ignore e.g. the main
+ * group of a specific user in case it's not listed in the group file.
+ * Calls tst_brk(TBROK) if no free GID is found or a lookup error occurs.
+ *
+ * Return: An unused gid_t value.
+ */
#define tst_get_free_gid(skip) tst_get_free_gid_(__FILE__, __LINE__, (skip))
/*
diff --git a/lib/tst_uid.c b/lib/tst_uid.c
index af4ef8cf7..47c267bc4 100644
--- a/lib/tst_uid.c
+++ b/lib/tst_uid.c
@@ -5,6 +5,7 @@
#include <sys/types.h>
#include <grp.h>
+#include <pwd.h>
#include <errno.h>
#define TST_NO_DEFAULT_MAIN
@@ -12,6 +13,33 @@
#include "tst_uid.h"
#define MAX_GID 32767
+#define MAX_UID 32767
+
+uid_t tst_get_free_uid_(const char *file, const int lineno, uid_t skip)
+{
+ uid_t ret;
+
+ for (ret = 1; ret < MAX_UID; ret++) {
+ if (ret == skip)
+ continue;
+
+ errno = 0;
+ if (getpwuid(ret))
+ continue;
+
+ if (errno == 0 || errno == ENOENT || errno == ESRCH) {
+ tst_res_(file, lineno, TINFO,
+ "Found unused UID %d", (int)ret);
+ return ret;
+ }
+
+ tst_brk_(file, lineno, TBROK | TERRNO, "User ID lookup failed");
+ return (uid_t)-1;
+ }
+
+ tst_brk_(file, lineno, TBROK, "No free user ID found");
+ return (uid_t)-1;
+}
gid_t tst_get_free_gid_(const char *file, const int lineno, gid_t skip)
{
@@ -24,7 +52,7 @@ gid_t tst_get_free_gid_(const char *file, const int lineno, gid_t skip)
continue;
if (errno == 0 || errno == ENOENT || errno == ESRCH) {
- tst_res_(file, lineno, TINFO | TERRNO,
+ tst_res_(file, lineno, TINFO,
"Found unused GID %d", (int)ret);
return ret;
}
--
2.54.0
--
Mailing list info: https://lists.linux.it/listinfo/ltp
^ permalink raw reply related [flat|nested] 15+ messages in thread* Re: [LTP] lib: New library function tst_get_free_uid
2026-07-21 7:41 ` [LTP] [PATCH v11 1/2] lib: New library function tst_get_free_uid Wei Gao via ltp
@ 2026-07-21 8:38 ` linuxtestproject.agent
0 siblings, 0 replies; 15+ messages in thread
From: linuxtestproject.agent @ 2026-07-21 8:38 UTC (permalink / raw)
To: Wei Gao; +Cc: ltp
Hi Wei,
On Tue, 21 Jul 2026 07:41:28 +0000, Wei Gao wrote:
> lib: New library function tst_get_free_uid
--- [PATCH 1/2] ---
> - tst_res_(file, lineno, TINFO | TERRNO,
> + tst_res_(file, lineno, TINFO,
> "Found unused GID %d", (int)ret);
This hunk is a fix to the existing tst_get_free_gid_() success path --
removing | TERRNO so errno is not printed when a free GID is found.
That is a reasonable fix on its own, but it has no relationship to the
new tst_get_free_uid() API that the commit message describes. The commit
message does not mention it.
Could these be split into two patches?
1/3 lib/tst_uid: Remove spurious TERRNO from tst_get_free_gid success path
2/3 lib: New library function tst_get_free_uid
3/3 open16: allow restricted O_CREAT of FIFOs and regular files
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] 15+ messages in thread
* [LTP] [PATCH v11 2/2] open16: allow restricted O_CREAT of FIFOs and regular files
2026-07-21 7:41 ` [LTP] [PATCH v11 0/2] open16: allow restricted O_CREAT of FIFOs and regular files Wei Gao via ltp
2026-07-21 7:41 ` [LTP] [PATCH v11 1/2] lib: New library function tst_get_free_uid Wei Gao via ltp
@ 2026-07-21 7:41 ` Wei Gao via ltp
2026-07-21 8:22 ` [LTP] [PATCH v11 0/2] " Andrea Cervesato via ltp
2 siblings, 0 replies; 15+ messages in thread
From: Wei Gao via ltp @ 2026-07-21 7:41 UTC (permalink / raw)
To: ltp
Add LTP coverage for kernel commit 30aba6656f61 (Linux 4.19), which
introduced protection against spoofing attacks via O_CREAT of FIFOs and
regular files in world-writable or group-writable sticky directories.
This commit adds test cases to verify these security restrictions (Level 1
and Level 2 protections) for opening FIFOs and regular files in world-writable
or group-writable sticky directories when the file is not owned by the opener.
Signed-off-by: Wei Gao <wegao@suse.com>
---
runtest/syscalls | 1 +
testcases/kernel/syscalls/open/.gitignore | 1 +
testcases/kernel/syscalls/open/open16.c | 135 ++++++++++++++++++++++
3 files changed, 137 insertions(+)
create mode 100644 testcases/kernel/syscalls/open/open16.c
diff --git a/runtest/syscalls b/runtest/syscalls
index a021c79da..4fd62efa8 100644
--- a/runtest/syscalls
+++ b/runtest/syscalls
@@ -1008,6 +1008,7 @@ open12 open12
open13 open13
open14 open14
open15 open15
+open16 open16
openat01 openat01
openat02 openat02
diff --git a/testcases/kernel/syscalls/open/.gitignore b/testcases/kernel/syscalls/open/.gitignore
index af5997572..d2cacc02e 100644
--- a/testcases/kernel/syscalls/open/.gitignore
+++ b/testcases/kernel/syscalls/open/.gitignore
@@ -13,3 +13,4 @@
/open13
/open14
/open15
+/open16
diff --git a/testcases/kernel/syscalls/open/open16.c b/testcases/kernel/syscalls/open/open16.c
new file mode 100644
index 000000000..c74601032
--- /dev/null
+++ b/testcases/kernel/syscalls/open/open16.c
@@ -0,0 +1,135 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright (c) 2026 Wei Gao <wegao@suse.com>
+ */
+
+/*\
+ * Verify restricted opening (:manpage:`open(2)` and :manpage:`openat(2)`) of
+ * FIFOs and regular files in sticky directories. This test covers the positive
+ * case where access is allowed when protection is disabled (level 0), and the
+ * negative cases where access is disallowed (EACCES) in world-writable (level
+ * 1) or group-writable (level 2) sticky directories when the file is not owned
+ * by the opener.
+ *
+ * This test requires root to modify /proc/sys/fs/protected_* sysctls and
+ * to manage file ownership and permissions in sticky directories.
+ */
+
+#include <pwd.h>
+#include <stdlib.h>
+#include "tst_test.h"
+#include "tst_safe_file_at.h"
+#include "tst_uid.h"
+
+#define DIR "ltp_tmp_check1"
+#define TEST_FILE "test_file_1"
+#define TEST_FIFO "test_fifo_1"
+#define PROTECTED_REGULAR "/proc/sys/fs/protected_regular"
+#define PROTECTED_FIFOS "/proc/sys/fs/protected_fifos"
+#define TEST_FIFO_PATH DIR "/" TEST_FIFO
+
+static int dir_fd = -1;
+static uid_t uid1, uid2;
+static gid_t gid1;
+
+static struct tcase {
+ char *level;
+ int exp_errno;
+ uid_t owner_uid;
+ int use_nobody_gid;
+ mode_t dir_mode;
+} tcases[] = {
+ {"0", 0, 0, 0, 0777 | S_ISVTX},
+ {"1", EACCES, 0, 0, 0777 | S_ISVTX},
+ {"2", EACCES, -1, 1, 0030 | S_ISVTX},
+};
+
+static void verify_open(unsigned int n)
+{
+ struct tcase *tc = &tcases[n];
+ pid_t pid;
+
+ SAFE_FILE_PRINTF(PROTECTED_REGULAR, "%s", tc->level);
+ SAFE_FILE_PRINTF(PROTECTED_FIFOS, "%s", tc->level);
+
+ if (tc->owner_uid != (uid_t)-1 || tc->use_nobody_gid) {
+ gid_t gid = tc->use_nobody_gid ? gid1 : 0;
+
+ SAFE_CHOWN(DIR, tc->owner_uid, gid);
+ }
+
+ if (tc->dir_mode)
+ SAFE_CHMOD(DIR, tc->dir_mode);
+
+ pid = SAFE_FORK();
+ if (!pid) {
+ SAFE_SETGID(gid1);
+ SAFE_SETUID(uid2);
+
+ if (tc->exp_errno) {
+ TST_EXP_FAIL2(openat(dir_fd, TEST_FILE, O_RDWR | O_CREAT, 0777),
+ tc->exp_errno, "openat %s (Level %s)", TEST_FILE, tc->level);
+ TST_EXP_FAIL2(open(TEST_FIFO_PATH, O_RDWR | O_CREAT, 0777),
+ tc->exp_errno, "open %s (Level %s)", TEST_FIFO, tc->level);
+ } else {
+ int fd = TST_EXP_FD(openat(dir_fd, TEST_FILE, O_CREAT | O_RDWR, 0777));
+
+ if (TST_PASS)
+ SAFE_CLOSE(fd);
+
+ fd = TST_EXP_FD(open(TEST_FIFO_PATH, O_RDWR | O_CREAT, 0777));
+ if (TST_PASS)
+ SAFE_CLOSE(fd);
+ }
+
+ exit(0);
+ }
+
+ SAFE_WAITPID(pid, NULL, 0);
+}
+
+static void setup(void)
+{
+ struct passwd *pw;
+
+ pw = SAFE_GETPWNAM("nobody");
+ uid1 = pw->pw_uid;
+ gid1 = pw->pw_gid;
+ uid2 = tst_get_free_uid(uid1);
+
+ umask(0);
+ SAFE_MKDIR(DIR, 0777 | S_ISVTX);
+ dir_fd = SAFE_OPEN(DIR, O_DIRECTORY);
+
+ int fd = SAFE_OPENAT(dir_fd, TEST_FILE, O_CREAT | O_RDWR, 0777);
+
+ SAFE_CLOSE(fd);
+ SAFE_MKFIFO(TEST_FIFO_PATH, 0777);
+ SAFE_CHOWN(TEST_FIFO_PATH, uid1, gid1);
+ SAFE_CHOWN(DIR "/" TEST_FILE, uid1, gid1);
+}
+
+static void cleanup(void)
+{
+ if (dir_fd != -1)
+ SAFE_CLOSE(dir_fd);
+}
+
+static struct tst_test test = {
+ .setup = setup,
+ .cleanup = cleanup,
+ .needs_root = 1,
+ .tcnt = ARRAY_SIZE(tcases),
+ .test = verify_open,
+ .needs_tmpdir = 1,
+ .forks_child = 1,
+ .save_restore = (const struct tst_path_val[]) {
+ {PROTECTED_REGULAR, NULL, TST_SR_TCONF},
+ {PROTECTED_FIFOS, NULL, TST_SR_TCONF},
+ {}
+ },
+ .tags = (const struct tst_tag[]) {
+ {"linux-git", "30aba6656f61"},
+ {}
+ }
+};
--
2.54.0
--
Mailing list info: https://lists.linux.it/listinfo/ltp
^ permalink raw reply related [flat|nested] 15+ messages in thread* Re: [LTP] [PATCH v11 0/2] open16: allow restricted O_CREAT of FIFOs and regular files
2026-07-21 7:41 ` [LTP] [PATCH v11 0/2] open16: allow restricted O_CREAT of FIFOs and regular files Wei Gao via ltp
2026-07-21 7:41 ` [LTP] [PATCH v11 1/2] lib: New library function tst_get_free_uid Wei Gao via ltp
2026-07-21 7:41 ` [LTP] [PATCH v11 2/2] open16: allow restricted O_CREAT of FIFOs and regular files Wei Gao via ltp
@ 2026-07-21 8:22 ` Andrea Cervesato via ltp
2026-07-21 8:55 ` Wei Gao via ltp
2 siblings, 1 reply; 15+ messages in thread
From: Andrea Cervesato via ltp @ 2026-07-21 8:22 UTC (permalink / raw)
To: Wei Gao; +Cc: ltp
Hi Wei,
can you please send the patch-set in a new thread, instead of replying
to the old version? we are having a really long thread in the lore
instance and it's getting diffciult to read.
https://lore.kernel.org/ltp/20250516151028.1254207-1-wegao@suse.com/
Thanks,
--
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] 15+ messages in thread
* [LTP] [PATCH v10 2/2] open16: allow restricted O_CREAT of FIFOs and regular files
2026-07-07 5:47 ` [LTP] [PATCH v10 0/2] open16: allow restricted O_CREAT of FIFOs and regular files Wei Gao via ltp
2026-07-07 5:47 ` [LTP] [PATCH v10 1/2] lib: New library function tst_get_free_uid Wei Gao via ltp
@ 2026-07-07 5:47 ` Wei Gao via ltp
1 sibling, 0 replies; 15+ messages in thread
From: Wei Gao via ltp @ 2026-07-07 5:47 UTC (permalink / raw)
To: ltp
Add LTP coverage for kernel commit 30aba6656f61 (Linux 4.19), which
introduced protection against spoofing attacks via O_CREAT of FIFOs and
regular files in world-writable sticky directories.
This commit adds test cases to verify these security restrictions for
opening FIFOs and regular files in world-writable sticky directories.
Signed-off-by: Wei Gao <wegao@suse.com>
---
runtest/syscalls | 1 +
testcases/kernel/syscalls/open/.gitignore | 1 +
testcases/kernel/syscalls/open/open16.c | 134 ++++++++++++++++++++++
3 files changed, 136 insertions(+)
create mode 100644 testcases/kernel/syscalls/open/open16.c
diff --git a/runtest/syscalls b/runtest/syscalls
index a021c79da..4fd62efa8 100644
--- a/runtest/syscalls
+++ b/runtest/syscalls
@@ -1008,6 +1008,7 @@ open12 open12
open13 open13
open14 open14
open15 open15
+open16 open16
openat01 openat01
openat02 openat02
diff --git a/testcases/kernel/syscalls/open/.gitignore b/testcases/kernel/syscalls/open/.gitignore
index af5997572..d2cacc02e 100644
--- a/testcases/kernel/syscalls/open/.gitignore
+++ b/testcases/kernel/syscalls/open/.gitignore
@@ -13,3 +13,4 @@
/open13
/open14
/open15
+/open16
diff --git a/testcases/kernel/syscalls/open/open16.c b/testcases/kernel/syscalls/open/open16.c
new file mode 100644
index 000000000..2e45d7f12
--- /dev/null
+++ b/testcases/kernel/syscalls/open/open16.c
@@ -0,0 +1,134 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright (c) 2026 Wei Gao <wegao@suse.com>
+ */
+
+/*\
+ * Verify restricted opening of FIFOs and regular files in sticky directories.
+ * This test covers the positive case where access is allowed when protection
+ * is disabled (level 0), and the negative cases where access is disallowed
+ * (EACCES) in world-writable (level 1) or group-writable (level 2) sticky
+ * directories when the file is not owned by the opener.
+ *
+ * This test requires root to modify /proc/sys/fs/protected_* sysctls and
+ * to manage file ownership and permissions in sticky directories.
+ */
+
+#include <pwd.h>
+#include <stdlib.h>
+#include "tst_test.h"
+#include "tst_safe_file_at.h"
+#include "tst_uid.h"
+
+#define DIR "ltp_tmp_check1"
+#define TEST_FILE "test_file_1"
+#define TEST_FIFO "test_fifo_1"
+#define PROTECTED_REGULAR "/proc/sys/fs/protected_regular"
+#define PROTECTED_FIFOS "/proc/sys/fs/protected_fifos"
+#define TEST_FIFO_PATH DIR "/" TEST_FIFO
+
+static int dir_fd = -1;
+static uid_t uid1, uid2;
+static gid_t gid1;
+
+static struct tcase {
+ char *level;
+ int exp_errno;
+ uid_t owner_uid;
+ int use_nobody_gid;
+ mode_t dir_mode;
+} tcases[] = {
+ {"0", 0, 0, 0, 0777 | S_ISVTX},
+ {"1", EACCES, 0, 0, 0777 | S_ISVTX},
+ {"2", EACCES, -1, 1, 0030 | S_ISVTX},
+};
+
+static void verify_open(unsigned int n)
+{
+ struct tcase *tc = &tcases[n];
+ pid_t pid;
+
+ SAFE_FILE_PRINTF(PROTECTED_REGULAR, "%s", tc->level);
+ SAFE_FILE_PRINTF(PROTECTED_FIFOS, "%s", tc->level);
+
+ if (tc->owner_uid != (uid_t)-1 || tc->use_nobody_gid) {
+ gid_t gid = tc->use_nobody_gid ? gid1 : 0;
+
+ SAFE_CHOWN(DIR, tc->owner_uid, gid);
+ }
+
+ if (tc->dir_mode)
+ SAFE_CHMOD(DIR, tc->dir_mode);
+
+ pid = SAFE_FORK();
+ if (!pid) {
+ SAFE_SETGID(gid1);
+ SAFE_SETUID(uid2);
+
+ if (tc->exp_errno) {
+ TST_EXP_FAIL2(openat(dir_fd, TEST_FILE, O_RDWR | O_CREAT, 0777),
+ tc->exp_errno, "openat %s (Level %s)", TEST_FILE, tc->level);
+ TST_EXP_FAIL2(open(TEST_FIFO_PATH, O_RDWR | O_CREAT, 0777),
+ tc->exp_errno, "open %s (Level %s)", TEST_FIFO, tc->level);
+ } else {
+ int fd = TST_EXP_FD(openat(dir_fd, TEST_FILE, O_CREAT | O_RDWR, 0777));
+
+ if (TST_PASS)
+ SAFE_CLOSE(fd);
+
+ fd = TST_EXP_FD(open(TEST_FIFO_PATH, O_RDWR | O_CREAT, 0777));
+ if (TST_PASS)
+ SAFE_CLOSE(fd);
+ }
+
+ exit(0);
+ }
+
+ SAFE_WAITPID(pid, NULL, 0);
+}
+
+static void setup(void)
+{
+ struct passwd *pw;
+
+ pw = SAFE_GETPWNAM("nobody");
+ uid1 = pw->pw_uid;
+ gid1 = pw->pw_gid;
+ uid2 = tst_get_free_uid(uid1);
+
+ umask(0);
+ SAFE_MKDIR(DIR, 0777 | S_ISVTX);
+ dir_fd = SAFE_OPEN(DIR, O_DIRECTORY);
+
+ int fd = SAFE_OPENAT(dir_fd, TEST_FILE, O_CREAT | O_RDWR, 0777);
+
+ SAFE_CLOSE(fd);
+ SAFE_MKFIFO(TEST_FIFO_PATH, 0777);
+ SAFE_CHOWN(TEST_FIFO_PATH, uid1, gid1);
+ SAFE_CHOWN(DIR "/" TEST_FILE, uid1, gid1);
+}
+
+static void cleanup(void)
+{
+ if (dir_fd != -1)
+ SAFE_CLOSE(dir_fd);
+}
+
+static struct tst_test test = {
+ .setup = setup,
+ .cleanup = cleanup,
+ .needs_root = 1,
+ .tcnt = ARRAY_SIZE(tcases),
+ .test = verify_open,
+ .needs_tmpdir = 1,
+ .forks_child = 1,
+ .save_restore = (const struct tst_path_val[]) {
+ {PROTECTED_REGULAR, NULL, TST_SR_TCONF},
+ {PROTECTED_FIFOS, NULL, TST_SR_TCONF},
+ {}
+ },
+ .tags = (const struct tst_tag[]) {
+ {"linux-git", "30aba6656f61"},
+ {}
+ }
+};
--
2.54.0
--
Mailing list info: https://lists.linux.it/listinfo/ltp
^ permalink raw reply related [flat|nested] 15+ messages in thread
* [LTP] [PATCH v9 1/2] lib: New library function tst_get_free_uid
@ 2026-07-07 2:29 Wei Gao via ltp
2026-07-07 3:34 ` [LTP] " linuxtestproject.agent
0 siblings, 1 reply; 15+ messages in thread
From: Wei Gao via ltp @ 2026-07-07 2:29 UTC (permalink / raw)
To: ltp
Add tst_get_free_uid() to dynamically find unused UIDs for tests.
Signed-off-by: Wei Gao <wegao@suse.com>
---
include/tst_uid.h | 7 +++++--
lib/tst_uid.c | 26 ++++++++++++++++++++++++++
2 files changed, 31 insertions(+), 2 deletions(-)
diff --git a/include/tst_uid.h b/include/tst_uid.h
index 2237ddcbf..394cb3edc 100644
--- a/include/tst_uid.h
+++ b/include/tst_uid.h
@@ -8,10 +8,13 @@
#include <sys/types.h>
/*
- * Find unassigned gid. The skip argument can be used to ignore e.g. the main
+ * Find unassigned uid/gid. The skip argument can be used to ignore e.g. the main
* group of a specific user in case it's not listed in the group file. If you
- * do not need to skip any specific gid, simply set it to 0.
+ * do not need to skip any specific id, simply set it to 0.
*/
+uid_t tst_get_free_uid_(const char *file, const int lineno, uid_t skip);
+#define tst_get_free_uid(skip) tst_get_free_uid_(__FILE__, __LINE__, (skip))
+
gid_t tst_get_free_gid_(const char *file, const int lineno, gid_t skip);
#define tst_get_free_gid(skip) tst_get_free_gid_(__FILE__, __LINE__, (skip))
diff --git a/lib/tst_uid.c b/lib/tst_uid.c
index af4ef8cf7..deff17085 100644
--- a/lib/tst_uid.c
+++ b/lib/tst_uid.c
@@ -5,6 +5,7 @@
#include <sys/types.h>
#include <grp.h>
+#include <pwd.h>
#include <errno.h>
#define TST_NO_DEFAULT_MAIN
@@ -12,6 +13,31 @@
#include "tst_uid.h"
#define MAX_GID 32767
+#define MAX_UID 32767
+
+uid_t tst_get_free_uid_(const char *file, const int lineno, uid_t skip)
+{
+ uid_t ret;
+
+ errno = 0;
+
+ for (ret = 1; ret < MAX_UID; ret++) {
+ if (ret == skip || getpwuid(ret))
+ continue;
+
+ if (errno == 0 || errno == ENOENT || errno == ESRCH) {
+ tst_res_(file, lineno, TINFO | TERRNO,
+ "Found unused UID %d", (int)ret);
+ return ret;
+ }
+
+ tst_brk_(file, lineno, TBROK|TERRNO, "User ID lookup failed");
+ return (uid_t)-1;
+ }
+
+ tst_brk_(file, lineno, TBROK, "No free user ID found");
+ return (uid_t)-1;
+}
gid_t tst_get_free_gid_(const char *file, const int lineno, gid_t skip)
{
--
2.54.0
--
Mailing list info: https://lists.linux.it/listinfo/ltp
^ permalink raw reply related [flat|nested] 15+ messages in thread* Re: [LTP] lib: New library function tst_get_free_uid
2026-07-07 2:29 [LTP] [PATCH v9 1/2] lib: New library function tst_get_free_uid Wei Gao via ltp
@ 2026-07-07 3:34 ` linuxtestproject.agent
0 siblings, 0 replies; 15+ messages in thread
From: linuxtestproject.agent @ 2026-07-07 3:34 UTC (permalink / raw)
To: Wei Gao; +Cc: ltp
Hi Wei,
On Tue, 07 Jul 2026 02:29:41 +0000, Wei Gao wrote:
> lib: New library function tst_get_free_uid
--- [PATCH 1/2] ---
> Add tst_get_free_uid() to dynamically find unused UIDs for tests.
The body restates what the subject already says. What scenario or
test requires a dynamically allocated free UID that tst_get_uids()
cannot cover?
> +uid_t tst_get_free_uid_(const char *file, const int lineno, uid_t skip);
> +#define tst_get_free_uid(skip) tst_get_free_uid_(__FILE__, __LINE__, (skip))
tst_get_free_uid_() is a new public function in lib/ and include/.
LTP documentation rules require a kernel-doc /** ... */ comment for
new public symbols there. Something like:
/**
* tst_get_free_uid() - Find a UID not assigned to any user.
* @skip: UID value to skip (pass 0 to skip none).
*
* Scans the password database for the first unused UID starting
* from 1, skipping @skip. Calls tst_brk(TBROK) if no free UID
* is found or a lookup error occurs.
*
* Return: An unused uid_t value.
*/
> - * Find unassigned gid. The skip argument can be used to ignore e.g. the main
> + * Find unassigned uid/gid. The skip argument can be used to ignore e.g. the main
> * group of a specific user in case it's not listed in the group file. If you
> - * do not need to skip any specific gid, simply set it to 0.
> + * do not need to skip any specific id, simply set it to 0.
"not listed in the group file" applies to GIDs only. UIDs live in
the password database (/etc/passwd or NSS passwd). The comment
should say "password or group file", or be split per-function.
> +uid_t tst_get_free_uid_(const char *file, const int lineno, uid_t skip)
> +{
> + uid_t ret;
> +
> + errno = 0;
> +
> + for (ret = 1; ret < MAX_UID; ret++) {
> + if (ret == skip || getpwuid(ret))
> + continue;
> +
> + if (errno == 0 || errno == ENOENT || errno == ESRCH) {
POSIX requires callers to set errno = 0 before each call to
getpwuid() so that a NULL return with non-zero errno means error
rather than "entry not found". The reset here is done once before
the loop. If a successful getpwuid() call for an earlier UID leaves
errno non-zero (POSIX does not guarantee it is cleared on success),
the next NULL-returning call could be misclassified as an error and
trigger the tst_brk() path below.
A per-iteration reset:
errno = 0;
if (ret == skip || getpwuid(ret))
continue;
would match the POSIX-recommended pattern and make the intent clear.
Verdict - Needs revision
Pre-existing issues:
tst_get_free_gid_() in lib/tst_uid.c has the same errno-reset issue
described above (errno set once before the loop, not before each
getgrgid() call).
---
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] 15+ messages in thread
* [LTP] [PATCH v8 1/2] lib: New library function tst_get_free_uid
@ 2026-04-16 0:55 Wei Gao via ltp
2026-04-16 2:43 ` [LTP] " linuxtestproject.agent
0 siblings, 1 reply; 15+ messages in thread
From: Wei Gao via ltp @ 2026-04-16 0:55 UTC (permalink / raw)
To: ltp
Add tst_get_free_uid() to dynamically find unused UIDs for tests.
Signed-off-by: Wei Gao <wegao@suse.com>
---
include/tst_uid.h | 7 +++++--
lib/tst_uid.c | 26 ++++++++++++++++++++++++++
2 files changed, 31 insertions(+), 2 deletions(-)
diff --git a/include/tst_uid.h b/include/tst_uid.h
index 2237ddcbf..394cb3edc 100644
--- a/include/tst_uid.h
+++ b/include/tst_uid.h
@@ -8,10 +8,13 @@
#include <sys/types.h>
/*
- * Find unassigned gid. The skip argument can be used to ignore e.g. the main
+ * Find unassigned uid/gid. The skip argument can be used to ignore e.g. the main
* group of a specific user in case it's not listed in the group file. If you
- * do not need to skip any specific gid, simply set it to 0.
+ * do not need to skip any specific id, simply set it to 0.
*/
+uid_t tst_get_free_uid_(const char *file, const int lineno, uid_t skip);
+#define tst_get_free_uid(skip) tst_get_free_uid_(__FILE__, __LINE__, (skip))
+
gid_t tst_get_free_gid_(const char *file, const int lineno, gid_t skip);
#define tst_get_free_gid(skip) tst_get_free_gid_(__FILE__, __LINE__, (skip))
diff --git a/lib/tst_uid.c b/lib/tst_uid.c
index af4ef8cf7..deff17085 100644
--- a/lib/tst_uid.c
+++ b/lib/tst_uid.c
@@ -5,6 +5,7 @@
#include <sys/types.h>
#include <grp.h>
+#include <pwd.h>
#include <errno.h>
#define TST_NO_DEFAULT_MAIN
@@ -12,6 +13,31 @@
#include "tst_uid.h"
#define MAX_GID 32767
+#define MAX_UID 32767
+
+uid_t tst_get_free_uid_(const char *file, const int lineno, uid_t skip)
+{
+ uid_t ret;
+
+ errno = 0;
+
+ for (ret = 1; ret < MAX_UID; ret++) {
+ if (ret == skip || getpwuid(ret))
+ continue;
+
+ if (errno == 0 || errno == ENOENT || errno == ESRCH) {
+ tst_res_(file, lineno, TINFO | TERRNO,
+ "Found unused UID %d", (int)ret);
+ return ret;
+ }
+
+ tst_brk_(file, lineno, TBROK|TERRNO, "User ID lookup failed");
+ return (uid_t)-1;
+ }
+
+ tst_brk_(file, lineno, TBROK, "No free user ID found");
+ return (uid_t)-1;
+}
gid_t tst_get_free_gid_(const char *file, const int lineno, gid_t skip)
{
--
2.52.0
--
Mailing list info: https://lists.linux.it/listinfo/ltp
^ permalink raw reply related [flat|nested] 15+ messages in thread* Re: [LTP] lib: New library function tst_get_free_uid
2026-04-16 0:55 [LTP] [PATCH v8 1/2] " Wei Gao via ltp
@ 2026-04-16 2:43 ` linuxtestproject.agent
2026-04-16 4:15 ` Wei Gao via ltp
0 siblings, 1 reply; 15+ messages in thread
From: linuxtestproject.agent @ 2026-04-16 2:43 UTC (permalink / raw)
To: Wei Gao; +Cc: ltp
Hi Wei,
On Thu, 16 Apr 2026 00:55:23 +0000, Wei Gao via ltp wrote:
> [PATCH 2/2] open16: allow restricted O_CREAT of FIFOs and regular files
>
> This commit adds test cases to verify the security restrictions for opening
> FIFOs and regular files in world-writable sticky directories.
The body only describes what the test does, not why it is being added.
State the motivation explicitly, e.g. "Add LTP coverage for kernel commit
30aba6656f61 (Linux 4.19), which introduced protection against spoofing
attacks via O_CREAT of FIFOs and regular files in world-writable sticky
directories."
[...]
Regards,
LTP AI Reviewer
---
Note:
Our agent completed the review of the patch.
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.
--
Mailing list info: https://lists.linux.it/listinfo/ltp
^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [LTP] lib: New library function tst_get_free_uid
2026-04-16 2:43 ` [LTP] " linuxtestproject.agent
@ 2026-04-16 4:15 ` Wei Gao via ltp
0 siblings, 0 replies; 15+ messages in thread
From: Wei Gao via ltp @ 2026-04-16 4:15 UTC (permalink / raw)
To: linuxtestproject.agent; +Cc: ltp
On Thu, Apr 16, 2026 at 02:43:24AM +0000, linuxtestproject.agent@gmail.com wrote:
> Hi Wei,
>
> On Thu, 16 Apr 2026 00:55:23 +0000, Wei Gao via ltp wrote:
> > [PATCH 2/2] open16: allow restricted O_CREAT of FIFOs and regular files
> >
> > This commit adds test cases to verify the security restrictions for opening
> > FIFOs and regular files in world-writable sticky directories.
>
> The body only describes what the test does, not why it is being added.
> State the motivation explicitly, e.g. "Add LTP coverage for kernel commit
> 30aba6656f61 (Linux 4.19), which introduced protection against spoofing
> attacks via O_CREAT of FIFOs and regular files in world-writable sticky
> directories."
Patchset cover letter and the tags within the test code (which already reference
linux-git 30aba6656f61) clearly established the purpose
>
> [...]
>
> Regards,
> LTP AI Reviewer
>
> ---
> Note:
>
> Our agent completed the review of the patch.
>
> 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.
--
Mailing list info: https://lists.linux.it/listinfo/ltp
^ permalink raw reply [flat|nested] 15+ messages in thread
* [LTP] [PATCH v7 1/2] lib: New library function tst_get_free_uid
@ 2026-04-15 10:37 Wei Gao via ltp
2026-04-15 11:08 ` [LTP] " linuxtestproject.agent
0 siblings, 1 reply; 15+ messages in thread
From: Wei Gao via ltp @ 2026-04-15 10:37 UTC (permalink / raw)
To: ltp
Add tst_get_free_uid() to dynamically find unused UIDs for tests.
Signed-off-by: Wei Gao <wegao@suse.com>
---
include/tst_uid.h | 7 +++++--
lib/tst_uid.c | 26 ++++++++++++++++++++++++++
2 files changed, 31 insertions(+), 2 deletions(-)
diff --git a/include/tst_uid.h b/include/tst_uid.h
index 2237ddcbf..394cb3edc 100644
--- a/include/tst_uid.h
+++ b/include/tst_uid.h
@@ -8,10 +8,13 @@
#include <sys/types.h>
/*
- * Find unassigned gid. The skip argument can be used to ignore e.g. the main
+ * Find unassigned uid/gid. The skip argument can be used to ignore e.g. the main
* group of a specific user in case it's not listed in the group file. If you
- * do not need to skip any specific gid, simply set it to 0.
+ * do not need to skip any specific id, simply set it to 0.
*/
+uid_t tst_get_free_uid_(const char *file, const int lineno, uid_t skip);
+#define tst_get_free_uid(skip) tst_get_free_uid_(__FILE__, __LINE__, (skip))
+
gid_t tst_get_free_gid_(const char *file, const int lineno, gid_t skip);
#define tst_get_free_gid(skip) tst_get_free_gid_(__FILE__, __LINE__, (skip))
diff --git a/lib/tst_uid.c b/lib/tst_uid.c
index af4ef8cf7..deff17085 100644
--- a/lib/tst_uid.c
+++ b/lib/tst_uid.c
@@ -5,6 +5,7 @@
#include <sys/types.h>
#include <grp.h>
+#include <pwd.h>
#include <errno.h>
#define TST_NO_DEFAULT_MAIN
@@ -12,6 +13,31 @@
#include "tst_uid.h"
#define MAX_GID 32767
+#define MAX_UID 32767
+
+uid_t tst_get_free_uid_(const char *file, const int lineno, uid_t skip)
+{
+ uid_t ret;
+
+ errno = 0;
+
+ for (ret = 1; ret < MAX_UID; ret++) {
+ if (ret == skip || getpwuid(ret))
+ continue;
+
+ if (errno == 0 || errno == ENOENT || errno == ESRCH) {
+ tst_res_(file, lineno, TINFO | TERRNO,
+ "Found unused UID %d", (int)ret);
+ return ret;
+ }
+
+ tst_brk_(file, lineno, TBROK|TERRNO, "User ID lookup failed");
+ return (uid_t)-1;
+ }
+
+ tst_brk_(file, lineno, TBROK, "No free user ID found");
+ return (uid_t)-1;
+}
gid_t tst_get_free_gid_(const char *file, const int lineno, gid_t skip)
{
--
2.52.0
--
Mailing list info: https://lists.linux.it/listinfo/ltp
^ permalink raw reply related [flat|nested] 15+ messages in thread* Re: [LTP] lib: New library function tst_get_free_uid
2026-04-15 10:37 [LTP] [PATCH v7 1/2] " Wei Gao via ltp
@ 2026-04-15 11:08 ` linuxtestproject.agent
0 siblings, 0 replies; 15+ messages in thread
From: linuxtestproject.agent @ 2026-04-15 11:08 UTC (permalink / raw)
To: Wei Gao; +Cc: ltp
Hi Wei,
On Wed, 15 Apr 2026, Wei Gao wrote:
> open16: allow restricted O_CREAT of FIFOs and regular files
--- [PATCH 2/2] ---
On Wed, 15 Apr 2026, Wei Gao wrote:
> open16: allow restricted O_CREAT of FIFOs and regular files
> + SAFE_FILE_PRINTF(PROTECTED_REGULAR, "2");
> + SAFE_FILE_PRINTF(PROTECTED_FIFOS, "2");
> + SAFE_CHMOD(DIR, 0020 | S_ISVTX);
> +
> + if (!SAFE_FORK()) {
> + SAFE_SETUID(uid2);
> + TST_EXP_FAIL(openat(dir_fd, TEST_FILE, O_RDWR | O_CREAT, 0777), EACCES);
> + TST_EXP_FAIL(open(TEST_FIFO_PATH, O_RDWR | O_CREAT, 0777), EACCES);
uid2 is a free (unused) UID with no group memberships. With mode 0020|S_ISVTX
the "other" bits are 0, so the kernel's DAC check rejects openat/open before
reaching the protected_regular/protected_fifos logic in may_open(). EACCES
fires for the wrong reason.
For a valid level-2 test the directory needs group-execute and group-write
(e.g. 0770|S_ISVTX), and uid2 must be placed in the directory's owning group
so it can access the directory but is still blocked by the protection check.
---
Note:
Our agent completed the review of the patch. The full review can be
found at: <review_url>
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] 15+ messages in thread
* [LTP] [PATCH v6 1/2] lib: New library function tst_get_free_uid
@ 2026-04-15 6:07 Wei Gao via ltp
2026-04-15 7:54 ` [LTP] " linuxtestproject.agent
0 siblings, 1 reply; 15+ messages in thread
From: Wei Gao via ltp @ 2026-04-15 6:07 UTC (permalink / raw)
To: ltp
Signed-off-by: Wei Gao <wegao@suse.com>
---
include/tst_uid.h | 7 +++++--
lib/tst_uid.c | 26 ++++++++++++++++++++++++++
2 files changed, 31 insertions(+), 2 deletions(-)
diff --git a/include/tst_uid.h b/include/tst_uid.h
index 2237ddcbf..394cb3edc 100644
--- a/include/tst_uid.h
+++ b/include/tst_uid.h
@@ -8,10 +8,13 @@
#include <sys/types.h>
/*
- * Find unassigned gid. The skip argument can be used to ignore e.g. the main
+ * Find unassigned uid/gid. The skip argument can be used to ignore e.g. the main
* group of a specific user in case it's not listed in the group file. If you
- * do not need to skip any specific gid, simply set it to 0.
+ * do not need to skip any specific id, simply set it to 0.
*/
+uid_t tst_get_free_uid_(const char *file, const int lineno, uid_t skip);
+#define tst_get_free_uid(skip) tst_get_free_uid_(__FILE__, __LINE__, (skip))
+
gid_t tst_get_free_gid_(const char *file, const int lineno, gid_t skip);
#define tst_get_free_gid(skip) tst_get_free_gid_(__FILE__, __LINE__, (skip))
diff --git a/lib/tst_uid.c b/lib/tst_uid.c
index af4ef8cf7..deff17085 100644
--- a/lib/tst_uid.c
+++ b/lib/tst_uid.c
@@ -5,6 +5,7 @@
#include <sys/types.h>
#include <grp.h>
+#include <pwd.h>
#include <errno.h>
#define TST_NO_DEFAULT_MAIN
@@ -12,6 +13,31 @@
#include "tst_uid.h"
#define MAX_GID 32767
+#define MAX_UID 32767
+
+uid_t tst_get_free_uid_(const char *file, const int lineno, uid_t skip)
+{
+ uid_t ret;
+
+ errno = 0;
+
+ for (ret = 1; ret < MAX_UID; ret++) {
+ if (ret == skip || getpwuid(ret))
+ continue;
+
+ if (errno == 0 || errno == ENOENT || errno == ESRCH) {
+ tst_res_(file, lineno, TINFO | TERRNO,
+ "Found unused UID %d", (int)ret);
+ return ret;
+ }
+
+ tst_brk_(file, lineno, TBROK|TERRNO, "User ID lookup failed");
+ return (uid_t)-1;
+ }
+
+ tst_brk_(file, lineno, TBROK, "No free user ID found");
+ return (uid_t)-1;
+}
gid_t tst_get_free_gid_(const char *file, const int lineno, gid_t skip)
{
--
2.52.0
--
Mailing list info: https://lists.linux.it/listinfo/ltp
^ permalink raw reply related [flat|nested] 15+ messages in thread* Re: [LTP] lib: New library function tst_get_free_uid
2026-04-15 6:07 [LTP] [PATCH v6 1/2] " Wei Gao via ltp
@ 2026-04-15 7:54 ` linuxtestproject.agent
0 siblings, 0 replies; 15+ messages in thread
From: linuxtestproject.agent @ 2026-04-15 7:54 UTC (permalink / raw)
To: Wei Gao; +Cc: ltp
Hi Wei,
--- [PATCH 1/2] ---
On Wed, 15 Apr 2026 06:07:16 +0000, Wei Gao wrote:
> [PATCH 1/2] lib: New library function tst_get_free_uid
The commit body is empty. Add at least one sentence explaining why
this helper is needed — e.g. that open16 requires two distinct
unprivileged UIDs and that this extends the existing tst_get_free_gid
pattern to UIDs.
--- [PATCH 2/2] ---
On Wed, 15 Apr 2026 06:07:17 +0000, Wei Gao wrote:
> [PATCH 2/2] open16: allow restricted O_CREAT of FIFOs and regular files
Same issue — no commit body. Describe what kernel feature is under
test (protected_regular/protected_fifos, kernel commit 30aba6656f61)
and why a dedicated test was needed.
> +/*\
> + * Verify disallows open of FIFOs or regular files not owned by the user in world
> + * writable sticky directories
> + */
Incomplete. The test also verifies the positive case (protection=0
allows access) and level 2 protection (group-writable sticky
directories via SAFE_CHMOD(DIR, 0020|S_ISVTX)). Update the doc
comment to cover all three scenarios.
---
Note:
Our agent completed the review of the patch. The full review can be
found at: https://github.com/linux-test-project/ltp-agent/actions/runs/24442661607
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] 15+ messages in thread
end of thread, other threads:[~2026-07-21 8:55 UTC | newest]
Thread overview: 15+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
[not found] <https://patchwork.ozlabs.org/project/ltp/patch/20260707022959.24088-2-wegao@suse.com/>
2026-07-07 5:47 ` [LTP] [PATCH v10 0/2] open16: allow restricted O_CREAT of FIFOs and regular files Wei Gao via ltp
2026-07-07 5:47 ` [LTP] [PATCH v10 1/2] lib: New library function tst_get_free_uid Wei Gao via ltp
2026-07-07 7:48 ` [LTP] " linuxtestproject.agent
2026-07-21 7:41 ` [LTP] [PATCH v11 0/2] open16: allow restricted O_CREAT of FIFOs and regular files Wei Gao via ltp
2026-07-21 7:41 ` [LTP] [PATCH v11 1/2] lib: New library function tst_get_free_uid Wei Gao via ltp
2026-07-21 8:38 ` [LTP] " linuxtestproject.agent
2026-07-21 7:41 ` [LTP] [PATCH v11 2/2] open16: allow restricted O_CREAT of FIFOs and regular files Wei Gao via ltp
2026-07-21 8:22 ` [LTP] [PATCH v11 0/2] " Andrea Cervesato via ltp
2026-07-21 8:55 ` Wei Gao via ltp
2026-07-07 5:47 ` [LTP] [PATCH v10 2/2] " Wei Gao via ltp
2026-07-07 2:29 [LTP] [PATCH v9 1/2] lib: New library function tst_get_free_uid Wei Gao via ltp
2026-07-07 3:34 ` [LTP] " linuxtestproject.agent
-- strict thread matches above, loose matches on Subject: below --
2026-04-16 0:55 [LTP] [PATCH v8 1/2] " Wei Gao via ltp
2026-04-16 2:43 ` [LTP] " linuxtestproject.agent
2026-04-16 4:15 ` Wei Gao via ltp
2026-04-15 10:37 [LTP] [PATCH v7 1/2] " Wei Gao via ltp
2026-04-15 11:08 ` [LTP] " linuxtestproject.agent
2026-04-15 6:07 [LTP] [PATCH v6 1/2] " Wei Gao via ltp
2026-04-15 7:54 ` [LTP] " linuxtestproject.agent
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox