* [LTP] [PATCH v12 0/3] open16: allow restricted O_CREAT of FIFOs and regular files
@ 2026-07-22 4:47 Wei Gao via ltp
2026-07-22 4:47 ` [LTP] [PATCH v12 1/3] lib/tst_uid: Remove spurious TERRNO from tst_get_free_gid success path Wei Gao via ltp
` (2 more replies)
0 siblings, 3 replies; 10+ messages in thread
From: Wei Gao via ltp @ 2026-07-22 4:47 UTC (permalink / raw)
To: ltp
v11->v12:
- Restructured the series into three clean commits
Wei Gao (3):
lib/tst_uid: Remove spurious TERRNO from tst_get_free_gid success path
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] 10+ messages in thread* [LTP] [PATCH v12 1/3] lib/tst_uid: Remove spurious TERRNO from tst_get_free_gid success path 2026-07-22 4:47 [LTP] [PATCH v12 0/3] open16: allow restricted O_CREAT of FIFOs and regular files Wei Gao via ltp @ 2026-07-22 4:47 ` Wei Gao via ltp 2026-07-22 5:59 ` [LTP] " linuxtestproject.agent 2026-07-23 12:39 ` [LTP] [PATCH v12 1/3] " Andrea Cervesato via ltp 2026-07-22 4:47 ` [LTP] [PATCH v12 2/3] lib: New library function tst_get_free_uid Wei Gao via ltp 2026-07-22 4:47 ` [LTP] [PATCH v12 3/3] open16: allow restricted O_CREAT of FIFOs and regular files Wei Gao via ltp 2 siblings, 2 replies; 10+ messages in thread From: Wei Gao via ltp @ 2026-07-22 4:47 UTC (permalink / raw) To: ltp tst_get_free_gid_() prints the found GID when it succeeds, but it incorrectly includes TERRNO in tst_res_(). This prints whatever value happens to be in errno (often 0 or a stale value) which is confusing in a success path. Remove the spurious TERRNO flag from the tst_res_() success message. Signed-off-by: Wei Gao <wegao@suse.com> --- lib/tst_uid.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/tst_uid.c b/lib/tst_uid.c index af4ef8cf7..b0b087362 100644 --- a/lib/tst_uid.c +++ b/lib/tst_uid.c @@ -24,7 +24,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] 10+ messages in thread
* Re: [LTP] lib/tst_uid: Remove spurious TERRNO from tst_get_free_gid success path 2026-07-22 4:47 ` [LTP] [PATCH v12 1/3] lib/tst_uid: Remove spurious TERRNO from tst_get_free_gid success path Wei Gao via ltp @ 2026-07-22 5:59 ` linuxtestproject.agent 2026-07-23 12:39 ` [LTP] [PATCH v12 1/3] " Andrea Cervesato via ltp 1 sibling, 0 replies; 10+ messages in thread From: linuxtestproject.agent @ 2026-07-22 5:59 UTC (permalink / raw) To: Wei Gao; +Cc: ltp Hi Wei, On Wed, 22 Jul 2026, Wei Gao wrote: > lib/tst_uid: Remove spurious TERRNO from tst_get_free_gid success path Verdict - Reviewed --- 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] 10+ messages in thread
* Re: [LTP] [PATCH v12 1/3] lib/tst_uid: Remove spurious TERRNO from tst_get_free_gid success path 2026-07-22 4:47 ` [LTP] [PATCH v12 1/3] lib/tst_uid: Remove spurious TERRNO from tst_get_free_gid success path Wei Gao via ltp 2026-07-22 5:59 ` [LTP] " linuxtestproject.agent @ 2026-07-23 12:39 ` Andrea Cervesato via ltp 2026-07-23 23:28 ` Wei Gao via ltp 1 sibling, 1 reply; 10+ messages in thread From: Andrea Cervesato via ltp @ 2026-07-23 12:39 UTC (permalink / raw) To: Wei Gao; +Cc: ltp Hi Wei, > tst_get_free_gid_() prints the found GID when it succeeds, but it > incorrectly includes TERRNO in tst_res_(). This prints whatever value > happens to be in errno (often 0 or a stale value) which is confusing in > a success path. > > Remove the spurious TERRNO flag from the tst_res_() success message. > > Signed-off-by: Wei Gao <wegao@suse.com> > --- > lib/tst_uid.c | 2 +- > 1 file changed, 1 insertion(+), 1 deletion(-) > > diff --git a/lib/tst_uid.c b/lib/tst_uid.c > index af4ef8cf7..b0b087362 100644 > --- a/lib/tst_uid.c > +++ b/lib/tst_uid.c > @@ -24,7 +24,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); uhm? technically it should print 0, ENOENT or ESRCH. That's what the statement is all about. Do you have a log showing what's the issue with it? -- 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] 10+ messages in thread
* Re: [LTP] [PATCH v12 1/3] lib/tst_uid: Remove spurious TERRNO from tst_get_free_gid success path 2026-07-23 12:39 ` [LTP] [PATCH v12 1/3] " Andrea Cervesato via ltp @ 2026-07-23 23:28 ` Wei Gao via ltp 0 siblings, 0 replies; 10+ messages in thread From: Wei Gao via ltp @ 2026-07-23 23:28 UTC (permalink / raw) To: Andrea Cervesato; +Cc: ltp On Thu, Jul 23, 2026 at 12:39:17PM +0000, Andrea Cervesato wrote: > Hi Wei, > > > tst_get_free_gid_() prints the found GID when it succeeds, but it > > incorrectly includes TERRNO in tst_res_(). This prints whatever value > > happens to be in errno (often 0 or a stale value) which is confusing in > > a success path. > > > > Remove the spurious TERRNO flag from the tst_res_() success message. > > > > Signed-off-by: Wei Gao <wegao@suse.com> > > --- > > lib/tst_uid.c | 2 +- > > 1 file changed, 1 insertion(+), 1 deletion(-) > > > > diff --git a/lib/tst_uid.c b/lib/tst_uid.c > > index af4ef8cf7..b0b087362 100644 > > --- a/lib/tst_uid.c > > +++ b/lib/tst_uid.c > > @@ -24,7 +24,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); > > uhm? technically it should print 0, ENOENT or ESRCH. That's what the > statement is all about. Do you have a log showing what's the issue with it? AI feedback error is misleading need remove in patch10 , so do you want add new AI rule fix it? Following is AI feedback: https://patchwork.ozlabs.org/project/ltp/patch/20260707054804.24232-2-wegao@suse.com/ > + 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"? > > -- > 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] 10+ messages in thread
* [LTP] [PATCH v12 2/3] lib: New library function tst_get_free_uid 2026-07-22 4:47 [LTP] [PATCH v12 0/3] open16: allow restricted O_CREAT of FIFOs and regular files Wei Gao via ltp 2026-07-22 4:47 ` [LTP] [PATCH v12 1/3] lib/tst_uid: Remove spurious TERRNO from tst_get_free_gid success path Wei Gao via ltp @ 2026-07-22 4:47 ` Wei Gao via ltp 2026-07-23 12:43 ` Andrea Cervesato via ltp 2026-07-22 4:47 ` [LTP] [PATCH v12 3/3] open16: allow restricted O_CREAT of FIFOs and regular files Wei Gao via ltp 2 siblings, 1 reply; 10+ messages in thread From: Wei Gao via ltp @ 2026-07-22 4: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 | 29 +++++++++++++++++++++++++---- lib/tst_uid.c | 28 ++++++++++++++++++++++++++++ 2 files changed, 53 insertions(+), 4 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 b0b087362..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) { -- 2.54.0 -- Mailing list info: https://lists.linux.it/listinfo/ltp ^ permalink raw reply related [flat|nested] 10+ messages in thread
* Re: [LTP] [PATCH v12 2/3] lib: New library function tst_get_free_uid 2026-07-22 4:47 ` [LTP] [PATCH v12 2/3] lib: New library function tst_get_free_uid Wei Gao via ltp @ 2026-07-23 12:43 ` Andrea Cervesato via ltp 2026-07-23 23:54 ` Wei Gao via ltp 0 siblings, 1 reply; 10+ messages in thread From: Andrea Cervesato via ltp @ 2026-07-23 12:43 UTC (permalink / raw) To: Wei Gao; +Cc: ltp Hi Wei, > +/** > + * 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. > + */ This documentation is out of scope and should be sent from an another patch-set. > + errno = 0; > + if (getpwuid(ret)) > + continue; > + > + if (errno == 0 || errno == ENOENT || errno == ESRCH) { This contradicts the patch 1/3. -- 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] 10+ messages in thread
* Re: [LTP] [PATCH v12 2/3] lib: New library function tst_get_free_uid 2026-07-23 12:43 ` Andrea Cervesato via ltp @ 2026-07-23 23:54 ` Wei Gao via ltp 0 siblings, 0 replies; 10+ messages in thread From: Wei Gao via ltp @ 2026-07-23 23:54 UTC (permalink / raw) To: Andrea Cervesato; +Cc: ltp On Thu, Jul 23, 2026 at 12:43:24PM +0000, Andrea Cervesato wrote: > Hi Wei, > > > +/** > > + * 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. > > + */ > > This documentation is out of scope and should be sent from an another > patch-set. > > > + errno = 0; > > + if (getpwuid(ret)) > > + continue; > > + > > + if (errno == 0 || errno == ENOENT || errno == ESRCH) { > > This contradicts the patch 1/3. This line is same as patch 1/3, could you give more detail where contradicts? > > -- > 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] 10+ messages in thread
* [LTP] [PATCH v12 3/3] open16: allow restricted O_CREAT of FIFOs and regular files 2026-07-22 4:47 [LTP] [PATCH v12 0/3] open16: allow restricted O_CREAT of FIFOs and regular files Wei Gao via ltp 2026-07-22 4:47 ` [LTP] [PATCH v12 1/3] lib/tst_uid: Remove spurious TERRNO from tst_get_free_gid success path Wei Gao via ltp 2026-07-22 4:47 ` [LTP] [PATCH v12 2/3] lib: New library function tst_get_free_uid Wei Gao via ltp @ 2026-07-22 4:47 ` Wei Gao via ltp 2026-07-23 12:46 ` Andrea Cervesato via ltp 2 siblings, 1 reply; 10+ messages in thread From: Wei Gao via ltp @ 2026-07-22 4: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 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] 10+ messages in thread
* Re: [LTP] [PATCH v12 3/3] open16: allow restricted O_CREAT of FIFOs and regular files 2026-07-22 4:47 ` [LTP] [PATCH v12 3/3] open16: allow restricted O_CREAT of FIFOs and regular files Wei Gao via ltp @ 2026-07-23 12:46 ` Andrea Cervesato via ltp 0 siblings, 0 replies; 10+ messages in thread From: Andrea Cervesato via ltp @ 2026-07-23 12:46 UTC (permalink / raw) To: Wei Gao; +Cc: ltp Hi Wei, > 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); not needed, we have tst_reap_children(). > +} > + > +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 > -- 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] 10+ messages in thread
end of thread, other threads:[~2026-07-23 23:54 UTC | newest] Thread overview: 10+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2026-07-22 4:47 [LTP] [PATCH v12 0/3] open16: allow restricted O_CREAT of FIFOs and regular files Wei Gao via ltp 2026-07-22 4:47 ` [LTP] [PATCH v12 1/3] lib/tst_uid: Remove spurious TERRNO from tst_get_free_gid success path Wei Gao via ltp 2026-07-22 5:59 ` [LTP] " linuxtestproject.agent 2026-07-23 12:39 ` [LTP] [PATCH v12 1/3] " Andrea Cervesato via ltp 2026-07-23 23:28 ` Wei Gao via ltp 2026-07-22 4:47 ` [LTP] [PATCH v12 2/3] lib: New library function tst_get_free_uid Wei Gao via ltp 2026-07-23 12:43 ` Andrea Cervesato via ltp 2026-07-23 23:54 ` Wei Gao via ltp 2026-07-22 4:47 ` [LTP] [PATCH v12 3/3] open16: allow restricted O_CREAT of FIFOs and regular files Wei Gao via ltp 2026-07-23 12:46 ` 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