diff options
author | Android Build Coastguard Worker <android-build-coastguard-worker@google.com> | 2024-03-04 22:00:57 +0000 |
---|---|---|
committer | Android Build Coastguard Worker <android-build-coastguard-worker@google.com> | 2024-03-04 22:00:57 +0000 |
commit | 78c753a2bc1062c1fdb4c7b2e618554896827b45 (patch) | |
tree | bed7e68b13373f89a7ffd8feb37b0cc557e9da5b /testcases/kernel/syscalls | |
parent | 215bb8bdef76ef57566913dc4e9fc0bc20b0d92d (diff) | |
parent | 90164cf586a337bcb89a75f9dd92b9803e278dc1 (diff) | |
download | ltp-simpleperf-release.tar.gz |
Snap for 11526323 from 90164cf586a337bcb89a75f9dd92b9803e278dc1 to simpleperf-releasesimpleperf-release
Change-Id: I288786e8fccc3a1f3a579fa5d8791b22977dd569
Diffstat (limited to 'testcases/kernel/syscalls')
179 files changed, 3359 insertions, 5192 deletions
diff --git a/testcases/kernel/syscalls/accept/.gitignore b/testcases/kernel/syscalls/accept/.gitignore index 5b1462699..f81d4bec9 100644 --- a/testcases/kernel/syscalls/accept/.gitignore +++ b/testcases/kernel/syscalls/accept/.gitignore @@ -1,2 +1,3 @@ /accept01 /accept02 +/accept03 diff --git a/testcases/kernel/syscalls/accept/accept01.c b/testcases/kernel/syscalls/accept/accept01.c index 85af0f8af..e5db1dfec 100644 --- a/testcases/kernel/syscalls/accept/accept01.c +++ b/testcases/kernel/syscalls/accept/accept01.c @@ -26,7 +26,6 @@ struct sockaddr_in sin0, sin1, fsin1; int invalid_socketfd = 400; /* anything that is not an open file */ -int devnull_fd; int socket_fd; int udp_fd; @@ -46,10 +45,6 @@ static struct test_case { "bad file descriptor" }, { - PF_INET, SOCK_STREAM, 0, &devnull_fd, (struct sockaddr *)&fsin1, - sizeof(fsin1), ENOTSOCK, "fd is not socket" - }, - { PF_INET, SOCK_STREAM, 0, &socket_fd, (struct sockaddr *)3, sizeof(fsin1), EINVAL, "invalid socket buffer" }, @@ -73,8 +68,6 @@ static void test_setup(void) sin0.sin_port = 0; sin0.sin_addr.s_addr = INADDR_ANY; - devnull_fd = SAFE_OPEN("/dev/null", O_WRONLY); - socket_fd = SAFE_SOCKET(PF_INET, SOCK_STREAM, 0); SAFE_BIND(socket_fd, (struct sockaddr *)&sin0, sizeof(sin0)); @@ -88,7 +81,6 @@ static void test_setup(void) static void test_cleanup(void) { - SAFE_CLOSE(devnull_fd); SAFE_CLOSE(socket_fd); SAFE_CLOSE(udp_fd); } diff --git a/testcases/kernel/syscalls/accept/accept03.c b/testcases/kernel/syscalls/accept/accept03.c new file mode 100644 index 000000000..b85ec0d9b --- /dev/null +++ b/testcases/kernel/syscalls/accept/accept03.c @@ -0,0 +1,60 @@ +// SPDX-License-Identifier: GPL-2.0-or-later + +/* + * Copyright (C) 2023-2024 Cyril Hrubis <chrubis@suse.cz> + */ + +/*\ + * [Description] + * + * Verify that accept() returns ENOTSOCK or EBADF for non-socket file + * descriptors. The EBADF is returned in the case that the file descriptor has + * not a file associated with it, which is for example in the case of O_PATH + * opened file. + */ + +#include <sys/socket.h> +#include <netinet/in.h> + +#include "tst_test.h" + +void check_accept(struct tst_fd *fd) +{ + struct sockaddr_in addr = { + .sin_family = AF_INET, + .sin_port = 0, + .sin_addr = {.s_addr = INADDR_ANY}, + }; + + socklen_t size = sizeof(addr); + + int exp_errno = ENOTSOCK; + + switch (fd->type) { + case TST_FD_UNIX_SOCK: + case TST_FD_INET_SOCK: + return; + /* + * With these two we fail even before we get to the do_accept() because + * the fd does not have a struct file associated. + */ + case TST_FD_OPEN_TREE: + case TST_FD_PATH: + exp_errno = EBADF; + default: + break; + } + + TST_EXP_FAIL2(accept(fd->fd, (void*)&addr, &size), + exp_errno, "accept() on %s", tst_fd_desc(fd)); +} + +static void verify_accept(void) +{ + TST_FD_FOREACH(fd) + check_accept(&fd); +} + +static struct tst_test test = { + .test_all = verify_accept, +}; diff --git a/testcases/kernel/syscalls/acct/acct01.c b/testcases/kernel/syscalls/acct/acct01.c index 52c4d41da..a05ed2ea9 100644 --- a/testcases/kernel/syscalls/acct/acct01.c +++ b/testcases/kernel/syscalls/acct/acct01.c @@ -1,14 +1,15 @@ // SPDX-License-Identifier: GPL-2.0-or-later /* - * Copyright (c) International Business Machines Corp., 2002 + * Copyright (c) International Business Machines Corp., 2002 + * Copyright (c) Linux Test Project, 2003-2023 + * 12/03/2002 Port to LTP robbiew@us.ibm.com + * 06/30/2001 Port to Linux nsharoff@us.ibm.com */ -/* 12/03/2002 Port to LTP robbiew@us.ibm.com */ -/* 06/30/2001 Port to Linux nsharoff@us.ibm.com */ - /*\ - * [DOCUMENTATION] + * [Description] + * * Verify that acct() returns proper errno on failure. */ diff --git a/testcases/kernel/syscalls/acct/acct02.c b/testcases/kernel/syscalls/acct/acct02.c index b8eb1aad4..d3f3d9d04 100644 --- a/testcases/kernel/syscalls/acct/acct02.c +++ b/testcases/kernel/syscalls/acct/acct02.c @@ -1,10 +1,11 @@ // SPDX-License-Identifier: GPL-2.0-or-later /* - * Copyright (c) SUSE LLC, 2019 - * Author: Christian Amann <camann@suse.com> + * Copyright (c) SUSE LLC, 2019 + * Copyright (c) Linux Test Project, 2019-2023 + * Author: Christian Amann <camann@suse.com> */ /*\ - * [DOCUMENTATION] + * [Description] * * This tests if the kernel writes correct data to the * process accounting file. @@ -19,8 +20,8 @@ * file, the contents get parsed until the correct entry is found, or EOF * is reached. * - * This is also accidental regression test for: - * 4d9570158b626 kernel/acct.c: fix the acct->needcheck check in check_free_space() + * This is also regression test for commit: + * 4d9570158b62 ("kernel/acct.c: fix the acct->needcheck check in check_free_space()") */ #include <sys/stat.h> @@ -55,10 +56,7 @@ static union acct_union { static int acct_version_is_3(void) { - struct tst_kconfig_var kconfig = { - .id = ACCT_V3, - .id_len = sizeof(ACCT_V3)-1, - }; + struct tst_kconfig_var kconfig = TST_KCONFIG_INIT(ACCT_V3); tst_kconfig_read(&kconfig, 1); diff --git a/testcases/kernel/syscalls/acct/acct02_helper.c b/testcases/kernel/syscalls/acct/acct02_helper.c index 66017cb9b..0f55a6ae6 100644 --- a/testcases/kernel/syscalls/acct/acct02_helper.c +++ b/testcases/kernel/syscalls/acct/acct02_helper.c @@ -1,7 +1,7 @@ // SPDX-License-Identifier: GPL-2.0-or-later /* - * Copyright (c) SUSE LLC, 2019 - * Author: Christian Amann <camann@suse.com> + * Copyright (c) SUSE LLC, 2019 + * Author: Christian Amann <camann@suse.com> */ /* * Dummy program used in acct02 diff --git a/testcases/kernel/syscalls/adjtimex/adjtimex03.c b/testcases/kernel/syscalls/adjtimex/adjtimex03.c index 7056973cc..9d34235e4 100644 --- a/testcases/kernel/syscalls/adjtimex/adjtimex03.c +++ b/testcases/kernel/syscalls/adjtimex/adjtimex03.c @@ -23,7 +23,7 @@ * To test that, Pass struct timex buffer filled with zero with * some INVALID mode to the system call adjtimex. Passing an invalid * parameters will not call do_adjtimex() and before that, it shall throw - * an error(On error test shall not break). Therefore, none of the parameters + * an error (on error test shall not break). Therefore, none of the parameters * will get initialized. * * On reading the last attribute tai of the struct, if the attribute is non- diff --git a/testcases/kernel/syscalls/clock_adjtime/clock_adjtime.h b/testcases/kernel/syscalls/clock_adjtime/clock_adjtime.h index 7577ab24d..63ebf5295 100644 --- a/testcases/kernel/syscalls/clock_adjtime/clock_adjtime.h +++ b/testcases/kernel/syscalls/clock_adjtime/clock_adjtime.h @@ -251,4 +251,5 @@ TIMEX_GET_SET_FIELD_TYPE(uint, uint); TIMEX_GET_SET_FIELD_TYPE(long, long long); #undef TIMEX_GET_SET_FIELD_TYPE -#endif + +#endif /* CLOCK_ADJTIME_H__ */ diff --git a/testcases/kernel/syscalls/dup/dup06.c b/testcases/kernel/syscalls/dup/dup06.c index e3f8070bf..cd4cb3513 100644 --- a/testcases/kernel/syscalls/dup/dup06.c +++ b/testcases/kernel/syscalls/dup/dup06.c @@ -1,41 +1,23 @@ +// SPDX-License-Identifier: GPL-2.0-or-later /* - * Copyright (c) International Business Machines Corp., 2002 - * ported from SPIE, section2/iosuite/dup1.c, by Airong Zhang - * Copyright (c) 2013 Cyril Hrubis <chrubis@suse.cz> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See - * the GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * Copyright (c) International Business Machines Corp., 2002 + * Ported from SPIE, section2/iosuite/dup1.c, by Airong Zhang + * Copyright (c) 2013 Cyril Hrubis <chrubis@suse.cz> + * Copyright (c) Linux Test Project, 2003-2024 */ -/* - WHAT: Does dup return -1 on the 21st file? - HOW: Create up to _NFILE (20) files and check for -1 return on the - next attempt - Should check NOFILE as well as _NFILE. 19-Jun-84 Dale. -*/ +/*\ + * [Description] + * + * Test for dup(2) syscall with max open file descriptors. + */ -#include <stdio.h> -#include <fcntl.h> -#include <errno.h> -#include <unistd.h> -#include <sys/types.h> -#include <sys/stat.h> -#include <sys/param.h> -#include "test.h" +#include <stdlib.h> +#include "tst_test.h" -char *TCID = "dup06"; -int TST_TOTAL = 1; +static int *pfildes; +static int minfd, maxfd, freefds; +static char pfilname[40]; static int cnt_free_fds(int maxfd) { @@ -45,70 +27,53 @@ static int cnt_free_fds(int maxfd) if (fcntl(maxfd, F_GETFD) == -1 && errno == EBADF) freefds++; - return (freefds); + return freefds; } -static void setup(void); -static void cleanup(void); - -int main(int ac, char **av) +static void setup(void) { - int *fildes, i; - int min; - int freefds; - int lc; - const char *pfilname = "dup06"; - - tst_parse_opts(ac, av, NULL, NULL); - - setup(); - - min = getdtablesize(); - freefds = cnt_free_fds(min); - fildes = malloc((min + 5) * sizeof(int)); - - for (i = 0; i < min + 5; i++) - fildes[i] = 0; - - for (lc = 0; TEST_LOOPING(lc); lc++) { - unlink(pfilname); - - if ((fildes[0] = creat(pfilname, 0666)) == -1) { - tst_resm(TFAIL, "Cannot open first file"); - } else { - for (i = 1; i < min + 5; i++) { - if ((fildes[i] = dup(fildes[i - 1])) == -1) - break; - } - if (i < freefds) { - tst_resm(TFAIL, "Not enough files duped"); - } else if (i > freefds) { - tst_resm(TFAIL, "Too many files duped"); - } else { - tst_resm(TPASS, "Test passed."); - } - } - - unlink(pfilname); - - for (i = 0; i < min + 5; i++) { - if (fildes[i] != 0 && fildes[i] != -1) - close(fildes[i]); - - fildes[i] = 0; - } - } - - cleanup(); - tst_exit(); + minfd = getdtablesize(); /* get number of files allowed open */ + maxfd = minfd + 5; + freefds = cnt_free_fds(minfd); + pfildes = SAFE_MALLOC(maxfd * sizeof(int)); + memset(pfildes, -1, maxfd * sizeof(int)); + sprintf(pfilname, "./dup06.%d\n", getpid()); } -static void setup(void) +static void cleanup(void) { - tst_tmpdir(); + if (pfildes != NULL) + free(pfildes); } -static void cleanup(void) +static void run(void) { - tst_rmdir(); + int i; + + pfildes[0] = SAFE_CREAT(pfilname, 0666); + for (i = 1; i < maxfd; i++) { + pfildes[i] = dup(pfildes[i - 1]); + if (pfildes[i] == -1) + break; + } + if (i < freefds) + tst_res(TFAIL, "Not enough files duped"); + else if (i > freefds) + tst_res(TFAIL, "Too many files duped"); + else + tst_res(TPASS, "Test passed"); + + SAFE_UNLINK(pfilname); + + for (i = 0; i < maxfd; i++) { + if (pfildes[i] != 0 && pfildes[i] != -1) + SAFE_CLOSE(pfildes[i]); + } } + +static struct tst_test test = { + .needs_tmpdir = 1, + .test_all = run, + .setup = setup, + .cleanup = cleanup, +}; diff --git a/testcases/kernel/syscalls/dup/dup07.c b/testcases/kernel/syscalls/dup/dup07.c index a100f5d58..688ee1989 100644 --- a/testcases/kernel/syscalls/dup/dup07.c +++ b/testcases/kernel/syscalls/dup/dup07.c @@ -1,142 +1,57 @@ +// SPDX-License-Identifier: GPL-2.0-or-later /* - * - * Copyright (c) International Business Machines Corp., 2002 - * ported from SPIE, section2/iosuite/dup3.c, by Airong Zhang - * Copyright (c) 2013 Cyril Hrubis <chrubis@suse.cz> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See - * the GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * Copyright (c) International Business Machines Corp., 2002 + * Ported from SPIE, section2/iosuite/dup3.c, by Airong Zhang + * Copyright (c) 2013 Cyril Hrubis <chrubis@suse.cz> + * Copyright (c) Linux Test Project, 2006-2024 */ -/* - WHAT: Is the access mode the same for both file descriptors? - 0: read only? - 1: write only? - 2: read/write? - HOW: Creat a file with each access mode; dup each file descriptor; - stat each file descriptor and compare mode of each pair -*/ - -#include <stdio.h> -#include <fcntl.h> -#include <sys/types.h> -#include <sys/stat.h> -#include <sys/types.h> -#include <sys/stat.h> -#include "test.h" +/*\ + * [Description] + * + * Verify that the file descriptor created by dup(2) syscall has the same + * access mode as the old one. + */ -char *TCID = "dup07"; -int TST_TOTAL = 3; +#include "tst_test.h" static const char *testfile = "dup07"; -static void setup(void); -static void cleanup(void); +static struct tcase { + char *mode_desc; + int mode; +} tcases[] = { + {"read only", 0444}, + {"write only", 0222}, + {"read/write", 0666}, +}; -int main(int ac, char **av) +static void run(unsigned int n) { - struct stat retbuf; - struct stat dupbuf; - int rdoret, wroret, rdwret; - int duprdo, dupwro, duprdwr; - - int lc; - - tst_parse_opts(ac, av, NULL, NULL); - - setup(); - - for (lc = 0; TEST_LOOPING(lc); lc++) { - - if ((rdoret = creat(testfile, 0444)) == -1) { - tst_resm(TFAIL, "Unable to creat file '%s'", testfile); - } else { - if ((duprdo = dup(rdoret)) == -1) { - tst_resm(TFAIL, "Unable to dup '%s'", testfile); - } else { - fstat(rdoret, &retbuf); - fstat(duprdo, &dupbuf); - if (retbuf.st_mode != dupbuf.st_mode) { - tst_resm(TFAIL, - "rdonly and dup do not match"); - } else { - tst_resm(TPASS, - "Passed in read mode."); - } - close(duprdo); - } - close(rdoret); - } - - unlink(testfile); - - if ((wroret = creat(testfile, 0222)) == -1) { - tst_resm(TFAIL, "Unable to creat file '%s'", testfile); - } else { - if ((dupwro = dup(wroret)) == -1) { - tst_resm(TFAIL, "Unable to dup '%s'", testfile); - } else { - fstat(wroret, &retbuf); - fstat(dupwro, &dupbuf); - if (retbuf.st_mode != dupbuf.st_mode) { - tst_resm(TFAIL, - "wronly and dup do not match"); - } else { - tst_resm(TPASS, - "Passed in write mode."); - } - close(dupwro); - } - close(wroret); - - } - - unlink(testfile); - - if ((rdwret = creat(testfile, 0666)) == -1) { - tst_resm(TFAIL, "Unable to creat file '%s'", testfile); - } else { - if ((duprdwr = dup(rdwret)) == -1) { - tst_resm(TFAIL, "Unable to dup '%s'", testfile); - } else { - fstat(rdwret, &retbuf); - fstat(duprdwr, &dupbuf); - if (retbuf.st_mode != dupbuf.st_mode) { - tst_resm(TFAIL, - "rdwr and dup do not match"); - } else { - tst_resm(TPASS, - "Passed in read/write mode."); - } - close(duprdwr); - } - close(rdwret); - } - - unlink(testfile); + int oldfd, dupfd; + struct stat oldbuf, dupbuf; + struct tcase *tc = &tcases[n]; + + oldfd = SAFE_CREAT(testfile, tc->mode); + dupfd = TST_EXP_FD_SILENT(dup(oldfd), "dup() %s file", tc->mode_desc); + if (TST_PASS) { + SAFE_FSTAT(oldfd, &oldbuf); + SAFE_FSTAT(dupfd, &dupbuf); + + if (oldbuf.st_mode != dupbuf.st_mode) + tst_res(TFAIL, "%s and dup do not match", tc->mode_desc); + else + tst_res(TPASS, "Passed in %s mode", tc->mode_desc); + + SAFE_CLOSE(dupfd); } - cleanup(); - tst_exit(); + SAFE_CLOSE(oldfd); + SAFE_UNLINK(testfile); } -static void setup(void) -{ - tst_tmpdir(); -} - -static void cleanup(void) -{ - tst_rmdir(); -} +static struct tst_test test = { + .needs_tmpdir = 1, + .test = run, + .tcnt = ARRAY_SIZE(tcases), +}; diff --git a/testcases/kernel/syscalls/eventfd2/eventfd2.h b/testcases/kernel/syscalls/eventfd2/eventfd2.h index 5350820b8..2333d1e53 100644 --- a/testcases/kernel/syscalls/eventfd2/eventfd2.h +++ b/testcases/kernel/syscalls/eventfd2/eventfd2.h @@ -3,6 +3,9 @@ * Copyright (C) 2023 SUSE LLC Andrea Cervesato <andrea.cervesato@suse.com> */ +#ifndef EVENTFD2_H__ +#define EVENTFD2_H__ + #include "tst_test.h" #include "lapi/syscalls.h" @@ -16,3 +19,5 @@ static inline int eventfd2(unsigned int count, unsigned int flags) return ret; } + +#endif /* EVENTFD2_H__ */ diff --git a/testcases/kernel/syscalls/execve/execve04.c b/testcases/kernel/syscalls/execve/execve04.c index 18e883ab3..3bac642e5 100644 --- a/testcases/kernel/syscalls/execve/execve04.c +++ b/testcases/kernel/syscalls/execve/execve04.c @@ -8,7 +8,9 @@ * 04/2008 Roy Lee <roylee@andestech.com> */ -/* +/*\ + * [Description] + * * Attempt to execve(2) a file which is being opened by another process for * writing fails with ETXTBSY. */ diff --git a/testcases/kernel/syscalls/execve/execve05.c b/testcases/kernel/syscalls/execve/execve05.c index 87565d994..d87d7446d 100644 --- a/testcases/kernel/syscalls/execve/execve05.c +++ b/testcases/kernel/syscalls/execve/execve05.c @@ -1,32 +1,21 @@ // SPDX-License-Identifier: GPL-2.0-or-later /* - * Copyright (c) 2018 Linux Test Project + * Copyright (c) 2001-2023 Linux Test Project * Copyright (c) International Business Machines Corp., 2001 - * + * Copyright (c) 2008 Renaud Lottiaux <Renaud.Lottiaux@kerlabs.com> * Ported to LTP: Wayne Boyer - * 21/04/2008 Renaud Lottiaux (Renaud.Lottiaux@kerlabs.com) */ -/* - * NAME - * execve05.c - * - * DESCRIPTION - * This testcase tests the basic functionality of the execve(2) system - * call. +/*\ + * [Description] * - * ALGORITHM - * This tests the functionality of the execve(2) system call by spawning - * a few children, each of which would execute "execve_child" simultaneously, - * and finally the parent ensures that they terminated correctly. - * - * USAGE - * execve05 -i 5 -n 20 + * This tests the functionality of the execve(2) system call by spawning + * a few children, each of which would execute "execve_child" simultaneously, + * and finally the parent ensures that they terminated correctly. */ -#ifndef _GNU_SOURCE #define _GNU_SOURCE -#endif + #include <stdio.h> #include <stdlib.h> #include <errno.h> diff --git a/testcases/kernel/syscalls/exit_group/Makefile b/testcases/kernel/syscalls/exit_group/Makefile index 1273a4e9c..adbac3c51 100644 --- a/testcases/kernel/syscalls/exit_group/Makefile +++ b/testcases/kernel/syscalls/exit_group/Makefile @@ -3,6 +3,8 @@ top_srcdir ?= ../../../.. +exit_group01: CFLAGS+=-pthread + include $(top_srcdir)/include/mk/testcases.mk include $(top_srcdir)/include/mk/generic_leaf_target.mk diff --git a/testcases/kernel/syscalls/exit_group/exit_group01.c b/testcases/kernel/syscalls/exit_group/exit_group01.c index 5bf5b0218..6407a20e8 100644 --- a/testcases/kernel/syscalls/exit_group/exit_group01.c +++ b/testcases/kernel/syscalls/exit_group/exit_group01.c @@ -1,68 +1,127 @@ -/****************************************************************************** - * Copyright (c) Crackerjack Project., 2007 * - * Ported to LTP by Manas Kumar Nayak <maknayak@in.ibm.com> * - * Copyright (C) 2015 Cyril Hrubis <chrubis@suse.cz> * - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * - * (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See * - * the GNU General Public License for more details. * - * * - * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the Free Software Foundation, * - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * - * * - ******************************************************************************/ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * Copyright (c) Crackerjack Project., 2007 + * Ported to LTP by Manas Kumar Nayak <maknayak@in.ibm.com> + * Copyright (c) 2015 Linux Test Project + * Copyright (C) 2015 Cyril Hrubis <chrubis@suse.cz> + * Copyright (C) 2023 SUSE LLC Andrea Cervesato <andrea.cervesato@suse.com> + */ -#include <stdio.h> -#include <errno.h> -#include <linux/unistd.h> -#include <sys/wait.h> +/*\ + * [Description] + * + * This test checks if exit_group() correctly ends a spawned child and all its + * running threads. + */ -#include "test.h" -#include "safe_macros.h" +#include <sched.h> +#include <stdio.h> +#include <stdlib.h> +#include "tst_test.h" #include "lapi/syscalls.h" +#include "tst_safe_pthread.h" + +static int cpu_count; -char *TCID = "exit_group01"; -int testno; -int TST_TOTAL = 1; +static struct worker_data { + pid_t tid; + int counter; +} *workers_data; -static void verify_exit_group(void) +static void *worker(void *arg) { - pid_t cpid, w; - int status; + struct worker_data *data; - cpid = fork(); - if (cpid == -1) - tst_brkm(TFAIL | TERRNO, NULL, "fork failed"); + data = (struct worker_data *)arg; + data->tid = tst_gettid(); - if (cpid == 0) { - TEST(tst_syscall(__NR_exit_group, 4)); - } else { - w = SAFE_WAIT(NULL, &status); - - if (WIFEXITED(status) && (WEXITSTATUS(status) == 4)) { - tst_resm(TPASS, "exit_group() succeeded"); - } else { - tst_resm(TFAIL | TERRNO, - "exit_group() failed (wait status = %d)", w); + while (1) { + tst_atomic_inc(&data->counter); + sched_yield(); + } + + return arg; +} + +static void spawn_threads(void) +{ + pthread_t threads[cpu_count]; + + for (int i = 0; i < cpu_count; i++) + SAFE_PTHREAD_CREATE(&threads[i], NULL, worker, (void *)(workers_data + i)); +} + +static void check_counters(void) +{ + struct worker_data data_copy[cpu_count]; + + memset(data_copy, 0, sizeof(struct worker_data) * cpu_count); + memcpy(data_copy, workers_data, sizeof(struct worker_data) * cpu_count); + + tst_res(TINFO, "Checking if threads are still running"); + usleep(100000); + + struct worker_data *old_data; + struct worker_data *new_data; + + for (int i = 0; i < cpu_count; i++) { + old_data = data_copy + i; + new_data = workers_data + i; + + if (old_data->counter != new_data->counter) { + tst_res(TFAIL, "Counter value has changed for thread[%d]", i); + return; } } + + tst_res(TINFO, "Threads counters value didn't change"); } -int main(int ac, char **av) +static void run(void) { - int lc; + pid_t pid; + int status; + + pid = SAFE_FORK(); + if (!pid) { + spawn_threads(); + + TEST(tst_syscall(__NR_exit_group, 4)); + if (TST_RET == -1) + tst_brk(TBROK | TERRNO, "exit_group() error"); + + return; + } - tst_parse_opts(ac, av, NULL, NULL); + SAFE_WAITPID(pid, &status, 0); - for (lc = 0; TEST_LOOPING(lc); lc++) - verify_exit_group(); + TST_EXP_EXPR(WIFEXITED(status) && WEXITSTATUS(status) == 4, + "exit_group() succeeded"); - tst_exit(); + check_counters(); } + +static void setup(void) +{ + cpu_count = MAX(2, tst_ncpus()); + + workers_data = SAFE_MMAP( + NULL, + sizeof(struct worker_data) * cpu_count, + PROT_READ | PROT_WRITE, + MAP_SHARED | MAP_ANONYMOUS, + -1, 0); +} + +static void cleanup(void) +{ + SAFE_MUNMAP(workers_data, sizeof(struct worker_data) * cpu_count); +} + +static struct tst_test test = { + .setup = setup, + .cleanup = cleanup, + .test_all = run, + .forks_child = 1, + .needs_checkpoints = 1, +}; diff --git a/testcases/kernel/syscalls/fallocate/fallocate06.c b/testcases/kernel/syscalls/fallocate/fallocate06.c index 124fb7eae..24f98e271 100644 --- a/testcases/kernel/syscalls/fallocate/fallocate06.c +++ b/testcases/kernel/syscalls/fallocate/fallocate06.c @@ -260,6 +260,8 @@ static struct tst_test test = { .test = run, .tcnt = ARRAY_SIZE(testcase_list), .needs_root = 1, + .dev_min_size = 1024, + .max_runtime = 120, .mount_device = 1, .mntpoint = MNTPOINT, .all_filesystems = 1, diff --git a/testcases/kernel/syscalls/fanotify/fanotify.h b/testcases/kernel/syscalls/fanotify/fanotify.h index 75a081dc9..e0d178bcc 100644 --- a/testcases/kernel/syscalls/fanotify/fanotify.h +++ b/testcases/kernel/syscalls/fanotify/fanotify.h @@ -68,19 +68,14 @@ static inline int safe_fanotify_mark(const char *file, const int lineno, #ifdef HAVE_NAME_TO_HANDLE_AT -#ifndef MAX_HANDLE_SZ -#define MAX_HANDLE_SZ 128 -#endif - -#ifndef AT_HANDLE_FID -#define AT_HANDLE_FID 0x200 -#endif - /* * Helper function used to obtain fsid and file_handle for a given path. * Used by test files correlated to FAN_REPORT_FID functionality. + * + * Returns 0 if normal NFS file handles are supported. + * Returns AT_HANDLE_FID, if only non-decodeable file handles are supported. */ -static inline void fanotify_get_fid(const char *path, __kernel_fsid_t *fsid, +static inline int fanotify_get_fid(const char *path, __kernel_fsid_t *fsid, struct file_handle *handle) { int mount_id; @@ -93,6 +88,11 @@ static inline void fanotify_get_fid(const char *path, __kernel_fsid_t *fsid, if (name_to_handle_at(AT_FDCWD, path, handle, &mount_id, 0) == -1) { if (errno == EOPNOTSUPP) { + /* Try to request non-decodeable fid instead */ + if (name_to_handle_at(AT_FDCWD, path, handle, &mount_id, + AT_HANDLE_FID) == 0) + return AT_HANDLE_FID; + tst_brk(TCONF, "filesystem %s does not support file handles", tst_device->fs_type); @@ -100,30 +100,30 @@ static inline void fanotify_get_fid(const char *path, __kernel_fsid_t *fsid, tst_brk(TBROK | TERRNO, "name_to_handle_at(AT_FDCWD, %s, ...) failed", path); } + return 0; } -#ifndef FILEID_INVALID -#define FILEID_INVALID 0xff -#endif - struct fanotify_fid_t { __kernel_fsid_t fsid; struct file_handle handle; char buf[MAX_HANDLE_SZ]; }; -static inline void fanotify_save_fid(const char *path, +static inline int fanotify_save_fid(const char *path, struct fanotify_fid_t *fid) { int *fh = (int *)(fid->handle.f_handle); + int ret; fh[0] = fh[1] = fh[2] = 0; fid->handle.handle_bytes = MAX_HANDLE_SZ; - fanotify_get_fid(path, &fid->fsid, &fid->handle); + ret = fanotify_get_fid(path, &fid->fsid, &fid->handle); tst_res(TINFO, "fid(%s) = %x.%x.%x.%x.%x...", path, fid->fsid.val[0], fid->fsid.val[1], fh[0], fh[1], fh[2]); + + return ret; } #endif /* HAVE_NAME_TO_HANDLE_AT */ @@ -133,13 +133,14 @@ static inline void fanotify_save_fid(const char *path, #define INIT_FANOTIFY_MARK_TYPE(t) \ { FAN_MARK_ ## t, "FAN_MARK_" #t } -static inline void require_fanotify_access_permissions_supported_by_kernel(void) +static inline void require_fanotify_access_permissions_supported_on_fs( + const char *fname) { int fd; fd = SAFE_FANOTIFY_INIT(FAN_CLASS_CONTENT, O_RDONLY); - if (fanotify_mark(fd, FAN_MARK_ADD, FAN_ACCESS_PERM, AT_FDCWD, ".") < 0) { + if (fanotify_mark(fd, FAN_MARK_ADD, FAN_ACCESS_PERM, AT_FDCWD, fname) < 0) { if (errno == EINVAL) { tst_brk(TCONF | TERRNO, "CONFIG_FANOTIFY_ACCESS_PERMISSIONS not configured in kernel?"); @@ -152,21 +153,42 @@ static inline void require_fanotify_access_permissions_supported_by_kernel(void) SAFE_CLOSE(fd); } -static inline int fanotify_events_supported_by_kernel(uint64_t mask, - unsigned int init_flags, - unsigned int mark_flags) +/* + * @return 0: fanotify flags supported both in kernel and on tested filesystem + * @return -1: @init_flags not supported in kernel + * @return -2: @mark_flags not supported on tested filesystem (tested if @fname is not NULL) + * @return -3: @mark_flags not supported on overlayfs (tested if @fname == OVL_MNT) + */ +static inline int fanotify_flags_supported_on_fs(unsigned int init_flags, + unsigned int mark_flags, + uint64_t event_flags, + const char *fname) { int fd; int rval = 0; - fd = SAFE_FANOTIFY_INIT(init_flags, O_RDONLY); + fd = fanotify_init(init_flags, O_RDONLY); - if (fanotify_mark(fd, FAN_MARK_ADD | mark_flags, mask, AT_FDCWD, ".") < 0) { - if (errno == EINVAL) { - rval = -1; - } else { + if (fd < 0) { + if (errno == ENOSYS) + tst_brk(TCONF, "fanotify not configured in kernel"); + if (errno != EINVAL) + tst_brk(TBROK | TERRNO, + "fanotify_init(%x, O_RDONLY) failed", + init_flags); + return -1; + } + + if (fname && fanotify_mark(fd, FAN_MARK_ADD | mark_flags, event_flags, AT_FDCWD, fname) < 0) { + if (errno == ENODEV || errno == EOPNOTSUPP || errno == EXDEV) { + rval = strcmp(fname, OVL_MNT) ? -2 : -3; + } else if (errno != EINVAL) { tst_brk(TBROK | TERRNO, - "fanotify_mark (%d, FAN_MARK_ADD, ..., AT_FDCWD, \".\") failed", fd); + "fanotify_mark (%d, FAN_MARK_ADD | %x, %llx, AT_FDCWD, %s) failed", + fd, mark_flags, (unsigned long long)event_flags, + fname); + } else { + rval = -1; } } @@ -175,95 +197,85 @@ static inline int fanotify_events_supported_by_kernel(uint64_t mask, return rval; } -/* - * @return 0: fanotify supported both in kernel and on tested filesystem - * @return -1: @flags not supported in kernel - * @return -2: @flags not supported on tested filesystem (tested if @fname is not NULL) - */ static inline int fanotify_init_flags_supported_on_fs(unsigned int flags, const char *fname) { - int fd; - int rval = 0; - - fd = fanotify_init(flags, O_RDONLY); + return fanotify_flags_supported_on_fs(flags, FAN_MARK_INODE, FAN_ACCESS, fname); +} - if (fd < 0) { - if (errno == ENOSYS) - tst_brk(TCONF, "fanotify not configured in kernel"); +static inline int fanotify_mark_supported_on_fs(uint64_t flag, const char *fname) +{ + return fanotify_flags_supported_on_fs(FAN_CLASS_NOTIF, flag, FAN_ACCESS, fname); +} - if (errno == EINVAL) - return -1; +#define TST_FANOTIFY_INIT_KNOWN_FLAGS \ + (FAN_REPORT_DFID_NAME_TARGET | FAN_REPORT_TID | FAN_REPORT_PIDFD | \ + FAN_CLASS_NOTIF | FAN_CLASS_CONTENT | FAN_CLASS_PRE_CONTENT) - tst_brk(TBROK | TERRNO, "fanotify_init() failed"); +/* + * Check support of given init flags one by one and return those which are + * supported. + */ +static inline unsigned int fanotify_get_supported_init_flags(unsigned int flags, + const char *fname) +{ + unsigned int i, flg, arg, ret = 0; + static const struct { unsigned int flag, deps; } deplist[] = { + {FAN_REPORT_NAME, FAN_REPORT_DIR_FID}, + {FAN_REPORT_TARGET_FID, FAN_REPORT_DFID_NAME_FID}, + {0, 0} + }; + + if (flags & ~TST_FANOTIFY_INIT_KNOWN_FLAGS) { + tst_brk(TBROK, "fanotify_init() feature check called with unknown flags %x, please update flag dependency table if needed", + flags & ~TST_FANOTIFY_INIT_KNOWN_FLAGS); } - if (fname && fanotify_mark(fd, FAN_MARK_ADD, FAN_ACCESS, AT_FDCWD, fname) < 0) { - if (errno == ENODEV || errno == EOPNOTSUPP || errno == EXDEV) { - rval = -2; - } else { - tst_brk(TBROK | TERRNO, - "fanotify_mark (%d, FAN_MARK_ADD, ..., AT_FDCWD, %s) failed", - fd, fname); - } - } + for (flg = 1; flg; flg <<= 1) { + if (!(flags & flg)) + continue; - SAFE_CLOSE(fd); + arg = flg; - return rval; -} + for (i = 0; deplist[i].flag; i++) { + if (deplist[i].flag == flg) { + arg |= deplist[i].deps; + break; + } + } -static inline int fanotify_init_flags_supported_by_kernel(unsigned int flags) -{ - return fanotify_init_flags_supported_on_fs(flags, NULL); + if (!fanotify_init_flags_supported_on_fs(arg, fname)) + ret |= flg; + } + + return ret; } typedef void (*tst_res_func_t)(const char *file, const int lineno, int ttype, const char *fmt, ...); -static inline void fanotify_init_flags_err_msg(const char *flags_str, +static inline void fanotify_flags_err_msg(const char *flags_str, const char *file, const int lineno, tst_res_func_t res_func, int fail) { if (fail == -1) res_func(file, lineno, TCONF, "%s not supported in kernel?", flags_str); - if (fail == -2) + if (fail == -2 || fail == -3) res_func(file, lineno, TCONF, - "%s not supported on %s filesystem", - flags_str, tst_device->fs_type); + "%s not supported on %s%s filesystem", + flags_str, fail == -3 ? "overlayfs over " : "", + tst_device->fs_type); } #define FANOTIFY_INIT_FLAGS_ERR_MSG(flags, fail) \ - fanotify_init_flags_err_msg(#flags, __FILE__, __LINE__, tst_res_, (fail)) + fanotify_flags_err_msg(#flags, __FILE__, __LINE__, tst_res_, (fail)) + +#define FANOTIFY_MARK_FLAGS_ERR_MSG(mark, fail) \ + fanotify_flags_err_msg((mark)->name, __FILE__, __LINE__, tst_res_, (fail)) #define REQUIRE_FANOTIFY_INIT_FLAGS_SUPPORTED_ON_FS(flags, fname) \ - fanotify_init_flags_err_msg(#flags, __FILE__, __LINE__, tst_brk_, \ + fanotify_flags_err_msg(#flags, __FILE__, __LINE__, tst_brk_, \ fanotify_init_flags_supported_on_fs(flags, fname)) -#define REQUIRE_FANOTIFY_INIT_FLAGS_SUPPORTED_BY_KERNEL(flags) \ - fanotify_init_flags_err_msg(#flags, __FILE__, __LINE__, tst_brk_, \ - fanotify_init_flags_supported_by_kernel(flags)) - -static inline int fanotify_mark_supported_by_kernel(uint64_t flag) -{ - int fd; - int rval = 0; - - fd = SAFE_FANOTIFY_INIT(FAN_CLASS_CONTENT, O_RDONLY); - - if (fanotify_mark(fd, FAN_MARK_ADD | flag, FAN_ACCESS, AT_FDCWD, ".") < 0) { - if (errno == EINVAL) { - rval = -1; - } else { - tst_brk(TBROK | TERRNO, - "fanotify_mark (%d, FAN_MARK_ADD, ..., FAN_ACCESS, AT_FDCWD, \".\") failed", fd); - } - } - - SAFE_CLOSE(fd); - - return rval; -} - static inline int fanotify_handle_supported_by_kernel(int flag) { /* @@ -277,21 +289,21 @@ static inline int fanotify_handle_supported_by_kernel(int flag) return 0; } -#define REQUIRE_MARK_TYPE_SUPPORTED_BY_KERNEL(mark_type) \ - fanotify_init_flags_err_msg(#mark_type, __FILE__, __LINE__, tst_brk_, \ - fanotify_mark_supported_by_kernel(mark_type)) +#define REQUIRE_MARK_TYPE_SUPPORTED_ON_FS(mark_type, fname) \ + fanotify_flags_err_msg(#mark_type, __FILE__, __LINE__, tst_brk_, \ + fanotify_mark_supported_on_fs(mark_type, fname)) #define REQUIRE_HANDLE_TYPE_SUPPORTED_BY_KERNEL(handle_type) \ - fanotify_init_flags_err_msg(#handle_type, __FILE__, __LINE__, tst_brk_, \ - fanotify_handle_supported_by_kernel(handle_type)) + fanotify_flags_err_msg(#handle_type, __FILE__, __LINE__, tst_brk_, \ + fanotify_handle_supported_by_kernel(handle_type)) #define REQUIRE_FANOTIFY_EVENTS_SUPPORTED_ON_FS(init_flags, mark_type, mask, fname) do { \ if (mark_type) \ - REQUIRE_MARK_TYPE_SUPPORTED_BY_KERNEL(mark_type); \ + REQUIRE_MARK_TYPE_SUPPORTED_ON_FS(mark_type, fname); \ if (init_flags) \ REQUIRE_FANOTIFY_INIT_FLAGS_SUPPORTED_ON_FS(init_flags, fname); \ - fanotify_init_flags_err_msg(#mask, __FILE__, __LINE__, tst_brk_, \ - fanotify_events_supported_by_kernel(mask, init_flags, mark_type)); \ + fanotify_flags_err_msg(#mask, __FILE__, __LINE__, tst_brk_, \ + fanotify_flags_supported_on_fs(init_flags, mark_type, mask, fname)); \ } while (0) static inline struct fanotify_event_info_header *get_event_info( diff --git a/testcases/kernel/syscalls/fanotify/fanotify01.c b/testcases/kernel/syscalls/fanotify/fanotify01.c index 3538335c9..e4398f236 100644 --- a/testcases/kernel/syscalls/fanotify/fanotify01.c +++ b/testcases/kernel/syscalls/fanotify/fanotify01.c @@ -76,6 +76,7 @@ static char fname[BUF_SIZE]; static char buf[BUF_SIZE]; static int fd_notify; static int fan_report_fid_unsupported; +static int mount_mark_fid_unsupported; static int filesystem_mark_unsupported; static unsigned long long event_set[EVENT_MAX]; @@ -88,16 +89,22 @@ static void test_fanotify(unsigned int n) struct fanotify_mark_type *mark = &tc->mark; int fd, ret, len, i = 0, test_num = 0; int tst_count = 0; + int report_fid = (tc->init_flags & FAN_REPORT_FID); tst_res(TINFO, "Test #%d: %s", n, tc->tname); - if (fan_report_fid_unsupported && (tc->init_flags & FAN_REPORT_FID)) { + if (fan_report_fid_unsupported && report_fid) { FANOTIFY_INIT_FLAGS_ERR_MSG(FAN_REPORT_FID, fan_report_fid_unsupported); return; } if (filesystem_mark_unsupported && mark->flag == FAN_MARK_FILESYSTEM) { - tst_res(TCONF, "FAN_MARK_FILESYSTEM not supported in kernel?"); + FANOTIFY_MARK_FLAGS_ERR_MSG(mark, filesystem_mark_unsupported); + return; + } + + if (mount_mark_fid_unsupported && report_fid && mark->flag != FAN_MARK_INODE) { + FANOTIFY_MARK_FLAGS_ERR_MSG(mark, mount_mark_fid_unsupported); return; } @@ -341,7 +348,10 @@ static void setup(void) SAFE_FILE_PRINTF(fname, "1"); fan_report_fid_unsupported = fanotify_init_flags_supported_on_fs(FAN_REPORT_FID, fname); - filesystem_mark_unsupported = fanotify_mark_supported_by_kernel(FAN_MARK_FILESYSTEM); + filesystem_mark_unsupported = fanotify_mark_supported_on_fs(FAN_MARK_FILESYSTEM, fname); + mount_mark_fid_unsupported = fanotify_flags_supported_on_fs(FAN_REPORT_FID, + FAN_MARK_MOUNT, + FAN_OPEN, fname); } static void cleanup(void) diff --git a/testcases/kernel/syscalls/fanotify/fanotify03.c b/testcases/kernel/syscalls/fanotify/fanotify03.c index 0bd61587a..028da742c 100644 --- a/testcases/kernel/syscalls/fanotify/fanotify03.c +++ b/testcases/kernel/syscalls/fanotify/fanotify03.c @@ -320,14 +320,14 @@ static void test_fanotify(unsigned int n) static void setup(void) { - require_fanotify_access_permissions_supported_by_kernel(); - - filesystem_mark_unsupported = fanotify_mark_supported_by_kernel(FAN_MARK_FILESYSTEM); - exec_events_unsupported = fanotify_events_supported_by_kernel(FAN_OPEN_EXEC_PERM, - FAN_CLASS_CONTENT, 0); sprintf(fname, MOUNT_PATH"/fname_%d", getpid()); SAFE_FILE_PRINTF(fname, "1"); + require_fanotify_access_permissions_supported_on_fs(fname); + filesystem_mark_unsupported = fanotify_mark_supported_on_fs(FAN_MARK_FILESYSTEM, fname); + exec_events_unsupported = fanotify_flags_supported_on_fs(FAN_CLASS_CONTENT, + 0, FAN_OPEN_EXEC_PERM, fname); + SAFE_CP(TEST_APP, FILE_EXEC_PATH); } diff --git a/testcases/kernel/syscalls/fanotify/fanotify07.c b/testcases/kernel/syscalls/fanotify/fanotify07.c index 396c8490e..34aa810c7 100644 --- a/testcases/kernel/syscalls/fanotify/fanotify07.c +++ b/testcases/kernel/syscalls/fanotify/fanotify07.c @@ -189,10 +189,9 @@ static void test_fanotify(void) static void setup(void) { - require_fanotify_access_permissions_supported_by_kernel(); - sprintf(fname, "fname_%d", getpid()); SAFE_FILE_PRINTF(fname, "%s", fname); + require_fanotify_access_permissions_supported_on_fs(fname); } static void cleanup(void) diff --git a/testcases/kernel/syscalls/fanotify/fanotify09.c b/testcases/kernel/syscalls/fanotify/fanotify09.c index 3f2db4709..f61c4e45a 100644 --- a/testcases/kernel/syscalls/fanotify/fanotify09.c +++ b/testcases/kernel/syscalls/fanotify/fanotify09.c @@ -480,9 +480,11 @@ static void test_fanotify(unsigned int n) static void setup(void) { - fan_report_dfid_unsupported = fanotify_init_flags_supported_on_fs(FAN_REPORT_DFID_NAME, - MOUNT_PATH); - ignore_mark_unsupported = fanotify_mark_supported_by_kernel(FAN_MARK_IGNORE_SURV); + fan_report_dfid_unsupported = fanotify_flags_supported_on_fs(FAN_REPORT_DFID_NAME, + FAN_MARK_MOUNT, + FAN_OPEN, MOUNT_PATH); + ignore_mark_unsupported = fanotify_mark_supported_on_fs(FAN_MARK_IGNORE_SURV, + MOUNT_PATH); SAFE_MKDIR(MOUNT_NAME, 0755); SAFE_MOUNT(MOUNT_PATH, MOUNT_NAME, "none", MS_BIND, NULL); diff --git a/testcases/kernel/syscalls/fanotify/fanotify10.c b/testcases/kernel/syscalls/fanotify/fanotify10.c index d0e9194e7..6c89ca1d0 100644 --- a/testcases/kernel/syscalls/fanotify/fanotify10.c +++ b/testcases/kernel/syscalls/fanotify/fanotify10.c @@ -874,13 +874,17 @@ static void setup(void) { int i; - exec_events_unsupported = fanotify_events_supported_by_kernel(FAN_OPEN_EXEC, - FAN_CLASS_CONTENT, 0); - filesystem_mark_unsupported = fanotify_mark_supported_by_kernel(FAN_MARK_FILESYSTEM); - evictable_mark_unsupported = fanotify_mark_supported_by_kernel(FAN_MARK_EVICTABLE); - ignore_mark_unsupported = fanotify_mark_supported_by_kernel(FAN_MARK_IGNORE_SURV); - fan_report_dfid_unsupported = fanotify_init_flags_supported_on_fs(FAN_REPORT_DFID_NAME, - MOUNT_PATH); + exec_events_unsupported = fanotify_flags_supported_on_fs(FAN_CLASS_CONTENT, + 0, FAN_OPEN_EXEC, MOUNT_PATH); + filesystem_mark_unsupported = fanotify_mark_supported_on_fs(FAN_MARK_FILESYSTEM, + MOUNT_PATH); + evictable_mark_unsupported = fanotify_mark_supported_on_fs(FAN_MARK_EVICTABLE, + MOUNT_PATH); + ignore_mark_unsupported = fanotify_mark_supported_on_fs(FAN_MARK_IGNORE_SURV, + MOUNT_PATH); + fan_report_dfid_unsupported = fanotify_flags_supported_on_fs(FAN_REPORT_DFID_NAME, + FAN_MARK_MOUNT, + FAN_OPEN, MOUNT_PATH); if (fan_report_dfid_unsupported) { FANOTIFY_INIT_FLAGS_ERR_MSG(FAN_REPORT_DFID_NAME, fan_report_dfid_unsupported); /* Limit tests to legacy priority classes */ diff --git a/testcases/kernel/syscalls/fanotify/fanotify11.c b/testcases/kernel/syscalls/fanotify/fanotify11.c index 03583d84b..ce46913b1 100644 --- a/testcases/kernel/syscalls/fanotify/fanotify11.c +++ b/testcases/kernel/syscalls/fanotify/fanotify11.c @@ -94,7 +94,7 @@ static void test01(unsigned int i) static void setup(void) { - fan_report_tid_unsupported = fanotify_init_flags_supported_by_kernel(FAN_REPORT_TID); + fan_report_tid_unsupported = fanotify_init_flags_supported_on_fs(FAN_REPORT_TID, "."); } static struct tst_test test = { diff --git a/testcases/kernel/syscalls/fanotify/fanotify12.c b/testcases/kernel/syscalls/fanotify/fanotify12.c index 7f8e97b17..42ba08800 100644 --- a/testcases/kernel/syscalls/fanotify/fanotify12.c +++ b/testcases/kernel/syscalls/fanotify/fanotify12.c @@ -222,11 +222,10 @@ cleanup: static void do_setup(void) { - exec_events_unsupported = fanotify_events_supported_by_kernel(FAN_OPEN_EXEC, - FAN_CLASS_NOTIF, 0); - sprintf(fname, "fname_%d", getpid()); SAFE_FILE_PRINTF(fname, "1"); + exec_events_unsupported = fanotify_flags_supported_on_fs(FAN_CLASS_NOTIF, + 0, FAN_OPEN_EXEC, fname); } static void do_cleanup(void) diff --git a/testcases/kernel/syscalls/fanotify/fanotify13.c b/testcases/kernel/syscalls/fanotify/fanotify13.c index a25a360fd..6086a81fc 100644 --- a/testcases/kernel/syscalls/fanotify/fanotify13.c +++ b/testcases/kernel/syscalls/fanotify/fanotify13.c @@ -91,8 +91,10 @@ static struct test_case_t { static int ovl_mounted; static int bind_mounted; +static int ovl_bind_mounted; static int nofid_fd; static int fanotify_fd; +static int at_handle_fid; static int filesystem_mark_unsupported; static char events_buf[BUF_SIZE]; static struct event_t event_set[EVENT_MAX]; @@ -113,8 +115,10 @@ static void get_object_stats(void) { unsigned int i; - for (i = 0; i < ARRAY_SIZE(objects); i++) - fanotify_save_fid(objects[i].path, &objects[i].fid); + for (i = 0; i < ARRAY_SIZE(objects); i++) { + at_handle_fid |= + fanotify_save_fid(objects[i].path, &objects[i].fid); + } } static int setup_marks(unsigned int fd, struct test_case_t *tc) @@ -154,8 +158,8 @@ static void do_test(unsigned int number) return; } - if (filesystem_mark_unsupported && mark->flag & FAN_MARK_FILESYSTEM) { - tst_res(TCONF, "FAN_MARK_FILESYSTEM not supported in kernel?"); + if (filesystem_mark_unsupported && mark->flag != FAN_MARK_INODE) { + FANOTIFY_MARK_FLAGS_ERR_MSG(mark, filesystem_mark_unsupported); return; } @@ -168,10 +172,10 @@ static void do_test(unsigned int number) if (setup_marks(fanotify_fd, tc) != 0) goto out; - /* Variant #1: watching upper fs - open files on overlayfs */ - if (tst_variant == 1) { + /* Watching base fs - open files on overlayfs */ + if (tst_variant && !ovl_bind_mounted) { if (mark->flag & FAN_MARK_MOUNT) { - tst_res(TCONF, "overlayfs upper fs cannot be watched with mount mark"); + tst_res(TCONF, "overlayfs base fs cannot be watched with mount mark"); goto out; } SAFE_MOUNT(OVL_MNT, MOUNT_PATH, "none", MS_BIND, NULL); @@ -191,7 +195,7 @@ static void do_test(unsigned int number) SAFE_CLOSE(fds[i]); } - if (tst_variant == 1) + if (tst_variant && !ovl_bind_mounted) SAFE_UMOUNT(MOUNT_PATH); /* Read events from event queue */ @@ -286,19 +290,27 @@ static void do_setup(void) /* * Bind mount to either base fs or to overlayfs over base fs: * Variant #0: watch base fs - open files on base fs - * Variant #1: watch upper fs - open files on overlayfs + * Variant #1: watch lower fs - open lower files on overlayfs + * Variant #2: watch upper fs - open upper files on overlayfs + * Variant #3: watch overlayfs - open lower files on overlayfs + * Variant #4: watch overlayfs - open upper files on overlayfs * - * Variant #1 tests a bug whose fix bc2473c90fca ("ovl: enable fsnotify + * Variants 1,2 test a bug whose fix bc2473c90fca ("ovl: enable fsnotify * events on underlying real files") in kernel 6.5 is not likely to be * backported to older kernels. * To avoid waiting for events that won't arrive when testing old kernels, - * require that kernel supports encoding fid with new flag AT_HADNLE_FID, + * require that kernel supports encoding fid with new flag AT_HANDLE_FID, * also merged to 6.5 and not likely to be backported to older kernels. + * Variants 3,4 test overlayfs watch with FAN_REPORT_FID, which also + * requires kernel with support for AT_HANDLE_FID. */ if (tst_variant) { REQUIRE_HANDLE_TYPE_SUPPORTED_BY_KERNEL(AT_HANDLE_FID); ovl_mounted = TST_MOUNT_OVERLAY(); - mnt = OVL_UPPER; + if (!ovl_mounted) + return; + + mnt = tst_variant & 1 ? OVL_LOWER : OVL_UPPER; } else { mnt = OVL_BASE_MNTPOINT; @@ -308,13 +320,21 @@ static void do_setup(void) SAFE_MOUNT(mnt, MOUNT_PATH, "none", MS_BIND, NULL); bind_mounted = 1; - filesystem_mark_unsupported = fanotify_mark_supported_by_kernel(FAN_MARK_FILESYSTEM); - nofid_fd = SAFE_FANOTIFY_INIT(FAN_CLASS_NOTIF, O_RDONLY); - /* Create file and directory objects for testing */ + /* Create file and directory objects for testing on base fs */ create_objects(); + if (tst_variant > 2) { + /* Setup watches on overlayfs */ + SAFE_MOUNT(OVL_MNT, MOUNT_PATH, "none", MS_BIND, NULL); + ovl_bind_mounted = 1; + } + + filesystem_mark_unsupported = + fanotify_flags_supported_on_fs(FAN_REPORT_FID, FAN_MARK_FILESYSTEM, FAN_OPEN, + ovl_bind_mounted ? OVL_MNT : MOUNT_PATH); + /* * Create a mark on first inode without FAN_REPORT_FID, to test * uninitialized connector->fsid cache. This mark remains for all test @@ -329,9 +349,12 @@ static void do_setup(void) static void do_cleanup(void) { - SAFE_CLOSE(nofid_fd); + if (nofid_fd > 0) + SAFE_CLOSE(nofid_fd); if (fanotify_fd > 0) SAFE_CLOSE(fanotify_fd); + if (ovl_bind_mounted) + SAFE_UMOUNT(MOUNT_PATH); if (bind_mounted) { SAFE_UMOUNT(MOUNT_PATH); SAFE_RMDIR(MOUNT_PATH); @@ -343,7 +366,7 @@ static void do_cleanup(void) static struct tst_test test = { .test = do_test, .tcnt = ARRAY_SIZE(test_cases), - .test_variants = 2, + .test_variants = 5, .setup = do_setup, .cleanup = do_cleanup, .needs_root = 1, diff --git a/testcases/kernel/syscalls/fanotify/fanotify14.c b/testcases/kernel/syscalls/fanotify/fanotify14.c index 4596511f0..0b0da89ca 100644 --- a/testcases/kernel/syscalls/fanotify/fanotify14.c +++ b/testcases/kernel/syscalls/fanotify/fanotify14.c @@ -45,8 +45,9 @@ static int pipes[2] = {-1, -1}; static int fanotify_fd; -static int fan_report_target_fid_unsupported; static int ignore_mark_unsupported; +static int filesystem_mark_unsupported; +static unsigned int supported_init_flags; struct test_case_flags_t { unsigned long long flags; @@ -246,9 +247,8 @@ static void do_test(unsigned int number) tst_res(TINFO, "Test case %d: fanotify_init(%s, O_RDONLY)", number, tc->init.desc); - if (fan_report_target_fid_unsupported && tc->init.flags & FAN_REPORT_TARGET_FID) { - FANOTIFY_INIT_FLAGS_ERR_MSG(FAN_REPORT_TARGET_FID, - fan_report_target_fid_unsupported); + if (tc->init.flags & ~supported_init_flags) { + tst_res(TCONF, "Unsupported init flags"); return; } @@ -300,7 +300,7 @@ static void do_test(unsigned int number) "Adding an inode mark on directory did not fail with " "ENOTDIR error as on non-dir inode"); - if (!(tc->mark.flags & FAN_MARK_ONLYDIR)) { + if (!(tc->mark.flags & FAN_MARK_ONLYDIR) && !filesystem_mark_unsupported) { SAFE_FANOTIFY_MARK(fanotify_fd, FAN_MARK_ADD | tc->mark.flags | FAN_MARK_FILESYSTEM, tc->mask.flags, AT_FDCWD, FILE1); @@ -317,12 +317,18 @@ out: static void do_setup(void) { + unsigned int all_init_flags = FAN_REPORT_DFID_NAME_TARGET | + FAN_CLASS_NOTIF | FAN_CLASS_CONTENT | FAN_CLASS_PRE_CONTENT; + /* Require FAN_REPORT_FID support for all tests to simplify per test case requirements */ REQUIRE_FANOTIFY_INIT_FLAGS_SUPPORTED_ON_FS(FAN_REPORT_FID, MNTPOINT); + supported_init_flags = fanotify_get_supported_init_flags(all_init_flags, MNTPOINT); - fan_report_target_fid_unsupported = - fanotify_init_flags_supported_on_fs(FAN_REPORT_DFID_NAME_TARGET, MNTPOINT); - ignore_mark_unsupported = fanotify_mark_supported_by_kernel(FAN_MARK_IGNORE_SURV); + ignore_mark_unsupported = fanotify_mark_supported_on_fs(FAN_MARK_IGNORE_SURV, + MNTPOINT); + filesystem_mark_unsupported = + fanotify_flags_supported_on_fs(FAN_REPORT_FID, FAN_MARK_FILESYSTEM, FAN_OPEN, + MNTPOINT); /* Create temporary test file to place marks on */ SAFE_FILE_PRINTF(FILE1, "0"); diff --git a/testcases/kernel/syscalls/fanotify/fanotify15.c b/testcases/kernel/syscalls/fanotify/fanotify15.c index 6109d32cd..bacf05049 100644 --- a/testcases/kernel/syscalls/fanotify/fanotify15.c +++ b/testcases/kernel/syscalls/fanotify/fanotify15.c @@ -52,6 +52,7 @@ struct event_t { }; static int fanotify_fd; +static int filesystem_mark_unsupported; static char events_buf[EVENT_BUF_LEN]; static struct event_t event_set[EVENT_MAX]; @@ -85,6 +86,11 @@ static void do_test(unsigned int number) tst_res(TINFO, "Test #%d: %s", number, tc->tname); + if (filesystem_mark_unsupported && mark->flag != FAN_MARK_INODE) { + FANOTIFY_MARK_FLAGS_ERR_MSG(mark, filesystem_mark_unsupported); + return; + } + SAFE_FANOTIFY_MARK(fanotify_fd, FAN_MARK_ADD | mark->flag, tc->mask | FAN_CREATE | FAN_DELETE | FAN_MOVE | FAN_MODIFY | FAN_ONDIR, @@ -274,6 +280,10 @@ static void do_setup(void) { SAFE_MKDIR(TEST_DIR, 0755); REQUIRE_FANOTIFY_INIT_FLAGS_SUPPORTED_ON_FS(FAN_REPORT_FID, TEST_DIR); + filesystem_mark_unsupported = + fanotify_flags_supported_on_fs(FAN_REPORT_FID, FAN_MARK_FILESYSTEM, FAN_OPEN, + MOUNT_POINT); + fanotify_fd = SAFE_FANOTIFY_INIT(FAN_REPORT_FID, O_RDONLY); } diff --git a/testcases/kernel/syscalls/fanotify/fanotify16.c b/testcases/kernel/syscalls/fanotify/fanotify16.c index d45270a9a..6ab360984 100644 --- a/testcases/kernel/syscalls/fanotify/fanotify16.c +++ b/testcases/kernel/syscalls/fanotify/fanotify16.c @@ -70,6 +70,7 @@ static char event_buf[EVENT_BUF_LEN]; #define TEMP_DIR MOUNT_PATH "/temp_dir" static int fan_report_target_fid_unsupported; +static int filesystem_mark_unsupported; static int rename_events_unsupported; static struct test_case_t { @@ -281,6 +282,16 @@ static void do_test(unsigned int number) return; } + if (filesystem_mark_unsupported) { + if (sub_mark && sub_mark->flag != FAN_MARK_INODE) + mark = sub_mark; + + if (mark->flag != FAN_MARK_INODE) { + FANOTIFY_MARK_FLAGS_ERR_MSG(mark, filesystem_mark_unsupported); + return; + } + } + fd_notify = SAFE_FANOTIFY_INIT(group->flag, 0); /* @@ -328,7 +339,15 @@ static void do_test(unsigned int number) tst_count++; /* Generate modify events "on child" */ - fd = SAFE_CREAT(fname1, 0755); + + /* + * Split SAFE_CREAT() into explicit SAFE_MKNOD() and SAFE_OPEN(), + * because with atomic open (e.g. fuse), SAFE_CREAT() generates + * FAN_OPEN before FAN_CREATE and it is inconsistent with the order + * of events expectated from other filesystems. + */ + SAFE_MKNOD(fname1, S_IFREG | 0644, 0); + fd = SAFE_OPEN(fname1, O_WRONLY); /* Save the file fid */ fanotify_save_fid(fname1, &file_fid); @@ -765,8 +784,12 @@ static void setup(void) REQUIRE_FANOTIFY_INIT_FLAGS_SUPPORTED_ON_FS(FAN_REPORT_DIR_FID, MOUNT_PATH); fan_report_target_fid_unsupported = fanotify_init_flags_supported_on_fs(FAN_REPORT_DFID_NAME_TARGET, MOUNT_PATH); + filesystem_mark_unsupported = + fanotify_flags_supported_on_fs(FAN_REPORT_FID, FAN_MARK_FILESYSTEM, FAN_OPEN, + MOUNT_PATH); rename_events_unsupported = - fanotify_events_supported_by_kernel(FAN_RENAME, FAN_REPORT_DFID_NAME, 0); + fanotify_flags_supported_on_fs(FAN_REPORT_DFID_NAME, 0, + FAN_RENAME, MOUNT_PATH); SAFE_MKDIR(TEMP_DIR, 0755); sprintf(dname1, "%s/%s", MOUNT_PATH, DIR_NAME1); diff --git a/testcases/kernel/syscalls/fanotify/fanotify20.c b/testcases/kernel/syscalls/fanotify/fanotify20.c index 71310fb86..1d249ac9c 100644 --- a/testcases/kernel/syscalls/fanotify/fanotify20.c +++ b/testcases/kernel/syscalls/fanotify/fanotify20.c @@ -50,7 +50,8 @@ static void do_setup(void) * An explicit check for FAN_REPORT_PIDFD is performed early on in the * test initialization as it's a prerequisite for all test cases. */ - REQUIRE_FANOTIFY_INIT_FLAGS_SUPPORTED_BY_KERNEL(FAN_REPORT_PIDFD); + REQUIRE_FANOTIFY_INIT_FLAGS_SUPPORTED_ON_FS(FAN_REPORT_PIDFD, + MOUNT_PATH); } static void do_test(unsigned int i) diff --git a/testcases/kernel/syscalls/fanotify/fanotify21.c b/testcases/kernel/syscalls/fanotify/fanotify21.c index 2b7202b8a..90a797fce 100644 --- a/testcases/kernel/syscalls/fanotify/fanotify21.c +++ b/testcases/kernel/syscalls/fanotify/fanotify21.c @@ -119,7 +119,8 @@ static void do_setup(void) * on in the test initialization as it's a prerequisite for * all test cases. */ - REQUIRE_FANOTIFY_INIT_FLAGS_SUPPORTED_BY_KERNEL(FAN_REPORT_PIDFD); + REQUIRE_FANOTIFY_INIT_FLAGS_SUPPORTED_ON_FS(FAN_REPORT_PIDFD, + TEST_FILE); fanotify_fd = SAFE_FANOTIFY_INIT(FAN_REPORT_PIDFD, O_RDONLY); SAFE_FANOTIFY_MARK(fanotify_fd, FAN_MARK_ADD, FAN_OPEN, AT_FDCWD, diff --git a/testcases/kernel/syscalls/fanotify/fanotify23.c b/testcases/kernel/syscalls/fanotify/fanotify23.c index fb812c51e..5a03503e9 100644 --- a/testcases/kernel/syscalls/fanotify/fanotify23.c +++ b/testcases/kernel/syscalls/fanotify/fanotify23.c @@ -230,7 +230,7 @@ static void setup(void) { SAFE_TOUCH(TEST_FILE, 0666, NULL); - REQUIRE_MARK_TYPE_SUPPORTED_BY_KERNEL(FAN_MARK_EVICTABLE); + REQUIRE_MARK_TYPE_SUPPORTED_ON_FS(FAN_MARK_EVICTABLE, "."); REQUIRE_FANOTIFY_EVENTS_SUPPORTED_ON_FS(FAN_CLASS_NOTIF|FAN_REPORT_FID, FAN_MARK_FILESYSTEM, FAN_ATTRIB, "."); diff --git a/testcases/kernel/syscalls/fchmodat/.gitignore b/testcases/kernel/syscalls/fchmodat/.gitignore index a9508bc5a..09d5c47d5 100644 --- a/testcases/kernel/syscalls/fchmodat/.gitignore +++ b/testcases/kernel/syscalls/fchmodat/.gitignore @@ -1 +1,2 @@ /fchmodat01 +/fchmodat02 diff --git a/testcases/kernel/syscalls/fchmodat/fchmodat01.c b/testcases/kernel/syscalls/fchmodat/fchmodat01.c index 3deff0ebe..bf3812738 100644 --- a/testcases/kernel/syscalls/fchmodat/fchmodat01.c +++ b/testcases/kernel/syscalls/fchmodat/fchmodat01.c @@ -1,99 +1,82 @@ // SPDX-License-Identifier: GPL-2.0-or-later /* * Copyright (c) International Business Machines Corp., 2006 - * + * Copyright (c) Linux Test Project, 2003-2023 * 08/28/2006 AUTHOR: Yi Yang <yyangcdl@cn.ibm.com> */ /*\ * [Description] * - * This test case will verify basic function of fchmodat. + * Check the basic functionality of the fchmodat() system call. + * + * - fchmodat() passes if dir_fd is file descriptor to the directory + * where the file is located and pathname is relative path of the file. + * - fchmodat() passes if pathname is absolute, then dirfd is ignored. + * - fchmodat() passes if dir_fd is AT_FDCWD and pathname is interpreted + * relative to the current working directory of the calling process. */ -#define _GNU_SOURCE - -#include <unistd.h> -#include <string.h> #include <stdlib.h> #include <stdio.h> #include "tst_test.h" -#include "lapi/syscalls.h" -#ifndef AT_FDCWD -#define AT_FDCWD -100 -#endif +#define TESTDIR "fchmodatdir" +#define TESTFILE "fchmodatfile" +#define FILEPATH "fchmodatdir/fchmodatfile" -static char pathname[256]; -static char testfile[256]; -static char testfile2[256]; -static char testfile3[256]; +static int dir_fd, file_fd; +static int atcwd_fd = AT_FDCWD; +static char *abs_path; +static char *test_file; +static char *file_path; static struct tcase { - int exp_errno; - char *exp_errval; + int *fd; + char **filenames; + char **full_path; } tcases[] = { - { 0, NULL}, - { 0, NULL}, - { ENOTDIR, "ENOTDIR"}, - { EBADF, "EBADF"}, - { 0, NULL}, - { 0, NULL}, + {&dir_fd, &test_file, &file_path}, + {&file_fd, &abs_path, &abs_path}, + {&atcwd_fd, &file_path, &file_path}, }; -static int fds[ARRAY_SIZE(tcases)]; -static char *filenames[ARRAY_SIZE(tcases)]; static void verify_fchmodat(unsigned int i) { struct tcase *tc = &tcases[i]; + struct stat st; - if (tc->exp_errno == 0) - TST_EXP_PASS(tst_syscall(__NR_fchmodat, fds[i], filenames[i], 0600), - "fchmodat() returned the expected errno %d: %s", - TST_ERR, strerror(TST_ERR)); + TST_EXP_PASS(fchmodat(*tc->fd, *tc->filenames, 0600, 0), + "fchmodat(%d, %s, 0600, 0)", + *tc->fd, *tc->filenames); + + SAFE_LSTAT(*tc->full_path, &st); + + if ((st.st_mode & ~S_IFREG) == 0600) + tst_res(TPASS, "File permission changed correctly"); else - TST_EXP_FAIL(tst_syscall(__NR_fchmodat, fds[i], filenames[i], 0600), - tc->exp_errno, - "fchmodat() returned the expected errno %d: %s", - TST_ERR, strerror(TST_ERR)); + tst_res(TFAIL, "File permission not changed correctly"); } static void setup(void) { - /* Initialize test dir and file names */ - char *abs_path = tst_get_tmpdir(); - int p = getpid(); - - sprintf(pathname, "fchmodattestdir%d", p); - sprintf(testfile, "fchmodattest%d.txt", p); - sprintf(testfile2, "%s/fchmodattest%d.txt", abs_path, p); - sprintf(testfile3, "fchmodattestdir%d/fchmodattest%d.txt", p, p); + char *tmpdir_path = tst_get_tmpdir(); - free(abs_path); + abs_path = tst_aprintf("%s/%s", tmpdir_path, FILEPATH); + free(tmpdir_path); - SAFE_MKDIR(pathname, 0700); - - fds[0] = SAFE_OPEN(pathname, O_DIRECTORY); - fds[1] = fds[4] = fds[0]; - - SAFE_FILE_PRINTF(testfile, "%s", testfile); - SAFE_FILE_PRINTF(testfile2, "%s", testfile2); - - fds[2] = SAFE_OPEN(testfile3, O_CREAT | O_RDWR, 0600); - fds[3] = 100; - fds[5] = AT_FDCWD; - - filenames[0] = filenames[2] = filenames[3] = filenames[4] = testfile; - filenames[1] = testfile2; - filenames[5] = testfile3; + SAFE_MKDIR(TESTDIR, 0700); + dir_fd = SAFE_OPEN(TESTDIR, O_DIRECTORY); + file_fd = SAFE_OPEN(FILEPATH, O_CREAT | O_RDWR, 0600); } static void cleanup(void) { - if (fds[0] > 0) - close(fds[0]); - if (fds[2] > 0) - close(fds[2]); + if (dir_fd > -1) + SAFE_CLOSE(dir_fd); + + if (file_fd > -1) + SAFE_CLOSE(file_fd); } static struct tst_test test = { @@ -101,5 +84,10 @@ static struct tst_test test = { .test = verify_fchmodat, .setup = setup, .cleanup = cleanup, + .bufs = (struct tst_buffers []) { + {&test_file, .str = TESTFILE}, + {&file_path, .str = FILEPATH}, + {}, + }, .needs_tmpdir = 1, }; diff --git a/testcases/kernel/syscalls/fchmodat/fchmodat02.c b/testcases/kernel/syscalls/fchmodat/fchmodat02.c new file mode 100644 index 000000000..117865a8f --- /dev/null +++ b/testcases/kernel/syscalls/fchmodat/fchmodat02.c @@ -0,0 +1,87 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * Copyright (c) International Business Machines Corp., 2006 + * Copyright (c) Linux Test Project, 2003-2023 + * Author: Yi Yang <yyangcdl@cn.ibm.com> + */ + +/*\ + * [Description] + * + * Tests basic error handling of the fchmodat() syscall. + * + * - fchmodat() fails with ENOTDIR if dir_fd is file descriptor + * to the file and pathname is relative path of the file. + * - fchmodat() fails with EBADF if dir_fd is invalid. + * - fchmodat() fails with EFAULT if pathname points outside + * the accessible address space. + * - fchmodat() fails with ENAMETOOLONG if path is too long. + * - fchmodat() fails with ENOENT if pathname does not exist. + * - fchmodat() fails with EINVAL if flag is invalid. + */ + +#include <stdlib.h> +#include <stdio.h> +#include "tst_test.h" + +#define TESTFILE "fchmodatfile" + +static int file_fd; +static int bad_fd = -1; +static char path[PATH_MAX + 2]; +static char *long_path = path; +static int fd_atcwd = AT_FDCWD; +static char *bad_path; +static char *test_path; +static char *empty_path; + +static struct tcase { + int *fd; + char **filenames; + int flag; + int exp_errno; + const char *desc; +} tcases[] = { + {&file_fd, &test_path, 0, ENOTDIR, "fd pointing to file"}, + {&bad_fd, &test_path, 0, EBADF, "invalid fd"}, + {&file_fd, &bad_path, 0, EFAULT, "invalid address"}, + {&file_fd, &long_path, 0, ENAMETOOLONG, "pathname too long"}, + {&file_fd, &empty_path, 0, ENOENT, "path is empty"}, + {&fd_atcwd, &test_path, -1, EINVAL, "invalid flag"}, +}; + +static void verify_fchmodat(unsigned int i) +{ + struct tcase *tc = &tcases[i]; + + TST_EXP_FAIL(fchmodat(*tc->fd, *tc->filenames, 0600, tc->flag), + tc->exp_errno, "fchmodat() with %s", tc->desc); +} + +static void setup(void) +{ + file_fd = SAFE_OPEN(TESTFILE, O_CREAT | O_RDWR, 0600); + + bad_path = tst_get_bad_addr(NULL); + + memset(path, 'a', PATH_MAX + 2); +} + +static void cleanup(void) +{ + if (file_fd > -1) + SAFE_CLOSE(file_fd); +} + +static struct tst_test test = { + .test = verify_fchmodat, + .tcnt = ARRAY_SIZE(tcases), + .setup = setup, + .cleanup = cleanup, + .bufs = (struct tst_buffers []) { + {&test_path, .str = TESTFILE}, + {&empty_path, .str = ""}, + {}, + }, + .needs_tmpdir = 1, +}; diff --git a/testcases/kernel/syscalls/fchownat/fchownat.h b/testcases/kernel/syscalls/fchownat/fchownat.h deleted file mode 100644 index 927cf929a..000000000 --- a/testcases/kernel/syscalls/fchownat/fchownat.h +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Copyright (c) 2014 Fujitsu Ltd. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Library General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - * - */ - -#ifndef FCHOWNAT_H -#define FCHOWNAT_H - -#include <sys/types.h> -#include "config.h" -#include "lapi/syscalls.h" - - -#if !defined(HAVE_FCHOWNAT) -static inline int fchownat(int dirfd, const char *filename, uid_t owner, - gid_t group, int flags) -{ - return tst_syscall(__NR_fchownat, dirfd, filename, owner, group, flags); -} -#endif - - -#endif /* FCHOWNAT_H */ diff --git a/testcases/kernel/syscalls/fchownat/fchownat01.c b/testcases/kernel/syscalls/fchownat/fchownat01.c index 3b29f1e75..7771c111a 100644 --- a/testcases/kernel/syscalls/fchownat/fchownat01.c +++ b/testcases/kernel/syscalls/fchownat/fchownat01.c @@ -34,7 +34,6 @@ #include "test.h" #include "safe_macros.h" -#include "fchownat.h" #include "lapi/fcntl.h" #define TESTFILE "testfile" diff --git a/testcases/kernel/syscalls/fchownat/fchownat02.c b/testcases/kernel/syscalls/fchownat/fchownat02.c index c39b0a919..6dd1e024e 100644 --- a/testcases/kernel/syscalls/fchownat/fchownat02.c +++ b/testcases/kernel/syscalls/fchownat/fchownat02.c @@ -31,7 +31,6 @@ #include <signal.h> #include "test.h" #include "safe_macros.h" -#include "fchownat.h" #include "lapi/fcntl.h" #define TESTFILE "testfile" diff --git a/testcases/kernel/syscalls/fcntl/Makefile b/testcases/kernel/syscalls/fcntl/Makefile index df663a50a..aac774111 100644 --- a/testcases/kernel/syscalls/fcntl/Makefile +++ b/testcases/kernel/syscalls/fcntl/Makefile @@ -17,6 +17,6 @@ include $(abs_srcdir)/../utils/newer_64.mk %_64: CPPFLAGS += -D_FILE_OFFSET_BITS=64 -CPPFLAGS += -D_GNU_SOURCE +CPPFLAGS += -D_GNU_SOURCE -D_LARGEFILE64_SOURCE include $(top_srcdir)/include/mk/generic_leaf_target.mk diff --git a/testcases/kernel/syscalls/fork/.gitignore b/testcases/kernel/syscalls/fork/.gitignore index b817e9c05..acab5f768 100644 --- a/testcases/kernel/syscalls/fork/.gitignore +++ b/testcases/kernel/syscalls/fork/.gitignore @@ -2,12 +2,10 @@ /fork03 /fork04 /fork05 -/fork06 /fork07 /fork08 /fork09 /fork10 -/fork11 -/fork12 /fork13 /fork14 +/fork_procs diff --git a/testcases/kernel/syscalls/fork/fork04.c b/testcases/kernel/syscalls/fork/fork04.c index 5e5e42c4e..1a515987e 100644 --- a/testcases/kernel/syscalls/fork/fork04.c +++ b/testcases/kernel/syscalls/fork/fork04.c @@ -1,328 +1,96 @@ +// SPDX-License-Identifier: GPL-2.0 /* * Copyright (c) 2000 Silicon Graphics, Inc. All Rights Reserved. + * Copyright (c) Linux Test Project, 2001-2023 + * Copyright (C) 2023 SUSE LLC Andrea Cervesato <andrea.cervesato@suse.com> + */ + +/*\ + *[Description] * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it would be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * - * Further, this software is distributed without any warranty that it is - * free of the rightful claim of any third person regarding infringement - * or the like. Any license provided herein, whether implied or - * otherwise, applies only to this software file. Patent licenses, if - * any, provided herein do not apply to combinations of this program with - * other software, or any other product whatsoever. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy, - * Mountain View, CA 94043, or: - * - * http://www.sgi.com - * - * For further information regarding this notice, see: - * - * http://oss.sgi.com/projects/GenInfo/NoticeExplan/ - * - * - * OS Test - Silicon Graphics, Inc. - * TEST IDENTIFIER : fork04 - * TEST TITLE : Child inheritance of Environment Variables after fork() - * PARENT DOCUMENT : frktds01 - * TEST CASE TOTAL : 3 - * WALL CLOCK TIME : 1 - * CPU TYPES : ALL - * AUTHOR : Kathy Olmsted - * CO-PILOT : Steve Shaw - * DATE STARTED : 06/17/92 - * INITIAL RELEASE : UNICOS 7.0 - * - * TEST CASES - * Test these environment variables correctly inherited by child: - * 1. TERM - * 2. NoTSetzWq - * 3. TESTPROG - * - * INPUT SPECIFICATIONS - * The standard options for system call tests are accepted. - * (See the parse_opts(3) man page). - * - * DURATION - * Terminates - with frequency and infinite modes. - * - * SIGNALS - * Uses SIGUSR1 to pause before test if option set. - * (See the parse_opts(3) man page). - * - * ENVIRONMENTAL NEEDS - * No run-time environmental needs. - * - * DETAILED DESCRIPTION - * - * Setup: - * Setup signal handling. - * Make and change to a temporary directory. - * Pause for SIGUSR1 if option specified. - * Add TESTPROG variable to the environment - * - * Test: - * Loop if the proper options are given. - * fork() - * Check return code, if system call failed (return=-1) - * Log the errno - * CHILD: - * open a temp file - * Determine environment values and write to file - * close file containing test values. - * exit. - * PARENT: - * Wait for child to exit. - * Verify exit status - * Open file containing test values. - * For each test case: - * Read the value from the file. - * Determine and report PASS/FAIL result. - * - * Cleanup: - * Print errno log and/or timing stats if options given - * Remove the temporary directory and exit. + * This test verifies that parent process shares environ variables with the + * child and that child doesn't change parent's environ variables. */ #include <stdlib.h> -#include <sys/types.h> -#include <sys/wait.h> -#include <unistd.h> -#include <fcntl.h> -#include <string.h> -#include <sys/param.h> -#include <signal.h> -#include <errno.h> -#include "test.h" -#include "safe_macros.h" - -char *TCID = "fork04"; - -#define KIDEXIT 42 -#define MAX_LINE_LENGTH 256 -#define OUTPUT_FILE "env.out" -#define ENV_NOT_SET "getenv() does not find variable set" +#include "tst_test.h" -/* list of environment variables to test */ -char *environ_list[] = { "TERM", "NoTSetzWq", "TESTPROG" }; +#define ENV_KEY "LTP_FORK04" +#define ENV_VAL0 "PASS" +#define ENV_VAL1 "FAIL" -#define NUMBER_OF_ENVIRON (sizeof(environ_list)/sizeof(char *)) -int TST_TOTAL = NUMBER_OF_ENVIRON; - -static void cleanup(void) +static void run_child(void) { - tst_rmdir(); -} + const char *val; -static void setup(void) -{ + val = getenv(ENV_KEY); + if (!val) + tst_brk(TBROK, "Can't find %s environ variable", ENV_KEY); - tst_sig(FORK, DEF_HANDLER, cleanup); - TEST_PAUSE; - tst_tmpdir(); + TST_EXP_EXPR(strcmp(ENV_VAL0, val) == 0, + "%s environ variable has been inherited by the child", + ENV_KEY) - /* add a variable to the environment */ - putenv("TESTPROG=FRKTCS04"); -} + tst_res(TINFO, "Unset %s environ variable inside child", ENV_KEY); -static void child_environment(void) -{ - - int fildes; - int index; - char msg[MAX_LINE_LENGTH]; - char *var; + if (unsetenv(ENV_KEY) == -1) + tst_brk(TBROK, "Can't unset %s environ variable", ENV_KEY); - fildes = creat(OUTPUT_FILE, 0700); + TST_CHECKPOINT_WAKE_AND_WAIT(0); - for (index = 0; index < (int)NUMBER_OF_ENVIRON; index++) { - memset(msg, 0, MAX_LINE_LENGTH); + tst_res(TINFO, "Set %s=%s environ variable inside child", ENV_KEY, ENV_VAL1); - var = getenv(environ_list[index]); - if (var == NULL) - (void)sprintf(msg, "%s:%s", environ_list[index], - ENV_NOT_SET); - else - (void)sprintf(msg, "%s:%s", environ_list[index], var); - /* includes extra null chars */ - write(fildes, msg, sizeof(msg)); - } + SAFE_SETENV(ENV_KEY, ENV_VAL1, 0); - close(fildes); + TST_CHECKPOINT_WAKE(0); } -/* - * Compare parent env string to child's string. - * Each string is in the format: <env var>:<value> - */ -static int cmp_env_strings(char *pstring, char *cstring) +static void run(void) { - char *penv, *cenv, *pvalue, *cvalue; + const char *val; - /* - * Break pstring into env and value - */ - penv = pstring; - pvalue = strchr(pstring, ':'); - if (pvalue == NULL) { - tst_resm(TBROK, - "internal error - parent's env string not in correct format:'%s'", - pstring); - return -1; - } else { - *pvalue = '\0'; - pvalue++; - if (*pvalue == '\0') { - tst_resm(TBROK, - "internal error - missing parent's env value"); - return -1; - } - } + tst_res(TINFO, + "Set %s=%s environ variable inside parent", + ENV_KEY, ENV_VAL0); - /* - * Break cstring into env and value - */ - cenv = cstring; - cvalue = strchr(cstring, ':'); - if (cvalue == NULL) { - tst_resm(TBROK, - "internal error - parent's env string not in correct format:'%s'", - cstring); - return -1; - } else { - *cvalue = '\0'; - cvalue++; - if (*cvalue == '\0') { - tst_resm(TBROK, - "internal error - missing child's env value"); - return -1; - } - } + SAFE_SETENV(ENV_KEY, ENV_VAL0, 0); - if (strcmp(penv, cenv) != 0) { - tst_resm(TBROK, "internal error - parent(%s) != child (%s) env", - penv, cenv); - return -1; - } + tst_res(TINFO, "Spawning child"); - if (strcmp(pvalue, cvalue) != 0) { - tst_resm(TFAIL, - "Env var %s changed after fork(), parent's %s, child's %s", - penv, pvalue, cvalue); - } else { - tst_resm(TPASS, "Env var %s unchanged after fork(): %s", - penv, cvalue); + if (!SAFE_FORK()) { + run_child(); + exit(0); } - return 0; - -} - -/*************************************************************** - * parent_environment - the parent side of the environment tests - * determine values for the variables - * read the values determined by the child - * compare values - ***************************************************************/ -void parent_environment(void) -{ - - int fildes; - char tmp_line[MAX_LINE_LENGTH]; - char parent_value[MAX_LINE_LENGTH]; - unsigned int index; - int ret; - char *var; - - fildes = SAFE_OPEN(cleanup, OUTPUT_FILE, O_RDWR); - for (index = 0; index < NUMBER_OF_ENVIRON; index++) { - ret = read(fildes, tmp_line, MAX_LINE_LENGTH); - if (ret == 0) { - tst_resm(TBROK, - "fork() test. parent_environment: failed to read from file with %d (%s)", - errno, strerror(errno)); - } else { - var = getenv(environ_list[index]); - if (var == NULL) - sprintf(parent_value, "%s:%s", - environ_list[index], ENV_NOT_SET); - else - sprintf(parent_value, "%s:%s", - environ_list[index], var); + TST_CHECKPOINT_WAIT(0); - cmp_env_strings(parent_value, tmp_line); - - } + val = getenv(ENV_KEY); + if (!val) { + tst_res(TFAIL, + "%s environ variable has been unset inside parent", + ENV_KEY); + } else { + TST_EXP_EXPR(strcmp(ENV_VAL0, val) == 0, + "%s environ variable is still present inside parent", + ENV_KEY) } - close(fildes); -} - -int main(int ac, char **av) -{ - int lc; - int kid_status; - int wait_status; - int fails; - - tst_parse_opts(ac, av, NULL, NULL); - - setup(); - - for (lc = 0; TEST_LOOPING(lc); lc++) { - tst_count = 0; - fails = 0; - - TEST(fork()); - - if (TEST_RETURN == -1) { - /* fork failed */ - tst_brkm(TFAIL, cleanup, - "fork() failed with %d (%s)", - TEST_ERRNO, strerror(TEST_ERRNO)); - } else if (TEST_RETURN == 0) { - /* child */ - /* determine environment variables */ - child_environment(); - /* exit with known value */ - exit(KIDEXIT); - } else { - /* parent of successful fork */ - /* wait for the child to complete */ - wait_status = waitpid(TEST_RETURN, &kid_status, 0); - /* validate the child exit status */ - if (wait_status == TEST_RETURN) { - if (kid_status != KIDEXIT << 8) { - tst_brkm(TBROK, cleanup, - "fork(): Incorrect child status returned on wait(): %d", - kid_status); - fails++; - } - } else { - tst_brkm(TBROK, cleanup, - "fork(): wait() for child status failed with %d errno: %d : %s", - wait_status, errno, - strerror(errno)); - fails++; - } - - if (fails == 0) { - /* verification tests */ - parent_environment(); - } - } - + TST_CHECKPOINT_WAKE_AND_WAIT(0); + + val = getenv(ENV_KEY); + if (!val) + tst_res(TFAIL, + "%s environ variable has been unset inside parent", + ENV_KEY); + else { + TST_EXP_EXPR(strcmp(ENV_VAL0, val) == 0, + "%s environ variable didn't change inside parent", + ENV_KEY) } - - cleanup(); - tst_exit(); } + +static struct tst_test test = { + .test_all = run, + .forks_child = 1, + .needs_checkpoints = 1, +}; diff --git a/testcases/kernel/syscalls/fork/fork06.c b/testcases/kernel/syscalls/fork/fork06.c deleted file mode 100644 index 3bc11b14b..000000000 --- a/testcases/kernel/syscalls/fork/fork06.c +++ /dev/null @@ -1,106 +0,0 @@ -/* - * Copyright (c) International Business Machines Corp., 2001 - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See - * the GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * NAME - * fork06.c - * - * DESCRIPTION - * Test that a process can fork children a large number of - * times in succession - * - * ALGORITHM - * Attempt to fork a child that exits immediately - * Repeat it many times(1000), counting the number of successes and - * failures - * - * USAGE - * fork06 - * - * HISTORY - * 07/2001 Ported by Wayne Boyer - * - * RESTRICTIONS - * None - */ - -#include <sys/types.h> -#include <sys/wait.h> -#include <stdio.h> -#include "test.h" - -char *TCID = "fork06"; -int TST_TOTAL = 1; - -static void setup(void); -static void cleanup(void); - -#define NUMFORKS 1000 - -int main(int ac, char **av) -{ - int i, pid, status, childpid, succeed, fail; - - int lc; - - tst_parse_opts(ac, av, NULL, NULL); - - setup(); - - for (lc = 0; TEST_LOOPING(lc); lc++) { - tst_count = 0; - succeed = 0; - fail = 0; - - for (i = 0; i < NUMFORKS; i++) { - pid = fork(); - if (pid == -1) { - fail++; - continue; - } - - if (pid == 0) - _exit(0); - - childpid = wait(&status); - if (pid != childpid) - tst_resm(TFAIL, "pid from wait %d", childpid); - succeed++; - } - - tst_resm(TINFO, "tries %d", i); - tst_resm(TINFO, "successes %d", succeed); - tst_resm(TINFO, "failures %d", fail); - - if ((wait(&status)) == -1) - tst_resm(TINFO, "There were no children to wait for"); - else - tst_resm(TINFO, "There were children left"); - } - - cleanup(); - tst_exit(); -} - -static void setup(void) -{ - tst_sig(FORK, DEF_HANDLER, cleanup); - TEST_PAUSE; -} - -static void cleanup(void) -{ -} diff --git a/testcases/kernel/syscalls/fork/fork10.c b/testcases/kernel/syscalls/fork/fork10.c index 815eee1f6..790e7b386 100644 --- a/testcases/kernel/syscalls/fork/fork10.c +++ b/testcases/kernel/syscalls/fork/fork10.c @@ -1,159 +1,100 @@ +// SPDX-License-Identifier: GPL-2.0-or-later /* - * Copyright (c) International Business Machines Corp., 2001 - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See - * the GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * - * NAME - * fork10.c - * - * DESCRIPTION - * Check inheritance of file descriptor by children, they - * should all be refering to the same file. + * Copyright (c) International Business Machines Corp., 2001 + * 07/2001 Ported by Wayne Boyer + * Copyright (C) 2023 SUSE LLC Andrea Cervesato <andrea.cervesato@suse.com> + */ + +/*\ + * [Description] * - * ALGORITHM - * Child reads several chars and exits. - * Parent forks another child, have the child and parent attempt to use - * that location + * This test verifies inheritance of file descriptors from parent to child + * process. We open a file from parent, then we check if file offset changes + * accordingly with file descriptor usage. * - * USAGE - * fork10 + * [Algorithm] * - * HISTORY - * 07/2001 Ported by Wayne Boyer + * Test steps are the following: + * - create a file made in three parts -> | aa..a | bb..b | cc..c | + * - from parent, open the file + * - from child, move file offset after the first part + * - from parent, read second part and check if it's | bb..b | + * - from child, read third part and check if it's | cc..c | * - * RESTRICTIONS - * None + * Test passes if we were able to read the correct file parts from parent and + * child. */ -#include <sys/types.h> -#include <sys/wait.h> -#include <sys/stat.h> -#include <fcntl.h> -#include <stdio.h> -#include <errno.h> -#include "test.h" -#include "safe_macros.h" - -char *TCID = "fork10"; -int TST_TOTAL = 1; +#include <stdlib.h> +#include "tst_test.h" -static void setup(void); -static void cleanup(void); +#define FILENAME "file.txt" +#define DATASIZE 1024 -static char pidbuf[10]; -static char fnamebuf[40]; +static int fd = -1; -int main(int ac, char **av) +static void run(void) { - int status, pid, fildes; - char parchar[2]; - char chilchar[2]; - - int lc; - - fildes = -1; - - tst_parse_opts(ac, av, NULL, NULL); - - setup(); - - for (lc = 0; TEST_LOOPING(lc); lc++) { - tst_count = 0; - - fildes = SAFE_CREAT(cleanup, fnamebuf, 0600); - write(fildes, "ABCDEFGHIJKLMNOPQRSTUVWXYZ\n", 27); - close(fildes); - - fildes = SAFE_OPEN(cleanup, fnamebuf, 0); - - pid = fork(); - if (pid == -1) - tst_brkm(TBROK, cleanup, "fork() #1 failed"); - - if (pid == 0) { /* child */ - tst_resm(TINFO, "fork child A"); - if (lseek(fildes, 10L, 0) == -1L) { - tst_resm(TFAIL, "bad lseek by child"); - exit(1); - } - exit(0); - } else { /* parent */ - wait(&status); - - /* parent starts second child */ - pid = fork(); - if (pid == -1) - tst_brkm(TBROK, cleanup, "fork() #2 failed"); - - if (pid == 0) { /* child */ - if (read(fildes, chilchar, 1) <= 0) { - tst_resm(TFAIL, "Child can't read " - "file"); - exit(1); - } else { - if (chilchar[0] != 'K') { - chilchar[1] = '\n'; - exit(1); - } else { - exit(0); - } - } - } else { /* parent */ - (void)wait(&status); - if (status >> 8 != 0) { - tst_resm(TFAIL, "Bad return from " - "second child"); - continue; - } - /* parent reads */ - if (read(fildes, parchar, 1) <= 0) { - tst_resm(TFAIL, "Parent cannot read " - "file"); - continue; - } else { - write(fildes, parchar, 1); - if (parchar[0] != 'L') { - parchar[1] = '\n'; - tst_resm(TFAIL, "Test failed"); - continue; - } - } - } - } - tst_resm(TPASS, "test 1 PASSED"); + int status; + char buff[DATASIZE]; + char data[DATASIZE]; + + fd = SAFE_OPEN(FILENAME, 0); + + if (!SAFE_FORK()) { + SAFE_LSEEK(fd, DATASIZE, SEEK_SET); + exit(0); + } + + SAFE_WAIT(&status); + + memset(buff, 'b', DATASIZE); + SAFE_READ(1, fd, data, DATASIZE); + + TST_EXP_EXPR(strncmp(buff, data, DATASIZE) == 0, + "read first part of data from parent process"); + + if (!SAFE_FORK()) { + memset(buff, 'c', DATASIZE); + SAFE_READ(1, fd, data, DATASIZE); + + TST_EXP_EXPR(strncmp(buff, data, DATASIZE) == 0, + "read second part of data from child process"); + + exit(0); } - close(fildes); - cleanup(); - tst_exit(); + SAFE_CLOSE(fd); } static void setup(void) { - tst_sig(FORK, DEF_HANDLER, cleanup); - umask(0); - TEST_PAUSE; - tst_tmpdir(); - - strcpy(fnamebuf, "fork10."); - sprintf(pidbuf, "%d", getpid()); - strcat(fnamebuf, pidbuf); + char buff[DATASIZE]; + + fd = SAFE_CREAT(FILENAME, 0600); + + memset(buff, 'a', DATASIZE); + SAFE_WRITE(SAFE_WRITE_ALL, fd, buff, DATASIZE); + + memset(buff, 'b', DATASIZE); + SAFE_WRITE(SAFE_WRITE_ALL, fd, buff, DATASIZE); + + memset(buff, 'c', DATASIZE); + SAFE_WRITE(SAFE_WRITE_ALL, fd, buff, DATASIZE); + + SAFE_CLOSE(fd); } static void cleanup(void) { - tst_rmdir(); + if (fd >= 0) + SAFE_CLOSE(fd); } + +static struct tst_test test = { + .forks_child = 1, + .needs_tmpdir = 1, + .test_all = run, + .setup = setup, + .cleanup = cleanup, +}; diff --git a/testcases/kernel/syscalls/fork/fork11.c b/testcases/kernel/syscalls/fork/fork11.c deleted file mode 100644 index 6afda3a33..000000000 --- a/testcases/kernel/syscalls/fork/fork11.c +++ /dev/null @@ -1,97 +0,0 @@ -/* - * Copyright (c) International Business Machines Corp., 2001 - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See - * the GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * - * NAME - * fork11.c - * - * DESCRIPTION - * Test that parent gets a pid from each child when doing wait - * - * ALGORITHM - * Fork NUMFORKS children that do nothing. - * - * USAGE - * fork11 - * - * HISTORY - * 07/2001 Ported by Wayne Boyer - * - * RESTRICTIONS - * None - */ - -#include <sys/types.h> -#include <sys/wait.h> -#include <stdio.h> -#include <errno.h> -#include "test.h" - -char *TCID = "fork11"; -int TST_TOTAL = 1; - -static void setup(void); -static void cleanup(void); - -#define NUMFORKS 100 - -int main(int ac, char **av) -{ - int i, pid, cpid, status; - int fail = 0; - int lc; - - tst_parse_opts(ac, av, NULL, NULL); - - setup(); - - for (lc = 0; TEST_LOOPING(lc); lc++) { - tst_count = 0; - - for (i = 0; i < NUMFORKS; i++) { - pid = fork(); - if (pid == 0) - exit(0); - - if (pid > 0) { /* parent */ - cpid = wait(&status); - if (cpid != pid) - fail++; - } else { - fail++; - break; - } - } - if (fail) - tst_resm(TFAIL, "fork failed %d times", fail); - else - tst_resm(TPASS, "fork test passed, %d processes", i); - } - - cleanup(); - tst_exit(); -} - -static void setup(void) -{ - tst_sig(FORK, DEF_HANDLER, cleanup); - TEST_PAUSE; -} - -static void cleanup(void) -{ -} diff --git a/testcases/kernel/syscalls/fork/fork12.c b/testcases/kernel/syscalls/fork/fork12.c deleted file mode 100644 index 1c55c0c30..000000000 --- a/testcases/kernel/syscalls/fork/fork12.c +++ /dev/null @@ -1,137 +0,0 @@ -/* - * Copyright (c) International Business Machines Corp., 2001 - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See - * the GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * - * NAME - * fork12.c - * - * DESCRIPTION - * Check that all children inherit parent's file descriptor - * - * ALGORITHM - * Parent forks processes until -1 is returned.$ - * - * USAGE - * fork12 - * ** CAUTION ** Can hang your machine, esp prior to 2.4.19 - * - * HISTORY - * 07/2001 Ported by Wayne Boyer - * 07/2002 Split from fork07 as a test case to exhaust available pids. - * - * RESTRICTIONS - * Should be run as root to avoid resource limits.$ - * Should not be run with other test programs because it tries to - * use all available pids. - */ - -#include <stdio.h> -#include <sys/wait.h> -#include <errno.h> -#include <string.h> -#include "test.h" -#include "safe_macros.h" - -char *TCID = "fork12"; -int TST_TOTAL = 1; - -static void setup(void); -static void cleanup(void); -static void fork12_sigs(int signum); - -int main(int ac, char **av) -{ - int forks, pid1, fork_errno, waitstatus; - int ret, status; - int lc; - - tst_parse_opts(ac, av, NULL, NULL); - - setup(); - - for (lc = 0; TEST_LOOPING(lc); lc++) { - tst_count = 0; - - tst_resm(TINFO, "Forking as many kids as possible"); - forks = 0; - while ((pid1 = fork()) != -1) { - if (pid1 == 0) { /* child */ - /* - * Taunt the OOM killer so that it doesn't - * kill system processes - */ - SAFE_FILE_PRINTF(NULL, - "/proc/self/oom_score_adj", "500"); - pause(); - exit(0); - } - forks++; - ret = SAFE_WAITPID(cleanup, -1, &status, WNOHANG); - if (ret > 0) { - /* a child may be killed by OOM killer */ - if (WTERMSIG(status) == SIGKILL) - break; - tst_brkm(TBROK, cleanup, - "child exit with error code %d or signal %d", - WEXITSTATUS(status), WTERMSIG(status)); - } - } - fork_errno = errno; - - /* parent */ - tst_resm(TINFO, "Number of processes forked is %d", forks); - tst_resm(TPASS, "fork() eventually failed with %d: %s", - fork_errno, strerror(fork_errno)); - /* collect our kids */ - /* - * Introducing a sleep(3) to make sure all children are - * at pause() when SIGQUIT is sent to them - */ - sleep(3); - kill(0, SIGQUIT); - while (wait(&waitstatus) > 0) ; - - } - - cleanup(); - tst_exit(); -} - -static void setup(void) -{ - tst_sig(FORK, fork12_sigs, cleanup); - TEST_PAUSE; -} - -static void cleanup(void) -{ - int waitstatus; - - /* collect our kids */ - kill(0, SIGQUIT); - while (wait(&waitstatus) > 0) ; -} - -static void fork12_sigs(int signum) -{ - if (signum == SIGQUIT) { - /* Children will continue, parent will ignore */ - } else { - tst_brkm(TBROK, cleanup, - "Unexpected signal %d received.", signum); - } -} diff --git a/testcases/kernel/syscalls/fork/fork_procs.c b/testcases/kernel/syscalls/fork/fork_procs.c new file mode 100644 index 000000000..c35bb480c --- /dev/null +++ b/testcases/kernel/syscalls/fork/fork_procs.c @@ -0,0 +1,55 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * Copyright (C) 2023 SUSE LLC Andrea Cervesato <andrea.cervesato@suse.com> + */ + +/*\ + *[Description] + * + * This test spawns multiple processes using fork() and it checks if wait() + * returns the right PID once they end up. + */ + +#include <stdlib.h> +#include "tst_test.h" + +static char *str_numforks; +static int numforks = 1000; + +static void run(void) +{ + pid_t pid; + int status; + int counter = 0; + + tst_res(TINFO, "Forking %d processes", numforks); + + for (int i = 0; i < numforks; i++) { + pid = SAFE_FORK(); + if (!pid) + exit(0); + + if (SAFE_WAIT(&status) == pid) + counter++; + } + + TST_EXP_EXPR(numforks == counter, + "%d processes ended successfully", + counter); +} + +static void setup(void) +{ + if (tst_parse_int(str_numforks, &numforks, 1, INT_MAX)) + tst_brk(TBROK, "wrong number of forks '%s'", str_numforks); +} + +static struct tst_test test = { + .test_all = run, + .setup = setup, + .forks_child = 1, + .options = (struct tst_option[]) { + { "n:", &str_numforks, "Number of processes to spawn" }, + {}, + }, +}; diff --git a/testcases/kernel/syscalls/fsetxattr/fsetxattr01.c b/testcases/kernel/syscalls/fsetxattr/fsetxattr01.c index d799e477f..b65b27bdf 100644 --- a/testcases/kernel/syscalls/fsetxattr/fsetxattr01.c +++ b/testcases/kernel/syscalls/fsetxattr/fsetxattr01.c @@ -140,7 +140,7 @@ static void verify_fsetxattr(unsigned int i) { /* some tests might require existing keys for each iteration */ if (tc[i].keyneeded) { - SAFE_FSETXATTR(fd, tc[i].key, tc[i].value, tc[i].size, + SAFE_FSETXATTR(fd, tc[i].key, *tc[i].value, tc[i].size, XATTR_CREATE); } diff --git a/testcases/kernel/syscalls/fsetxattr/fsetxattr02.c b/testcases/kernel/syscalls/fsetxattr/fsetxattr02.c index 0336c964a..39265af36 100644 --- a/testcases/kernel/syscalls/fsetxattr/fsetxattr02.c +++ b/testcases/kernel/syscalls/fsetxattr/fsetxattr02.c @@ -1,27 +1,33 @@ // SPDX-License-Identifier: GPL-2.0-or-later /* * Copyright (c) 2018 Linaro Limited. All rights reserved. + * Copyright (c) Linux Test Project, 2018-2023 * Author: Rafael David Tinoco <rafael.tinoco@linaro.org> */ +/*\ + * [Description] + * + * Verify basic fsetxattr(2) syscall functionality: + * + * - Set attribute to a regular file, fsetxattr(2) should succeed. + * - Set attribute to a directory, fsetxattr(2) should succeed. + * - Set attribute to a symlink which points to the regular file, + * fsetxattr(2) should return -1 and set errno to EEXIST. + * - Set attribute to a FIFO, fsetxattr(2) should return -1 and set + * errno to EPERM. + * - Set attribute to a char special file, fsetxattr(2) should + * return -1 and set errno to EPERM. + * - Set attribute to a block special file, fsetxattr(2) should + * return -1 and set errno to EPERM. + * - Set attribute to a UNIX domain socket, fsetxattr(2) should + * return -1 and set errno to EPERM. + */ + /* * In the user.* namespace, only regular files and directories can * have extended attributes. Otherwise fsetxattr(2) will return -1 * and set errno to EPERM. - * - * There are 7 test cases: - * 1. Set attribute to a regular file, fsetxattr(2) should succeed - * 2. Set attribute to a directory, fsetxattr(2) should succeed - * 3. Set attribute to a symlink which points to the regular file, - * fsetxattr(2) should return -1 and set errno to EEXIST - * 4. Set attribute to a FIFO, fsetxattr(2) should return -1 and set - * errno to EPERM - * 5. Set attribute to a char special file, fsetxattr(2) should - * return -1 and set errno to EPERM - * 6. Set attribute to a block special file, fsetxattr(2) should - * return -1 and set errno to EPERM - * 7. Set attribute to a UNIX domain socket, fsetxattr(2) should - * return -1 and set errno to EPERM */ #include "config.h" diff --git a/testcases/kernel/syscalls/getcwd/getcwd01.c b/testcases/kernel/syscalls/getcwd/getcwd01.c index 65d827873..218bf4ef2 100644 --- a/testcases/kernel/syscalls/getcwd/getcwd01.c +++ b/testcases/kernel/syscalls/getcwd/getcwd01.c @@ -14,17 +14,17 @@ * * Expected Result: * 1) getcwd(2) should return NULL and set errno to EFAULT. - * 2) getcwd(2) should return NULL and set errno to ENOMEM. - * 3) getcwd(2) should return NULL and set errno to EINVAL. + * 2) getcwd(2) should return NULL and set errno to EFAULT. + * 3) getcwd(2) should return NULL and set errno to ERANGE. * 4) getcwd(2) should return NULL and set errno to ERANGE. * 5) getcwd(2) should return NULL and set errno to ERANGE. - * */ #include <errno.h> #include <unistd.h> #include <limits.h> #include "tst_test.h" +#include "lapi/syscalls.h" static char buffer[5]; @@ -34,32 +34,18 @@ static struct t_case { int exp_err; } tcases[] = { {(void *)-1, PATH_MAX, EFAULT}, - {NULL, (size_t)-1, ENOMEM}, - {buffer, 0, EINVAL}, + {NULL, (size_t)-1, EFAULT}, + {buffer, 0, ERANGE}, {buffer, 1, ERANGE}, {NULL, 1, ERANGE} }; + static void verify_getcwd(unsigned int n) { struct t_case *tc = &tcases[n]; - char *res; - - errno = 0; - res = getcwd(tc->buf, tc->size); - TST_ERR = errno; - if (res) { - tst_res(TFAIL, "getcwd() succeeded unexpectedly"); - return; - } - - if (TST_ERR != tc->exp_err) { - tst_res(TFAIL | TTERRNO, "getcwd() failed unexpectedly, expected %s", - tst_strerrno(tc->exp_err)); - return; - } - tst_res(TPASS | TTERRNO, "getcwd() failed as expected"); + TST_EXP_FAIL2(tst_syscall(__NR_getcwd, tc->buf, tc->size), tc->exp_err); } static struct tst_test test = { diff --git a/testcases/kernel/syscalls/getcwd/getcwd02.c b/testcases/kernel/syscalls/getcwd/getcwd02.c index cb111a698..e3df22ceb 100644 --- a/testcases/kernel/syscalls/getcwd/getcwd02.c +++ b/testcases/kernel/syscalls/getcwd/getcwd02.c @@ -3,12 +3,14 @@ * Copyright (c) International Business Machines Corp., 2001 */ -/* - * DESCRIPTION +/*\ + * [Description] + * * Testcase to check the basic functionality of the getcwd(2) system call. - * 1) getcwd(2) works fine if buf and size are valid. - * 2) getcwd(2) works fine if buf points to NULL and size is set to 0. - * 3) getcwd(2) works fine if buf points to NULL and size is greater than strlen(path). + * + * 1. getcwd(2) works fine if buf and size are valid. + * 2. getcwd(2) works fine if buf points to NULL and size is set to 0. + * 3. getcwd(2) works fine if buf points to NULL and size is greater than strlen(path). */ #include <errno.h> diff --git a/testcases/kernel/syscalls/getcwd/getcwd03.c b/testcases/kernel/syscalls/getcwd/getcwd03.c index 97f4f3a33..9e3828a93 100644 --- a/testcases/kernel/syscalls/getcwd/getcwd03.c +++ b/testcases/kernel/syscalls/getcwd/getcwd03.c @@ -3,18 +3,20 @@ * Copyright (c) International Business Machines Corp., 2001 */ -/* - * DESCRIPTION +/*\ + * [Description] + * * Testcase to check the basic functionality of the getcwd(2) * system call on a symbolic link. * - * ALGORITHM - * 1) create a directory, and create a symbolic link to it at the + * [Algorithm] + * + * 1. create a directory, and create a symbolic link to it at the * same directory level. - * 2) get the working directory of a directory, and its pathname. - * 3) get the working directory of a symbolic link, and its pathname, + * 2. get the working directory of a directory, and its pathname. + * 3. get the working directory of a symbolic link, and its pathname, * and its readlink info. - * 4) compare the working directories and link information. + * 4. compare the working directories and link information. */ #define _GNU_SOURCE 1 diff --git a/testcases/kernel/syscalls/getdtablesize/.gitignore b/testcases/kernel/syscalls/getdtablesize/.gitignore deleted file mode 100644 index 67a71b5e2..000000000 --- a/testcases/kernel/syscalls/getdtablesize/.gitignore +++ /dev/null @@ -1 +0,0 @@ -/getdtablesize01 diff --git a/testcases/kernel/syscalls/getdtablesize/Makefile b/testcases/kernel/syscalls/getdtablesize/Makefile deleted file mode 100644 index 044619fb8..000000000 --- a/testcases/kernel/syscalls/getdtablesize/Makefile +++ /dev/null @@ -1,8 +0,0 @@ -# SPDX-License-Identifier: GPL-2.0-or-later -# Copyright (c) International Business Machines Corp., 2001 - -top_srcdir ?= ../../../.. - -include $(top_srcdir)/include/mk/testcases.mk - -include $(top_srcdir)/include/mk/generic_leaf_target.mk diff --git a/testcases/kernel/syscalls/getdtablesize/getdtablesize01.c b/testcases/kernel/syscalls/getdtablesize/getdtablesize01.c deleted file mode 100644 index d25cac261..000000000 --- a/testcases/kernel/syscalls/getdtablesize/getdtablesize01.c +++ /dev/null @@ -1,119 +0,0 @@ -/* - * Copyright (c) International Business Machines Corp., 2005 - * Copyright (c) Wipro Technologies Ltd, 2005. All Rights Reserved. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it would be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * - */ -/********************************************************** - * - * TEST IDENTIFIER : getdtablesize01 - * - * EXECUTED BY : root / superuser - * - * TEST TITLE : Basic tests for getdtablesize01(2) - * - * TEST CASE TOTAL : 1 - * - * AUTHOR : Prashant P Yendigeri - * <prashant.yendigeri@wipro.com> - * Robbie Williamson - * <robbiew@us.ibm.com> - * - * DESCRIPTION - * This is a Phase I test for the getdtablesize01(2) system call. - * It is intended to provide a limited exposure of the system call. - * - **********************************************************/ - -#include <stdio.h> -#include <errno.h> -#include <sys/types.h> -#include <sys/stat.h> -#include <fcntl.h> -#include <sys/time.h> -#include <sys/resource.h> -#include <unistd.h> -#include "test.h" - -void setup(); -void cleanup(); - -char *TCID = "getdtablesize01"; -int TST_TOTAL = 1; - -int main(void) -{ - int table_size, fd = 0, count = 0; - int max_val_opfiles; - struct rlimit rlp; - - setup(); - table_size = getdtablesize(); - getrlimit(RLIMIT_NOFILE, &rlp); - max_val_opfiles = (rlim_t) rlp.rlim_cur; - - tst_resm(TINFO, - "Maximum number of files a process can have opened is %d", - table_size); - tst_resm(TINFO, - "Checking with the value returned by getrlimit...RLIMIT_NOFILE"); - - if (table_size == max_val_opfiles) - tst_resm(TPASS, "got correct dtablesize, value is %d", - max_val_opfiles); - else { - tst_resm(TFAIL, "got incorrect table size, value is %d", - max_val_opfiles); - cleanup(); - } - - tst_resm(TINFO, - "Checking Max num of files that can be opened by a process.Should be: RLIMIT_NOFILE - 1"); - for (;;) { - fd = open("/etc/hosts", O_RDONLY); - - if (fd == -1) - break; - count = fd; - -#ifdef DEBUG - printf("Opened file num %d\n", fd); -#endif - } - -//Now the max files opened should be RLIMIT_NOFILE - 1 , why ? read getdtablesize man page - - if (count > 0) - close(count); - if (count == (max_val_opfiles - 1)) - tst_resm(TPASS, "%d = %d", count, (max_val_opfiles - 1)); - else if (fd < 0 && errno == ENFILE) - tst_brkm(TCONF, cleanup, "Reached maximum number of open files for the system"); - else - tst_resm(TFAIL, "%d != %d", count, (max_val_opfiles - 1)); - - cleanup(); - tst_exit(); -} - -void setup(void) -{ - tst_sig(NOFORK, DEF_HANDLER, cleanup); - - TEST_PAUSE; -} - -void cleanup(void) -{ -} diff --git a/testcases/kernel/syscalls/getegid/getegid01.c b/testcases/kernel/syscalls/getegid/getegid01.c index 271fbb6b6..46cdc680b 100644 --- a/testcases/kernel/syscalls/getegid/getegid01.c +++ b/testcases/kernel/syscalls/getegid/getegid01.c @@ -1,87 +1,32 @@ +// SPDX-License-Identifier: GPL-2.0-or-later /* * Copyright (c) 2000 Silicon Graphics, Inc. All Rights Reserved. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it would be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * - * Further, this software is distributed without any warranty that it is - * free of the rightful claim of any third person regarding infringement - * or the like. Any license provided herein, whether implied or - * otherwise, applies only to this software file. Patent licenses, if - * any, provided herein do not apply to combinations of this program with - * other software, or any other product whatsoever. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy, - * Mountain View, CA 94043, or: - * - * http://www.sgi.com - * - * For further information regarding this notice, see: - * - * http://oss.sgi.com/projects/GenInfo/NoticeExplan/ - * + * William Roske, Dave Fenner + * Copyright (C) 2023 SUSE LLC Andrea Cervesato <andrea.cervesato@suse.com> */ -/* - * AUTHOR : William Roske - * CO-PILOT : Dave Fenner +/*\ + * [Description] + * + * This test checks if getegid() returns the effective group id. */ -#include <sys/types.h> -#include <errno.h> -#include <string.h> -#include <signal.h> - -#include "test.h" -#include "compat_16.h" - -static void setup(); -static void cleanup(); +#include "tst_test.h" +#include "compat_tst_16.h" -TCID_DEFINE(getegid01); -int TST_TOTAL = 1; - -int main(int ac, char **av) +static void run(void) { - int lc; - - tst_parse_opts(ac, av, NULL, NULL); - - setup(); - - for (lc = 0; TEST_LOOPING(lc); lc++) { - - tst_count = 0; - - TEST(GETEGID(cleanup)); + gid_t gid, st_egid; - if (TEST_RETURN == -1) { - tst_resm(TFAIL | TTERRNO, "getegid failed"); - continue; /* next loop for MTKERNEL */ - } + SAFE_FILE_LINES_SCANF("/proc/self/status", "Gid: %*d %d", &st_egid); + gid = getegid(); - tst_resm(TPASS, "getegid returned %ld", TEST_RETURN); - } - - cleanup(); - tst_exit(); -} - -static void setup(void) -{ - tst_sig(NOFORK, DEF_HANDLER, cleanup); - TEST_PAUSE; + if (GID_SIZE_CHECK(st_egid)) + TST_EXP_EQ_LI(gid, st_egid); + else + tst_res(TPASS, "getegid() passed"); } -static void cleanup(void) -{ -} +static struct tst_test test = { + .test_all = run, +}; diff --git a/testcases/kernel/syscalls/getegid/getegid02.c b/testcases/kernel/syscalls/getegid/getegid02.c index 60f09501e..2f64bd869 100644 --- a/testcases/kernel/syscalls/getegid/getegid02.c +++ b/testcases/kernel/syscalls/getegid/getegid02.c @@ -1,90 +1,39 @@ +// SPDX-License-Identifier: GPL-2.0-or-later /* - * Copyright (c) International Business Machines Corp., 2001 - * Ported by Wayne Boyer - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See - * the GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * Copyright (c) 2000 Silicon Graphics, Inc. All Rights Reserved. + * William Roske, Dave Fenner + * Copyright (C) 2023 SUSE LLC Andrea Cervesato <andrea.cervesato@suse.com> */ -/* - * Testcase to check the basic functionality of getegid(). +/*\ + * [Description] * - * For functionality test the return value from getegid() is compared to passwd - * entry. + * This test checks if getegid() returns the same effective group given by + * passwd entry via getpwuid(). */ #include <pwd.h> -#include <errno.h> - -#include "test.h" -#include "compat_16.h" -static void cleanup(void); -static void setup(void); +#include "tst_test.h" +#include "compat_tst_16.h" -TCID_DEFINE(getegid02); -int TST_TOTAL = 1; - -int main(int ac, char **av) +static void run(void) { - int lc; uid_t euid; + gid_t egid; struct passwd *pwent; - tst_parse_opts(ac, av, NULL, NULL); - - setup(); - - for (lc = 0; TEST_LOOPING(lc); lc++) { - tst_count = 0; - - TEST(GETEGID(cleanup)); + UID16_CHECK((euid = geteuid()), "geteuid"); - if (TEST_RETURN < 0) { - tst_brkm(TBROK, cleanup, "This should never happen"); - } + pwent = getpwuid(euid); + if (!pwent) + tst_brk(TBROK | TERRNO, "getpwuid() error"); - euid = geteuid(); - pwent = getpwuid(euid); + GID16_CHECK((egid = getegid()), "getegid"); - if (pwent == NULL) - tst_brkm(TBROK, cleanup, "geteuid() returned " - "unexpected value %d", euid); - - GID16_CHECK(pwent->pw_gid, getegid, cleanup); - - if (pwent->pw_gid != TEST_RETURN) { - tst_resm(TFAIL, "getegid() return value" - " %ld unexpected - expected %d", - TEST_RETURN, pwent->pw_gid); - } else { - tst_resm(TPASS, - "effective group id %ld " - "is correct", TEST_RETURN); - } - } - - cleanup(); - tst_exit(); -} - -static void setup(void) -{ - tst_sig(NOFORK, DEF_HANDLER, cleanup); - TEST_PAUSE; + TST_EXP_EQ_LI(pwent->pw_gid, egid); } -static void cleanup(void) -{ -} +static struct tst_test test = { + .test_all = run, +}; diff --git a/testcases/kernel/syscalls/getgroups/Makefile b/testcases/kernel/syscalls/getgroups/Makefile index b2bb1e005..a319acf85 100644 --- a/testcases/kernel/syscalls/getgroups/Makefile +++ b/testcases/kernel/syscalls/getgroups/Makefile @@ -3,6 +3,9 @@ top_srcdir ?= ../../../.. +# Remove after rewriting all tests to the new API. +USE_LEGACY_COMPAT_16_H := 1 + include $(top_srcdir)/include/mk/testcases.mk include $(abs_srcdir)/../utils/compat_16.mk include $(top_srcdir)/include/mk/generic_leaf_target.mk diff --git a/testcases/kernel/syscalls/getgroups/getgroups01.c b/testcases/kernel/syscalls/getgroups/getgroups01.c index cfddeb408..c253e487f 100644 --- a/testcases/kernel/syscalls/getgroups/getgroups01.c +++ b/testcases/kernel/syscalls/getgroups/getgroups01.c @@ -54,6 +54,11 @@ #include <sys/types.h> #include "test.h" + +/* + * Don't forget to remove USE_LEGACY_COMPAT_16_H from Makefile after + * rewriting all tests to the new API. + */ #include "compat_16.h" static void setup(void); diff --git a/testcases/kernel/syscalls/getgroups/getgroups03.c b/testcases/kernel/syscalls/getgroups/getgroups03.c index 5ba20ef82..fc94f0b8e 100644 --- a/testcases/kernel/syscalls/getgroups/getgroups03.c +++ b/testcases/kernel/syscalls/getgroups/getgroups03.c @@ -40,6 +40,11 @@ #include <pwd.h> #include "test.h" + +/* + * Don't forget to remove USE_LEGACY_COMPAT_16_H from Makefile after + * rewriting all tests to the new API. + */ #include "compat_16.h" #define TESTUSER "root" diff --git a/testcases/kernel/syscalls/getpid/getpid01.c b/testcases/kernel/syscalls/getpid/getpid01.c index ec18b67d5..495002037 100644 --- a/testcases/kernel/syscalls/getpid/getpid01.c +++ b/testcases/kernel/syscalls/getpid/getpid01.c @@ -6,26 +6,31 @@ /*\ * [Description] * - * Verify that getpid() system call returns process ID in range 2 ... PID_MAX + * Verify that getpid() system call returns process ID in range <2, PID_MAX>. */ #include <stdlib.h> #include "tst_test.h" +static pid_t pid_max; + +static void setup(void) +{ + SAFE_FILE_SCANF("/proc/sys/kernel/pid_max", "%d\n", &pid_max); +} + static void verify_getpid(void) { - pid_t pid_max, pid; + pid_t pid; int i; - SAFE_FILE_SCANF("/proc/sys/kernel/pid_max", "%d\n", &pid_max); - for (i = 0; i < 100; i++) { pid = SAFE_FORK(); if (pid == 0) { pid = getpid(); /* pid should not be 1 or out of maximum */ - if (1 < pid && pid <= pid_max) + if (pid > 1 && pid <= pid_max) tst_res(TPASS, "getpid() returns %d", pid); else tst_res(TFAIL, @@ -38,6 +43,7 @@ static void verify_getpid(void) } static struct tst_test test = { + .setup = setup, .forks_child = 1, .test_all = verify_getpid, }; diff --git a/testcases/kernel/syscalls/getppid/getppid01.c b/testcases/kernel/syscalls/getppid/getppid01.c index f37948dd4..57efe1c1f 100644 --- a/testcases/kernel/syscalls/getppid/getppid01.c +++ b/testcases/kernel/syscalls/getppid/getppid01.c @@ -1,6 +1,7 @@ // SPDX-License-Identifier: GPL-2.0 /* * Copyright (c) 2000 Silicon Graphics, Inc. All Rights Reserved. + * Copyright (c) Linux Test Project, 2006-2023 */ /*\ @@ -12,11 +13,16 @@ #include <errno.h> #include "tst_test.h" -static void verify_getppid(void) -{ - pid_t ppid, pid_max; +static pid_t pid_max; +static void setup(void) +{ SAFE_FILE_SCANF("/proc/sys/kernel/pid_max", "%d\n", &pid_max); +} + +static void verify_getppid(void) +{ + pid_t ppid; ppid = getppid(); if (ppid > pid_max) @@ -26,5 +32,6 @@ static void verify_getppid(void) } static struct tst_test test = { + .setup = setup, .test_all = verify_getppid, }; diff --git a/testcases/kernel/syscalls/getresgid/Makefile b/testcases/kernel/syscalls/getresgid/Makefile index b2bb1e005..a319acf85 100644 --- a/testcases/kernel/syscalls/getresgid/Makefile +++ b/testcases/kernel/syscalls/getresgid/Makefile @@ -3,6 +3,9 @@ top_srcdir ?= ../../../.. +# Remove after rewriting all tests to the new API. +USE_LEGACY_COMPAT_16_H := 1 + include $(top_srcdir)/include/mk/testcases.mk include $(abs_srcdir)/../utils/compat_16.mk include $(top_srcdir)/include/mk/generic_leaf_target.mk diff --git a/testcases/kernel/syscalls/getresgid/getresgid01.c b/testcases/kernel/syscalls/getresgid/getresgid01.c index b5fb804ee..8000200e1 100644 --- a/testcases/kernel/syscalls/getresgid/getresgid01.c +++ b/testcases/kernel/syscalls/getresgid/getresgid01.c @@ -73,6 +73,11 @@ #include <signal.h> #include "test.h" + +/* + * Don't forget to remove USE_LEGACY_COMPAT_16_H from Makefile after + * rewriting all tests to the new API. + */ #include "compat_16.h" char *TCID = "getresgid01"; diff --git a/testcases/kernel/syscalls/getresgid/getresgid02.c b/testcases/kernel/syscalls/getresgid/getresgid02.c index 8bddf9824..ca4502aac 100644 --- a/testcases/kernel/syscalls/getresgid/getresgid02.c +++ b/testcases/kernel/syscalls/getresgid/getresgid02.c @@ -75,6 +75,11 @@ #include <pwd.h> #include "test.h" + +/* + * Don't forget to remove USE_LEGACY_COMPAT_16_H from Makefile after + * rewriting all tests to the new API. + */ #include "compat_16.h" #define LTPUSER "nobody" diff --git a/testcases/kernel/syscalls/getresgid/getresgid03.c b/testcases/kernel/syscalls/getresgid/getresgid03.c index 0785359e0..1d7bcabd2 100644 --- a/testcases/kernel/syscalls/getresgid/getresgid03.c +++ b/testcases/kernel/syscalls/getresgid/getresgid03.c @@ -77,6 +77,11 @@ #include <pwd.h> #include "test.h" + +/* + * Don't forget to remove USE_LEGACY_COMPAT_16_H from Makefile after + * rewriting all tests to the new API. + */ #include "compat_16.h" char *TCID = "getresgid03"; diff --git a/testcases/kernel/syscalls/getresuid/Makefile b/testcases/kernel/syscalls/getresuid/Makefile index b2bb1e005..a319acf85 100644 --- a/testcases/kernel/syscalls/getresuid/Makefile +++ b/testcases/kernel/syscalls/getresuid/Makefile @@ -3,6 +3,9 @@ top_srcdir ?= ../../../.. +# Remove after rewriting all tests to the new API. +USE_LEGACY_COMPAT_16_H := 1 + include $(top_srcdir)/include/mk/testcases.mk include $(abs_srcdir)/../utils/compat_16.mk include $(top_srcdir)/include/mk/generic_leaf_target.mk diff --git a/testcases/kernel/syscalls/getresuid/getresuid01.c b/testcases/kernel/syscalls/getresuid/getresuid01.c index 07fed9c13..a04918d6f 100644 --- a/testcases/kernel/syscalls/getresuid/getresuid01.c +++ b/testcases/kernel/syscalls/getresuid/getresuid01.c @@ -72,6 +72,11 @@ #include <signal.h> #include "test.h" + +/* + * Don't forget to remove USE_LEGACY_COMPAT_16_H from Makefile after + * rewriting all tests to the new API. + */ #include "compat_16.h" char *TCID = "getresuid01"; diff --git a/testcases/kernel/syscalls/getresuid/getresuid02.c b/testcases/kernel/syscalls/getresuid/getresuid02.c index 23f7944dd..77896a8a3 100644 --- a/testcases/kernel/syscalls/getresuid/getresuid02.c +++ b/testcases/kernel/syscalls/getresuid/getresuid02.c @@ -75,6 +75,11 @@ #include <pwd.h> #include "test.h" + +/* + * Don't forget to remove USE_LEGACY_COMPAT_16_H from Makefile after + * rewriting all tests to the new API. + */ #include "compat_16.h" #define LTPUSER "nobody" diff --git a/testcases/kernel/syscalls/getresuid/getresuid03.c b/testcases/kernel/syscalls/getresuid/getresuid03.c index bf117038b..34e40c45d 100644 --- a/testcases/kernel/syscalls/getresuid/getresuid03.c +++ b/testcases/kernel/syscalls/getresuid/getresuid03.c @@ -76,6 +76,11 @@ #include <pwd.h> #include "test.h" + +/* + * Don't forget to remove USE_LEGACY_COMPAT_16_H from Makefile after + * rewriting all tests to the new API. + */ #include "compat_16.h" char *TCID = "getresuid03"; diff --git a/testcases/kernel/syscalls/getrlimit/getrlimit02.c b/testcases/kernel/syscalls/getrlimit/getrlimit02.c index 9b68ce20b..9f5b2bf9c 100644 --- a/testcases/kernel/syscalls/getrlimit/getrlimit02.c +++ b/testcases/kernel/syscalls/getrlimit/getrlimit02.c @@ -7,12 +7,13 @@ /*\ * [Description] * - * Test for checking error conditions for getrlimit(2) - * 1) getrlimit(2) returns -1 and sets errno to EFAULT if an invalid - * address is given for address parameter. - * 2) getrlimit(2) returns -1 and sets errno to EINVAL if an invalid - * resource type (RLIM_NLIMITS is a out of range resource type) is - * passed. + * Test for checking error conditions for getrlimit(2): + * + * 1. getrlimit(2) returns -1 and sets errno to EFAULT if an invalid + * address is given for address parameter. + * 2. getrlimit(2) returns -1 and sets errno to EINVAL if an invalid + * resource type (RLIM_NLIMITS is a out of range resource type) is + * passed. */ #include <sys/resource.h> diff --git a/testcases/kernel/syscalls/getsockopt/getsockopt02.c b/testcases/kernel/syscalls/getsockopt/getsockopt02.c index 47aef32af..d24e9b693 100644 --- a/testcases/kernel/syscalls/getsockopt/getsockopt02.c +++ b/testcases/kernel/syscalls/getsockopt/getsockopt02.c @@ -3,9 +3,10 @@ * Copyright (C) 2017 Red Hat, Inc. */ -/* - * Test description: Test retrieving of peer credentials (SO_PEERCRED) +/*\ + * [Description] * + * Test getsockopt(2) for retrieving peer credentials (SO_PEERCRED). */ #define _GNU_SOURCE @@ -53,6 +54,7 @@ static void test_function(void) tst_res(TFAIL | TERRNO, "Error with accepting connection"); goto clean; } + if (getsockopt(accepted, SOL_SOCKET, SO_PEERCRED, &cred, &cred_len) < 0) { tst_res(TFAIL | TERRNO, "Error while getting socket option"); @@ -67,6 +69,7 @@ static void test_function(void) clean: if (accepted >= 0) SAFE_CLOSE(accepted); + TST_CHECKPOINT_WAKE(0); } @@ -74,6 +77,7 @@ static void cleanup(void) { if (accepted >= 0) SAFE_CLOSE(accepted); + if (socket_fd >= 0) SAFE_CLOSE(socket_fd); } diff --git a/testcases/kernel/syscalls/gettid/.gitignore b/testcases/kernel/syscalls/gettid/.gitignore index 78dce3499..9014f7c3a 100644 --- a/testcases/kernel/syscalls/gettid/.gitignore +++ b/testcases/kernel/syscalls/gettid/.gitignore @@ -1 +1,2 @@ /gettid01 +/gettid02 diff --git a/testcases/kernel/syscalls/gettid/Makefile b/testcases/kernel/syscalls/gettid/Makefile index 4e9982f76..5345eb0f5 100644 --- a/testcases/kernel/syscalls/gettid/Makefile +++ b/testcases/kernel/syscalls/gettid/Makefile @@ -10,7 +10,9 @@ top_srcdir ?= ../../../.. include $(top_srcdir)/include/mk/testcases.mk ifeq ($(ANDROID), 1) -FILTER_OUT_MAKE_TARGETS += gettid01 +FILTER_OUT_MAKE_TARGETS += gettid01 gettid02 endif +gettid02: LDLIBS += -lpthread + include $(top_srcdir)/include/mk/generic_leaf_target.mk diff --git a/testcases/kernel/syscalls/gettid/gettid01.c b/testcases/kernel/syscalls/gettid/gettid01.c index 7e5b6b175..22ba15016 100644 --- a/testcases/kernel/syscalls/gettid/gettid01.c +++ b/testcases/kernel/syscalls/gettid/gettid01.c @@ -1,96 +1,32 @@ +// SPDX-License-Identifier: GPL-2.0-or-later /* - * Crackerjack Project - * * Copyright (C) 2007-2008, Hitachi, Ltd. - * Author(s): Takahiro Yasui <takahiro.yasui.mp@hitachi.com>, - * Yumiko Sugita <yumiko.sugita.yf@hitachi.com>, - * Satoshi Fujiwara <sa-fuji@sdl.hitachi.co.jp> - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - * $Id: gettid01.c,v 1.5 2009/10/26 14:55:47 subrata_modak Exp $ + * Copyright (C) 2023 SUSE LLC Andrea Cervesato <andrea.cervesato@suse.com> + */ +/*\ + * [Description] * + * This test checks if parent pid is equal to tid in single-threaded + * application. */ -/* Porting from Crackerjack to LTP is done - by Masatake YAMATO <yamato@redhat.com> */ - -#include <sys/types.h> -#include <linux/unistd.h> -#include <errno.h> - -#include "test.h" - -void setup(); -void cleanup(); - -char *TCID = "gettid01"; - -int TST_TOTAL = 1; - -pid_t my_gettid(void) -{ - return (pid_t) syscall(__NR_gettid); -} - -int main(int ac, char **av) -{ - int lc; - - tst_parse_opts(ac, av, NULL, NULL); - - setup(); - - /* - * The following loop checks looping state if -c option given - */ - for (lc = 0; TEST_LOOPING(lc); lc++) { +#include "tst_test.h" +#include "lapi/syscalls.h" - tst_count = 0; - - TEST(my_gettid()); - - if (TEST_RETURN == -1) { - tst_resm(TFAIL, "gettid() Failed, errno=%d: %s", - TEST_ERRNO, strerror(TEST_ERRNO)); - } else { - tst_resm(TPASS, "gettid() returned %ld", - TEST_RETURN); - } - } - - cleanup(); - tst_exit(); -} - -/* - * setup() - performs all ONE TIME setup for this test. - */ -void setup(void) +static void run(void) { + long pid, tid; - tst_sig(NOFORK, DEF_HANDLER, cleanup); + SAFE_FILE_LINES_SCANF("/proc/self/status", "Pid: %ld", &pid); + SAFE_FILE_LINES_SCANF("/proc/self/status", "Tgid: %ld", &tid); - TEST_PAUSE; + if (pid != tid) + tst_brk(TBROK, "Test function has been moved inside a thread?"); + TST_EXP_EQ_LI(tst_syscall(__NR_gettid), tst_syscall(__NR_getpid)); + TST_EXP_EQ_LI(tst_syscall(__NR_gettid), pid); } -/* - * cleanup() - performs all ONE TIME cleanup for this test at - * completion or premature exit. - */ -void cleanup(void) -{ -} +static struct tst_test test = { + .test_all = run, +}; diff --git a/testcases/kernel/syscalls/gettid/gettid02.c b/testcases/kernel/syscalls/gettid/gettid02.c new file mode 100644 index 000000000..ef44761c4 --- /dev/null +++ b/testcases/kernel/syscalls/gettid/gettid02.c @@ -0,0 +1,66 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * Copyright (C) 2023 SUSE LLC Andrea Cervesato <andrea.cervesato@suse.com> + */ +/*\ + * [Description] + * + * This test spawns multiple threads, then check for each one of them if the + * parent ID is different AND if the thread ID is different from all the other + * spwaned threads. + */ + +#include "tst_test.h" +#include "lapi/syscalls.h" +#include "tst_safe_pthread.h" + +#define THREADS_NUM 10 + +static volatile pid_t tids[THREADS_NUM]; + +static void *threaded(void *arg) +{ + int i = *(int *)arg; + pid_t pid, tid; + + pid = tst_syscall(__NR_getpid); + tid = tst_syscall(__NR_gettid); + + TST_EXP_EXPR(pid != tid, + "parent ID (%d) differs from thread[%d] ID (%d)", + pid, i, tid); + tids[i] = tid; + return NULL; +} + +static void run(void) +{ + pthread_t thread[THREADS_NUM]; + int args[THREADS_NUM]; + int error = 0; + + for (int i = 0; i < THREADS_NUM; i++) { + args[i] = i; + SAFE_PTHREAD_CREATE(&thread[i], NULL, threaded, &args[i]); + } + for (int i = 0; i < THREADS_NUM; i++) + SAFE_PTHREAD_JOIN(thread[i], NULL); + + for (int i = 0; i < THREADS_NUM; i++) { + for (int j = i + 1; j < THREADS_NUM; j++) { + if (tids[i] == tids[j]) { + tst_res(TINFO, "thread[%d] and thread[%d] have the same ID %d", i, j, tids[i]); + error = 1; + } + } + } + + if (error) + tst_res(TFAIL, "Some threads have the same TID"); + else + tst_res(TPASS, "All threads have a different TID"); +} + +static struct tst_test test = { + .test_all = run, +}; diff --git a/testcases/kernel/syscalls/gettimeofday/gettimeofday01.c b/testcases/kernel/syscalls/gettimeofday/gettimeofday01.c index f9acb9665..887a36688 100644 --- a/testcases/kernel/syscalls/gettimeofday/gettimeofday01.c +++ b/testcases/kernel/syscalls/gettimeofday/gettimeofday01.c @@ -1,107 +1,42 @@ +// SPDX-License-Identifier: GPL-2.0-or-later /* - * - * Copyright (c) International Business Machines Corp., 2001 - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See - * the GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * Copyright (c) International Business Machines Corp., 2001 + * Copyright (c) Linux Test Project, 2001-2023 */ -/* - * NAME - * gettimeofday01.c - * - * DESCRIPTION - * Testcase to check that gettimeofday(2) sets errno to EFAULT. - * - * ALGORITHM - * Call gettimeofday() with an invalid buffer, and expect EFAULT to be - * set in errno. +/*\ + * [Description] * - * HISTORY - * 07/2001 Ported by Wayne Boyer + * Test for gettimeofday error. * - * RESTRICTIONS - * NONE + * - EFAULT: tv pointed outside the accessible address space + * - EFAULT: tz pointed outside the accessible address space + * - EFAULT: both tv and tz pointed outside the accessible address space */ -#include <sys/time.h> -#include <errno.h> -#include "test.h" -#include <unistd.h> +#include "tst_test.h" #include "lapi/syscalls.h" -char *TCID = "gettimeofday01"; -int TST_TOTAL = 1; +static struct timeval tv1; -#if !defined UCLINUX +static struct tcase { + void *tv; + void *tz; +} tcases[] = { + /* timezone structure is obsolete, tz should be treated as null */ + {(void *)-1, NULL}, + {&tv1, (void *)-1}, + {(void *)-1, (void *)-1}, +}; -void cleanup(void); -void setup(void); - -int main(int ac, char **av) +static void verify_gettimeofday(unsigned int n) { - int lc; - int ret; - - tst_parse_opts(ac, av, NULL, NULL); - - setup(); - - for (lc = 0; TEST_LOOPING(lc); lc++) { - tst_count = 0; - - TEST(tst_syscall(__NR_gettimeofday, (void *)-1, (void *)-1)); - - /* gettimeofday returns an int, so we need to turn the long - * TEST_RETURN into an int to test with */ - ret = TEST_RETURN; - if (ret != -1) { - tst_resm(TFAIL, - "call succeeded unexpectedly (got back %i, wanted -1)", - ret); - continue; - } + struct tcase *tc = &tcases[n]; - if (TEST_ERRNO == EFAULT) - tst_resm(TPASS, - "gettimeofday(2) set the errno EFAULT correctly"); - else - tst_resm(TFAIL, - "gettimeofday(2) didn't set errno to EFAULT, errno=%i (%s)", - errno, strerror(errno)); - } - - cleanup(); - tst_exit(); -} - -void setup(void) -{ - - tst_sig(NOFORK, DEF_HANDLER, cleanup); - - TEST_PAUSE; -} - -void cleanup(void) -{ -} -#else - -int main(void) -{ - tst_brkm(TCONF, "gettimeofday EFAULT check disabled on uClinux"); + TST_EXP_FAIL(tst_syscall(__NR_gettimeofday, tc->tv, tc->tz), EFAULT); } -#endif +static struct tst_test test = { + .tcnt = ARRAY_SIZE(tcases), + .test = verify_gettimeofday, +}; diff --git a/testcases/kernel/syscalls/gettimeofday/gettimeofday02.c b/testcases/kernel/syscalls/gettimeofday/gettimeofday02.c index 7c462cc29..84bf1f773 100644 --- a/testcases/kernel/syscalls/gettimeofday/gettimeofday02.c +++ b/testcases/kernel/syscalls/gettimeofday/gettimeofday02.c @@ -4,13 +4,13 @@ * Copyright (C) 2017 Cyril Hrubis <chrubis@suse.cz> */ -/* - * DESCRIPTION - * Check if gettimeofday is monotonous +/*\ + * [Description] + * + * Check if gettimeofday() is monotonous during 10s: * - * ALGORITHM - * Call gettimeofday() to get a t1 (fist value) - * call it again to get t2, see if t2 < t1, set t2 = t1, repeat for 10 sec + * - Call gettimeofday() to get a t1 (fist value) + * - Call it again to get t2, see if t2 < t1, set t2 = t1, repeat for 10 sec */ #include <stdint.h> diff --git a/testcases/kernel/syscalls/getxattr/getxattr02.c b/testcases/kernel/syscalls/getxattr/getxattr02.c index a42057d0a..5a84d876c 100644 --- a/testcases/kernel/syscalls/getxattr/getxattr02.c +++ b/testcases/kernel/syscalls/getxattr/getxattr02.c @@ -1,64 +1,41 @@ +// SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (C) 2011 Red Hat, Inc. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of version 2 of the GNU General Public - * License as published by the Free Software Foundation. - * - * This program is distributed in the hope that it would be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * - * Further, this software is distributed without any warranty that it - * is free of the rightful claim of any third person regarding - * infringement or the like. Any license provided herein, whether - * implied or otherwise, applies only to this software file. Patent - * licenses, if any, provided herein do not apply to combinations of - * this program with other software, or any other product whatsoever. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - * 02110-1301, USA. + * Copyright (C) 2011 Red Hat, Inc. + * Copyright (c) Linux Test Project, 2012-2022 + * Copyright (c) 2023 Marius Kittler <mkittler@suse.de> */ -/* +/*\ + * [Description] + * * In the user.* namespace, only regular files and directories can * have extended attributes. Otherwise getxattr(2) will return -1 * and set errno to ENODATA. * * There are 4 test cases: - * 1. Get attribute from a FIFO, setxattr(2) should return -1 and + * + * - Get attribute from a FIFO, setxattr(2) should return -1 and * set errno to ENODATA - * 2. Get attribute from a char special file, setxattr(2) should + * - Get attribute from a char special file, setxattr(2) should * return -1 and set errno to ENODATA - * 3. Get attribute from a block special file, setxattr(2) should + * - Get attribute from a block special file, setxattr(2) should * return -1 and set errno to ENODATA - * 4. Get attribute from a UNIX domain socket, setxattr(2) should + * - Get attribute from a UNIX domain socket, setxattr(2) should * return -1 and set errno to ENODATA */ -#include "config.h" #include <sys/types.h> -#include <sys/stat.h> #include <sys/sysmacros.h> -#include <sys/wait.h> -#include <errno.h> -#include <fcntl.h> -#include <unistd.h> -#include <signal.h> +#include <sys/xattr.h> #include <stdio.h> #include <stdlib.h> -#include <string.h> -#ifdef HAVE_SYS_XATTR_H -# include <sys/xattr.h> -#endif -#include "test.h" -#include "safe_macros.h" -char *TCID = "getxattr02"; +#include "tst_res_flags.h" +#include "tst_test.h" +#include "tst_test_macros.h" -#ifdef HAVE_SYS_XATTR_H +#define MNTPOINT "mntpoint" +#define FNAME MNTPOINT"/getxattr02" #define XATTR_TEST_KEY "user.testkey" #define FIFO "getxattr02fifo" @@ -66,94 +43,78 @@ char *TCID = "getxattr02"; #define BLK "getxattr02blk" #define SOCK "getxattr02sock" -static void setup(void); -static void cleanup(void); - -static char *tc[] = { - FIFO, /* case 00, get attr from fifo */ - CHR, /* case 01, get attr from char special */ - BLK, /* case 02, get attr from block special */ - SOCK, /* case 03, get attr from UNIX domain socket */ +static struct test_case { + const char *desc; + char *fname; + int mode; +} tcases[] = { + { + .desc = "get attr from fifo", + .fname = FNAME FIFO, + .mode = S_IFIFO, + }, + { + .desc = "get attr from char special", + .fname = FNAME CHR, + .mode = S_IFCHR, + }, + { + .desc = "get attr from block special", + .fname = FNAME BLK, + .mode = S_IFBLK, + }, + { + .desc = "get attr from UNIX domain socket", + .fname = FNAME SOCK, + .mode = S_IFSOCK, + }, }; -int TST_TOTAL = sizeof(tc) / sizeof(tc[0]); - -int main(int argc, char *argv[]) +static void run(unsigned int i) { - int lc; - int i; - int exp_eno; char buf[BUFSIZ]; - - tst_parse_opts(argc, argv, NULL, NULL); - - setup(); - - for (lc = 0; TEST_LOOPING(lc); lc++) { - tst_count = 0; - exp_eno = ENODATA; - - for (i = 0; i < TST_TOTAL; i++) { - TEST(getxattr(tc[0], XATTR_TEST_KEY, buf, BUFSIZ)); - - if (TEST_RETURN == -1 && TEST_ERRNO == exp_eno) - tst_resm(TPASS | TTERRNO, "expected behavior"); - else - tst_resm(TFAIL | TTERRNO, "unexpected behavior" - " - expected errno %d - Got", exp_eno); - } - } - - cleanup(); - tst_exit(); + struct test_case *tc = &tcases[i]; + dev_t dev = tc->mode == S_IFCHR ? makedev(1, 3) : 0u; + + if (mknod(tc->fname, tc->mode | 0777, dev) < 0) + tst_brk(TBROK | TERRNO, "create %s (mode %i) failed (%s)", + tc->fname, tc->mode, tc->desc); + + TEST(getxattr(tc->fname, XATTR_TEST_KEY, buf, BUFSIZ)); + if (TST_RET == -1 && TST_ERR == ENODATA) + tst_res(TPASS | TTERRNO, "%s: expected return value", + tc->desc); + else + tst_res(TFAIL | TTERRNO, + "%s: unexpected return value - expected errno %d - got", + tc->desc, ENODATA); + + unlink(tc->fname); } static void setup(void) { - int fd; - dev_t dev; - - tst_require_root(); - - tst_tmpdir(); - - /* Test for xattr support */ - fd = SAFE_CREAT(cleanup, "testfile", 0644); - close(fd); - if (setxattr("testfile", "user.test", "test", 4, XATTR_CREATE) == -1) - if (errno == ENOTSUP) - tst_brkm(TCONF, cleanup, "No xattr support in fs or " - "mount without user_xattr option"); - unlink("testfile"); - - /* Create test files */ - if (mknod(FIFO, S_IFIFO | 0777, 0) == -1) - tst_brkm(TBROK | TERRNO, cleanup, "Create FIFO(%s) failed", - FIFO); - - dev = makedev(1, 3); - if (mknod(CHR, S_IFCHR | 0777, dev) == -1) - tst_brkm(TBROK | TERRNO, cleanup, "Create char special(%s)" - " failed", CHR); - - if (mknod(BLK, S_IFBLK | 0777, 0) == -1) - tst_brkm(TBROK | TERRNO, cleanup, "Create block special(%s)" - " failed", BLK); - - if (mknod(SOCK, S_IFSOCK | 0777, 0) == -1) - tst_brkm(TBROK | TERRNO, cleanup, "Create socket(%s) failed", - SOCK); - - TEST_PAUSE; + /* assert xattr support in the current filesystem */ + SAFE_TOUCH(FNAME, 0644, NULL); + TEST(setxattr(FNAME, "user.test", "test", 4, XATTR_CREATE)); + if (TST_ERR == ENOTSUP) + tst_brk(TCONF, + "No xattr support in fs or mount without user_xattr option"); + else if (TST_RET != 0) + tst_brk(TBROK | TTERRNO, "setxattr failed"); } -static void cleanup(void) -{ - tst_rmdir(); -} -#else /* HAVE_SYS_XATTR_H */ -int main(int argc, char *argv[]) -{ - tst_brkm(TCONF, NULL, "<sys/xattr.h> does not exist."); -} -#endif +static struct tst_test test = { + .all_filesystems = 1, + .needs_root = 1, + .mntpoint = MNTPOINT, + .mount_device = 1, + .skip_filesystems = (const char *const []) { + "ramfs", + "nfs", + NULL + }, + .setup = setup, + .test = run, + .tcnt = ARRAY_SIZE(tcases) +}; diff --git a/testcases/kernel/syscalls/getxattr/getxattr03.c b/testcases/kernel/syscalls/getxattr/getxattr03.c index b6ea14287..1fe4ba48f 100644 --- a/testcases/kernel/syscalls/getxattr/getxattr03.c +++ b/testcases/kernel/syscalls/getxattr/getxattr03.c @@ -1,117 +1,54 @@ +// SPDX-License-Identifier: GPL-2.0-or-later /* - * Copyright (C) 2012 Red Hat, Inc. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of version 2 of the GNU General Public - * License as published by the Free Software Foundation. - * - * This program is distributed in the hope that it would be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * - * Further, this software is distributed without any warranty that it - * is free of the rightful claim of any third person regarding - * infringement or the like. Any license provided herein, whether - * implied or otherwise, applies only to this software file. Patent - * licenses, if any, provided herein do not apply to combinations of - * this program with other software, or any other product whatsoever. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - * 02110-1301, USA. + * Copyright (C) 2012 Red Hat, Inc. + * Copyright (c) 2023 Marius Kittler <mkittler@suse.de> */ -/* - * An empty buffer of size zero can be passed into getxattr(2) to return - * the current size of the named extended attribute. +/*\ + * [Description] + * + * An empty buffer of size zero can be passed into getxattr(2) to + * return the current size of the named extended attribute. */ #include "config.h" -#include <sys/types.h> -#include <sys/stat.h> -#include <sys/wait.h> -#include <errno.h> -#include <fcntl.h> -#include <unistd.h> -#include <signal.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#ifdef HAVE_SYS_XATTR_H -# include <sys/xattr.h> -#endif -#include "test.h" -#include "safe_macros.h" +#include "tst_test.h" -char *TCID = "getxattr03"; +#include <sys/xattr.h> +#include "tst_safe_macros.h" -#ifdef HAVE_SYS_XATTR_H +#define MNTPOINT "mntpoint" +#define FNAME MNTPOINT"/getxattr03testfile" #define XATTR_TEST_KEY "user.testkey" #define XATTR_TEST_VALUE "test value" #define XATTR_TEST_VALUE_SIZE (sizeof(XATTR_TEST_VALUE) - 1) -#define TESTFILE "getxattr03testfile" -static void setup(void); -static void cleanup(void); - -int TST_TOTAL = 1; - -int main(int argc, char *argv[]) +static void run(void) { - int lc; - - tst_parse_opts(argc, argv, NULL, NULL); - - setup(); - - for (lc = 0; TEST_LOOPING(lc); lc++) { - tst_count = 0; - - TEST(getxattr(TESTFILE, XATTR_TEST_KEY, NULL, 0)); - - if (TEST_RETURN == XATTR_TEST_VALUE_SIZE) - tst_resm(TPASS, "getxattr(2) returned correct value"); - else - tst_resm(TFAIL | TTERRNO, "getxattr(2) failed"); - } - - cleanup(); - tst_exit(); + TST_EXP_VAL(getxattr(FNAME, XATTR_TEST_KEY, NULL, 0), + XATTR_TEST_VALUE_SIZE); } static void setup(void) { - int fd; - - tst_require_root(); - - tst_tmpdir(); - - /* Test for xattr support and set attr value */ - fd = SAFE_CREAT(cleanup, TESTFILE, 0644); - close(fd); - - if (setxattr(TESTFILE, XATTR_TEST_KEY, XATTR_TEST_VALUE, - XATTR_TEST_VALUE_SIZE, XATTR_CREATE) == -1) { - if (errno == ENOTSUP) - tst_brkm(TCONF, cleanup, "No xattr support in fs or " - "fs mounted without user_xattr option"); - else - tst_brkm(TBROK | TERRNO, cleanup, "setxattr %s failed", - TESTFILE); - } - - TEST_PAUSE; + SAFE_TOUCH(FNAME, 0644, NULL); + SAFE_SETXATTR(FNAME, XATTR_TEST_KEY, XATTR_TEST_VALUE, + XATTR_TEST_VALUE_SIZE, XATTR_CREATE); } -static void cleanup(void) -{ - tst_rmdir(); -} -#else /* HAVE_SYS_XATTR_H */ -int main(int argc, char *argv[]) -{ - tst_brkm(TCONF, NULL, "<sys/xattr.h> does not exist."); -} -#endif +static struct tst_test test = { + .all_filesystems = 1, + .needs_root = 1, + .mntpoint = MNTPOINT, + .mount_device = 1, + .skip_filesystems = (const char *const []) { + "exfat", + "tmpfs", + "ramfs", + "nfs", + "vfat", + NULL + }, + .setup = setup, + .test_all = run, +}; diff --git a/testcases/kernel/syscalls/ioctl/ioctl02.c b/testcases/kernel/syscalls/ioctl/ioctl02.c index b4d4a3594..aab80b251 100644 --- a/testcases/kernel/syscalls/ioctl/ioctl02.c +++ b/testcases/kernel/syscalls/ioctl/ioctl02.c @@ -1,468 +1,256 @@ +// SPDX-License-Identifier: GPL-2.0-or-later /* - * Copyright (c) International Business Machines Corp., 2001 - * Copyright (c) 2020 Petr Vorel <pvorel@suse.cz> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See - * the GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * Copyright (c) International Business Machines Corp., 2001 + * Copyright (c) 2020 Petr Vorel <pvorel@suse.cz> + * Copyright (c) 2023 Marius Kittler <mkittler@suse.de> */ -/* - * NAME - * ioctl02.c - * - * DESCRIPTION - * Testcase to test the TCGETA, and TCSETA ioctl implementations for - * the tty driver +/*\ + * [Description] * - * ALGORITHM - * In this test, the parent and child open the parentty and the childtty - * respectively. After opening the childtty the child flushes the stream - * and sends a SIGUSR1 to the parent (thereby asking it to continue its - * testing). The parent, which was waiting for this signal to arrive, now - * starts the testing. It issues a TCGETA ioctl to get all the tty - * parameters. It then changes them to known values by issuing a TCSETA - * ioctl. Then the parent issues a TCGETA ioctl again and compares the - * received values with what it had set earlier. The test fails if TCGETA - * or TCSETA fails, or if the received values don't match those that were - * set. The parent does all the testing, the requirement of the child - * process is to moniter the testing done by the parent, and hence the - * child just waits for the parent. + * Test TCGETA/TCGETS and TCSETA/TCSETS ioctl implementations for tty driver. * - * USAGE: <for command-line> - * ioctl02 -D /dev/tty[0-9] [-c n] [-f] [-i n] [-I x] [-P x] [-t] - * where, -c n : Run n copies concurrently. - * -f : Turn off functionality Testing. - * -i n : Execute test n times. - * -I x : Execute test for x seconds. - * -P x : Pause for x seconds between iterations. - * -t : Turn on syscall timing. - * - * HISTORY - * 07/2001 Ported by Wayne Boyer - * - * RESTRICTIONS - * test must be run with the -D option - * test may have to be run as root depending on the tty permissions + * In this test, the parent and child open the parentty and the childtty + * respectively. After opening the childtty the child flushes the stream + * and wakes the parent (thereby asking it to continue its testing). The + * parent, then starts the testing. It issues a TCGETA/TCGETS ioctl to + * get all the tty parameters. It then changes them to known values by + * issuing a TCSETA/TCSETS ioctl. Then the parent issues a TCSETA/TCGETS + * ioctl again and compares the received values with what it had set + * earlier. The test fails if TCGETA/TCGETS or TCSETA/TCSETS fails, or if + * the received values don't match those that were set. The parent does + * all the testing, the requirement of the child process is to moniter + * the testing done by the parent, and hence the child just waits for the + * parent. */ #include <stdio.h> -#include <fcntl.h> -#include <signal.h> -#include <errno.h> -#include <sys/wait.h> -#include <sys/types.h> -#include <sys/stat.h> +#include <stdlib.h> #include <termios.h> -#include "test.h" -#include "safe_macros.h" -#include "lapi/ioctl.h" -#define CNUL 0 - -char *TCID = "ioctl02"; -int TST_TOTAL = 1; +#include "lapi/ioctl.h" +#include "tst_test.h" -static struct termio termio, save_io; +static struct termio termio, termio_exp; +static struct termios termios, termios_exp, termios_bak; static char *parenttty, *childtty; -static int parentfd, childfd; +static int parentfd = -1; static int parentpid, childpid; -static volatile int sigterm, sigusr1, sigusr2; -static int closed = 1; - -static int do_child_setup(void); -static int do_parent_setup(void); -static int run_ptest(void); -static int run_ctest(void); -static int chk_tty_parms(); + +static void do_child(void); +static void prepare_termio(void); +static void run_ptest(void); +static void chk_tty_parms_termio(void); +static void chk_tty_parms_termios(void); static void setup(void); static void cleanup(void); -static void help(void); -static void do_child(void); -void do_child_uclinux(void); -static void sigterm_handler(void); -static int Devflag; -static char *devname; - -static option_t options[] = { - {"D:", &Devflag, &devname}, - {NULL, NULL, NULL} +static char *device; + +static struct variant { + const char *name; + void *termio, *termio_exp, *termio_bak; + size_t termio_size; + void (*check)(void); + int tcget, tcset; +} variants[] = { + { + .name = "termio", + .termio = &termio, + .termio_exp = &termio_exp, + .termio_size = sizeof(termio), + .check = &chk_tty_parms_termio, + .tcget = TCGETA, + .tcset = TCSETA, + }, + { + .name = "termios", + .termio = &termios, + .termio_exp = &termios_exp, + .termio_size = sizeof(termios), + .check = &chk_tty_parms_termios, + .tcget = TCGETS, + .tcset = TCSETS, + }, }; -int main(int ac, char **av) +static void verify_ioctl(void) { - int lc; - int rval; - - tst_parse_opts(ac, av, options, &help); - -#ifdef UCLINUX - maybe_run_child(&do_child_uclinux, "dS", &parentpid, &childtty); -#endif - - if (!Devflag) - tst_brkm(TBROK, NULL, "You must specify a tty device with " - "the -D option."); - - tst_require_root(); - - setup(); - - for (lc = 0; TEST_LOOPING(lc); lc++) { - - tst_count = 0; - - parenttty = devname; - childtty = devname; - - parentpid = getpid(); - - childpid = FORK_OR_VFORK(); - if (childpid < 0) - tst_brkm(TBROK, cleanup, "fork failed"); - - if (childpid == 0) { /* child */ -#ifdef UCLINUX - if (self_exec(av[0], "dS", parentpid, childtty) < 0) - tst_brkm(TBROK, cleanup, "self_exec failed"); -#else - do_child(); -#endif - } - - while (!sigusr1) - sleep(1); - - sigusr1 = 0; - - parentfd = do_parent_setup(); - if (parentfd < 0) { - kill(childpid, SIGTERM); - waitpid(childpid, NULL, 0); - cleanup(); - } - - /* run the parent test */ - rval = run_ptest(); - if (rval == -1) { - /* - * Parent cannot set/get ioctl parameters. - * SIGTERM the child and cleanup. - */ - kill(childpid, SIGTERM); - waitpid(childpid, NULL, 0); - cleanup(); - } - - if (rval != 0) - tst_resm(TFAIL, "TCGETA/TCSETA tests FAILED with " - "%d %s", rval, rval > 1 ? "errors" : "error"); - else - tst_resm(TPASS, "TCGETA/TCSETA tests SUCCEEDED"); - - /* FIXME: check return codes. */ - (void)kill(childpid, SIGTERM); - (void)waitpid(childpid, NULL, 0); - - /* - * Clean up things from the parent by restoring the - * tty device information that was saved in setup() - * and closing the tty file descriptor. - */ - if (ioctl(parentfd, TCSETA, &save_io) == -1) - tst_resm(TINFO, "ioctl restore failed in main"); - SAFE_CLOSE(cleanup, parentfd); - - closed = 1; - } - cleanup(); + tst_res(TINFO, "Testing %s variant", variants[tst_variant].name); - tst_exit(); -} + parenttty = device; + childtty = device; -static void do_child(void) -{ - childfd = do_child_setup(); - if (childfd < 0) - _exit(1); - run_ctest(); - _exit(0); -} + parentpid = getpid(); + childpid = SAFE_FORK(); + if (!childpid) { + do_child(); + exit(EXIT_SUCCESS); + } -void do_child_uclinux(void) -{ - struct sigaction act; + TST_CHECKPOINT_WAIT(0); + + parentfd = SAFE_OPEN(parenttty, O_RDWR, 0777); + SAFE_IOCTL(parentfd, TCFLSH, TCIOFLUSH); - /* Set up the signal handlers again */ - act.sa_handler = (void *)sigterm_handler; - act.sa_flags = 0; - sigemptyset(&act.sa_mask); - (void)sigaction(SIGTERM, &act, 0); + run_ptest(); - /* Run the normal child */ - do_child(); + TST_CHECKPOINT_WAKE(0); + SAFE_CLOSE(parentfd); } -/* - * run_ptest() - setup the various termio structure values and issue - * the TCSETA ioctl call with the TEST macro. - */ -static int run_ptest(void) +static void prepare_termio(void) { - int i, rval; - /* Use "old" line discipline */ - termio.c_line = 0; + termios_exp.c_line = termio_exp.c_line = 0; /* Set control modes */ - termio.c_cflag = B50 | CS7 | CREAD | PARENB | PARODD | CLOCAL; + termios_exp.c_cflag = termio_exp.c_cflag = B50 | CS7 | CREAD | PARENB | PARODD | CLOCAL; /* Set control chars. */ - for (i = 0; i < NCC; i++) { - if (i == VEOL2) - continue; - termio.c_cc[i] = CSTART; - } + for (int i = 0; i < NCC; i++) + termio_exp.c_cc[i] = CSTART; + for (int i = 0; i < VEOL2; i++) + termios_exp.c_cc[i] = CSTART; /* Set local modes. */ - termio.c_lflag = + termios_exp.c_lflag = termio_exp.c_lflag = ((unsigned short)(ISIG | ICANON | XCASE | ECHO | ECHOE | NOFLSH)); /* Set input modes. */ - termio.c_iflag = + termios_exp.c_iflag = termio_exp.c_iflag = BRKINT | IGNPAR | INPCK | ISTRIP | ICRNL | IUCLC | IXON | IXANY | IXOFF; /* Set output modes. */ - termio.c_oflag = OPOST | OLCUC | ONLCR | ONOCR; - - TEST(ioctl(parentfd, TCSETA, &termio)); - - if (TEST_RETURN < 0) { - tst_resm(TFAIL, "ioctl TCSETA failed : " - "errno = %d", TEST_ERRNO); - return -1; - } - - /* Get termio and see if all parameters actually got set */ - rval = ioctl(parentfd, TCGETA, &termio); - if (rval < 0) { - tst_resm(TFAIL, "ioctl TCGETA failed. Ending test."); - return -1; - } - - return chk_tty_parms(); + termios_exp.c_oflag = termio_exp.c_oflag = OPOST | OLCUC | ONLCR | ONOCR; } -static int run_ctest(void) +/* + * run_ptest() - setup the various termio/termios structure values and issue + * the TCSETA/TCSETS ioctl call with the TEST macro. + */ +static void run_ptest(void) { - /* - * Wait till the parent has finished testing. - */ - while (!sigterm) - sleep(1); + struct variant *v = &variants[tst_variant]; - sigterm = 0; + /* Init termio/termios structures used to check if all params got set */ + memset(v->termio, 0, v->termio_size); - tst_resm(TINFO, "child: Got SIGTERM from parent."); + SAFE_IOCTL(parentfd, v->tcset, v->termio_exp); - if (close(childfd) == -1) - tst_resm(TINFO, "close() in run_ctest() failed"); - return 0; + /* Get termio and see if all parameters actually got set */ + SAFE_IOCTL(parentfd, v->tcget, v->termio); + v->check(); } -static int chk_tty_parms(void) +static int cmp_attr(unsigned long long exp, unsigned long long act, const char *attr) { - int i, flag = 0; - - if (termio.c_line != 0) { - tst_resm(TINFO, "line discipline has incorrect value %o", - termio.c_line); - flag++; - } - /* - * The following Code Sniffet is disabled to check the value of c_cflag - * as it seems that due to some changes from 2.6.24 onwards, this - * setting is not done properly for either of (B50|CS7|CREAD|PARENB| - * PARODD|CLOCAL|(CREAD|HUPCL|CLOCAL). - * However, it has been observed that other flags are properly set. - */ -#if 0 - if (termio.c_cflag != (B50 | CS7 | CREAD | PARENB | PARODD | CLOCAL)) { - tst_resm(TINFO, "cflag has incorrect value. %o", - termio.c_cflag); - flag++; - } -#endif - - for (i = 0; i < NCC; i++) { - if (i == VEOL2) { - if (termio.c_cc[VEOL2] == CNUL) { - continue; - } else { - tst_resm(TINFO, "control char %d has " - "incorrect value %d %d", i, - termio.c_cc[i], CNUL); - flag++; - continue; - } - } - - if (termio.c_cc[i] != CSTART) { - tst_resm(TINFO, "control char %d has incorrect " - "value %d.", i, termio.c_cc[i]); - flag++; - } - } + if (act == exp) + return 0; + tst_res(TFAIL, "%s has incorrect value %llu, expected %llu", + attr, act, exp); + return 1; +} - if (! - (termio.c_lflag - && (ISIG | ICANON | XCASE | ECHO | ECHOE | NOFLSH))) { - tst_resm(TINFO, "lflag has incorrect value. %o", - termio.c_lflag); - flag++; - } +static int cmp_c_cc(unsigned char *exp_c_cc, unsigned char *act_c_cc, int ncc) +{ + int i, fails = 0; + char what[32]; - if (! - (termio.c_iflag - && (BRKINT | IGNPAR | INPCK | ISTRIP | ICRNL | IUCLC | IXON | IXANY - | IXOFF))) { - tst_resm(TINFO, "iflag has incorrect value. %o", - termio.c_iflag); - flag++; + for (i = 0; i < ncc; ++i) { + sprintf(what, "control char %d", i); + fails += cmp_attr(exp_c_cc[i], act_c_cc[i], what); } + return fails; +} - if (!(termio.c_oflag && (OPOST | OLCUC | ONLCR | ONOCR))) { - tst_resm(TINFO, "oflag has incorrect value. %o", - termio.c_oflag); - flag++; - } +#define CMP_ATTR(term_exp, term, attr, flag) \ +({ \ + flag += cmp_attr((term_exp).attr, (term).attr, #attr); \ + flag; \ +}) - if (!flag) - tst_resm(TINFO, "termio values are set as expected"); +#define CMP_C_CC(term_exp, term, flag) \ +({ \ + flag += cmp_c_cc(term_exp.c_cc, term.c_cc, sizeof(term.c_cc)); \ + flag; \ +}) - return flag; -} - -static int do_parent_setup(void) +static void chk_tty_parms_termio(void) { - int pfd; - - pfd = SAFE_OPEN(cleanup, parenttty, O_RDWR, 0777); + int flag = 0; - /* unset the closed flag */ - closed = 0; + flag = CMP_ATTR(termio_exp, termio, c_line, flag); + flag = CMP_C_CC(termio_exp, termio, flag); + flag = CMP_ATTR(termio_exp, termio, c_lflag, flag); + flag = CMP_ATTR(termio_exp, termio, c_iflag, flag); + flag = CMP_ATTR(termio_exp, termio, c_oflag, flag); - /* flush tty queues to remove old output */ - SAFE_IOCTL(cleanup, pfd, TCFLSH, 2); - return pfd; + if (!flag) + tst_res(TPASS, "TCGETA/TCSETA tests"); } -static int do_child_setup(void) +static void chk_tty_parms_termios(void) { - int cfd; - - cfd = open(childtty, O_RDWR, 0777); - if (cfd < 0) { - tst_resm(TINFO, "Could not open %s in do_child_setup(), errno " - "= %d", childtty, errno); - /* signal the parent so we don't hang the test */ - kill(parentpid, SIGUSR1); - return -1; - } + int flag = 0; - /* flush tty queues to remove old output */ - if (ioctl(cfd, TCFLSH, 2) < 0) { - tst_resm(TINFO, "ioctl TCFLSH failed. : errno = %d", errno); - /* signal the parent so we don't hang the test */ - kill(parentpid, SIGUSR1); - return -1; - } + flag = CMP_ATTR(termios_exp, termios, c_line, flag); + flag = CMP_C_CC(termios_exp, termios, flag); + flag = CMP_ATTR(termios_exp, termios, c_lflag, flag); + flag = CMP_ATTR(termios_exp, termios, c_iflag, flag); + flag = CMP_ATTR(termios_exp, termios, c_oflag, flag); - /* tell the parent that we're done */ - kill(parentpid, SIGUSR1); - - return cfd; + if (!flag) + tst_res(TPASS, "TCGETS/TCSETS tests"); } -/* - * Define the signals handlers here. - */ -static void sigterm_handler(void) +static void do_child(void) { - sigterm = 1; -} + int cfd = SAFE_OPEN(childtty, O_RDWR, 0777); -static void sigusr1_handler(void) -{ - sigusr1 = 1; -} + SAFE_IOCTL(cfd, TCFLSH, TCIOFLUSH); -static void sigusr2_handler(void) -{ - sigusr2 = 1; -} + /* tell the parent that we're done */ + TST_CHECKPOINT_WAKE(0); -static void help(void) -{ - printf(" -D <tty device> : for example, /dev/tty[0-9]\n"); + TST_CHECKPOINT_WAIT(0); + tst_res(TINFO, "child: parent has finished testing"); + SAFE_CLOSE(cfd); } static void setup(void) { - int fd; - struct sigaction act; + if (!device) + tst_brk(TBROK, "You must specify a tty device with -d option"); - /* XXX: TERRNO required all over the place */ - fd = SAFE_OPEN(NULL, devname, O_RDWR, 0777); + int fd = SAFE_OPEN(device, O_RDWR, 0777); - /* Save the current device information - to be restored in cleanup() */ - SAFE_IOCTL(cleanup, fd, TCGETA, &save_io); + SAFE_IOCTL(fd, TCGETS, &termios_bak); + SAFE_CLOSE(fd); - /* Close the device */ - SAFE_CLOSE(cleanup, fd); - - /* Set up the signal handlers */ - act.sa_handler = (void *)sigterm_handler; - act.sa_flags = 0; - sigemptyset(&act.sa_mask); - (void)sigaction(SIGTERM, &act, 0); - - act.sa_handler = (void *)sigusr1_handler; - act.sa_flags = 0; - (void)sigaction(SIGUSR1, &act, 0); - - act.sa_handler = (void *)sigusr2_handler; - act.sa_flags = 0; - (void)sigaction(SIGUSR2, &act, 0); - - act.sa_handler = SIG_IGN; - act.sa_flags = 0; - (void)sigaction(SIGTTOU, &act, 0); - - sigterm = sigusr1 = sigusr2 = 0; - - TEST_PAUSE; + prepare_termio(); } static void cleanup(void) { - if (!closed) { - if (ioctl(parentfd, TCSETA, &save_io) == -1) - tst_resm(TINFO, "ioctl restore failed in cleanup()"); - if (close(parentfd) == -1) - tst_resm(TINFO, "close() failed in cleanup()"); + if (parentfd >= 0) { + SAFE_IOCTL(parentfd, TCSETS, &termios_bak); + SAFE_CLOSE(parentfd); } } + +static struct tst_test test = { + .needs_root = 1, + .needs_checkpoints = 1, + .forks_child = 1, + .setup = setup, + .cleanup = cleanup, + .test_all = verify_ioctl, + .test_variants = 2, + .options = (struct tst_option[]) { + {"d:", &device, "Tty device. For example, /dev/tty[0-9]"}, + {} + } +}; diff --git a/testcases/kernel/syscalls/ioctl/ioctl_loop06.c b/testcases/kernel/syscalls/ioctl/ioctl_loop06.c index 6d009af6a..64800b4ee 100644 --- a/testcases/kernel/syscalls/ioctl/ioctl_loop06.c +++ b/testcases/kernel/syscalls/ioctl/ioctl_loop06.c @@ -109,8 +109,9 @@ static void setup(void) unalign_value = pg_size - 1; dev_fd = SAFE_OPEN(dev_path, O_RDWR); + ret = ioctl(dev_fd, LOOP_SET_BLOCK_SIZE, 512); - if (ioctl(dev_fd, LOOP_SET_BLOCK_SIZE, 512) && errno == EINVAL) + if (ret && (errno == EINVAL || errno == ENOTTY)) tst_brk(TCONF, "LOOP_SET_BLOCK_SIZE is not supported"); file_fd = SAFE_OPEN("test.img", O_RDWR); diff --git a/testcases/kernel/syscalls/ioctl/test_ioctl b/testcases/kernel/syscalls/ioctl/test_ioctl index 43836a229..8549e5608 100755 --- a/testcases/kernel/syscalls/ioctl/test_ioctl +++ b/testcases/kernel/syscalls/ioctl/test_ioctl @@ -45,7 +45,7 @@ case "$device_no" in continue fi tst_resm TINFO "Testing ioctl02 with $tttype" - ioctl02 -D $tttype + ioctl02 -d $tttype RC=$? if [ $RC -eq 0 ] then diff --git a/testcases/kernel/syscalls/ipc/msgctl/msgctl06.c b/testcases/kernel/syscalls/ipc/msgctl/msgctl06.c index 6f5476383..c1264b71e 100644 --- a/testcases/kernel/syscalls/ipc/msgctl/msgctl06.c +++ b/testcases/kernel/syscalls/ipc/msgctl/msgctl06.c @@ -139,12 +139,16 @@ static void verify_msgctl(unsigned int n) static void setup(void) { struct msqid_ds temp_buf; + struct buf { + long type; + char text[5]; + } msgbuf = {MSGTYPE, "abcd"}; ltpuser = SAFE_GETPWNAM("nobody"); nobody_uid = ltpuser->pw_uid; root_uid = 0; msg_id = SAFE_MSGGET(IPC_PRIVATE, IPC_CREAT | MSG_RW); - SAFE_MSGSND(msg_id, "abcd", 4, 0); + SAFE_MSGSND(msg_id, &msgbuf, sizeof(msgbuf.text), 0); TEST(msgctl(msg_id, MSG_STAT_ANY, &temp_buf)); if (TST_RET == -1) { diff --git a/testcases/kernel/syscalls/ipc/shmget/shmget02.c b/testcases/kernel/syscalls/ipc/shmget/shmget02.c index 8168803a5..10b8c9292 100644 --- a/testcases/kernel/syscalls/ipc/shmget/shmget02.c +++ b/testcases/kernel/syscalls/ipc/shmget/shmget02.c @@ -37,8 +37,6 @@ #include "libnewipc.h" #include "lapi/shm.h" -#define CONFIG_HUGETLBFS "CONFIG_HUGETLBFS" - static int shm_id = -1; static key_t shmkey, shmkey1; static struct passwd *pw; @@ -66,10 +64,7 @@ static struct tcase { static int get_hugetlb_exp_error(void) { long tmp; - struct tst_kconfig_var kconfig = { - .id = CONFIG_HUGETLBFS, - .id_len = sizeof(CONFIG_HUGETLBFS)-1, - }; + struct tst_kconfig_var kconfig = TST_KCONFIG_INIT("CONFIG_HUGETLBFS"); tst_kconfig_read(&kconfig, 1); diff --git a/testcases/kernel/syscalls/keyctl/keyctl01.c b/testcases/kernel/syscalls/keyctl/keyctl01.c index 55e069c68..674094eec 100644 --- a/testcases/kernel/syscalls/keyctl/keyctl01.c +++ b/testcases/kernel/syscalls/keyctl/keyctl01.c @@ -2,14 +2,17 @@ /* * Copyright (c) Crackerjack Project., 2007 * Copyright (c) 2017 Fujitsu Ltd. + * Copyright (c) Linux Test Project, 2009-2024 + * Ported by Manas Kumar Nayak maknayak@in.ibm.com> + * Modified by Guangwen Feng <fenggw-fnst@cn.fujitsu.com> */ -/* - * Description: This tests the keyctl() syscall - * Manipulate the kernel's key management facility +/*\ + * [Description] * - * Ported by Manas Kumar Nayak maknayak@in.ibm.com> - * Modified by Guangwen Feng <fenggw-fnst@cn.fujitsu.com> + * Tests the keyctl(2) syscall. + * + * Manipulate the kernel's key management facility. */ #include <errno.h> diff --git a/testcases/kernel/syscalls/keyctl/keyctl02.c b/testcases/kernel/syscalls/keyctl/keyctl02.c index 35cc2838d..fd3f86bbc 100644 --- a/testcases/kernel/syscalls/keyctl/keyctl02.c +++ b/testcases/kernel/syscalls/keyctl/keyctl02.c @@ -1,11 +1,14 @@ // SPDX-License-Identifier: GPL-2.0-or-later /* * Copyright (c) 2017 Fujitsu Ltd. - * Ported: Guangwen Feng <fenggw-fnst@cn.fujitsu.com> + * Copyright (c) Linux Test Project, 2017-2024 + * Ported: Guangwen Feng <fenggw-fnst@cn.fujitsu.com> */ -/* - * This is a regression test for the race between keyctl_read() and +/*\ + * [Description] + * + * Regression test for the race between keyctl_read() and * keyctl_revoke(), if the revoke happens between keyctl_read() * checking the validity of a key and the key's semaphore being taken, * then the key type read method will see a revoked key. @@ -14,13 +17,8 @@ * assumes in its read method that there will always be a payload * in a non-revoked key and doesn't check for a NULL pointer. * - * This test can crash the buggy kernel, and the bug was fixed in: - * - * commit b4a1b4f5047e4f54e194681125c74c0aa64d637d - * Author: David Howells <dhowells@redhat.com> - * Date: Fri Dec 18 01:34:26 2015 +0000 - * - * KEYS: Fix race between read and revoke + * Bug was fixed in commit + * b4a1b4f5047e ("KEYS: Fix race between read and revoke") */ #include <errno.h> @@ -29,6 +27,7 @@ #include "tst_safe_pthread.h" #include "tst_test.h" +#include "tst_kconfig.h" #include "lapi/keyctl.h" #define LOOPS 20000 @@ -36,6 +35,7 @@ #define PATH_KEY_COUNT_QUOTA "/proc/sys/kernel/keys/root_maxkeys" static int orig_maxkeys; +static int realtime_kernel; static void *do_read(void *arg) { @@ -86,6 +86,15 @@ static void do_test(void) tst_res(TINFO, "Runtime exhausted, exiting after %d loops", i); break; } + + /* + * Realtime kernel has deferred post-join thread cleanup which + * may result in exhaustion of cgroup thread limit. Add delay + * to limit the maximum number of stale threads to 4000 + * even with CONFIG_HZ=100. + */ + if (realtime_kernel) + usleep(100); } /* @@ -126,8 +135,19 @@ static void do_test(void) static void setup(void) { + unsigned int i; + struct tst_kconfig_var rt_kconfigs[] = { + TST_KCONFIG_INIT("CONFIG_PREEMPT_RT"), + TST_KCONFIG_INIT("CONFIG_PREEMPT_RT_FULL") + }; + SAFE_FILE_SCANF(PATH_KEY_COUNT_QUOTA, "%d", &orig_maxkeys); SAFE_FILE_PRINTF(PATH_KEY_COUNT_QUOTA, "%d", orig_maxkeys + LOOPS + 1); + + tst_kconfig_read(rt_kconfigs, ARRAY_SIZE(rt_kconfigs)); + + for (i = 0; i < ARRAY_SIZE(rt_kconfigs); i++) + realtime_kernel |= rt_kconfigs[i].choice == 'y'; } static void cleanup(void) diff --git a/testcases/kernel/syscalls/keyctl/keyctl03.c b/testcases/kernel/syscalls/keyctl/keyctl03.c index 9d7b9a0b5..563ee96a9 100644 --- a/testcases/kernel/syscalls/keyctl/keyctl03.c +++ b/testcases/kernel/syscalls/keyctl/keyctl03.c @@ -1,19 +1,15 @@ // SPDX-License-Identifier: GPL-2.0-or-later /* * Copyright (c) 2017 Fujitsu Ltd. - * Ported: Guangwen Feng <fenggw-fnst@cn.fujitsu.com> + * Copyright (c) Linux Test Project, 2017-2024 + * Ported: Guangwen Feng <fenggw-fnst@cn.fujitsu.com> */ -/* - * This regression test can crash the buggy kernel, - * and the bug was fixed in: - * - * commit f05819df10d7b09f6d1eb6f8534a8f68e5a4fe61 - * Author: David Howells <dhowells@redhat.com> - * Date: Thu Oct 15 17:21:37 2015 +0100 +/*\ + * [Description] * - * KEYS: Fix crash when attempt to garbage collect - * an uninstantiated keyring + * Regression test for commit + * f05819df10d7 ("KEYS: Fix crash when attempt to garbage collect an uninstantiated keyring") */ #include <errno.h> diff --git a/testcases/kernel/syscalls/keyctl/keyctl04.c b/testcases/kernel/syscalls/keyctl/keyctl04.c index 1fed23ca6..50c9244de 100644 --- a/testcases/kernel/syscalls/keyctl/keyctl04.c +++ b/testcases/kernel/syscalls/keyctl/keyctl04.c @@ -1,9 +1,12 @@ // SPDX-License-Identifier: GPL-2.0-or-later /* * Copyright (c) 2017 Google, Inc. + * Copyright (c) Linux Test Project, 2017-2024 */ -/* +/*\ + * [Description] + * * Regression test for commit c9f838d104fe ("KEYS: fix * keyctl_set_reqkey_keyring() to not leak thread keyrings"), a.k.a. * CVE-2017-7472. This bug could be used to exhaust kernel memory, though it diff --git a/testcases/kernel/syscalls/keyctl/keyctl05.c b/testcases/kernel/syscalls/keyctl/keyctl05.c index 7d7c076c0..0ad106774 100644 --- a/testcases/kernel/syscalls/keyctl/keyctl05.c +++ b/testcases/kernel/syscalls/keyctl/keyctl05.c @@ -1,9 +1,12 @@ // SPDX-License-Identifier: GPL-2.0-or-later /* * Copyright (c) 2017 Google, Inc. + * Copyright (c) Linux Test Project, 2017-2024 */ -/* +/*\ + * [Description] + * * Regression test for commit 63a0b0509e70 ("KEYS: fix freeing uninitialized * memory in key_update()"). Try to reproduce the crash in two different ways: * @@ -31,6 +34,8 @@ #include "tst_test.h" #include "lapi/keyctl.h" +#define MODULE "dns_resolver" + /* * A valid payload for the "asymmetric" key type. This is an x509 certificate * in DER format, generated using: @@ -190,6 +195,9 @@ static void test_update_setperm_race(void) static void setup(void) { + /* There is no way to trigger automatic dns_resolver module loading. */ + tst_cmd((const char*[]){"modprobe", MODULE, NULL}, NULL, NULL, 0); + fips_enabled = tst_fips_enabled(); } @@ -198,8 +206,12 @@ static void do_test(unsigned int i) /* * We need to pass check in dns_resolver_preparse(), * give it dummy server list request. + * From v6.8-rc1 commit acc657692aed438e9931438f8c923b2b107aebf9: + * the incoming data for add_key() sysdall should be not less than 6 + * bytes, because struct dns_server_list_v1_header is 6 bytes. + * The minimum payload will be tested here for boundary testing. */ - static char dns_res_payload[] = { 0x00, 0x00, 0x01, 0xff, 0x00 }; + static char dns_res_payload[] = { 0x00, 0x00, 0x01, 0xff, 0x00, 0x00 }; switch (i) { case 0: @@ -207,7 +219,7 @@ static void do_test(unsigned int i) x509_cert, sizeof(x509_cert)); break; case 1: - test_update_nonupdatable("dns_resolver", dns_res_payload, + test_update_nonupdatable(MODULE, dns_res_payload, sizeof(dns_res_payload)); break; case 2: @@ -217,12 +229,14 @@ static void do_test(unsigned int i) } static struct tst_test test = { + .needs_root = 1, .tcnt = 3, .setup = setup, .test = do_test, .forks_child = 1, .tags = (const struct tst_tag[]) { {"linux-git", "63a0b0509e70"}, + {"linux-git", "acc657692aed"}, {} } }; diff --git a/testcases/kernel/syscalls/keyctl/keyctl06.c b/testcases/kernel/syscalls/keyctl/keyctl06.c index f76a85ff2..4564601d1 100644 --- a/testcases/kernel/syscalls/keyctl/keyctl06.c +++ b/testcases/kernel/syscalls/keyctl/keyctl06.c @@ -1,19 +1,19 @@ // SPDX-License-Identifier: GPL-2.0-or-later /* * Copyright (c) 2017 Google, Inc. + * Copyright (c) Linux Test Project, 2017-2024 */ -/* - * Regression test for: +/*\ + * [Description] * - * commit e645016abc80 ("KEYS: fix writing past end of user-supplied buffer - * in keyring_read()"). + * Regression test for commit: * - * as well as its follow-on fix: + * e645016abc80 ("KEYS: fix writing past end of user-supplied buffer in keyring_read()") * - * commit 3239b6f29bdf ("KEYS: return full count in keyring_read() if - * buffer is too small") + * as well as its follow-on fix: * + * commit 3239b6f29bdf ("KEYS: return full count in keyring_read() if buffer is too small") */ #include <errno.h> diff --git a/testcases/kernel/syscalls/keyctl/keyctl07.c b/testcases/kernel/syscalls/keyctl/keyctl07.c index d9e20db5f..8b10ee803 100644 --- a/testcases/kernel/syscalls/keyctl/keyctl07.c +++ b/testcases/kernel/syscalls/keyctl/keyctl07.c @@ -1,9 +1,12 @@ // SPDX-License-Identifier: GPL-2.0-or-later /* * Copyright (c) 2017 Google, Inc. + * Copyright (c) Linux Test Project, 2018-2024 */ -/* +/*\ + * [Description] + * * Regression test for commit 37863c43b2c6 ("KEYS: prevent KEYCTL_READ on * negative key"). This is CVE-2017-12192. */ diff --git a/testcases/kernel/syscalls/keyctl/keyctl08.c b/testcases/kernel/syscalls/keyctl/keyctl08.c index be4b23b14..30e077c50 100644 --- a/testcases/kernel/syscalls/keyctl/keyctl08.c +++ b/testcases/kernel/syscalls/keyctl/keyctl08.c @@ -1,10 +1,16 @@ // SPDX-License-Identifier: GPL-2.0-or-later /* * Copyright (c) 2017 Richard Palethorpe <rpalethorpe@suse.com> + * Copyright (c) Linux Test Project, 2019-2024 */ -/* Check for CVE-2016-9604; that keys beginning with "." are disallowed. + +/*\ + * [Description] + * + * Test for CVE-2016-9604, checks that keys beginning with "." are disallowed. * - * See commit ee8f844e3c5a73b999edf733df1c529d6503ec2f + * See commit + * ee8f844e3c5a ("KEYS: Disallow keyrings beginning with '.' to be joined as session keyrings") */ #include <errno.h> diff --git a/testcases/kernel/syscalls/keyctl/keyctl09.c b/testcases/kernel/syscalls/keyctl/keyctl09.c index cfd5f7e5f..1f24f804a 100644 --- a/testcases/kernel/syscalls/keyctl/keyctl09.c +++ b/testcases/kernel/syscalls/keyctl/keyctl09.c @@ -1,6 +1,7 @@ // SPDX-License-Identifier: GPL-2.0-or-later /* * Copyright (c) 2022 Google, Inc. + * Copyright (c) Linux Test Project, 2023 */ /*\ diff --git a/testcases/kernel/syscalls/lchown/Makefile b/testcases/kernel/syscalls/lchown/Makefile index 305fee281..7c76afea5 100644 --- a/testcases/kernel/syscalls/lchown/Makefile +++ b/testcases/kernel/syscalls/lchown/Makefile @@ -3,6 +3,9 @@ top_srcdir ?= ../../../.. +# Remove after rewriting all tests to the new API. +USE_LEGACY_COMPAT_16_H := 1 + include $(top_srcdir)/include/mk/testcases.mk SRCS := $(sort $(wildcard $(abs_srcdir)/lchown*.c)) diff --git a/testcases/kernel/syscalls/lchown/lchown01.c b/testcases/kernel/syscalls/lchown/lchown01.c index 4e6076e1f..aaa0ef403 100644 --- a/testcases/kernel/syscalls/lchown/lchown01.c +++ b/testcases/kernel/syscalls/lchown/lchown01.c @@ -41,6 +41,11 @@ #include "test.h" #include "safe_macros.h" + +/* + * Don't forget to remove USE_LEGACY_COMPAT_16_H from Makefile after + * rewriting all tests to the new API. + */ #include "compat_16.h" #define FILE_MODE (S_IFREG|S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH) diff --git a/testcases/kernel/syscalls/lchown/lchown02.c b/testcases/kernel/syscalls/lchown/lchown02.c index 97966f6be..c0932fb7a 100644 --- a/testcases/kernel/syscalls/lchown/lchown02.c +++ b/testcases/kernel/syscalls/lchown/lchown02.c @@ -58,6 +58,11 @@ #include "test.h" #include "safe_macros.h" + +/* + * Don't forget to remove USE_LEGACY_COMPAT_16_H from Makefile after + * rewriting all tests to the new API. + */ #include "compat_16.h" #define TEST_USER "nobody" diff --git a/testcases/kernel/syscalls/lchown/lchown03.c b/testcases/kernel/syscalls/lchown/lchown03.c index c26f54c21..ecb6ed64d 100644 --- a/testcases/kernel/syscalls/lchown/lchown03.c +++ b/testcases/kernel/syscalls/lchown/lchown03.c @@ -39,6 +39,11 @@ #include "test.h" #include "safe_macros.h" + +/* + * Don't forget to remove USE_LEGACY_COMPAT_16_H from Makefile after + * rewriting all tests to the new API. + */ #include "compat_16.h" #define DIR_MODE (S_IRUSR|S_IWUSR|S_IXUSR|S_IRGRP| \ diff --git a/testcases/kernel/syscalls/link/.gitignore b/testcases/kernel/syscalls/link/.gitignore index e5d7f1bbc..b2b9db632 100644 --- a/testcases/kernel/syscalls/link/.gitignore +++ b/testcases/kernel/syscalls/link/.gitignore @@ -1,5 +1,4 @@ /link02 -/link03 /link04 /link05 /link08 diff --git a/testcases/kernel/syscalls/link/link03.c b/testcases/kernel/syscalls/link/link03.c deleted file mode 100644 index 1f45240ae..000000000 --- a/testcases/kernel/syscalls/link/link03.c +++ /dev/null @@ -1,167 +0,0 @@ -/* - * Copyright (c) 2000 Silicon Graphics, Inc. All Rights Reserved. - * AUTHOR : Richard Logan - * CO-PILOT : William Roske - * Copyright (c) 2014 Cyril Hrubis <chrubis@suse.cz> - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it would be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * - * Further, this software is distributed without any warranty that it is - * free of the rightful claim of any third person regarding infringement - * or the like. Any license provided herein, whether implied or - * otherwise, applies only to this software file. Patent licenses, if - * any, provided herein do not apply to combinations of this program with - * other software, or any other product whatsoever. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy, - * Mountain View, CA 94043, or: - * - * http://www.sgi.com - * - * For further information regarding this notice, see: - * - * http://oss.sgi.com/projects/GenInfo/NoticeExplan/ - * - */ - - /* - * Tests that link(2) succeds with creating n links. - */ - -#include <sys/types.h> -#include <fcntl.h> -#include <sys/stat.h> -#include <errno.h> -#include <string.h> -#include <signal.h> -#include "test.h" -#include "safe_macros.h" - -static void setup(void); -static void help(void); -static void cleanup(void); - -char *TCID = "link03"; -int TST_TOTAL = 2; - -#define BASENAME "lkfile" - -static char fname[255]; -static int nlinks = 0; -static char *links_arg; - -option_t options[] = { - {"N:", NULL, &links_arg}, - {NULL, NULL, NULL} -}; - -int main(int ac, char **av) -{ - int lc; - struct stat buf; - int i, links; - char lname[255]; - - tst_parse_opts(ac, av, options, &help); - - if (links_arg) { - nlinks = atoi(links_arg); - - if (nlinks == 0) { - tst_brkm(TBROK, NULL, - "nlinks is not a positive number"); - } - - if (nlinks > 1000) { - tst_resm(TINFO, - "nlinks > 1000 - may get errno:%d (EMLINK)", - EMLINK); - } - } - - setup(); - - for (lc = 0; TEST_LOOPING(lc); lc++) { - tst_count = 0; - - if (nlinks) - links = nlinks; - else - links = (lc % 90) + 10; - - /* Create links - 1 hardlinks so that the st_nlink == links */ - for (i = 1; i < links; i++) { - sprintf(lname, "%s%d", fname, i); - TEST(link(fname, lname)); - - if (TEST_RETURN == -1) { - tst_brkm(TFAIL | TTERRNO, cleanup, - "link(%s, %s) Failed", fname, lname); - } - } - - SAFE_STAT(cleanup, fname, &buf); - - if (buf.st_nlink != (nlink_t)links) { - tst_resm(TFAIL, "Wrong number of links for " - "'%s' have %i, should be %i", - fname, (int)buf.st_nlink, links); - goto unlink; - } - - for (i = 1; i < links; i++) { - sprintf(lname, "%s%d", fname, i); - SAFE_STAT(cleanup, lname, &buf); - if (buf.st_nlink != (nlink_t)links) { - tst_resm(TFAIL, - "Wrong number of links for " - "'%s' have %i, should be %i", - lname, (int)buf.st_nlink, links); - goto unlink; - } - } - - tst_resm(TPASS, "link() passed and linkcounts=%d match", links); - -unlink: - for (i = 1; i < links; i++) { - sprintf(lname, "%s%d", fname, i); - SAFE_UNLINK(cleanup, lname); - } - } - - cleanup(); - tst_exit(); -} - -static void help(void) -{ - printf(" -N #links : create #links hard links every iteration\n"); -} - -static void setup(void) -{ - tst_sig(NOFORK, DEF_HANDLER, cleanup); - - TEST_PAUSE; - - tst_tmpdir(); - - sprintf(fname, "%s_%d", BASENAME, getpid()); - SAFE_TOUCH(cleanup, fname, 0700, NULL); -} - -static void cleanup(void) -{ - tst_rmdir(); -} diff --git a/testcases/kernel/syscalls/link/link05.c b/testcases/kernel/syscalls/link/link05.c index 95787ec24..dfef3d458 100644 --- a/testcases/kernel/syscalls/link/link05.c +++ b/testcases/kernel/syscalls/link/link05.c @@ -1,13 +1,15 @@ // SPDX-License-Identifier: GPL-2.0-or-later /* * Copyright (c) 2000 Silicon Graphics, Inc. All Rights Reserved. - * AUTHOR : Richard Logan - * CO-PILOT : William Roske + * Authors: Richard Logan, William Roske * Copyright (c) 2014 Cyril Hrubis <chrubis@suse.cz> + * Copyright (c) Linux Test Project, 2001-2023 */ -/* - * Test if link(2) fails with EMLINK. +/*\ + * [Description] + * + * Tests that link(2) succeeds with creating 1000 links. */ #include <stdio.h> @@ -41,10 +43,8 @@ static void verify_link(void) (fbuf.st_nlink != lbuf.st_nlink)) { tst_res(TFAIL, - "link(%s, %s[1-%d]) ret %ld for %d " - "files, stat values do not match %d %d", - fname, fname, nlinks, - TST_RET, nlinks, + "link(%s, %s[1-%d]) ret %ld for %d files, stat values do not match %d %d", + fname, fname, nlinks, TST_RET, nlinks, (int)fbuf.st_nlink, (int)lbuf.st_nlink); break; } @@ -52,10 +52,8 @@ static void verify_link(void) if (cnt >= nlinks) { tst_res(TPASS, - "link(%s, %s[1-%d]) ret %ld for %d files, " - "stat linkcounts match %d", - fname, fname, nlinks, TST_RET, - nlinks, (int)fbuf.st_nlink); + "link(%s, %s[1-%d]) ret %ld for %d files, stat linkcounts match %d", + fname, fname, nlinks, TST_RET, nlinks, (int)fbuf.st_nlink); } for (cnt = 1; cnt < nlinks; cnt++) { @@ -71,7 +69,7 @@ static void setup(void) } static struct tst_test test = { - .test_all = verify_link, - .setup = setup, - .needs_tmpdir = 1, + .test_all = verify_link, + .setup = setup, + .needs_tmpdir = 1, }; diff --git a/testcases/kernel/syscalls/link/link08.c b/testcases/kernel/syscalls/link/link08.c index d3e33d077..92d507489 100644 --- a/testcases/kernel/syscalls/link/link08.c +++ b/testcases/kernel/syscalls/link/link08.c @@ -1,23 +1,26 @@ // SPDX-License-Identifier: GPL-2.0-or-later /* * Copyright (c) 2014 Fujitsu Ltd. + * Copyright (c) Linux Test Project, 2014-2023 * Author: Zeng Linggang <zenglg.jy@cn.fujitsu.com> */ -/* - * Test Description: - * Verify that, - * 1. link() fails with -1 return value and sets errno to EPERM - * if oldpath is a directory. - * 2. link() fails with -1 return value and sets errno to EXDEV - * if oldpath and newpath are not on the same mounted file system( Linux - * permits a file system to be mounted at multiple points, but link() - * does not work across different mount points, even if the same - * file system is mounted on both. ). - * 3. link() fails with -1 return value and sets errno to EROFS - * if the file is on a read-only file system. - * 4. link() fails with -1 return value and sets errno to ELOOP - * if too many symbolic links were encountered in resolving path. + +/*\ + * [Description] + * + * Verify that: + * + * - link() fails with EPERM if the old path is a directory. + * - link() fails with EXDEV if the old path and the new path + * are not on the same mounted file system(Linux permits + * a file system to be mounted at multiple points, but link() + * does not work across different mount points, even if the same + * file system is mounted on both). + * - link() fails with EROFS if the file is on a read-only file system. + * - link() fails with ELOOP if too many symbolic links were encountered + * in resolving path. */ + #include <errno.h> #include "tst_test.h" diff --git a/testcases/kernel/syscalls/mkdirat/mkdirat01.c b/testcases/kernel/syscalls/mkdirat/mkdirat01.c index a323ed5b3..ca536bdab 100644 --- a/testcases/kernel/syscalls/mkdirat/mkdirat01.c +++ b/testcases/kernel/syscalls/mkdirat/mkdirat01.c @@ -35,7 +35,6 @@ #include <string.h> #include <signal.h> #include "test.h" -#include "lapi/mkdirat.h" #include "safe_macros.h" static void setup(void); diff --git a/testcases/kernel/syscalls/mkdirat/mkdirat02.c b/testcases/kernel/syscalls/mkdirat/mkdirat02.c index ebc0ed16b..2bd8fe9c0 100644 --- a/testcases/kernel/syscalls/mkdirat/mkdirat02.c +++ b/testcases/kernel/syscalls/mkdirat/mkdirat02.c @@ -11,7 +11,6 @@ #define _GNU_SOURCE #include "tst_test.h" -#include "lapi/mkdirat.h" #define MNT_POINT "mntpoint" #define TEST_DIR "mntpoint/test_dir" diff --git a/testcases/kernel/syscalls/mknodat/mknodat.h b/testcases/kernel/syscalls/mknodat/mknodat.h deleted file mode 100644 index 8f3a1f007..000000000 --- a/testcases/kernel/syscalls/mknodat/mknodat.h +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Copyright (c) International Business Machines Corp., 2007 - * Copyright (c) 2014 Fujitsu Ltd. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Library General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - * - */ - -#ifndef MKNODAT_H -#define MKNODAT_H - -#include <sys/types.h> -#include "config.h" -#include "lapi/syscalls.h" - -#if !defined(HAVE_MKNODAT) -int mknodat(int dirfd, const char *filename, mode_t mode, dev_t dev) -{ - return tst_syscall(__NR_mknodat, dirfd, filename, mode, dev); -} -#endif - -#endif /* MKNODAT_H */ diff --git a/testcases/kernel/syscalls/mknodat/mknodat01.c b/testcases/kernel/syscalls/mknodat/mknodat01.c index 6500ca362..3be0a4f87 100644 --- a/testcases/kernel/syscalls/mknodat/mknodat01.c +++ b/testcases/kernel/syscalls/mknodat/mknodat01.c @@ -35,7 +35,6 @@ #include "test.h" #include "safe_macros.h" #include "lapi/fcntl.h" -#include "mknodat.h" #define PATHNAME "mknodattestdir" diff --git a/testcases/kernel/syscalls/mknodat/mknodat02.c b/testcases/kernel/syscalls/mknodat/mknodat02.c index eda247fda..fdac5db15 100644 --- a/testcases/kernel/syscalls/mknodat/mknodat02.c +++ b/testcases/kernel/syscalls/mknodat/mknodat02.c @@ -37,7 +37,7 @@ #include "test.h" #include "safe_macros.h" #include "lapi/fcntl.h" -#include "mknodat.h" +#include "lapi/syscalls.h" static void setup(void); static void cleanup(void); diff --git a/testcases/kernel/syscalls/mmap/mmap04.c b/testcases/kernel/syscalls/mmap/mmap04.c index 43f7b7525..fa85deed1 100644 --- a/testcases/kernel/syscalls/mmap/mmap04.c +++ b/testcases/kernel/syscalls/mmap/mmap04.c @@ -1,185 +1,79 @@ +// SPDX-License-Identifier: GPL-2.0-or-later /* * Copyright (c) International Business Machines Corp., 2001 - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See - * the GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * 07/2001 Ported by Wayne Boyer + * Copyright (c) 2023 SUSE LLC Avinesh Kumar <avinesh.kumar@suse.com> */ -/* - * Test Description: - * Call mmap() to map a file creating a mapped region with read/exec access - * under the following conditions - - * - The prot parameter is set to PROT_READ|PROT_EXEC - * - The file descriptor is open for read - * - The file being mapped has read and execute permission bit set. - * - The minimum file permissions should be 0555. - * - * The call should succeed to map the file creating mapped memory with the - * required attributes. - * - * Expected Result: - * mmap() should succeed returning the address of the mapped region, - * and the mapped region should contain the contents of the mapped file. +/*\ + * [Description] * - * HISTORY - * 07/2001 Ported by Wayne Boyer + * Verify that, after a successful mmap() call, permission bits of the new + * mapping in /proc/pid/maps file matches the prot and flags arguments in + * mmap() call. */ +#include <inttypes.h> +#include "tst_test.h" #include <stdio.h> -#include <stdlib.h> -#include <sys/types.h> -#include <errno.h> -#include <unistd.h> -#include <fcntl.h> -#include <string.h> -#include <signal.h> -#include <sys/stat.h> -#include <sys/mman.h> -#include "test.h" - -#define TEMPFILE "mmapfile" - -char *TCID = "mmap04"; -int TST_TOTAL = 1; - -static size_t page_sz; -static char *addr; -static char *dummy; -static int fildes; - -static void setup(void); -static void cleanup(void); - -int main(int ac, char **av) +static char *addr1; +static char *addr2; + +static struct tcase { + int prot; + int flags; + char *exp_perms; +} tcases[] = { + {PROT_NONE, MAP_ANONYMOUS | MAP_PRIVATE, "---p"}, + {PROT_NONE, MAP_ANONYMOUS | MAP_SHARED, "---s"}, + {PROT_READ, MAP_ANONYMOUS | MAP_PRIVATE, "r--p"}, + {PROT_READ, MAP_ANONYMOUS | MAP_SHARED, "r--s"}, + {PROT_WRITE, MAP_ANONYMOUS | MAP_PRIVATE, "-w-p"}, + {PROT_WRITE, MAP_ANONYMOUS | MAP_SHARED, "-w-s"}, + {PROT_READ | PROT_WRITE, MAP_ANONYMOUS | MAP_PRIVATE, "rw-p"}, + {PROT_READ | PROT_WRITE, MAP_ANONYMOUS | MAP_SHARED, "rw-s"}, + {PROT_READ | PROT_EXEC, MAP_ANONYMOUS | MAP_PRIVATE, "r-xp"}, + {PROT_READ | PROT_EXEC, MAP_ANONYMOUS | MAP_SHARED, "r-xs"}, + {PROT_WRITE | PROT_EXEC, MAP_ANONYMOUS | MAP_PRIVATE, "-wxp"}, + {PROT_WRITE | PROT_EXEC, MAP_ANONYMOUS | MAP_SHARED, "-wxs"}, + {PROT_READ | PROT_WRITE | PROT_EXEC, MAP_ANONYMOUS | MAP_PRIVATE, "rwxp"}, + {PROT_READ | PROT_WRITE | PROT_EXEC, MAP_ANONYMOUS | MAP_SHARED, "rwxs"} +}; + +static void run(unsigned int i) { - int lc; - - tst_parse_opts(ac, av, NULL, NULL); - - setup(); - - for (lc = 0; TEST_LOOPING(lc); lc++) { - - tst_count = 0; - - /* - * Call mmap to map the temporary file 'TEMPFILE' - * with read and execute access. - */ - errno = 0; - addr = mmap(0, page_sz, PROT_READ | PROT_EXEC, - MAP_FILE | MAP_SHARED, fildes, 0); - - /* Check for the return value of mmap() */ - if (addr == MAP_FAILED) { - tst_resm(TFAIL | TERRNO, "mmap of %s failed", TEMPFILE); - continue; - } - - /* - * Read the file contents into the dummy - * variable. - */ - if (read(fildes, dummy, page_sz) < 0) { - tst_brkm(TFAIL, cleanup, "reading %s failed", - TEMPFILE); - } - - /* - * Check whether the mapped memory region - * has the file contents. - */ - if (memcmp(dummy, addr, page_sz)) { - tst_resm(TFAIL, - "mapped memory region contains invalid " - "data"); - } else { - tst_resm(TPASS, - "Functionality of mmap() successful"); - } - - /* Clean up things in case we are looping. */ - /* Unmap the mapped memory */ - if (munmap(addr, page_sz) != 0) { - tst_brkm(TFAIL, cleanup, "munmapping failed"); - } + struct tcase *tc = &tcases[i]; + char perms[8]; + char fmt[1024]; + unsigned int pagesize; + int flag; + + pagesize = SAFE_SYSCONF(_SC_PAGESIZE); + + /* To avoid new mapping getting merged with existing mappings, we first + * create a 2-page mapping with the different permissions, and then remap + * the 2nd page with the perms being tested. + */ + flag = (tc->flags & MAP_PRIVATE) ? MAP_SHARED : MAP_PRIVATE; + addr1 = SAFE_MMAP(NULL, pagesize * 2, PROT_NONE, MAP_ANONYMOUS | flag, -1, 0); + + addr2 = SAFE_MMAP(addr1 + pagesize, pagesize, tc->prot, tc->flags | MAP_FIXED, -1, 0); + + sprintf(fmt, "%" PRIxPTR "-%%*x %%s", (uintptr_t)addr2); + SAFE_FILE_LINES_SCANF("/proc/self/maps", fmt, perms); + + if (!strcmp(perms, tc->exp_perms)) { + tst_res(TPASS, "mapping permissions in /proc matched: %s", perms); + } else { + tst_res(TFAIL, "mapping permissions in /proc mismatched, expected: %s, found: %s", + tc->exp_perms, perms); } - cleanup(); - tst_exit(); + SAFE_MUNMAP(addr1, pagesize * 2); } -static void setup(void) -{ - char *tst_buff; - - tst_sig(NOFORK, DEF_HANDLER, cleanup); - - TEST_PAUSE; - - page_sz = getpagesize(); - - if ((tst_buff = calloc(page_sz, sizeof(char))) == NULL) { - tst_brkm(TFAIL, NULL, "calloc failed (tst_buff)"); - } - - /* Fill the test buffer with the known data */ - memset(tst_buff, 'A', page_sz); - - tst_tmpdir(); - - /* Creat a temporary file used for mapping */ - if ((fildes = open(TEMPFILE, O_WRONLY | O_CREAT, 0666)) < 0) { - free(tst_buff); - tst_brkm(TFAIL, cleanup, "opening %s failed", TEMPFILE); - } - - /* Write test buffer contents into temporary file */ - if (write(fildes, tst_buff, page_sz) < (ssize_t)page_sz) { - free(tst_buff); - tst_brkm(TFAIL, cleanup, "writing to %s failed", TEMPFILE); - } - - /* Free the memory allocated for test buffer */ - free(tst_buff); - - /* Make sure proper permissions set on file */ - if (fchmod(fildes, 0555) < 0) { - tst_brkm(TFAIL, cleanup, "fchmod of %s failed", TEMPFILE); - } - - /* Close the temporary file opened for write */ - if (close(fildes) < 0) { - tst_brkm(TFAIL, cleanup, "closing %s failed", TEMPFILE); - } - - /* Allocate and initialize dummy string of system page size bytes */ - if ((dummy = calloc(page_sz, sizeof(char))) == NULL) { - tst_brkm(TFAIL, cleanup, "calloc failed (dummy)"); - } - - /* Open the temporary file again for reading */ - if ((fildes = open(TEMPFILE, O_RDONLY)) < 0) { - tst_brkm(TFAIL, cleanup, - "opening %s read-only failed", TEMPFILE); - } -} - -static void cleanup(void) -{ - close(fildes); - free(dummy); - tst_rmdir(); -} +static struct tst_test test = { + .test = run, + .tcnt = ARRAY_SIZE(tcases), +}; diff --git a/testcases/kernel/syscalls/mmap/mmap15.c b/testcases/kernel/syscalls/mmap/mmap15.c index 443a37eb8..71c18a10a 100644 --- a/testcases/kernel/syscalls/mmap/mmap15.c +++ b/testcases/kernel/syscalls/mmap/mmap15.c @@ -1,113 +1,66 @@ +// SPDX-License-Identifier: GPL-2.0-or-later /* * Copyright (c) International Business Machines Corp., 2004 - * Written by Robbie Williamson - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See - * the GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * Written by Robbie Williamson + * Copyright (c) 2023 SUSE LLC Avinesh Kumar <avinesh.kumar@suse.com> + * Copyright (c) Linux Test Project, 2014-2023 */ -/* - * Test Description: Test that a normal page cannot be mapped into a high - * memory region. +/*\ + * [Description] + * + * Verify that, a normal page cannot be mapped into a high memory region, + * and mmap() call fails with either ENOMEM or EINVAL errno. */ -#include <sys/types.h> -#include <sys/mman.h> -#include <sys/mount.h> -#include <sys/stat.h> -#include <errno.h> -#include <fcntl.h> -#include <signal.h> -#include <stdint.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <unistd.h> -#include "test.h" -#include "safe_macros.h" -#include "lapi/abisize.h" - -char *TCID = "mmap15"; -int TST_TOTAL = 1; +#include "tst_test.h" #ifdef __ia64__ -# define HIGH_ADDR (void *)(0xa000000000000000UL) +# define HIGH_ADDR ((void *)(0xa000000000000000UL)) #else -# define HIGH_ADDR (void *)(-page_size) +# define HIGH_ADDR ((void *)(-page_size)) #endif -static long page_size; +#define TEMPFILE "mmapfile" -static void setup(void); -static void cleanup(void); +static long page_size; +static int fd; -int main(int ac, char **av) +static void run(void) { - int lc, fd; - void *addr; - -#ifdef TST_ABI32 - tst_brkm(TCONF, NULL, "This test is only for 64bit"); -#endif + fd = SAFE_OPEN(TEMPFILE, O_RDWR | O_CREAT, 0666); - tst_parse_opts(ac, av, NULL, NULL); + TESTPTR(mmap(HIGH_ADDR, page_size, PROT_READ, MAP_SHARED | MAP_FIXED, fd, 0)); - setup(); - - for (lc = 0; TEST_LOOPING(lc); lc++) { - tst_count = 0; - - fd = SAFE_OPEN(cleanup, "testfile", O_RDWR | O_CREAT, 0666); - - /* Attempt to mmap into highmem addr, should get ENOMEM */ - addr = mmap(HIGH_ADDR, page_size, PROT_READ, - MAP_SHARED | MAP_FIXED, fd, 0); - if (addr != MAP_FAILED) { - tst_resm(TFAIL, "mmap into high region " - "succeeded unexpectedly"); - munmap(addr, page_size); - close(fd); - continue; - } - - if (errno != ENOMEM && errno != EINVAL) { - tst_resm(TFAIL | TERRNO, "mmap into high region " - "failed unexpectedly"); - } else { - tst_resm(TPASS | TERRNO, "mmap into high region " - "failed as expected"); - } - - SAFE_CLOSE(cleanup, fd); + if (TST_RET_PTR != MAP_FAILED) { + tst_res(TFAIL, "mmap() into high mem region succeeded unexpectedly"); + SAFE_MUNMAP(TST_RET_PTR, page_size); + return; } - cleanup(); - tst_exit(); + if (TST_ERR == ENOMEM || TST_ERR == EINVAL) + tst_res(TPASS | TERRNO, "mmap() failed with expected errno"); + else + tst_res(TFAIL | TERRNO, "mmap() failed with unexpected errno"); + + SAFE_CLOSE(fd); } static void setup(void) { - tst_require_root(); - - tst_tmpdir(); - page_size = getpagesize(); - - TEST_PAUSE; } static void cleanup(void) { - tst_rmdir(); + if (fd > 0) + SAFE_CLOSE(fd); } + +static struct tst_test test = { + .setup = setup, + .cleanup = cleanup, + .test_all = run, + .skip_in_compat = 1, + .needs_tmpdir = 1 +}; diff --git a/testcases/kernel/syscalls/mount/mount04.c b/testcases/kernel/syscalls/mount/mount04.c index 5969fbacb..5eb5ee11b 100644 --- a/testcases/kernel/syscalls/mount/mount04.c +++ b/testcases/kernel/syscalls/mount/mount04.c @@ -1,119 +1,50 @@ +// SPDX-License-Identifier: GPL-2.0-or-later /* * Copyright (c) Wipro Technologies Ltd, 2002. All Rights Reserved. + * Nirmala Devi Dhanasekar <nirmala.devi@wipro.com> + * Copyright (C) 2023 SUSE LLC Andrea Cervesato <andrea.cervesato@suse.com> + */ + +/*\ + * [Description] * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it would be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * - * DESCRIPTION - * Verify that mount(2) returns -1 and sets errno to EPERM if the user - * is not the super-user. + * Verify that mount(2) returns -1 and sets errno to EPERM if the user + * is not root. */ -#include <errno.h> -#include <sys/mount.h> -#include <sys/types.h> -#include <sys/stat.h> -#include <fcntl.h> +#include "tst_test.h" #include <pwd.h> -#include "test.h" -#include "safe_macros.h" - -static void setup(void); -static void cleanup(void); - -char *TCID = "mount04"; - -#define DIR_MODE S_IRWXU | S_IRUSR | S_IXUSR | S_IRGRP | S_IXGRP - -static char *mntpoint = "mntpoint"; -static const char *fs_type; -static const char *device; - -int TST_TOTAL = 1; - -static void verify_mount(void) -{ - - TEST(mount(device, mntpoint, fs_type, 0, NULL)); - - if (TEST_RETURN == -1) { - if (TEST_ERRNO == EPERM) - tst_resm(TPASS | TTERRNO, "mount() failed expectedly"); - else - tst_resm(TFAIL | TTERRNO, - "mount() was expected to fail with EPERM"); - return; - } +#include <sys/mount.h> - if (TEST_RETURN == 0) { - tst_resm(TFAIL, "mount() succeeded unexpectedly"); - if (tst_umount(mntpoint)) - tst_brkm(TBROK, cleanup, "umount() failed"); - return; - } +#define MNTPOINT "mntpoint" - tst_resm(TFAIL | TTERRNO, "mount() returned %li", TEST_RETURN); -} - -int main(int ac, char **av) +static void cleanup(void) { - int lc; - - tst_parse_opts(ac, av, NULL, NULL); - - setup(); - - for (lc = 0; TEST_LOOPING(lc); lc++) { - tst_count = 0; - verify_mount(); - } - - cleanup(); - tst_exit(); + if (tst_is_mounted(MNTPOINT)) + SAFE_UMOUNT(MNTPOINT); } -static void setup(void) +static void run(void) { - char nobody_uid[] = "nobody"; struct passwd *ltpuser; - tst_sig(FORK, DEF_HANDLER, cleanup); - - tst_require_root(); - - tst_tmpdir(); + ltpuser = SAFE_GETPWNAM("nobody"); + SAFE_SETEUID(ltpuser->pw_uid); - fs_type = tst_dev_fs_type(); - device = tst_acquire_device(cleanup); + TST_EXP_FAIL( + mount(tst_device->dev, MNTPOINT, tst_device->fs_type, 0, NULL), + EPERM, + "mount() failed expectedly for normal user" + ); - if (!device) - tst_brkm(TCONF, cleanup, "Failed to obtain block device"); - - tst_mkfs(cleanup, device, fs_type, NULL, NULL); - - ltpuser = SAFE_GETPWNAM(cleanup, nobody_uid); - SAFE_SETEUID(cleanup, ltpuser->pw_uid); - SAFE_MKDIR(cleanup, mntpoint, DIR_MODE); - - TEST_PAUSE; + if (tst_is_mounted(MNTPOINT)) + SAFE_UMOUNT(MNTPOINT); } -static void cleanup(void) -{ - if (seteuid(0)) - tst_resm(TWARN | TERRNO, "seteuid(0) failed"); - - if (device) - tst_release_device(device); - - tst_rmdir(); -} +static struct tst_test test = { + .cleanup = cleanup, + .test_all = run, + .needs_root = 1, + .format_device = 1, + .mntpoint = MNTPOINT, +}; diff --git a/testcases/kernel/syscalls/mount/mount05.c b/testcases/kernel/syscalls/mount/mount05.c index ca26f9738..616eeee79 100644 --- a/testcases/kernel/syscalls/mount/mount05.c +++ b/testcases/kernel/syscalls/mount/mount05.c @@ -1,131 +1,72 @@ +// SPDX-License-Identifier: GPL-2.0-or-later /* - * Copyright (c) 2013 Fujitsu Ltd. - * Author: DAN LI <li.dan@cn.fujitsu.com> - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it would be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * + * Copyright (c) 2013 Fujitsu Ltd. Dan Li <li.dan@cn.fujitsu.com> + * Copyright (C) 2023 SUSE LLC Andrea Cervesato <andrea.cervesato@suse.com> */ -/* - * DESCRIPTION - * Test for feature MS_BIND of mount. - * "Perform a bind mount, making a file or a directory subtree visible - * at another point within a file system." +/*\ + * [Description] + * + * Test for feature MS_BIND of mount, which performs a bind mount, making a file + * or a directory subtree visible at another point within a file system. */ -#include <errno.h> +#include "tst_test.h" #include <sys/mount.h> -#include <sys/types.h> -#include <sys/stat.h> -#include <unistd.h> -#include <fcntl.h> - -#include "test.h" -#include "safe_macros.h" - -static void help(void); -static void setup(void); -static void cleanup(void); -char *TCID = "mount05"; -int TST_TOTAL = 1; +#define MNTPOINT1 "mntpoint1" +#define TESTFILE1 MNTPOINT1 "/testfile" +#define TESTDIR1 MNTPOINT1 "/testdir" -#define DIR_MODE (S_IRWXU | S_IRUSR | S_IXUSR | S_IRGRP | S_IXGRP) +#define MNTPOINT2 "mntpoint2" +#define TESTFILE2 MNTPOINT2 "/testfile" +#define TESTDIR2 MNTPOINT2 "/testdir" -static int dflag; -static char *fstype = "ext2"; -static char *device; -static const char file_src[] = "mnt_src/tstfile"; -static const char file_des[] = "mnt_des/tstfile"; -static const char mntpoint_src[] = "mnt_src"; -static const char mntpoint_des[] = "mnt_des"; - -static option_t options[] = { - {"T:", NULL, &fstype}, - {"D:", &dflag, &device}, - {NULL, NULL, NULL}, -}; - -int main(int argc, char *argv[]) +static void setup(void) { - int lc; - - tst_parse_opts(argc, argv, options, &help); - - setup(); - - for (lc = 0; TEST_LOOPING(lc); lc++) { - - tst_count = 0; + SAFE_MOUNT(tst_device->dev, MNTPOINT1, tst_device->fs_type, 0, NULL); - TEST(mount(mntpoint_src, mntpoint_des, fstype, MS_BIND, NULL)); + tst_res(TINFO, "Creating file in '%s'", TESTFILE1); - if (TEST_RETURN != 0) { - tst_resm(TFAIL | TTERRNO, "mount(2) failed"); - } else { - - if (open(file_des, O_CREAT | O_EXCL, S_IRWXU) == -1 && - errno == EEXIST) - tst_resm(TPASS, "bind mount is ok"); - else - tst_resm(TFAIL, "file %s is not available", - file_des); - - TEST(tst_umount(mntpoint_des)); - if (TEST_RETURN != 0) - tst_brkm(TBROK | TTERRNO, cleanup, - "umount(2) failed"); - } - } - - cleanup(); - tst_exit(); + SAFE_FILE_PRINTF(TESTFILE1, "LTP TEST FILE"); + SAFE_MKDIR(TESTDIR1, 0750); } -void setup(void) +static void cleanup(void) { - tst_require_root(); - - tst_sig(NOFORK, DEF_HANDLER, cleanup); - - tst_tmpdir(); - - SAFE_MKDIR(cleanup, mntpoint_src, DIR_MODE); - SAFE_MKDIR(cleanup, mntpoint_des, DIR_MODE); - - if (dflag) { - tst_mkfs(NULL, device, fstype, NULL, NULL); + if (tst_is_mounted(MNTPOINT1)) + SAFE_UMOUNT(MNTPOINT1); - SAFE_MOUNT(cleanup, device, mntpoint_src, fstype, 0, NULL); - } - - SAFE_FILE_PRINTF(cleanup, file_src, "TEST FILE"); - - TEST_PAUSE; + if (tst_is_mounted(MNTPOINT2)) + SAFE_UMOUNT(MNTPOINT2); } -void cleanup(void) +static void run(void) { - if (dflag) - if (tst_umount(mntpoint_src) != 0) - tst_brkm(TBROK | TTERRNO, NULL, "umount(2) failed"); + SAFE_MKDIR(MNTPOINT2, 0750); + SAFE_MOUNT(MNTPOINT1, MNTPOINT2, tst_device->fs_type, MS_BIND, NULL); - tst_rmdir(); -} + TST_EXP_PASS(access(TESTFILE2, F_OK), "Accessing to '%s'", TESTFILE2); + TST_EXP_PASS(access(TESTDIR2, F_OK), "Accessing to '%s'", TESTDIR2); -void help(void) -{ - printf("-T type : specifies the type of filesystem to be mounted. " - "Default ext2.\n"); - printf("-D device : device used for mounting.\n"); + if (tst_is_mounted(MNTPOINT2)) + SAFE_UMOUNT(MNTPOINT2); + + SAFE_RMDIR(MNTPOINT2); } + +static struct tst_test test = { + .setup = setup, + .cleanup = cleanup, + .test_all = run, + .needs_root = 1, + .format_device = 1, + .mntpoint = MNTPOINT1, + .all_filesystems = 1, + .skip_filesystems = (const char *const []){ + "exfat", + "vfat", + "ntfs", + NULL + }, +}; diff --git a/testcases/kernel/syscalls/mount/mount06.c b/testcases/kernel/syscalls/mount/mount06.c index 857f5f905..2376deab3 100644 --- a/testcases/kernel/syscalls/mount/mount06.c +++ b/testcases/kernel/syscalls/mount/mount06.c @@ -1,34 +1,19 @@ +// SPDX-License-Identifier: GPL-2.0-or-later /* - * Copyright (c) 2013 Fujitsu Ltd. - * Author: DAN LI <li.dan@cn.fujitsu.com> - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it would be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * + * Copyright (c) 2013 Fujitsu Ltd. Dan Li <li.dan@cn.fujitsu.com> + * Copyright (C) 2023 SUSE LLC Andrea Cervesato <andrea.cervesato@suse.com> */ -/* - * DESCRIPTION - * Test for feature MS_MOVE of mount(2). - * "Move an existing mount point to the new location." +/*\ + * [Description] + * + * Test for feature MS_MOVE of mount, which moves an existing mount point to + * a new location. */ -#include <errno.h> +#include "tst_test.h" +#include <stdio.h> #include <sys/mount.h> -#include <unistd.h> -#include <fcntl.h> - -#include "test.h" -#include "safe_macros.h" #ifndef MS_MOVE #define MS_MOVE 8192 @@ -38,126 +23,86 @@ #define MS_PRIVATE (1 << 18) #endif -#define MNTPOINT_SRC "mnt_src" -#define MNTPOINT_DES "mnt_des" -#define LINELENGTH 256 -#define DIR_MODE (S_IRWXU | S_IRUSR | S_IXUSR | S_IRGRP | S_IXGRP) - -static int ismount(char *mntpoint); -static void setup(void); -static void cleanup(void); +#define MNTPOINT_SRC "mntpoint1" +#define MNTPOINT_DST "mntpoint2" -char *TCID = "mount06"; -int TST_TOTAL = 1; - -static const char *fs_type; -static const char *device; -static char path_name[PATH_MAX]; +static char *tmppath; static char mntpoint_src[PATH_MAX]; -static char mntpoint_des[PATH_MAX]; -static int mount_flag; +static char mntpoint_dst[PATH_MAX]; +static char tstfiles_src[PATH_MAX]; +static char tstfiles_dst[PATH_MAX]; -int main(int argc, char *argv[]) +static void setup(void) { - int lc; + tmppath = tst_get_tmpdir(); - tst_parse_opts(argc, argv, NULL, NULL); - - setup(); - - for (lc = 0; TEST_LOOPING(lc); lc++) { - - tst_count = 0; - - SAFE_MOUNT(cleanup, device, mntpoint_src, fs_type, 0, NULL); - - TEST(mount(mntpoint_src, mntpoint_des, fs_type, MS_MOVE, NULL)); - - if (TEST_RETURN != 0) { - tst_resm(TFAIL | TTERRNO, "mount(2) failed"); - } else { - - if (!ismount(mntpoint_src) && ismount(mntpoint_des)) - tst_resm(TPASS, "move mount is ok"); - else - tst_resm(TFAIL, "move mount does not work"); + /* + * Turn current dir into a private mount point being a parent + * mount which is required by move mount. + */ + SAFE_MOUNT(tmppath, tmppath, "none", MS_BIND, NULL); + SAFE_MOUNT("none", tmppath, "none", MS_PRIVATE, NULL); - TEST(tst_umount(mntpoint_des)); - if (TEST_RETURN != 0) - tst_brkm(TBROK | TTERRNO, cleanup, - "umount(2) failed"); - } - } + snprintf(mntpoint_src, PATH_MAX, "%s/%s", tmppath, MNTPOINT_SRC); + snprintf(mntpoint_dst, PATH_MAX, "%s/%s", tmppath, MNTPOINT_DST); - cleanup(); - tst_exit(); -} + snprintf(tstfiles_src, PATH_MAX, "%s/%s/testfile", tmppath, MNTPOINT_SRC); + snprintf(tstfiles_dst, PATH_MAX, "%s/%s/testfile", tmppath, MNTPOINT_DST); -int ismount(char *mntpoint) -{ - int ret = 0; - FILE *file; - char line[LINELENGTH]; - - file = fopen("/proc/mounts", "r"); - if (file == NULL) - tst_brkm(TFAIL | TERRNO, NULL, "Open /proc/mounts failed"); - - while (fgets(line, LINELENGTH, file) != NULL) { - if (strstr(line, mntpoint) != NULL) { - ret = 1; - break; - } - } - fclose(file); - return ret; + SAFE_MKDIR(mntpoint_dst, 0750); } -static void setup(void) +static void cleanup(void) { - tst_require_root(); + if (tst_is_mounted(mntpoint_src)) + SAFE_UMOUNT(mntpoint_src); - tst_sig(NOFORK, DEF_HANDLER, cleanup); + if (tst_is_mounted(mntpoint_dst)) + SAFE_UMOUNT(mntpoint_dst); - tst_tmpdir(); + if (tst_is_mounted(tmppath)) + SAFE_UMOUNT(tmppath); - fs_type = tst_dev_fs_type(); - device = tst_acquire_device(cleanup); - - if (!device) - tst_brkm(TCONF, cleanup, "Failed to obtain block device"); - - tst_mkfs(cleanup, device, fs_type, NULL, NULL); - - if (getcwd(path_name, sizeof(path_name)) == NULL) - tst_brkm(TBROK, cleanup, "getcwd failed"); + SAFE_RMDIR(mntpoint_dst); +} - /* - * Turn current dir into a private mount point being a parent - * mount which is required by move mount. - */ - SAFE_MOUNT(cleanup, path_name, path_name, "none", MS_BIND, NULL); +static void run(void) +{ + SAFE_MOUNT(tst_device->dev, mntpoint_src, tst_device->fs_type, 0, NULL); + SAFE_FILE_PRINTF(tstfiles_src, "LTP TEST FILE"); - mount_flag = 1; + SAFE_MOUNT(mntpoint_src, mntpoint_dst, tst_device->fs_type, MS_MOVE, NULL); - SAFE_MOUNT(cleanup, "none", path_name, "none", MS_PRIVATE, NULL); + TST_EXP_FAIL( + access(tstfiles_src, F_OK), + ENOENT, + "File %s doesn't exist", + tstfiles_src); - snprintf(mntpoint_src, PATH_MAX, "%s/%s", path_name, MNTPOINT_SRC); - snprintf(mntpoint_des, PATH_MAX, "%s/%s", path_name, MNTPOINT_DES); + TST_EXP_PASS( + access(tstfiles_dst, F_OK), + "File %s exists :", + tstfiles_dst); - SAFE_MKDIR(cleanup, mntpoint_src, DIR_MODE); - SAFE_MKDIR(cleanup, mntpoint_des, DIR_MODE); + if (tst_is_mounted(mntpoint_src)) + SAFE_UMOUNT(mntpoint_src); - TEST_PAUSE; + if (tst_is_mounted(mntpoint_dst)) + SAFE_UMOUNT(mntpoint_dst); } -static void cleanup(void) -{ - if (mount_flag && tst_umount(path_name) != 0) - tst_resm(TWARN | TERRNO, "umount(2) %s failed", path_name); - - if (device) - tst_release_device(device); - - tst_rmdir(); -} +static struct tst_test test = { + .setup = setup, + .cleanup = cleanup, + .test_all = run, + .needs_root = 1, + .format_device = 1, + .mntpoint = MNTPOINT_SRC, + .all_filesystems = 1, + .skip_filesystems = (const char *const []){ + "exfat", + "vfat", + "ntfs", + NULL + }, +}; diff --git a/testcases/kernel/syscalls/mremap/mremap06.c b/testcases/kernel/syscalls/mremap/mremap06.c index a19262750..3bbaf441a 100644 --- a/testcases/kernel/syscalls/mremap/mremap06.c +++ b/testcases/kernel/syscalls/mremap/mremap06.c @@ -18,15 +18,16 @@ #include <stdio.h> #include <fcntl.h> #include <sys/mman.h> +#include <lapi/mmap.h> #include "tst_test.h" #include "tst_safe_macros.h" -#define NUM_PAGES 3 +#define NUM_GRANULARITYS 3 static int fd; static char *buf, *buf2; -static int page_size, mmap_size, mremap_size; +static int mmap_size, mremap_size; static struct tcase { size_t incompatible; @@ -37,11 +38,11 @@ static struct tcase { }, { .incompatible = 3, - .desc = "third page's mapping incompatible", + .desc = "third MMAP_GRANULARITY's mapping incompatible", }, { .incompatible = 1, - .desc = "first page's mapping incompatible", + .desc = "first MMAP_GRANULARITY's mapping incompatible", }, }; @@ -51,7 +52,7 @@ static int check_pages(void) char val; for (i = 0; i < (int)ARRAY_SIZE(tcases); i++) { - val = buf[i * page_size]; + val = buf[i * MMAP_GRANULARITY]; if (val != 0x30 + i) { tst_res(TFAIL, "page %d wrong value %d (0x%x)", i, val - 0x30, val); fail = 1; @@ -70,19 +71,20 @@ static void do_test(unsigned int n) buf = SAFE_MMAP(0, mmap_size, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0); - buf2 = mremap(buf + page_size, page_size, page_size, + buf2 = mremap(buf + MMAP_GRANULARITY, MMAP_GRANULARITY, MMAP_GRANULARITY, MREMAP_MAYMOVE|MREMAP_FIXED, buf + mremap_size); if (buf2 == MAP_FAILED) tst_brk(TBROK, "mremap() failed"); if (tc->incompatible) { - ret = mprotect(buf + (tc->incompatible-1)*page_size, page_size, PROT_READ); + ret = mprotect(buf + (tc->incompatible-1)*MMAP_GRANULARITY, + MMAP_GRANULARITY, PROT_READ); if (ret == -1) tst_brk(TBROK, "mprotect() failed"); } - buf2 = mremap(buf + mremap_size, page_size, page_size, - MREMAP_MAYMOVE|MREMAP_FIXED, buf + page_size); + buf2 = mremap(buf + mremap_size, MMAP_GRANULARITY, MMAP_GRANULARITY, + MREMAP_MAYMOVE|MREMAP_FIXED, buf + MMAP_GRANULARITY); if (buf2 == MAP_FAILED) tst_brk(TBROK, "mremap() failed"); @@ -96,9 +98,8 @@ static void setup(void) { int ret, i; - page_size = getpagesize(); - mmap_size = (NUM_PAGES+1) * page_size; - mremap_size = NUM_PAGES * page_size; + mmap_size = (NUM_GRANULARITYS+1) * MMAP_GRANULARITY; + mremap_size = NUM_GRANULARITYS * MMAP_GRANULARITY; fd = SAFE_OPEN("testfile", O_CREAT | O_RDWR | O_TRUNC, 0600); @@ -109,7 +110,7 @@ static void setup(void) buf = SAFE_MMAP(0, mmap_size, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0); for (i = 0; i < (int)ARRAY_SIZE(tcases)+1; i++) - buf[i*page_size] = 0x30 + i; + buf[i*MMAP_GRANULARITY] = 0x30 + i; /* clear the page tables */ SAFE_MUNMAP(buf, mmap_size); diff --git a/testcases/kernel/syscalls/open/open11.c b/testcases/kernel/syscalls/open/open11.c index 3c3c11b84..3431efc2c 100644 --- a/testcases/kernel/syscalls/open/open11.c +++ b/testcases/kernel/syscalls/open/open11.c @@ -1,28 +1,34 @@ // SPDX-License-Identifier: GPL-2.0-or-later /* * Copyright (C) 2013 Red Hat, Inc. + * Copyright (c) Linux Test Project, 2013-2022 + */ + +/*\ + * [Description] * * Basic tests for open(2) and make sure open(2) works and handles error * conditions correctly. * * There are 28 test cases: + * * 1. Open regular file O_RDONLY * 2. Open regular file O_WRONLY * 3. Open regular file O_RDWR * 4. Open regular file O_RDWR | O_SYNC * 5. Open regular file O_RDWR | O_TRUNC - * 6. Open dir O_RDONLY - * 7. Open dir O_RDWR, expect EISDIR + * 6. Open directory O_RDONLY + * 7. Open directory O_RDWR, expect EISDIR * 8. Open regular file O_DIRECTORY, expect ENOTDIR * 9. Open hard link file O_RDONLY * 10. Open hard link file O_WRONLY * 11. Open hard link file O_RDWR - * 12. Open sym link file O_RDONLY - * 13. Open sym link file O_WRONLY - * 14. Open sym link file O_RDWR - * 15. Open sym link dir O_RDONLY - * 16. Open sym link dir O_WRONLY, expect EISDIR - * 17. Open sym link dir O_RDWR, expect EISDIR + * 12. Open symlink file O_RDONLY + * 13. Open symlink file O_WRONLY + * 14. Open symlink file O_RDWR + * 15. Open symlink directory O_RDONLY + * 16. Open symlink directory O_WRONLY, expect EISDIR + * 17. Open symlink directory O_RDWR, expect EISDIR * 18. Open device special file O_RDONLY * 19. Open device special file O_WRONLY * 20. Open device special file O_RDWR @@ -30,8 +36,8 @@ * 22. Open link file O_RDONLY | O_CREAT * 23. Open symlink file O_RDONLY | O_CREAT * 24. Open regular file O_RDONLY | O_CREAT - * 25. Open symlink dir O_RDONLY | O_CREAT, expect EISDIR - * 26. Open dir O_RDONLY | O_CREAT, expect EISDIR + * 25. Open symlink directory O_RDONLY | O_CREAT, expect EISDIR + * 26. Open directory O_RDONLY | O_CREAT, expect EISDIR * 27. Open regular file O_RDONLY | O_TRUNC, behaviour is undefined but should * not oops or hang * 28. Open regular file(non-empty) O_RDONLY | O_TRUNC, behaviour is undefined @@ -54,7 +60,7 @@ #define T_LINK_REG "t_link_reg" /* hard link to T_REG */ #define T_NEW_REG "t_new_reg" /* new regular file to be created */ #define T_SYMLINK_REG "t_symlink_reg" /* symlink to T_REG */ -#define T_DIR "t_dir" /* test dir */ +#define T_DIR "t_dir" /* test directory */ #define T_SYMLINK_DIR "t_symlink_dir" /* symlink to T_DIR */ #define T_DEV MNTPOINT"/t_dev" /* test device special file */ @@ -68,205 +74,191 @@ static struct test_case { int err; } tc[] = { /* Test open(2) regular file */ - { /* open regular file O_RDONLY */ - .desc = "Open regular file O_RDONLY", + { + .desc = "open regular file O_RDONLY", .path = T_REG_EMPTY, .flags = O_RDONLY, .mode = 0644, - .err = 0, }, - { /* open regular file O_WRONLY */ - .desc = "Open regular file O_WRONLY", + { + .desc = "open regular file O_WRONLY", .path = T_REG_EMPTY, .flags = O_WRONLY, .mode = 0644, - .err = 0, }, - { /* open regular file O_RDWR */ - .desc = "Open regular file O_RDWR", + { + .desc = "open regular file O_RDWR", .path = T_REG_EMPTY, .flags = O_RDWR, .mode = 0644, - .err = 0, }, - { /* open regular file O_RDWR | O_SYNC*/ - .desc = "Open regular file O_RDWR | O_SYNC", + { + .desc = "open regular file O_RDWR | O_SYNC", .path = T_REG_EMPTY, .flags = O_RDWR | O_SYNC, .mode = 0644, - .err = 0, }, - { /* open regular file O_RDWR | O_TRUNC */ - .desc = "Open regular file O_RDWR | O_TRUNC", + { + .desc = "open regular file O_RDWR | O_TRUNC", .path = T_REG_EMPTY, .flags = O_RDWR | O_TRUNC, .mode = 0644, - .err = 0, }, + /* Test open(2) directory */ - { /* open dir O_RDONLY */ - .desc = "Open dir O_RDONLY", + { + .desc = "open directory O_RDONLY", .path = T_DIR, .flags = O_RDONLY, .mode = 0755, - .err = 0, }, - { /* open dir O_RDWR */ - .desc = "Open dir O_RDWR, expect EISDIR", + { + .desc = "open directory O_RDWR", .path = T_DIR, .flags = O_RDWR, .mode = 0755, .err = EISDIR, }, - { /* open regular file O_DIRECTORY */ - .desc = "Open regular file O_DIRECTORY, expect ENOTDIR", + { + .desc = "open regular file O_DIRECTORY", .path = T_REG_EMPTY, .flags = O_RDONLY | O_DIRECTORY, .mode = 0644, .err = ENOTDIR, }, /* Test open(2) hard link */ - { /* open hard link file O_RDONLY */ - .desc = "Open hard link file O_RDONLY", + { + .desc = "open hard link file O_RDONLY", .path = T_LINK_REG, .flags = O_RDONLY, .mode = 0644, - .err = 0, }, - { /* open hard link file O_WRONLY */ - .desc = "Open hard link file O_WRONLY", + { + .desc = "open hard link file O_WRONLY", .path = T_LINK_REG, .flags = O_WRONLY, .mode = 0644, - .err = 0, }, - { /* open hard link file O_RDWR */ - .desc = "Open hard link file O_RDWR", + { + .desc = "open hard link file O_RDWR", .path = T_LINK_REG, .flags = O_RDWR, .mode = 0644, - .err = 0, }, - /* Test open(2) sym link */ - { /* open sym link file O_RDONLY */ - .desc = "Open sym link file O_RDONLY", + + /* Test open(2) symlink */ + { + .desc = "open symlink file O_RDONLY", .path = T_SYMLINK_REG, .flags = O_RDONLY, .mode = 0644, - .err = 0, }, - { /* open sym link file O_WRONLY */ - .desc = "Open sym link file O_WRONLY", + { + .desc = "open symlink file O_WRONLY", .path = T_SYMLINK_REG, .flags = O_WRONLY, .mode = 0644, - .err = 0, }, - { /* open sym link file O_RDWR */ - .desc = "Open sym link file O_RDWR", + { + .desc = "open symlink file O_RDWR", .path = T_SYMLINK_REG, .flags = O_RDWR, .mode = 0644, - .err = 0, }, - { /* open sym link dir O_RDONLY */ - .desc = "Open sym link dir O_RDONLY", + { + .desc = "open symlink directory O_RDONLY", .path = T_SYMLINK_DIR, .flags = O_RDONLY, .mode = 0644, - .err = 0, }, - { /* open sym link dir O_WRONLY */ - .desc = "Open sym link dir O_WRONLY, expect EISDIR", + { + .desc = "open symlink directory O_WRONLY", .path = T_SYMLINK_DIR, .flags = O_WRONLY, .mode = 0644, .err = EISDIR, }, - { /* open sym link dir O_RDWR */ - .desc = "Open sym link dir O_RDWR, expect EISDIR", + { + .desc = "open symlink directory O_RDWR", .path = T_SYMLINK_DIR, .flags = O_RDWR, .mode = 0644, .err = EISDIR, }, - /* * Test open(2) device special */ - { /* open device special file O_RDONLY */ - .desc = "Open device special file O_RDONLY", + + /* Test open(2) device special */ + { + .desc = "open device special file O_RDONLY", .path = T_DEV, .flags = O_RDONLY, .mode = 0644, - .err = 0, }, - { /* open device special file O_WRONLY */ - .desc = "Open device special file O_WRONLY", + { + .desc = "open device special file O_WRONLY", .path = T_DEV, .flags = O_WRONLY, .mode = 0644, - .err = 0, }, - { /* open device special file O_RDWR */ - .desc = "Open device special file O_RDWR", + { + .desc = "open device special file O_RDWR", .path = T_DEV, .flags = O_RDWR, .mode = 0644, - .err = 0, }, - /* * Test open(2) non-existing file */ - { /* open non-existing regular file in existing dir */ - .desc = "Open non-existing regular file in existing dir", + + /* Test open(2) non-existing file */ + { + .desc = "open non-existing regular file in existing dir", .path = T_DIR"/"T_NEW_REG, .flags = O_RDWR | O_CREAT, .mode = 0644, - .err = 0, }, + /* test open(2) with O_CREAT */ - { /* open hard link file O_RDONLY | O_CREAT */ - .desc = "Open link file O_RDONLY | O_CREAT", + { + .desc = "open link file O_RDONLY | O_CREAT", .path = T_LINK_REG, .flags = O_RDONLY | O_CREAT, .mode = 0644, - .err = 0, }, - { /* open sym link file O_RDONLY | O_CREAT */ - .desc = "Open symlink file O_RDONLY | O_CREAT", + { + .desc = "open symlink file O_RDONLY | O_CREAT", .path = T_SYMLINK_REG, .flags = O_RDONLY | O_CREAT, .mode = 0644, - .err = 0, }, - { /* open regular file O_RDONLY | O_CREAT */ - .desc = "Open regular file O_RDONLY | O_CREAT", + { + .desc = "open regular file O_RDONLY | O_CREAT", .path = T_REG_EMPTY, .flags = O_RDONLY | O_CREAT, .mode = 0644, - .err = 0, }, - { /* open symlink dir O_RDONLY | O_CREAT */ - .desc = "Open symlink dir O_RDONLY | O_CREAT, expect EISDIR", + { + .desc = "open symlink directory O_RDONLY | O_CREAT", .path = T_SYMLINK_DIR, .flags = O_RDONLY | O_CREAT, .mode = 0644, .err = EISDIR, }, - { /* open dir O_RDONLY | O_CREAT */ - .desc = "Open dir O_RDONLY | O_CREAT, expect EISDIR", + { + .desc = "open directory O_RDONLY | O_CREAT", .path = T_DIR, .flags = O_RDONLY | O_CREAT, .mode = 0644, .err = EISDIR, }, + /* Other random open(2) tests */ - { /* open regular file O_RDONLY | O_TRUNC */ - .desc = "Open regular file O_RDONLY | O_TRUNC, " + { + .desc = "open regular file O_RDONLY | O_TRUNC, " "behaviour is undefined but should not oops or hang", .path = T_REG_EMPTY, .flags = O_RDONLY | O_TRUNC, .mode = 0644, .err = -1, }, - { /* open regular(non-empty) file O_RDONLY | O_TRUNC */ - .desc = "Open regular file(non-empty) O_RDONLY | O_TRUNC, " + { + .desc = "open regular file(non-empty) O_RDONLY | O_TRUNC, " "behaviour is undefined but should not oops or hang", .path = T_REG, .flags = O_RDONLY | O_TRUNC, diff --git a/testcases/kernel/syscalls/pathconf/.gitignore b/testcases/kernel/syscalls/pathconf/.gitignore index 31abe8a28..82e38b253 100644 --- a/testcases/kernel/syscalls/pathconf/.gitignore +++ b/testcases/kernel/syscalls/pathconf/.gitignore @@ -1 +1,2 @@ /pathconf01 +/pathconf02 diff --git a/testcases/kernel/syscalls/pathconf/pathconf01.c b/testcases/kernel/syscalls/pathconf/pathconf01.c index 362bae94f..66b8d1fc1 100644 --- a/testcases/kernel/syscalls/pathconf/pathconf01.c +++ b/testcases/kernel/syscalls/pathconf/pathconf01.c @@ -1,237 +1,68 @@ +// SPDX-License-Identifier: GPL-2.0-only /* * Copyright (c) 2000 Silicon Graphics, Inc. All Rights Reserved. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it would be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * - * Further, this software is distributed without any warranty that it is - * free of the rightful claim of any third person regarding infringement - * or the like. Any license provided herein, whether implied or - * otherwise, applies only to this software file. Patent licenses, if - * any, provided herein do not apply to combinations of this program with - * other software, or any other product whatsoever. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy, - * Mountain View, CA 94043, or: - * - * http://www.sgi.com - * - * For further information regarding this notice, see: - * - * http://oss.sgi.com/projects/GenInfo/NoticeExplan/ - * + * Copyright (c) Linux Test Project, 2000-2023 + * Authors: William Roske, Dave Fenner */ -/* $Id: pathconf01.c,v 1.5 2009/11/02 13:57:17 subrata_modak Exp $ */ -/********************************************************** - * - * OS Test - Silicon Graphics, Inc. - * - * TEST IDENTIFIER : pathconf01 - * - * EXECUTED BY : anyone - * - * TEST TITLE : Basic test for pathconf(2) - * - * PARENT DOCUMENT : usctpl01 - * - * TEST CASE TOTAL : 6 - * - * WALL CLOCK TIME : 1 - * - * CPU TYPES : ALL - * - * AUTHOR : William Roske - * - * CO-PILOT : Dave Fenner - * - * DATE STARTED : 03/30/92 - * - * INITIAL RELEASE : UNICOS 7.0 - * - * TEST CASES - * - * 1.) pathconf(2) returns...(See Description) - * - * INPUT SPECIFICATIONS - * The standard options for system call tests are accepted. - * (See the parse_opts(3) man page). - * - * OUTPUT SPECIFICATIONS - * - * DURATION - * Terminates - with frequency and infinite modes. - * - * SIGNALS - * Uses SIGUSR1 to pause before test if option set. - * (See the parse_opts(3) man page). - * - * RESOURCES - * None - * - * ENVIRONMENTAL NEEDS - * No run-time environmental needs. - * - * SPECIAL PROCEDURAL REQUIREMENTS - * None - * - * INTERCASE DEPENDENCIES - * None - * - * DETAILED DESCRIPTION - * This is a Phase I test for the pathconf(2) system call. It is intended - * to provide a limited exposure of the system call, for now. It - * should/will be extended when full functional tests are written for - * pathconf(2). - * - * Setup: - * Setup signal handling. - * Pause for SIGUSR1 if option specified. - * - * Test: - * Loop if the proper options are given. - * Execute system call - * Check return code, if system call failed (return=-1) - * Log the errno and Issue a FAIL message. - * Otherwise, Issue a PASS message. - * - * Cleanup: - * Print errno log and/or timing stats if options given - * - * - *#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#**/ - -#include <unistd.h> -#include <errno.h> -#include <string.h> -#include <signal.h> -#include "test.h" -void setup(); -void cleanup(); -void help(); - -struct pathconf_args { - char *define_tag; - int value; -} args[] = { - { - "_PC_LINK_MAX", _PC_LINK_MAX}, { - "_PC_NAME_MAX", _PC_NAME_MAX}, { - "_PC_PATH_MAX", _PC_PATH_MAX}, { - "_PC_PIPE_BUF", _PC_PIPE_BUF}, { - "_PC_CHOWN_RESTRICTED", _PC_CHOWN_RESTRICTED}, { - "_PC_NO_TRUNC", _PC_NO_TRUNC}, { - NULL, 0} -}; - -char *TCID = "pathconf01"; -int TST_TOTAL = ARRAY_SIZE(args); +/*\ + * [Description] + * + * Check the basic functionality of the pathconf(2) system call. + */ -int i; +#include <stdlib.h> +#include "tst_test.h" +#define NAME_DESC(x) .value = x, .name = #x -int lflag; -char *path; +static char *path; -option_t options[] = { - {"l:", &lflag, &path}, /* -l <path to test> */ - {NULL, NULL, NULL} +static struct tcase { + int value; + char *name; +} tcases[] = { + {NAME_DESC(_PC_LINK_MAX)}, + {NAME_DESC(_PC_MAX_CANON)}, + {NAME_DESC(_PC_MAX_INPUT)}, + {NAME_DESC(_PC_NAME_MAX)}, + {NAME_DESC(_PC_PATH_MAX)}, + {NAME_DESC(_PC_PIPE_BUF)}, + {NAME_DESC(_PC_CHOWN_RESTRICTED)}, + {NAME_DESC(_PC_NO_TRUNC)}, + {NAME_DESC(_PC_VDISABLE)}, + {NAME_DESC(_PC_SYNC_IO)}, + {NAME_DESC(_PC_ASYNC_IO)}, + {NAME_DESC(_PC_PRIO_IO)}, + {NAME_DESC(_PC_FILESIZEBITS)}, + {NAME_DESC(_PC_REC_INCR_XFER_SIZE)}, + {NAME_DESC(_PC_REC_MAX_XFER_SIZE)}, + {NAME_DESC(_PC_REC_MIN_XFER_SIZE)}, + {NAME_DESC(_PC_REC_XFER_ALIGN)}, }; -int main(int ac, char **av) +static void verify_pathconf(unsigned int i) { - int lc; + struct tcase *tc = &tcases[i]; - tst_parse_opts(ac, av, options, &help); + path = tst_get_tmpdir(); - if (!lflag) { - tst_tmpdir(); - path = tst_get_tmpdir(); - } - /*************************************************************** - * perform global setup for test - ***************************************************************/ - setup(); + TEST(pathconf(path, tc->value)); - /*************************************************************** - * check looping state if -c option given - ***************************************************************/ - for (lc = 0; TEST_LOOPING(lc); lc++) { - - tst_count = 0; - - for (i = 0; i < TST_TOTAL; i++) { - - errno = -4; - - /* - * Call pathconf(2) - */ - TEST(pathconf(path, args[i].value)); - - /* - * A test case can only fail if -1 is returned and the errno - * was set. If the errno remains unchanged, the - * system call did not fail. - */ - if (TEST_RETURN == -1 && errno != -4) { - tst_resm(TFAIL, - "pathconf(%s, %s) Failed, errno=%d : %s", - path, args[i].define_tag, TEST_ERRNO, - strerror(TEST_ERRNO)); - } else { - tst_resm(TPASS, - "pathconf(%s, %s) returned %ld", - path, args[i].define_tag, - TEST_RETURN); - } - } - } - - /*************************************************************** - * cleanup and exit - ***************************************************************/ - cleanup(); - - tst_exit(); + if (TST_RET == -1 && errno != 0) + tst_res(TFAIL, "pathconf Failed, errno = %d", TST_ERR); + else + tst_res(TPASS, "pathconf(%s, %s)", path, tc->name); } -/*************************************************************** - * setup() - performs all ONE TIME setup for this test. - ***************************************************************/ -void setup(void) +static void cleanup(void) { - - tst_sig(NOFORK, DEF_HANDLER, cleanup); - - TEST_PAUSE; -} - -/*************************************************************** - * cleanup() - performs all ONE TIME cleanup for this test at - * completion or premature exit. - ***************************************************************/ -void cleanup(void) -{ - if (!lflag) { - tst_rmdir(); - free(path); - } + free(path); } -/*************************************************************** - * help - ***************************************************************/ -void help(void) -{ - printf(" -l path a path to test with pathconf(2) (def: /tmp)\n"); -} +static struct tst_test test = { + .needs_tmpdir = 1, + .test = verify_pathconf, + .tcnt = ARRAY_SIZE(tcases), + .cleanup = cleanup, +}; diff --git a/testcases/kernel/syscalls/pathconf/pathconf02.c b/testcases/kernel/syscalls/pathconf/pathconf02.c new file mode 100644 index 000000000..3fb2cdbe8 --- /dev/null +++ b/testcases/kernel/syscalls/pathconf/pathconf02.c @@ -0,0 +1,98 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * Copyright (c) 2023 FUJITSU LIMITED. All rights reserved. + * Author: Yang Xu <xuyang2018.jy@cn.fujitsu.com> + */ + +/*\ + * [Description] + * + * Verify that, + * + * - pathconf() fails with ENOTDIR if a component used as a directory + * in path is not in fact a directory. + * - pathconf() fails with ENOENT if path is an empty string. + * - pathconf() fails with ENAMETOOLONG if path is too long. + * - pathconf() fails with EINVA if name is invalid. + * - pathconf() fails with EACCES if search permission is denied for + * one of the directories in the path prefix of path. + * - pathconf() fails with ELOOP if too many symbolic links were + * encountered while resolving path. + */ + +#define FILEPATH "testfile/testfile_1" +#define TESTELOOP "test_eloop1" +#define PATH_LEN (PATH_MAX + 2) + +#include <stdlib.h> +#include <pwd.h> +#include "tst_test.h" + +static char *fpath; +static char *emptypath; +static char path[PATH_LEN]; +static char *long_path = path; +static char *abs_path; +static char *testeloop; +static struct passwd *user; + +static struct tcase { + char **path; + int name; + int exp_errno; + char *desc; +} tcases[] = { + {&fpath, 0, ENOTDIR, "path prefix is not a directory"}, + {&emptypath, 0, ENOENT, "path is an empty string"}, + {&long_path, 0, ENAMETOOLONG, "path is too long"}, + {&abs_path, -1, EINVAL, "name is invalid"}, + {&abs_path, 0, EACCES, "without full permissions of the path prefix"}, + {&testeloop, 0, ELOOP, "too many symbolic links"}, +}; + +static void verify_fpathconf(unsigned int i) +{ + struct tcase *tc = &tcases[i]; + + if (tc->exp_errno == EACCES) + SAFE_SETEUID(user->pw_uid); + + TST_EXP_FAIL(pathconf(*tc->path, tc->name), tc->exp_errno, + "pathconf() fail with %s", tc->desc); + + if (tc->exp_errno == EACCES) + SAFE_SETEUID(0); +} + +static void setup(void) +{ + user = SAFE_GETPWNAM("nobody"); + + SAFE_TOUCH("testfile", 0777, NULL); + + char *tmpdir = tst_get_tmpdir(); + + abs_path = tst_aprintf("%s/%s", tmpdir, FILEPATH); + + SAFE_CHMOD(tmpdir, 0); + free(tmpdir); + + memset(path, 'a', PATH_LEN); + + SAFE_SYMLINK("test_eloop1", "test_eloop2"); + SAFE_SYMLINK("test_eloop2", "test_eloop1"); +} + +static struct tst_test test = { + .tcnt = ARRAY_SIZE(tcases), + .test = verify_fpathconf, + .setup = setup, + .needs_tmpdir = 1, + .bufs = (struct tst_buffers []) { + {&fpath, .str = FILEPATH}, + {&emptypath, .str = ""}, + {&testeloop, .str = TESTELOOP}, + {}, + }, + .needs_root = 1, +}; diff --git a/testcases/kernel/syscalls/pipe/.gitignore b/testcases/kernel/syscalls/pipe/.gitignore index 774d73205..581a68b78 100644 --- a/testcases/kernel/syscalls/pipe/.gitignore +++ b/testcases/kernel/syscalls/pipe/.gitignore @@ -12,3 +12,4 @@ /pipe12 /pipe13 /pipe14 +/pipe15 diff --git a/testcases/kernel/syscalls/pipe/pipe15.c b/testcases/kernel/syscalls/pipe/pipe15.c new file mode 100644 index 000000000..c85ad1820 --- /dev/null +++ b/testcases/kernel/syscalls/pipe/pipe15.c @@ -0,0 +1,94 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * Copyright (c) 2023 SUSE LLC Marius Kittler <mkittler@suse.de> + */ + +/*\ + * [Description] + * + * This is a regression test for hangup on pipe operations. See + * https://www.spinics.net/lists/linux-api/msg49762.html for + * additional context. It tests that pipe operations do not block + * indefinitely when going to the soft limit on the total size of + * all pipes created by a single user. + */ + +#define _GNU_SOURCE +#include <fcntl.h> +#include <stdlib.h> +#include <unistd.h> + +#include "tst_test.h" +#include "tst_safe_stdio.h" +#include "tst_safe_macros.h" + +static int pipe_count; +static int *pipes; +static char *buffer; + +static void run(void) +{ + const int *const pipe = pipes + 2 * (pipe_count - 1); + const int buffer_size = SAFE_FCNTL(pipe[1], F_GETPIPE_SZ); + + tst_res(TINFO, "Soft-limited buffer size: %d bytes", buffer_size); + SAFE_WRITE(1, pipe[1], buffer, buffer_size); + SAFE_READ(1, pipe[0], buffer, buffer_size - 1); + SAFE_WRITE(1, pipe[1], buffer, 1); + tst_res(TPASS, "Pipe operation did not block"); + + SAFE_READ(1, pipe[0], buffer, 2); +} + +static void setup(void) +{ + int pipe[2]; + int page_size = getpagesize(), soft_limit; + struct rlimit nfd; + + SAFE_PIPE(pipe); + const int buffer_size = SAFE_FCNTL(pipe[1], F_GETPIPE_SZ); + SAFE_CLOSE(pipe[0]); + SAFE_CLOSE(pipe[1]); + + SAFE_FILE_SCANF("/proc/sys/fs/pipe-user-pages-soft", "%i", &soft_limit); + pipe_count = soft_limit * page_size / buffer_size; + + tst_res(TINFO, "Soft limit for pipes: %i pages", soft_limit); + tst_res(TINFO, "Buffer size: %d byte", buffer_size); + tst_res(TINFO, "Creating %i pipes", pipe_count); + + SAFE_GETRLIMIT(RLIMIT_NOFILE, &nfd); + if (nfd.rlim_max < (unsigned long)pipe_count) + tst_brk(TCONF, "NOFILE limit max too low: %lu < %i", nfd.rlim_max, pipe_count); + if (nfd.rlim_cur < nfd.rlim_max) { + nfd.rlim_cur = nfd.rlim_max; + SAFE_SETRLIMIT(RLIMIT_NOFILE, &nfd); + } + + buffer = SAFE_MALLOC(buffer_size); + pipes = SAFE_MALLOC(pipe_count * 2 * sizeof(int)); + for (int i = 0; i < pipe_count; ++i) + SAFE_PIPE(pipes + i * 2); + +} + +static void cleanup(void) +{ + for (int i = 0; i < pipe_count * 2; i++) + if (pipes[i] > 0) + SAFE_CLOSE(pipes[i]); + if (pipes) + free(pipes); + if (buffer) + free(buffer); +} + +static struct tst_test test = { + .setup = setup, + .test_all = run, + .cleanup = cleanup, + .tags = (const struct tst_tag[]){ + {"linux-git", "46c4c9d1beb7"}, + }, +}; diff --git a/testcases/kernel/syscalls/preadv/preadv.h b/testcases/kernel/syscalls/preadv/preadv.h index 73466a9aa..c715715b1 100644 --- a/testcases/kernel/syscalls/preadv/preadv.h +++ b/testcases/kernel/syscalls/preadv/preadv.h @@ -1,18 +1,9 @@ -/* -* Copyright (c) 2015 Fujitsu Ltd. -* Author: Xiao Yang <yangx.jy@cn.fujitsu.com> -* -* This program is free software; you can redistribute it and/or modify it -* under the terms of version 2 of the GNU General Public License as -* published by the Free Software Foundation. -* -* This program is distributed in the hope that it would be useful, but -* WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. -* -* You should have received a copy of the GNU General Public License -* alone with this program. -*/ +/* SPDX-License-Identifier: GPL-2.0-or-later + * + * Copyright (c) 2015 Fujitsu Ltd. + * Author: Xiao Yang <yangx.jy@cn.fujitsu.com> + * Copyright (c) Linux Test Project, 2016-2023 + */ #ifndef PREADV_H #define PREADV_H diff --git a/testcases/kernel/syscalls/preadv/preadv01.c b/testcases/kernel/syscalls/preadv/preadv01.c index 62f9296f2..871b3ab42 100644 --- a/testcases/kernel/syscalls/preadv/preadv01.c +++ b/testcases/kernel/syscalls/preadv/preadv01.c @@ -1,17 +1,18 @@ // SPDX-License-Identifier: GPL-2.0-or-later /* -* Copyright (c) 2015 Fujitsu Ltd. -* Author: Xiao Yang <yangx.jy@cn.fujitsu.com> -*/ - -/* -* Test Name: preadv01 -* -* Test Description: -* Testcase to check the basic functionality of the preadv(2). -* Preadv(2) should succeed to read the expected content of data -* and after reading the file, the file offset is not changed. -*/ + * Copyright (c) 2015 Fujitsu Ltd. + * Author: Xiao Yang <yangx.jy@cn.fujitsu.com> + * Copyright (c) Linux Test Project, 2016-2023 + */ + +/*\ + * [Description] + * + * Testcase to check the basic functionality of the preadv(2). + * + * Preadv(2) should succeed to read the expected content of data + * and after reading the file, the file offset is not changed. + */ #define _GNU_SOURCE @@ -38,7 +39,7 @@ static struct tcase { {1, CHUNK*3/2, CHUNK/2, 'b'} }; -void verify_preadv(unsigned int n) +static void verify_preadv(unsigned int n) { int i; char *vec; @@ -81,7 +82,7 @@ void verify_preadv(unsigned int n) "with content '%c' expectedly", tc->size, tc->content); } -void setup(void) +static void setup(void) { char buf[CHUNK]; @@ -94,7 +95,7 @@ void setup(void) SAFE_WRITE(SAFE_WRITE_ALL, fd, buf, sizeof(buf)); } -void cleanup(void) +static void cleanup(void) { if (fd > 0) SAFE_CLOSE(fd); diff --git a/testcases/kernel/syscalls/preadv/preadv02.c b/testcases/kernel/syscalls/preadv/preadv02.c index 500059e42..9977a4f48 100644 --- a/testcases/kernel/syscalls/preadv/preadv02.c +++ b/testcases/kernel/syscalls/preadv/preadv02.c @@ -1,32 +1,22 @@ // SPDX-License-Identifier: GPL-2.0-or-later /* -* Copyright (c) 2015-2016 Fujitsu Ltd. -* Author: Xiao Yang <yangx.jy@cn.fujitsu.com> -*/ - -/* -* Test Name: preadv02 -* -* Description: -* 1) preadv(2) fails if iov_len is invalid. -* 2) preadv(2) fails if the vector count iovcnt is less than zero. -* 3) preadv(2) fails if offset is negative. -* 4) preadv(2) fails when attempts to read into a invalid address. -* 5) preadv(2) fails if file descriptor is invalid. -* 6) preadv(2) fails if file descriptor is not open for reading. -* 7) preadv(2) fails when fd refers to a directory. -* 8) preadv(2) fails if fd is associated with a pipe. -* -* Expected Result: -* 1) preadv(2) should return -1 and set errno to EINVAL. -* 2) preadv(2) should return -1 and set errno to EINVAL. -* 3) preadv(2) should return -1 and set errno to EINVAL. -* 4) preadv(2) should return -1 and set errno to EFAULT. -* 5) preadv(2) should return -1 and set errno to EBADF. -* 6) preadv(2) should return -1 and set errno to EBADF. -* 7) preadv(2) should return -1 and set errno to EISDIR. -* 8) preadv(2) should return -1 and set errno to ESPIPE. -*/ + * Copyright (c) 2015-2016 Fujitsu Ltd. + * Author: Xiao Yang <yangx.jy@cn.fujitsu.com> + * Copyright (c) Linux Test Project, 2017-2023 + */ + +/*\ + * [Description] + * + * - EINVAL when iov_len is invalid. + * - EINVAL when the vector count iovcnt is less than zero. + * - EINVAL when offset is negative. + * - EFAULT when attempts to read into a invalid address. + * - EBADF when file descriptor is invalid. + * - EBADF when file descriptor is not open for reading. + * - EISDIR when fd refers to a directory. + * - ESPIPE when fd is associated with a pipe. + */ #define _GNU_SOURCE diff --git a/testcases/kernel/syscalls/preadv/preadv03.c b/testcases/kernel/syscalls/preadv/preadv03.c index d4595dda6..558d85050 100644 --- a/testcases/kernel/syscalls/preadv/preadv03.c +++ b/testcases/kernel/syscalls/preadv/preadv03.c @@ -2,12 +2,15 @@ /* * Copyright (c) 2018 FUJITSU LIMITED. All rights reserved. * Author: Xiao Yang <yangx.jy@cn.fujitsu.com> + * Copyright (c) Linux Test Project, 2019-2023 */ -/* - * Description: +/*\ + * [Description] + * * Check the basic functionality of the preadv(2) for the file * opened with O_DIRECT in all filesystem. + * * preadv(2) should succeed to read the expected content of data * and after reading the file, the file offset is not changed. */ diff --git a/testcases/kernel/syscalls/ptrace/.gitignore b/testcases/kernel/syscalls/ptrace/.gitignore index 01cbc6072..1ee6117e9 100644 --- a/testcases/kernel/syscalls/ptrace/.gitignore +++ b/testcases/kernel/syscalls/ptrace/.gitignore @@ -3,6 +3,7 @@ /ptrace03 /ptrace04 /ptrace05 +/ptrace06 /ptrace07 /ptrace08 /ptrace09 diff --git a/testcases/kernel/syscalls/ptrace/Makefile b/testcases/kernel/syscalls/ptrace/Makefile index 9ee7b8374..d7eca6837 100644 --- a/testcases/kernel/syscalls/ptrace/Makefile +++ b/testcases/kernel/syscalls/ptrace/Makefile @@ -1,34 +1,9 @@ # SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (c) Linux Test Project, 2002-2023 # Copyright (c) International Business Machines Corp., 2001 top_srcdir ?= ../../../.. include $(top_srcdir)/include/mk/testcases.mk -# - ptrace06 is a broken test ; it hangs the target consistently, chewing up -# CPU. See: `Issue 3 - ptrace06 hung for 7 hours' -- -# http://sourceforge.net/mailarchive/forum.php?thread_name=364299f40910062300s65c43c93w9cccdfe8835c2334%40mail.gmail.com&forum_name=ltp-list -# - simple_tracer is a utility that Mike Frysinger added that shouldn't be -# compiled by default: -# -# gcc -g -O2 -g -O2 -fno-strict-aliasing -pipe -Wall -# -I//scratch/ltp-install6/include -I../../../../include -# -L//scratch/ltp-install6/lib simple_tracer.c -laio -lltp -o -# simple_tracer -# In file included from simple_tracer.c:25: -# syscalls.h:6:23: error: _syscalls.h: No such file or directory -# make[4]: *** [simple_tracer] Error 1 -# make[4]: Leaving directory -# `/scratch/ltp-dev2/ltp/testcases/kernel/syscalls/ptrace' -# make[3]: *** [all] Error 2 -# make[3]: Leaving directory `/scratch/ltp-dev2/ltp/testcases/kernel/syscalls' -# make[2]: *** [all] Error 2 -# make[2]: Leaving directory `/scratch/ltp-dev2/ltp/testcases/kernel' -# make[1]: *** [all] Error 2 -# make[1]: Leaving directory `/scratch/ltp-dev2/ltp/testcases' -# make: *** [testcases-all] Error 2 -# - -FILTER_OUT_MAKE_TARGETS := ptrace06 simple_tracer - include $(top_srcdir)/include/mk/generic_leaf_target.mk diff --git a/testcases/kernel/syscalls/ptrace/make_syscall_list.sh b/testcases/kernel/syscalls/ptrace/make_syscall_list.sh deleted file mode 100755 index e5d6d2765..000000000 --- a/testcases/kernel/syscalls/ptrace/make_syscall_list.sh +++ /dev/null @@ -1,7 +0,0 @@ -#!/bin/sh -set -- $( \ - printf '#include <sys/syscall.h>' | \ - ${CC:-gcc} -E -dD - | \ - awk '$2 ~ /^SYS_/ { sub(/SYS_/,"",$2); print $2; }' -) -printf 'P(%s)\n' "$@" diff --git a/testcases/kernel/syscalls/ptrace/ptrace.h b/testcases/kernel/syscalls/ptrace/ptrace.h deleted file mode 100644 index 4a43f01ef..000000000 --- a/testcases/kernel/syscalls/ptrace/ptrace.h +++ /dev/null @@ -1,35 +0,0 @@ -/* - * ptrace is a fickle beast and each arch sucks in a different way - */ - -#ifndef __LTP_PTRACE_H__ -#define __LTP_PTRACE_H__ - -#ifdef HAVE_SYS_PTRACE_H -# include <sys/ptrace.h> -#endif -#ifdef HAVE_SYS_REG_H -# include <sys/reg.h> -#endif -#ifdef __ia64__ /* what a pos */ -# define ia64_fpreg FU_ia64_fpreg -# define pt_all_user_regs FU_pt_all_user_regs -#endif -#ifdef HAVE_ASM_PTRACE_H -# include <asm/ptrace.h> -#endif -#ifdef HAVE_LINUX_PTRACE_H -# ifndef HAVE_STRUCT_PTRACE_PEEKSIGINFO_ARGS -# include <linux/ptrace.h> -# endif -#endif -#undef FU_ia64_fpreg -#undef FU_pt_all_user_regs - -#if defined(HAVE_STRUCT_PT_REGS) -typedef struct pt_regs ptrace_regs; -#elif defined(HAVE_STRUCT_USER_REGS_STRUCT) -typedef struct user_regs_struct ptrace_regs; -#endif - -#endif diff --git a/testcases/kernel/syscalls/ptrace/ptrace01.c b/testcases/kernel/syscalls/ptrace/ptrace01.c index 9071bbaba..53ddfb393 100644 --- a/testcases/kernel/syscalls/ptrace/ptrace01.c +++ b/testcases/kernel/syscalls/ptrace/ptrace01.c @@ -26,8 +26,7 @@ #include <errno.h> #include <signal.h> #include <sys/wait.h> -#include <config.h> -#include "ptrace.h" +#include <sys/ptrace.h> #include "tst_test.h" static struct tcase { diff --git a/testcases/kernel/syscalls/ptrace/ptrace02.c b/testcases/kernel/syscalls/ptrace/ptrace02.c index e330f459e..a48ef58a5 100644 --- a/testcases/kernel/syscalls/ptrace/ptrace02.c +++ b/testcases/kernel/syscalls/ptrace/ptrace02.c @@ -11,9 +11,8 @@ #include <signal.h> #include <sys/wait.h> #include <pwd.h> -#include <config.h> #include <stdlib.h> -#include "ptrace.h" +#include <sys/ptrace.h> #include "tst_test.h" uid_t uid; diff --git a/testcases/kernel/syscalls/ptrace/ptrace03.c b/testcases/kernel/syscalls/ptrace/ptrace03.c index b2b3fb49d..42ac3e7cf 100644 --- a/testcases/kernel/syscalls/ptrace/ptrace03.c +++ b/testcases/kernel/syscalls/ptrace/ptrace03.c @@ -14,9 +14,8 @@ #include <signal.h> #include <sys/wait.h> #include <pwd.h> -#include <config.h> #include <stdlib.h> -#include "ptrace.h" +#include <sys/ptrace.h> #include "tst_test.h" static pid_t unused_pid; diff --git a/testcases/kernel/syscalls/ptrace/ptrace04.c b/testcases/kernel/syscalls/ptrace/ptrace04.c index af35fb3a2..8f1b5c6cc 100644 --- a/testcases/kernel/syscalls/ptrace/ptrace04.c +++ b/testcases/kernel/syscalls/ptrace/ptrace04.c @@ -13,9 +13,7 @@ #include <stdio.h> #include <stdlib.h> #include <unistd.h> - -#include <config.h> -#include "ptrace.h" +#include <sys/ptrace.h> #include "test.h" #include "spawn_ptrace_child.h" @@ -49,7 +47,7 @@ int TST_TOTAL = 2; void compare_registers(unsigned char poison) { -#ifdef HAVE_STRUCT_PTRACE_REGS +#if defined(HAVE_STRUCT_PTRACE_REGS) && defined(PTRACE_GETREGS) ptrace_regs _pt_regs; size_t i; long ret; diff --git a/testcases/kernel/syscalls/ptrace/ptrace05.c b/testcases/kernel/syscalls/ptrace/ptrace05.c index 54cfa4d7b..541018393 100644 --- a/testcases/kernel/syscalls/ptrace/ptrace05.c +++ b/testcases/kernel/syscalls/ptrace/ptrace05.c @@ -33,9 +33,7 @@ #include <stdio.h> #include <string.h> #include <unistd.h> - -#include <config.h> -#include "ptrace.h" +#include <sys/ptrace.h> #include "test.h" #include "lapi/signal.h" diff --git a/testcases/kernel/syscalls/ptrace/ptrace06.c b/testcases/kernel/syscalls/ptrace/ptrace06.c index c0cb3b9bd..a1db3bab8 100644 --- a/testcases/kernel/syscalls/ptrace/ptrace06.c +++ b/testcases/kernel/syscalls/ptrace/ptrace06.c @@ -16,13 +16,10 @@ #include <stdio.h> #include <stdlib.h> #include <unistd.h> - -#include <config.h> -#include "ptrace.h" +#include <sys/ptrace.h> #include "test.h" #include "spawn_ptrace_child.h" -#include "config.h" /* this should be sizeof(struct user), but that info is only found * in the kernel asm/user.h which is not exported to userspace. diff --git a/testcases/kernel/syscalls/ptrace/ptrace07.c b/testcases/kernel/syscalls/ptrace/ptrace07.c index 362cee543..a78243671 100644 --- a/testcases/kernel/syscalls/ptrace/ptrace07.c +++ b/testcases/kernel/syscalls/ptrace/ptrace07.c @@ -35,9 +35,8 @@ #include <stdlib.h> #include <sys/uio.h> #include <sys/wait.h> +#include <sys/ptrace.h> -#include "config.h" -#include "ptrace.h" #include "tst_safe_macros.h" #include "lapi/cpuid.h" diff --git a/testcases/kernel/syscalls/ptrace/ptrace11.c b/testcases/kernel/syscalls/ptrace/ptrace11.c index c54441671..90154852f 100644 --- a/testcases/kernel/syscalls/ptrace/ptrace11.c +++ b/testcases/kernel/syscalls/ptrace/ptrace11.c @@ -16,9 +16,8 @@ #include <signal.h> #include <sys/wait.h> #include <pwd.h> -#include <config.h> #include <stdlib.h> -#include "ptrace.h" +#include <sys/ptrace.h> #include "tst_test.h" static void verify_ptrace(void) diff --git a/testcases/kernel/syscalls/ptrace/simple_tracer.c b/testcases/kernel/syscalls/ptrace/simple_tracer.c deleted file mode 100644 index ae1af7c2f..000000000 --- a/testcases/kernel/syscalls/ptrace/simple_tracer.c +++ /dev/null @@ -1,144 +0,0 @@ -/* - * simple example ptrace() code to help build basis for other tests - * - * Copyright (c) 2009 Analog Devices Inc. - * - * Licensed under the GPL-2 or later - */ - -#define _GNU_SOURCE - -#include <config.h> - -#include <errno.h> -#include <stdbool.h> -#include <stdio.h> -#include <stdlib.h> -#include <unistd.h> -#include <sys/ptrace.h> -#include <sys/syscall.h> -#include "ptrace.h" - -#include "test.h" -#include "spawn_ptrace_child.h" - -#include "syscalls.h" - -char *TCID = "simple_tracer"; -int TST_TOTAL = 0; - -#define _decode(name, val) \ -({ \ - if (sizeof(long) == 4) \ - printf(name ":%08lx ", val); \ - else if (sizeof(long) == 8) \ - printf(name ":%016lx ", val); \ - else \ - printf(name ":%lx ", val); \ - val; \ -}) -#define decode(reg) _decode(#reg, pt->reg) -#define decode_user(name, offset) \ - _decode(name, vptrace(PTRACE_PEEKUSER, pid, offset, NULL)); -#define decode_sysnum(nr) printf("%s ", get_sysnum(nr)) -static void decode_regs(struct pt_regs *pt) -{ -#if defined(__bfin__) - long nr = decode_user("orig_p0", PT_ORIG_P0); - decode(p0); - decode(r0); - decode(r1); - decode(r2); - decode(r3); - decode(r4); - decode(r5); - decode_sysnum(nr); - puts(""); -#elif defined(__i386__) - long nr = decode_user("orig_eax", 4 * ORIG_EAX); - decode(eax); - decode(ebx); - decode(ecx); - decode(edx); - decode(esi); - decode(edi); - decode(ebp); - decode_sysnum(nr); - puts(""); -#elif defined(__x86_64__) - long nr = decode_user("orig_rax", 8 * ORIG_RAX); - decode(rax); - decode(rbx); - decode(rcx); - decode(rdx); - decode(rsi); - decode(rdi); - decode(rbp); - decode_sysnum(nr); - puts(""); -#elif defined(__sparc__) -#define G1 u_regs[0] -#define G2 u_regs[1] -#define G3 u_regs[2] -#define G4 u_regs[3] -#define G5 u_regs[4] -#define G6 u_regs[5] -#define G7 u_regs[6] -#define O0 u_regs[7] -#define O1 u_regs[8] -#define O2 u_regs[9] -#define O3 u_regs[10] -#define O4 u_regs[11] -#define O5 u_regs[12] -#define O6 u_regs[13] -#define O7 u_regs[14] - decode(G1); - decode(G2); - decode(G3); - decode(G4); - decode(G5); - decode(G6); - decode(G7); - decode(O0); - decode(O1); - decode(O2); - decode(O3); - decode(O4); - decode(O5); - decode(O6); - decode(O7); - decode_sysnum(pt->G1); - puts(""); -#else -#warning "no idea how to decode your arch" - puts("no idea how to decode your arch"); -#endif -} - -int main(int argc, char *argv[]) -{ - struct pt_regs pt_regs; - long ret; - int status; - - make_a_baby(argc, argv); - - while (1) { - ret = vptrace(PTRACE_GETREGS, pid, NULL, &pt_regs); - if (ret) - break; - decode_regs(&pt_regs); - - ret = vptrace(PTRACE_SYSCALL, pid, NULL, NULL); - if (ret) - break; - - if (waitpid(pid, &status, 0) == -1) - break; - } - - /* hopefully this worked */ - vptrace(PTRACE_KILL, pid, NULL, NULL); - - tst_exit(); -} diff --git a/testcases/kernel/syscalls/ptrace/syscalls.h b/testcases/kernel/syscalls/ptrace/syscalls.h deleted file mode 100644 index 2d9c5ceb6..000000000 --- a/testcases/kernel/syscalls/ptrace/syscalls.h +++ /dev/null @@ -1,17 +0,0 @@ -const struct sysnums { - long nr; - const char *snr; -} sysnums[] = { -#define P(NR) { .nr = SYS_##NR, .snr = #NR, }, -#include "_syscalls.h" -#undef P -}; - -const char *get_sysnum(long nr) -{ - int i; - for (i = 0; i < ARRAY_SIZE(sysnums); ++i) - if (sysnums[i].nr == nr) - break; - return i == ARRAY_SIZE(sysnums) ? "???" : sysnums[i].snr; -} diff --git a/testcases/kernel/syscalls/pwritev/pwritev.h b/testcases/kernel/syscalls/pwritev/pwritev.h index 833160ddb..e657dc7e6 100644 --- a/testcases/kernel/syscalls/pwritev/pwritev.h +++ b/testcases/kernel/syscalls/pwritev/pwritev.h @@ -1,18 +1,9 @@ -/* -* Copyright (c) 2015 Fujitsu Ltd. -* Author: Xiao Yang <yangx.jy@cn.fujitsu.com> -* -* This program is free software; you can redistribute it and/or modify it -* under the terms of version 2 of the GNU General Public License as -* published by the Free Software Foundation. -* -* This program is distributed in the hope that it would be useful, but -* WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. -* -* You should have received a copy of the GNU General Public License -* alone with this program. -*/ +/* SPDX-License-Identifier: GPL-2.0-or-later + * + * Copyright (c) 2015 Fujitsu Ltd. + * Author: Xiao Yang <yangx.jy@cn.fujitsu.com> + * Copyright (c) Linux Test Project, 2016-2023 + */ #ifndef PWRITEV_H #define PWRITEV_H diff --git a/testcases/kernel/syscalls/pwritev/pwritev01.c b/testcases/kernel/syscalls/pwritev/pwritev01.c index 66358f7c4..f5fce81f2 100644 --- a/testcases/kernel/syscalls/pwritev/pwritev01.c +++ b/testcases/kernel/syscalls/pwritev/pwritev01.c @@ -1,17 +1,18 @@ // SPDX-License-Identifier: GPL-2.0-or-later /* -* Copyright (c) 2015 Fujitsu Ltd. -* Author: Xiao Yang <yangx.jy@cn.fujitsu.com> -*/ - -/* -* Test Name: pwritev01 -* -* Test Description: -* Testcase to check the basic functionality of the pwritev(2). -* pwritev(2) should succeed to write the expected content of data -* and after writing the file, the file offset is not changed. -*/ + * Copyright (c) 2015 Fujitsu Ltd. + * Author: Xiao Yang <yangx.jy@cn.fujitsu.com> + * Copyright (c) Linux Test Project, 2016-2023 + */ + +/*\ + * [Description] + * + * Testcase to check the basic functionality of the pwritev(2). + * + * pwritev(2) should succeed to write the expected content of data + * and after writing the file, the file offset is not changed. + */ #define _GNU_SOURCE #include <string.h> diff --git a/testcases/kernel/syscalls/pwritev/pwritev02.c b/testcases/kernel/syscalls/pwritev/pwritev02.c index 0881b7566..59a286847 100644 --- a/testcases/kernel/syscalls/pwritev/pwritev02.c +++ b/testcases/kernel/syscalls/pwritev/pwritev02.c @@ -1,30 +1,21 @@ // SPDX-License-Identifier: GPL-2.0-or-later /* -* Copyright (c) 2015-2016 Fujitsu Ltd. -* Author: Xiao Yang <yangx.jy@cn.fujitsu.com> -*/ - -/* -* Test Name: pwritev02 -* -* Description: -* 1) pwritev(2) fails if iov_len is invalid. -* 2) pwritev(2) fails if the vector count iovcnt is less than zero. -* 3) pwritev(2) fails if offset is negative. -* 4) pwritev(2) fails when attempts to write from a invalid address -* 5) pwritev(2) fails if file descriptor is invalid. -* 6) pwritev(2) fails if file descriptor is not open for writing. -* 7) pwritev(2) fails if fd is associated with a pipe. -* -* Expected Result: -* 1) pwritev(2) should return -1 and set errno to EINVAL. -* 2) pwritev(2) should return -1 and set errno to EINVAL. -* 3) pwritev(2) should return -1 and set errno to EINVAL. -* 4) pwritev(2) should return -1 and set errno to EFAULT. -* 5) pwritev(2) should return -1 and set errno to EBADF. -* 6) pwritev(2) should return -1 and set errno to EBADF. -* 7) pwritev(2) should return -1 and set errno to ESPIPE. -*/ + * Copyright (c) 2015-2016 Fujitsu Ltd. + * Author: Xiao Yang <yangx.jy@cn.fujitsu.com> + * Copyright (c) Linux Test Project, 2017-2023 + */ + +/*\ + * [Description] + * + * - EINVAL when iov_len is invalid. + * - EINVAL when the vector count iovcnt is less than zero. + * - EINVAL when offset is negative. + * - EFAULT when attempts to write from a invalid address + * - EBADF when file descriptor is invalid. + * - EBADF when file descriptor is not open for writing. + * - ESPIPE when fd is associated with a pipe. + */ #define _GNU_SOURCE diff --git a/testcases/kernel/syscalls/pwritev/pwritev03.c b/testcases/kernel/syscalls/pwritev/pwritev03.c index 8b91de336..1bf9d5731 100644 --- a/testcases/kernel/syscalls/pwritev/pwritev03.c +++ b/testcases/kernel/syscalls/pwritev/pwritev03.c @@ -2,12 +2,15 @@ /* * Copyright (c) 2018 FUJITSU LIMITED. All rights reserved. * Author: Xiao Yang <yangx.jy@cn.fujitsu.com> + * Copyright (c) Linux Test Project, 2019-2023 */ -/* - * Description: +/*\ + * [Description] + * * Check the basic functionality of the pwritev(2) for the file * opened with O_DIRECT in all filesystem. + * * pwritev(2) should succeed to write the expected content of data * and after writing the file, the file offset is not changed. */ @@ -90,7 +93,7 @@ static void verify_direct_pwritev(unsigned int n) static void setup(void) { int dev_fd, ret; - + dev_fd = SAFE_OPEN(tst_device->dev, O_RDWR); SAFE_IOCTL(dev_fd, BLKSSZGET, &ret); SAFE_CLOSE(dev_fd); diff --git a/testcases/kernel/syscalls/readahead/readahead01.c b/testcases/kernel/syscalls/readahead/readahead01.c index bdef7945d..a1f313605 100644 --- a/testcases/kernel/syscalls/readahead/readahead01.c +++ b/testcases/kernel/syscalls/readahead/readahead01.c @@ -1,6 +1,7 @@ // SPDX-License-Identifier: GPL-2.0 /* * Copyright (C) 2012 Linux Test Project, Inc. + * Copyright (C) 2023-2024 Cyril Hrubis <chrubis@suse.cz> */ /*\ @@ -30,43 +31,45 @@ static void test_bad_fd(void) { - char tempname[PATH_MAX] = "readahead01_XXXXXX"; - int fd; + int fd[2]; + + TST_EXP_FAIL(readahead(-1, 0, getpagesize()), EBADF, + "readahead() with fd = -1"); - tst_res(TINFO, "%s -1", __func__); - TST_EXP_FAIL(readahead(-1, 0, getpagesize()), EBADF); + SAFE_PIPE(fd); + SAFE_CLOSE(fd[0]); + SAFE_CLOSE(fd[1]); - tst_res(TINFO, "%s O_WRONLY", __func__); - fd = mkstemp(tempname); - if (fd == -1) - tst_res(TFAIL | TERRNO, "mkstemp failed"); - SAFE_CLOSE(fd); - fd = SAFE_OPEN(tempname, O_WRONLY); - TST_EXP_FAIL(readahead(fd, 0, getpagesize()), EBADF); - SAFE_CLOSE(fd); - unlink(tempname); + TST_EXP_FAIL(readahead(fd[0], 0, getpagesize()), EBADF, + "readahead() with invalid fd"); } -static void test_invalid_fd(void) +static void test_invalid_fd(struct tst_fd *fd) { - int fd[2]; - tst_res(TINFO, "%s pipe", __func__); - SAFE_PIPE(fd); - TST_EXP_FAIL(readahead(fd[0], 0, getpagesize()), EINVAL); - SAFE_CLOSE(fd[0]); - SAFE_CLOSE(fd[1]); + switch (fd->type) { + /* These succeed */ + case TST_FD_FILE: + case TST_FD_MEMFD: + case TST_FD_MEMFD_SECRET: + case TST_FD_PROC_MAPS: + return; + default: + break; + } - tst_res(TINFO, "%s socket", __func__); - fd[0] = SAFE_SOCKET(AF_INET, SOCK_STREAM, 0); - TST_EXP_FAIL(readahead(fd[0], 0, getpagesize()), EINVAL); - SAFE_CLOSE(fd[0]); + int exp_errnos[] = {EBADF, EINVAL, ESPIPE}; + + TST_EXP_FAIL_ARR(readahead(fd->fd, 0, getpagesize()), exp_errnos, + "readahead() on %s", tst_fd_desc(fd)); } static void test_readahead(void) { test_bad_fd(); - test_invalid_fd(); + + TST_FD_FOREACH(fd) + test_invalid_fd(&fd); } static void setup(void) diff --git a/testcases/kernel/syscalls/remap_file_pages/remap_file_pages01.c b/testcases/kernel/syscalls/remap_file_pages/remap_file_pages01.c index 09143a2d0..8a401fe0a 100644 --- a/testcases/kernel/syscalls/remap_file_pages/remap_file_pages01.c +++ b/testcases/kernel/syscalls/remap_file_pages/remap_file_pages01.c @@ -85,6 +85,7 @@ #include <sys/ioctl.h> #include <sys/syscall.h> #include <linux/unistd.h> +#include <lapi/mmap.h> #include "test.h" /*LTP Specific Include File */ @@ -92,6 +93,7 @@ #define WINDOW_START 0x48000000 static int page_sz; +static int granula; size_t page_words; size_t cache_pages; size_t cache_sz; @@ -140,10 +142,10 @@ static void test_nonlinear(int fd) char *data = NULL; int i, j, repeat = 2; - for (i = 0; i < (int)cache_pages; i++) { + for (i = 0; i < (int)cache_pages; i += granula) { char *page = cache_contents + i * page_sz; - for (j = 0; j < (int)page_words; j++) + for (j = 0; j < (int)page_words * granula; j++) page[j] = i; } @@ -164,24 +166,24 @@ static void test_nonlinear(int fd) } again: - for (i = 0; i < (int)window_pages; i += 2) { + for (i = 0; i < (int)window_pages; i += 2 * granula) { char *page = data + i * page_sz; - if (remap_file_pages(page, page_sz * 2, 0, - (window_pages - i - 2), 0) == -1) { + if (remap_file_pages(page, 2 * MMAP_GRANULARITY, 0, + (window_pages - i - 2 * granula), 0) == -1) { tst_resm(TFAIL | TERRNO, "remap_file_pages error for page=%p, " - "page_sz=%d, window_pages=%zu", - page, (page_sz * 2), (window_pages - i - 2)); + "remap_sz=%d, window_pages=%zu", + page, 2 * MMAP_GRANULARITY, (window_pages - i - 2 * granula)); cleanup(data); } } - for (i = 0; i < (int)window_pages; i++) { + for (i = 0, j = 0; i < (int)window_pages; i += granula, j++) { /* * Double-check the correctness of the mapping: */ - if (i & 1) { + if (j & 1) { if (data[i * page_sz] != ((int)window_pages) - i) { tst_resm(TFAIL, "hm, mapped incorrect data, " @@ -191,12 +193,12 @@ again: cleanup(data); } } else { - if (data[i * page_sz] != ((int)window_pages) - i - 2) { + if (data[i * page_sz] != ((int)window_pages) - i - 2 * granula) { tst_resm(TFAIL, "hm, mapped incorrect data, " - "data[%d]=%d, (window_pages-%d-2)=%zu", + "data[%d]=%d, (window_pages-%d-2 * min_pages)=%zu", (i * page_sz), data[i * page_sz], i, - (window_pages - i - 2)); + (window_pages - i - 2 * granula)); cleanup(data); } } @@ -223,13 +225,15 @@ void setup(void) page_words = page_sz; + granula = MMAP_GRANULARITY / page_sz; + /* Set the cache size */ - cache_pages = 1024; + cache_pages = 1024 * granula; cache_sz = cache_pages * page_sz; cache_contents = malloc(cache_sz * sizeof(char)); /* Set the window size */ - window_pages = 16; + window_pages = 16 * granula; window_sz = window_pages * page_sz; sprintf(fname, "/dev/shm/cache_%d", getpid()); diff --git a/testcases/kernel/syscalls/rename/rename10.c b/testcases/kernel/syscalls/rename/rename10.c index 444f65366..5b5f79073 100644 --- a/testcases/kernel/syscalls/rename/rename10.c +++ b/testcases/kernel/syscalls/rename/rename10.c @@ -18,7 +18,13 @@ #define MNT_POINT "mntpoint" #define TEMP_FILE "tmpfile" -static char long_path[NAME_MAX + 1] = {[0 ... NAME_MAX] = 'a'}; +/* Path longer than PATH_MAX: fails the syscall right away (getname() fails) */ +static char long_path[PATH_MAX + 1] = {[0 ... PATH_MAX] = 'a'}; +/* + * Path fitting in PATH_MAX, but with an excessively long file name: rejected + * by the underlying filesystem + */ +static char long_name[PATH_MAX] = {[0 ... PATH_MAX - 2] = 'a', [PATH_MAX - 1] = '\0'}; static void setup(void) { @@ -30,6 +36,8 @@ static void run(void) { TST_EXP_FAIL(rename(TEMP_FILE, long_path), ENAMETOOLONG); + TST_EXP_FAIL(rename(TEMP_FILE, long_name), + ENAMETOOLONG); } static struct tst_test test = { diff --git a/testcases/kernel/syscalls/renameat/renameat01.c b/testcases/kernel/syscalls/renameat/renameat01.c index 3de103563..c318a7971 100644 --- a/testcases/kernel/syscalls/renameat/renameat01.c +++ b/testcases/kernel/syscalls/renameat/renameat01.c @@ -50,7 +50,6 @@ #include "test.h" #include "safe_macros.h" #include "lapi/fcntl.h" -#include "lapi/renameat.h" #define MNTPOINT "mntpoint" #define TESTDIR "testdir" diff --git a/testcases/kernel/syscalls/sched_rr_get_interval/sched_rr_get_interval01.c b/testcases/kernel/syscalls/sched_rr_get_interval/sched_rr_get_interval01.c index 597de4665..40ff6e988 100644 --- a/testcases/kernel/syscalls/sched_rr_get_interval/sched_rr_get_interval01.c +++ b/testcases/kernel/syscalls/sched_rr_get_interval/sched_rr_get_interval01.c @@ -2,13 +2,17 @@ /* * Copyright (c) Wipro Technologies Ltd, 2002. All Rights Reserved. * AUTHOR : Saji Kumar.V.R <saji.kumar@wipro.com> + */ +/*\ + * [Description] * * Gets round-robin time quantum by calling sched_rr_get_interval() and * checks that the value is sane. * - * It is also a regression test for kernel - * commit 975e155ed873 ("sched/rt: Show the 'sched_rr_timeslice' SCHED_RR - * timeslice tuning knob in milliseconds"). + * It is also a regression test for: + * + * - 975e155ed873 (sched/rt: Show the 'sched_rr_timeslice' SCHED_RR timeslice tuning knob in milliseconds) + * - c7fcb99877f9 ( sched/rt: Fix sysctl_sched_rr_timeslice intial value) */ #include "time64_variants.h" diff --git a/testcases/kernel/syscalls/sched_rr_get_interval/sched_rr_get_interval02.c b/testcases/kernel/syscalls/sched_rr_get_interval/sched_rr_get_interval02.c index 15e4a3053..a61e2969b 100644 --- a/testcases/kernel/syscalls/sched_rr_get_interval/sched_rr_get_interval02.c +++ b/testcases/kernel/syscalls/sched_rr_get_interval/sched_rr_get_interval02.c @@ -2,6 +2,9 @@ /* * Copyright (c) Wipro Technologies Ltd, 2002. All Rights Reserved. * AUTHOR : Saji Kumar.V.R <saji.kumar@wipro.com> + */ +/*\ + * [Description] * * Verify that for a process with scheduling policy SCHED_FIFO, * sched_rr_get_interval() writes zero into timespec structure diff --git a/testcases/kernel/syscalls/sched_rr_get_interval/sched_rr_get_interval03.c b/testcases/kernel/syscalls/sched_rr_get_interval/sched_rr_get_interval03.c index f5a88f084..731c50082 100644 --- a/testcases/kernel/syscalls/sched_rr_get_interval/sched_rr_get_interval03.c +++ b/testcases/kernel/syscalls/sched_rr_get_interval/sched_rr_get_interval03.c @@ -2,14 +2,20 @@ /* * Copyright (c) Wipro Technologies Ltd, 2002. All Rights Reserved. * AUTHOR : Saji Kumar.V.R <saji.kumar@wipro.com> + */ +/*\ + * [Description] + * + * Verify that: + * + * - sched_rr_get_interval() fails with errno set to EINVAL for an + * invalid pid + * + * - sched_rr_get_interval() fails with errno set to ESRCH if the + * process with specified pid does not exists * - * Verify that - * 1) sched_rr_get_interval() fails with errno set to EINVAL for an - * invalid pid - * 2) sched_rr_get_interval() fails with errno set to ESRCH if the - * process with specified pid does not exists - * 3) sched_rr_get_interval() fails with errno set to EFAULT if the - * address specified as &tp is invalid + * - sched_rr_get_interval() fails with errno set to EFAULT if the + * address specified as &tp is invalid */ #include "time64_variants.h" diff --git a/testcases/kernel/syscalls/sched_setparam/sched_setparam03.c b/testcases/kernel/syscalls/sched_setparam/sched_setparam03.c index 759b790b6..ffa92a3bf 100644 --- a/testcases/kernel/syscalls/sched_setparam/sched_setparam03.c +++ b/testcases/kernel/syscalls/sched_setparam/sched_setparam03.c @@ -49,7 +49,7 @@ void setup(void) tst_res(TINFO, "Testing %s variant", tv->desc); if (tv->sched_setscheduler(0, SCHED_FIFO, &p)) - tst_brk(TBROK | TERRNO, "sched_setcheduler(0, SCHED_FIFO, 1)"); + tst_brk(TBROK | TERRNO, "sched_setscheduler(0, SCHED_FIFO, 1)"); } static struct tst_test test = { diff --git a/testcases/kernel/syscalls/sched_setparam/sched_setparam04.c b/testcases/kernel/syscalls/sched_setparam/sched_setparam04.c index dbcb3c55c..26477e455 100644 --- a/testcases/kernel/syscalls/sched_setparam/sched_setparam04.c +++ b/testcases/kernel/syscalls/sched_setparam/sched_setparam04.c @@ -2,22 +2,23 @@ /* * Copyright (c) 2021, BELLSOFT. All rights reserved. * Copyright (c) Wipro Technologies Ltd, 2002. All Rights Reserved. - * AUTHOR: Saji Kumar.V.R <saji.kumar@wipro.com> + * Author: Saji Kumar.V.R <saji.kumar@wipro.com> */ /*\ * [Description] * * Verify that: + * * 1. sched_setparam(2) returns -1 and sets errno to ESRCH if the - * process with specified pid could not be found + * process with specified pid could not be found. * 2. sched_setparam(2) returns -1 and sets errno to EINVAL if - * the parameter pid is an invalid value (-1) + * the parameter pid is an invalid value (-1). * 3. sched_setparam(2) returns -1 and sets errno to EINVAL if the - * parameter p is an invalid address + * parameter p is an invalid address. * 4. sched_setparam(2) returns -1 sets errno to EINVAL if the * value for p.sched_priority is other than 0 for scheduling - * policy, SCHED_OTHER + * policy, SCHED_OTHER. */ #include "tst_test.h" diff --git a/testcases/kernel/syscalls/sched_setscheduler/.gitignore b/testcases/kernel/syscalls/sched_setscheduler/.gitignore index aa8ad9695..1b8860d2c 100644 --- a/testcases/kernel/syscalls/sched_setscheduler/.gitignore +++ b/testcases/kernel/syscalls/sched_setscheduler/.gitignore @@ -1,3 +1,4 @@ /sched_setscheduler01 /sched_setscheduler02 /sched_setscheduler03 +/sched_setscheduler04 diff --git a/testcases/kernel/syscalls/sched_setscheduler/sched_setscheduler04.c b/testcases/kernel/syscalls/sched_setscheduler/sched_setscheduler04.c new file mode 100644 index 000000000..828d1ec09 --- /dev/null +++ b/testcases/kernel/syscalls/sched_setscheduler/sched_setscheduler04.c @@ -0,0 +1,78 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * Copyright (c) 2022 Federico Bonfiglio <federico.bonfiglio@protonmail.ch> + */ + +/* + * [Description] + * + * Testcases that test if sched_setscheduler with flag + * SCHED_RESET_ON_FORK restores children policy to + * SCHED_NORMAL. + * + */ + +#define _GNU_SOURCE +#include <stdio.h> +#include <stdlib.h> +#include <sched.h> +#include <linux/sched.h> + +#include "tst_test.h" +#include "tst_sched.h" + +struct test_case_t { + int policy; + char *desc; +}; + +static struct test_case_t cases[] = { + { + .policy = SCHED_FIFO, + .desc = "SCHED_FIFO" + }, + { + .policy = SCHED_RR, + .desc = "SCHED_RR" + } +}; + +static void test_reset_on_fork(unsigned int i) +{ + struct sched_variant *tv = &sched_variants[tst_variant]; + struct test_case_t *tc = &cases[i]; + + tst_res(TINFO, "Testing %s variant %s policy", tv->desc, tc->desc); + + struct sched_param param = { .sched_priority = 10 }; + + tv->sched_setscheduler(getpid(), tc->policy | SCHED_RESET_ON_FORK, ¶m); + + pid_t pid = SAFE_FORK(); + + if (pid) { + if (sched_getscheduler(pid) == SCHED_NORMAL) + tst_res(TPASS, "Policy reset to SCHED_NORMAL"); + else + tst_res(TFAIL, "Policy NOT reset to SCHED_NORMAL"); + + sched_getparam(pid, ¶m); + + /* kernel will return sched_priority 0 if task is not RT Policy */ + if (param.sched_priority == 0) + tst_res(TPASS, "Priority set to 0"); + else + tst_res(TFAIL, "Priority not set to 0"); + } +} + +static struct tst_test test = { + .forks_child = 1, + .caps = (struct tst_cap[]) { + TST_CAP(TST_CAP_REQ, CAP_SYS_NICE), + {} + }, + .test_variants = ARRAY_SIZE(sched_variants), + .tcnt = ARRAY_SIZE(cases), + .test = test_reset_on_fork, +}; diff --git a/testcases/kernel/syscalls/sendfile/sendfile09.c b/testcases/kernel/syscalls/sendfile/sendfile09.c index 4a2d2083f..6cb3cd593 100644 --- a/testcases/kernel/syscalls/sendfile/sendfile09.c +++ b/testcases/kernel/syscalls/sendfile/sendfile09.c @@ -1,6 +1,7 @@ // SPDX-License-Identifier: GPL-2.0-or-later /* * Copyright (c) International Business Machines Corp., 2014 + * Copyright (c) Linux Test Project, 2013-2023 */ /*\ @@ -20,11 +21,7 @@ #include <inttypes.h> #include <sys/sendfile.h> - #include "tst_test.h" -#include "lapi/abisize.h" - -#ifndef TST_ABI32 #define ONE_GB (INT64_C(1) << 30) #define IN_FILE "in_file" @@ -97,12 +94,9 @@ static struct tst_test test = { .test = run, .tcnt = ARRAY_SIZE(tc), .max_runtime = 120, + .skip_in_compat = 1, .tags = (const struct tst_tag[]) { {"linux-git", "5d73320a96fcc"}, {} } }; - -#else -TST_TEST_TCONF("This test is only for 64bit"); -#endif diff --git a/testcases/kernel/syscalls/sendmmsg/sendmmsg.h b/testcases/kernel/syscalls/sendmmsg/sendmmsg.h index 65d5b680f..69ed80d44 100644 --- a/testcases/kernel/syscalls/sendmmsg/sendmmsg.h +++ b/testcases/kernel/syscalls/sendmmsg/sendmmsg.h @@ -1,5 +1,8 @@ /* SPDX-License-Identifier: GPL-2.0-or-later */ +#ifndef SENDMMSG_H__ +#define SENDMMSG_H__ + #include <netinet/ip.h> #include <stdio.h> #include <stdlib.h> @@ -25,3 +28,5 @@ static struct time64_variants variants[] = { { .recvmmsg = sys_recvmmsg64, .sendmmsg = sys_sendmmsg, .ts_type = TST_KERN_TIMESPEC, .desc = "syscall time64 with kernel spec"}, #endif }; + +#endif /* SENDMMSG_H__ */ diff --git a/testcases/kernel/syscalls/setgroups/.gitignore b/testcases/kernel/syscalls/setgroups/.gitignore index 9de928241..0649a3425 100644 --- a/testcases/kernel/syscalls/setgroups/.gitignore +++ b/testcases/kernel/syscalls/setgroups/.gitignore @@ -4,3 +4,5 @@ /setgroups02_16 /setgroups03 /setgroups03_16 +/setgroups04 +/setgroups04_16 diff --git a/testcases/kernel/syscalls/setgroups/Makefile b/testcases/kernel/syscalls/setgroups/Makefile index b2bb1e005..41160978e 100644 --- a/testcases/kernel/syscalls/setgroups/Makefile +++ b/testcases/kernel/syscalls/setgroups/Makefile @@ -3,6 +3,9 @@ top_srcdir ?= ../../../.. +# Remove after rewriting setgroups04.c to the new API. +USE_LEGACY_COMPAT_16_H := 1 + include $(top_srcdir)/include/mk/testcases.mk include $(abs_srcdir)/../utils/compat_16.mk include $(top_srcdir)/include/mk/generic_leaf_target.mk diff --git a/testcases/kernel/syscalls/setgroups/setgroups04.c b/testcases/kernel/syscalls/setgroups/setgroups04.c new file mode 100644 index 000000000..93a064cda --- /dev/null +++ b/testcases/kernel/syscalls/setgroups/setgroups04.c @@ -0,0 +1,167 @@ +/* + * Copyright (C) Bull S.A. 2001 + * Copyright (c) International Business Machines Corp., 2001 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See + * the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/* + * Test Name: setgroups04 + * + * Test Description: + * Verify that, setgroups() fails with -1 and sets errno to EFAULT if the list has an invalid address. + * + * Expected Result: + * setgroups() should fail with return value -1 and set expected errno. + * + * Algorithm: + * Setup: + * Setup signal handling. + * Pause for SIGUSR1 if option specified. + * + * Test: + * Loop if the proper options are given. + * Execute system call + * Check return code, if system call failed (return=-1) + * if errno set == expected errno + * Issue sys call fails with expected return value and errno. + * Otherwise, + * Issue sys call fails with unexpected errno. + * Otherwise, + * Issue sys call returns unexpected value. + * + * Cleanup: + * Print errno log and/or timing stats if options given + * + * Usage: <for command-line> + * setgroups04 [-c n] [-e] [-i n] [-I x] [-P x] [-t] + * where, -c n : Run n copies concurrently. + * -f : Turn off functionality Testing. + * -i n : Execute test n times. + * -I x : Execute test for x seconds. + * -P x : Pause for x seconds between iterations. + * -t : Turn on syscall timing. + * + * HISTORY + * 05/2002 Ported by André Merlier + * + * RESTRICTIONS: + * none. + * + */ +#include <sys/types.h> +#include <sys/param.h> +#include <unistd.h> +#include <errno.h> +#include <pwd.h> +#include <grp.h> + +#include "test.h" + +/* + * Don't forget to remove USE_LEGACY_COMPAT_16_H from Makefile after + * rewriting this test to the new API. + */ +#include "compat_16.h" + +TCID_DEFINE(setgroups04); +int TST_TOTAL = 1; + +GID_T groups_list[NGROUPS]; + +void setup(); /* setup function for the test */ +void cleanup(); /* cleanup function for the test */ + +#if !defined(UCLINUX) + +int main(int ac, char **av) +{ + int lc; + int gidsetsize; /* total no. of groups */ + char *test_desc; /* test specific error message */ + + tst_parse_opts(ac, av, NULL, NULL); + + /* Perform setup for test */ + setup(); + + for (lc = 0; TEST_LOOPING(lc); lc++) { + + tst_count = 0; + + gidsetsize = NGROUPS; + test_desc = "EFAULT"; + + /* + * Call setgroups() to test condition + * verify that it fails with -1 return value and + * sets appropriate errno. + */ + TEST(SETGROUPS(cleanup, gidsetsize, sbrk(0))); + + if (TEST_RETURN != -1) { + tst_resm(TFAIL, "setgroups() returned %ld, " + "expected -1, errno=%d", TEST_RETURN, + EFAULT); + } else { + + if (TEST_ERRNO == EFAULT) { + tst_resm(TPASS, + "setgroups() fails with expected " + "error EFAULT errno:%d", TEST_ERRNO); + } else { + tst_resm(TFAIL, "setgroups() fails, %s, " + "errno=%d, expected errno=%d", + test_desc, TEST_ERRNO, EFAULT); + } + } + + } + + cleanup(); + tst_exit(); + +} + +#else + +int main(void) +{ + tst_resm(TINFO, "test is not available on uClinux"); + tst_exit(); +} + +#endif /* if !defined(UCLINUX) */ + +/* + * setup() + */ +void setup(void) +{ + tst_require_root(); + + tst_sig(NOFORK, DEF_HANDLER, cleanup); + + TEST_PAUSE; + +} + +/* + * cleanup() + */ +void cleanup(void) +{ + +} diff --git a/testcases/kernel/syscalls/setsockopt/.gitignore b/testcases/kernel/syscalls/setsockopt/.gitignore index fd3235bb3..5c05290a5 100644 --- a/testcases/kernel/syscalls/setsockopt/.gitignore +++ b/testcases/kernel/syscalls/setsockopt/.gitignore @@ -7,3 +7,4 @@ /setsockopt07 /setsockopt08 /setsockopt09 +/setsockopt10 diff --git a/testcases/kernel/syscalls/setsockopt/setsockopt10.c b/testcases/kernel/syscalls/setsockopt/setsockopt10.c new file mode 100644 index 000000000..4e7e44938 --- /dev/null +++ b/testcases/kernel/syscalls/setsockopt/setsockopt10.c @@ -0,0 +1,205 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * Copyright (C) 2023 SUSE LLC Richard Palethorpe <rpalethorpe@suse.com> + */ +/*\ + * [Description] + * + * Reproducer for CVE-2023-0461 which is an exploitable use-after-free + * in a TLS socket. In fact it is exploitable in any User Level + * Protocol (ULP) which does not clone its context when accepting a + * connection. + * + * Because it does not clone the context, the child socket which is + * created on accept has a pointer to the listening socket's + * context. When the child is closed the parent's context is freed + * while it still has a reference to it. + * + * TLS can only be added to a socket which is connected. Not listening + * or disconnected, and a connected socket can not be set to + * listening. So we have to connect the socket, add TLS, then + * disconnect, then set it to listening. + * + * To my knowledge, setting a socket from open to disconnected + * requires a trick; we have to "connect" to an unspecified + * address. This could explain why the bug was not found earlier. + * + * The accepted fix was to disallow listening on sockets with a ULP + * set which does not have a clone function. + * + * The test uses two processes, first the child acts as a server so + * that the parent can create the TLS socket. Then the child connects + * to the parent's TLS socket. + * + * When we try to listen on the parent, the current kernel should + * return EINVAL. However if clone is implemented then this could + * become a valid operation. It is also quite easy to crash the kernel + * if we set some TLS options before doing a double free. + * + * commit 2c02d41d71f90a5168391b6a5f2954112ba2307c + * Author: Paolo Abeni <pabeni@redhat.com> + * Date: Tue Jan 3 12:19:17 2023 +0100 + * + * net/ulp: prevent ULP without clone op from entering the LISTEN status + */ + +#include "sched.h" +#include "tst_test.h" + +#ifdef HAVE_LINUX_TLS_H + +#include <linux/tls.h> +#include <netinet/in.h> + +#include "lapi/sched.h" +#include "lapi/socket.h" +#include "lapi/tcp.h" +#include "tst_checkpoint.h" +#include "tst_net.h" +#include "tst_safe_net.h" +#include "tst_taint.h" + +static struct tls12_crypto_info_aes_gcm_128 opts = { + .info = { + .version = TLS_1_2_VERSION, + .cipher_type = TLS_CIPHER_AES_GCM_128, + }, + .iv = { 'i', 'v' }, + .key = { 'k', 'e', 'y' }, + .salt = { 's', 'a', 'l', 't' }, + .rec_seq = { 'r', 'e', 'c', 's' }, +}; + +static struct sockaddr_in tcp0_addr, tcp1_addr; +static const struct sockaddr unspec_addr = { + .sa_family = AF_UNSPEC +}; + +static int tcp0_sk, tcp1_sk, tcp2_sk, tcp3_sk; + +static void setup(void) +{ + tst_init_sockaddr_inet(&tcp0_addr, "127.0.0.1", 0x7c90); + tst_init_sockaddr_inet(&tcp1_addr, "127.0.0.1", 0x7c91); +} + +static void cleanup(void) +{ + if (tcp0_sk > 0) + SAFE_CLOSE(tcp0_sk); + if (tcp1_sk > 0) + SAFE_CLOSE(tcp1_sk); + if (tcp2_sk > 0) + SAFE_CLOSE(tcp2_sk); + if (tcp3_sk > 0) + SAFE_CLOSE(tcp3_sk); +} + +static void child(void) +{ + tst_res(TINFO, "child: Listen for tcp1 connection"); + tcp0_sk = SAFE_SOCKET(AF_INET, SOCK_STREAM, 0); + SAFE_BIND(tcp0_sk, (struct sockaddr *)&tcp0_addr, sizeof(tcp0_addr)); + SAFE_LISTEN(tcp0_sk, 1); + TST_CHECKPOINT_WAKE(0); + + tcp3_sk = SAFE_ACCEPT(tcp0_sk, NULL, 0); + TST_CHECKPOINT_WAIT(1); + SAFE_CLOSE(tcp3_sk); + SAFE_CLOSE(tcp0_sk); + + tcp3_sk = SAFE_SOCKET(AF_INET, SOCK_STREAM, 0); + TST_CHECKPOINT_WAIT(2); + + tst_res(TINFO, "child: connect for tcp2 connection"); + TEST(connect(tcp3_sk, (struct sockaddr *)&tcp1_addr, sizeof(tcp1_addr))); + + if (TST_RET == -1) { + tst_res(TINFO | TTERRNO, "child: could not connect to tcp1"); + return; + } + + TST_CHECKPOINT_WAIT(3); +} + +static void run(void) +{ + const pid_t child_pid = SAFE_FORK(); + + if (child_pid == 0) { + child(); + return; + } + + tcp1_sk = SAFE_SOCKET(AF_INET, SOCK_STREAM, 0); + TST_CHECKPOINT_WAIT(0); + + tst_res(TINFO, "parent: Connect for tcp0 connection"); + SAFE_CONNECT(tcp1_sk, (struct sockaddr *)&tcp0_addr, sizeof(tcp0_addr)); + TEST(setsockopt(tcp1_sk, SOL_TCP, TCP_ULP, "tls", 3)); + + if (TST_RET == -1 && TST_ERR == ENOENT) + tst_brk(TCONF | TTERRNO, "parent: setsockopt failed: The TLS module is probably not loaded"); + else if (TST_RET == -1) + tst_brk(TBROK | TTERRNO, "parent: setsockopt failed"); + + SAFE_SETSOCKOPT(tcp1_sk, SOL_TLS, TLS_TX, &opts, sizeof(opts)); + TST_CHECKPOINT_WAKE(1); + + tst_res(TINFO, "parent: Disconnect by setting unspec address"); + SAFE_CONNECT(tcp1_sk, &unspec_addr, sizeof(unspec_addr)); + SAFE_BIND(tcp1_sk, (struct sockaddr *)&tcp1_addr, sizeof(tcp1_addr)); + + TEST(listen(tcp1_sk, 1)); + + if (TST_RET == -1) { + if (TST_ERR == EINVAL) + tst_res(TPASS | TTERRNO, "parent: Can't listen on disconnected TLS socket"); + else + tst_res(TCONF | TTERRNO, "parent: Can't listen on disconnected TLS socket, but the errno is not EINVAL as expected"); + + TST_CHECKPOINT_WAKE(2); + tst_reap_children(); + return; + } + + tst_res(TINFO, "parent: Can listen on disconnected TLS socket"); + TST_CHECKPOINT_WAKE(2); + + tcp2_sk = SAFE_ACCEPT(tcp1_sk, NULL, 0); + SAFE_CLOSE(tcp2_sk); + + tst_res(TINFO, "parent: Attempting double free, because we set cipher options this should result in an crash"); + tst_flush(); + SAFE_CLOSE(tcp1_sk); + + TST_CHECKPOINT_WAKE(3); + tst_reap_children(); + sched_yield(); + + tst_res(TCONF, "parent: We're still here, maybe the kernel can clone the TLS-ULP context now?"); +} + +static struct tst_test test = { + .setup = setup, + .cleanup = cleanup, + .test_all = run, + .forks_child = 1, + .needs_checkpoints = 1, + .taint_check = TST_TAINT_W | TST_TAINT_D, + .needs_kconfigs = (const char *[]) { + "CONFIG_TLS", + NULL + }, + .tags = (const struct tst_tag[]) { + {"linux-git", "2c02d41d71f90"}, + {"CVE", "2023-0461"}, + {} + } +}; + +#else + +TST_TEST_TCONF("linux/tls.h missing, we assume your system is too old"); + +#endif diff --git a/testcases/kernel/syscalls/setuid/Makefile b/testcases/kernel/syscalls/setuid/Makefile index 1fdd7bd76..88d6385d9 100644 --- a/testcases/kernel/syscalls/setuid/Makefile +++ b/testcases/kernel/syscalls/setuid/Makefile @@ -4,8 +4,5 @@ top_srcdir ?= ../../../.. include $(top_srcdir)/include/mk/testcases.mk -#for compat_16.mk uses the compat_16_tst.h -COMPAT_TST_16_H := 1 - include $(abs_srcdir)/../utils/compat_16.mk include $(top_srcdir)/include/mk/generic_leaf_target.mk diff --git a/testcases/kernel/syscalls/setxattr/setxattr01.c b/testcases/kernel/syscalls/setxattr/setxattr01.c index 8cd2821d0..31f41369a 100644 --- a/testcases/kernel/syscalls/setxattr/setxattr01.c +++ b/testcases/kernel/syscalls/setxattr/setxattr01.c @@ -137,7 +137,7 @@ static void verify_setxattr(unsigned int i) { /* 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, + SAFE_SETXATTR(FNAME, tc[i].key, *tc[i].value, tc[i].size, XATTR_CREATE); } diff --git a/testcases/kernel/syscalls/sighold/sighold02.c b/testcases/kernel/syscalls/sighold/sighold02.c index 1cfb7688b..2807bf67e 100644 --- a/testcases/kernel/syscalls/sighold/sighold02.c +++ b/testcases/kernel/syscalls/sighold/sighold02.c @@ -1,9 +1,7 @@ // SPDX-License-Identifier: GPL-2.0-or-later /* * Copyright (c) 2000 Silicon Graphics, Inc. All Rights Reserved. - * AUTHOR : Bob Clark - * CO-PILOT : Barrie Kletscher - * DATE STARTED : 9/26/86 + * Authors: Bob Clark, Barrie Kletscher * Copyright (C) 2015 Cyril Hrubis <chrubis@suse.cz> * Copyright (C) 2021 SUSE LLC Andrea Cervesato <andrea.cervesato@suse.com> */ @@ -12,8 +10,9 @@ * [Description] * * This test checks following conditions: - * 1. sighold action to turn off the receipt of all signals was done without error. - * 2. After signals were held, and sent, no signals were trapped. + * + * 1. sighold action to turn off the receipt of all signals was done without error. + * 2. After signals were held, and sent, no signals were trapped. */ #define _XOPEN_SOURCE 600 diff --git a/testcases/kernel/syscalls/splice/.gitignore b/testcases/kernel/syscalls/splice/.gitignore index a3e502f00..88a8dff78 100644 --- a/testcases/kernel/syscalls/splice/.gitignore +++ b/testcases/kernel/syscalls/splice/.gitignore @@ -3,3 +3,5 @@ /splice03 /splice04 /splice05 +/splice06 +/splice07 diff --git a/testcases/kernel/syscalls/splice/splice06.c b/testcases/kernel/syscalls/splice/splice06.c new file mode 100644 index 000000000..0cb5dec29 --- /dev/null +++ b/testcases/kernel/syscalls/splice/splice06.c @@ -0,0 +1,228 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * Copyright (c) 2023 SUSE LLC <wegao@suse.com> + */ + +/*\ + * [Description] + * + * This test is cover splice() on proc files. + * + */ + +#define _GNU_SOURCE + +#include <stdio.h> +#include <errno.h> +#include <string.h> +#include <signal.h> +#include <sys/types.h> +#include <fcntl.h> +#include <ctype.h> + +#include "tst_test.h" +#include "lapi/splice.h" + +#define BUF_SIZE 100 +#define PIPE_MAX_INIT_SIZE 65536 +#define DOMAIN_INIT_NAME "LTP_INIT" +#define DOMAIN_TEST_NAME "LTP_TEST" +#define INTEGER_PROCFILE "/proc/sys/fs/pipe-max-size" +#define STRING_PROCFILE "/proc/sys/kernel/domainname" +static int pipe_max_test_size; + +static void format_str(char *str) +{ + int i; + + for (i = 0; i < BUF_SIZE ; i++) { + if (!isdigit(str[i])) { + str[i] = '\0'; + break; + } + } + if (i == BUF_SIZE) + tst_brk(TBROK, "can not find nonnumeric character from input string"); +} + +static int splice_read_num(const char *file) +{ + int pipes[2]; + int fd_in; + int ret; + int num; + char buf[BUF_SIZE]; + + memset(buf, '\0', sizeof(buf)); + fd_in = SAFE_OPEN(file, O_RDONLY); + SAFE_PIPE(pipes); + + ret = splice(fd_in, NULL, pipes[1], NULL, BUF_SIZE - 1, 0); + if (ret < 0) + tst_brk(TBROK | TERRNO, "splice(fd_in, pipe) failed"); + + SAFE_READ(0, pipes[0], buf, BUF_SIZE); + + /* Search for the first nonnumeric character and replace it with \0 */ + format_str(buf); + + if (tst_parse_int(buf, &num, 0, INT_MAX)) + tst_brk(TBROK, "Invalid buffer num %s", buf); + + SAFE_CLOSE(fd_in); + SAFE_CLOSE(pipes[0]); + SAFE_CLOSE(pipes[1]); + + return num; +} + +static char *splice_read_str(const char *file, char *dest) +{ + int pipes[2]; + int fd_in; + int ret; + + fd_in = SAFE_OPEN(file, O_RDONLY); + SAFE_PIPE(pipes); + + ret = splice(fd_in, NULL, pipes[1], NULL, BUF_SIZE, 0); + if (ret < 0) + tst_brk(TBROK | TERRNO, "splice(fd_in, pipe) failed"); + + SAFE_READ(0, pipes[0], dest, BUF_SIZE); + + SAFE_CLOSE(fd_in); + SAFE_CLOSE(pipes[0]); + SAFE_CLOSE(pipes[1]); + + return dest; +} + + +static void splice_write_num(const char *file, int num) +{ + int pipes[2]; + int fd_out; + int ret; + char buf[BUF_SIZE]; + + memset(buf, '\0', sizeof(buf)); + + fd_out = SAFE_OPEN(file, O_WRONLY, 0777); + SAFE_PIPE(pipes); + sprintf(buf, "%d", num); + + SAFE_WRITE(SAFE_WRITE_ALL, pipes[1], buf, strlen(buf)); + + ret = splice(pipes[0], NULL, fd_out, NULL, BUF_SIZE, 0); + if (ret < 0) + tst_brk(TBROK | TERRNO, "splice write failed"); + + SAFE_CLOSE(fd_out); + SAFE_CLOSE(pipes[0]); + SAFE_CLOSE(pipes[1]); +} + +static void splice_write_str(const char *file, char *dest) +{ + int pipes[2]; + int fd_out; + int ret; + + fd_out = SAFE_OPEN(file, O_WRONLY, 0777); + SAFE_PIPE(pipes); + + SAFE_WRITE(SAFE_WRITE_ALL, pipes[1], dest, strlen(dest)); + + ret = splice(pipes[0], NULL, fd_out, NULL, BUF_SIZE, 0); + if (ret < 0) + tst_brk(TBROK | TERRNO, "splice write failed"); + + SAFE_CLOSE(fd_out); + SAFE_CLOSE(pipes[0]); + SAFE_CLOSE(pipes[1]); +} + +static void file_write_num(const char *file, int num) +{ + SAFE_FILE_PRINTF(file, "%d", num); +} + +static void file_write_str(const char *file, char *dest) +{ + SAFE_FILE_PRINTF(file, "%s", dest); +} + +static int file_read_num(const char *file) +{ + int num; + + SAFE_FILE_SCANF(file, "%d", &num); + + return num; +} + +static char *file_read_str(const char *file, char *dest) +{ + SAFE_FILE_SCANF(file, "%s", dest); + return dest; +} + +static void splice_test(void) +{ + + char buf_file[BUF_SIZE]; + char buf_splice[BUF_SIZE]; + + if (file_read_num(INTEGER_PROCFILE) == splice_read_num(INTEGER_PROCFILE)) + tst_res(TPASS, "Read num through splice correctly"); + else + tst_brk(TBROK | TERRNO, "Read num through splice failed"); + + splice_write_num(INTEGER_PROCFILE, pipe_max_test_size); + + if (file_read_num(INTEGER_PROCFILE) == pipe_max_test_size) + tst_res(TPASS, "Write num through splice correctly"); + else + tst_brk(TBROK | TERRNO, "Write num through splice failed"); + + memset(buf_file, '\0', sizeof(buf_file)); + memset(buf_splice, '\0', sizeof(buf_splice)); + + file_read_str(STRING_PROCFILE, buf_file); + splice_read_str(STRING_PROCFILE, buf_splice); + + if (!strncmp(buf_file, buf_splice, strlen(buf_file))) + tst_res(TPASS, "Read string through splice correctly"); + else + tst_brk(TBROK | TERRNO, "Read string through splice failed"); + + memset(buf_file, '\0', sizeof(buf_file)); + + splice_write_str(STRING_PROCFILE, DOMAIN_TEST_NAME); + file_read_str(STRING_PROCFILE, buf_file); + + if (!strncmp(buf_file, DOMAIN_TEST_NAME, strlen(buf_file))) + tst_res(TPASS, "Write string through splice correctly"); + else + tst_brk(TBROK | TERRNO, "Write string through splice failed"); +} + +static void setup(void) +{ + pipe_max_test_size = getpagesize(); + file_write_str(STRING_PROCFILE, DOMAIN_INIT_NAME); + file_write_num(STRING_PROCFILE, PIPE_MAX_INIT_SIZE); +} + +static struct tst_test test = { + .min_kver = "5.11", + .setup = setup, + .test_all = splice_test, + .needs_tmpdir = 1, + .save_restore = (const struct tst_path_val[]) { + {INTEGER_PROCFILE, NULL, TST_SR_TCONF}, + {STRING_PROCFILE, NULL, TST_SR_TCONF}, + {} + }, +}; diff --git a/testcases/kernel/syscalls/splice/splice07.c b/testcases/kernel/syscalls/splice/splice07.c new file mode 100644 index 000000000..9c23e0aac --- /dev/null +++ b/testcases/kernel/syscalls/splice/splice07.c @@ -0,0 +1,72 @@ +// SPDX-License-Identifier: GPL-2.0-or-later + +/* + * Copyright (C) 2023-2024 Cyril Hrubis <chrubis@suse.cz> + */ + +/*\ + * [Description] + * + * Iterate over all kinds of file descriptors and feed splice() with all possible + * combinations where at least one file descriptor is invalid. We do expect the + * syscall to fail either with EINVAL or EBADF. + */ + +#define _GNU_SOURCE + +#include <sys/socket.h> +#include <netinet/in.h> + +#include "tst_test.h" + +static void check_splice(struct tst_fd *fd_in, struct tst_fd *fd_out) +{ + /* These combinations just hang since the pipe is empty */ + if (fd_in->type == TST_FD_PIPE_READ) { + switch (fd_out->type) { + case TST_FD_FILE: + case TST_FD_PIPE_WRITE: + case TST_FD_UNIX_SOCK: + case TST_FD_INET_SOCK: + case TST_FD_MEMFD: + return; + default: + break; + } + } + + if (fd_out->type == TST_FD_PIPE_WRITE) { + switch (fd_in->type) { + /* While these combinations succeeed */ + case TST_FD_DEV_ZERO: + case TST_FD_FILE: + case TST_FD_PROC_MAPS: + case TST_FD_MEMFD: + return; + /* And this complains about socket not being connected */ + case TST_FD_INET_SOCK: + return; + default: + break; + } + } + + const int exp_errnos[] = {EBADF, EINVAL}; + + TST_EXP_FAIL2_ARR(splice(fd_in->fd, NULL, fd_out->fd, NULL, 1, 0), + exp_errnos, "splice() on %s -> %s", + tst_fd_desc(fd_in), tst_fd_desc(fd_out)); +} + +static void verify_splice(void) +{ + TST_FD_FOREACH(fd_in) { + tst_res(TINFO, "%s -> ...", tst_fd_desc(&fd_in)); + TST_FD_FOREACH(fd_out) + check_splice(&fd_in, &fd_out); + } +} + +static struct tst_test test = { + .test_all = verify_splice, +}; diff --git a/testcases/kernel/syscalls/swapon/swapon01.c b/testcases/kernel/syscalls/swapon/swapon01.c index c334ae246..e59fb20a1 100644 --- a/testcases/kernel/syscalls/swapon/swapon01.c +++ b/testcases/kernel/syscalls/swapon/swapon01.c @@ -1,6 +1,7 @@ // SPDX-License-Identifier: GPL-2.0-or-later /* * Copyright (c) Wipro Technologies Ltd, 2002. All Rights Reserved. + * Copyright (c) Linux Test Project, 2003-2024 */ /*\ @@ -16,30 +17,26 @@ #include "lapi/syscalls.h" #include "libswap.h" +#define SWAP_FILE "swapfile01" + static void verify_swapon(void) { - TEST(tst_syscall(__NR_swapon, "./swapfile01", 0)); + TST_EXP_PASS(tst_syscall(__NR_swapon, SWAP_FILE, 0)); - if (TST_RET == -1) { - tst_res(TFAIL | TTERRNO, "Failed to turn on swapfile"); - } else { - tst_res(TPASS, "Succeeded to turn on swapfile"); - /*we need to turn this swap file off for -i option */ - if (tst_syscall(__NR_swapoff, "./swapfile01") != 0) { - tst_brk(TBROK | TERRNO, "Failed to turn off swapfile," - " system reboot after execution of LTP " - "test suite is recommended."); - } + if (TST_PASS && tst_syscall(__NR_swapoff, SWAP_FILE) != 0) { + tst_brk(TBROK | TERRNO, + "Failed to turn off swapfile, system reboot recommended"); } } static void setup(void) { - is_swap_supported("./tstswap"); - make_swapfile("swapfile01", 0); + is_swap_supported(SWAP_FILE); + make_swapfile(SWAP_FILE, 0); } static struct tst_test test = { + .needs_root = 1, .needs_tmpdir = 1, .test_all = verify_swapon, .setup = setup diff --git a/testcases/kernel/syscalls/swapon/swapon02.c b/testcases/kernel/syscalls/swapon/swapon02.c index d34c17a80..fceea77be 100644 --- a/testcases/kernel/syscalls/swapon/swapon02.c +++ b/testcases/kernel/syscalls/swapon/swapon02.c @@ -1,56 +1,39 @@ // SPDX-License-Identifier: GPL-2.0-or-later - /* * Copyright (c) Wipro Technologies Ltd, 2002. All Rights Reserved. + * Copyright (c) Linux Test Project, 2002-2023 */ /*\ * [Description] * * This test case checks whether swapon(2) system call returns - * 1. ENOENT when the path does not exist - * 2. EINVAL when the path exists but is invalid - * 3. EPERM when user is not a superuser - * 4. EBUSY when the specified path is already being used as a swap area + * - ENOENT when the path does not exist + * - EINVAL when the path exists but is invalid + * - EPERM when user is not a superuser + * - EBUSY when the specified path is already being used as a swap area */ -#include <errno.h> #include <pwd.h> #include "tst_test.h" #include "lapi/syscalls.h" #include "libswap.h" -static void setup01(void); -static void cleanup01(void); - static uid_t nobody_uid; static int do_swapoff; static struct tcase { char *err_desc; int exp_errno; - char *exp_errval; char *path; - void (*setup)(void); - void (*cleanup)(void); } tcases[] = { - {"Path does not exist", ENOENT, "ENOENT", "./doesnotexist", NULL, NULL}, - {"Invalid path", EINVAL, "EINVAL", "./notswap", NULL, NULL}, - {"Permission denied", EPERM, "EPERM", "./swapfile01", setup01, cleanup01}, - {"File already used", EBUSY, "EBUSY", "./alreadyused", NULL, NULL}, + {"Path does not exist", ENOENT, "./doesnotexist"}, + {"Invalid path", EINVAL, "./notswap"}, + {"Permission denied", EPERM, "./swapfile01"}, + {"File already used", EBUSY, "./alreadyused"}, }; -static void setup01(void) -{ - SAFE_SETEUID(nobody_uid); -} - -static void cleanup01(void) -{ - SAFE_SETEUID(0); -} - static void setup(void) { struct passwd *nobody; @@ -70,7 +53,7 @@ static void setup(void) do_swapoff = 1; } -void cleanup(void) +static void cleanup(void) { if (do_swapoff && tst_syscall(__NR_swapoff, "alreadyused")) tst_res(TWARN | TERRNO, "swapoff(alreadyused) failed"); @@ -79,24 +62,19 @@ void cleanup(void) static void verify_swapon(unsigned int i) { struct tcase *tc = tcases + i; - if (tc->setup) - tc->setup(); + if (tc->exp_errno == EPERM) + SAFE_SETEUID(nobody_uid); - TEST(tst_syscall(__NR_swapon, tc->path, 0)); + TST_EXP_FAIL(tst_syscall(__NR_swapon, tc->path, 0), tc->exp_errno, + "swapon(2) fail with %s", tc->err_desc); - if (tc->cleanup) - tc->cleanup(); + if (tc->exp_errno == EPERM) + SAFE_SETEUID(0); - if (TST_RET == -1 && TST_ERR == tc->exp_errno) { - tst_res(TPASS, "swapon(2) expected failure;" - " Got errno - %s : %s", - tc->exp_errval, tc->err_desc); - return; + if (TST_RET != -1) { + tst_res(TFAIL, "swapon(2) failed unexpectedly, expected: %s", + tst_strerrno(tc->exp_errno)); } - - tst_res(TFAIL, "swapon(2) failed to produce expected error:" - " %d, errno: %s and got %d.", tc->exp_errno, - tc->exp_errval, TST_ERR); } static struct tst_test test = { diff --git a/testcases/kernel/syscalls/swapon/swaponoff.h b/testcases/kernel/syscalls/swapon/swaponoff.h index e3eae3fe3..900761bda 100644 --- a/testcases/kernel/syscalls/swapon/swaponoff.h +++ b/testcases/kernel/syscalls/swapon/swaponoff.h @@ -2,17 +2,7 @@ #ifndef __SWAP_ON_OFF_H_ #define __SWAP_ON_OFF_H_ -/* - * Read swapon(2) / swapoff(2) for a full history lesson behind the value of - * MAX_SWAPFILES. - */ #include <linux/version.h> -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 18) #define MAX_SWAPFILES 30 -#elif LINUX_VERSION_CODE > KERNEL_VERSION(2, 4, 10) -#define MAX_SWAPFILES 32 -#else -#define MAX_SWAPFILES 8 -#endif #endif diff --git a/testcases/kernel/syscalls/symlink/.gitignore b/testcases/kernel/syscalls/symlink/.gitignore index d1497e680..6ea587ff3 100644 --- a/testcases/kernel/syscalls/symlink/.gitignore +++ b/testcases/kernel/syscalls/symlink/.gitignore @@ -2,4 +2,3 @@ /symlink02 /symlink03 /symlink04 -/symlink05 diff --git a/testcases/kernel/syscalls/symlink/symlink02.c b/testcases/kernel/syscalls/symlink/symlink02.c index c18db2b37..d2226501e 100644 --- a/testcases/kernel/syscalls/symlink/symlink02.c +++ b/testcases/kernel/syscalls/symlink/symlink02.c @@ -1,208 +1,40 @@ +// SPDX-License-Identifier: GPL-2.0-only /* * Copyright (c) 2000 Silicon Graphics, Inc. All Rights Reserved. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it would be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * - * Further, this software is distributed without any warranty that it is - * free of the rightful claim of any third person regarding infringement - * or the like. Any license provided herein, whether implied or - * otherwise, applies only to this software file. Patent licenses, if - * any, provided herein do not apply to combinations of this program with - * other software, or any other product whatsoever. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy, - * Mountain View, CA 94043, or: - * - * http://www.sgi.com - * - * For further information regarding this notice, see: - * - * http://oss.sgi.com/projects/GenInfo/NoticeExplan/ - * + * Copyright (c) Linux Test Project, 2001-2023 + * Author: William Roske */ -/* $Id: symlink02.c,v 1.6 2009/08/28 14:17:14 vapier Exp $ */ -/********************************************************** - * - * OS Test - Silicon Graphics, Inc. - * - * TEST IDENTIFIER : symlink02 - * - * EXECUTED BY : anyone - * - * TEST TITLE : Basic test for symlink(2) - * - * PARENT DOCUMENT : usctpl01 - * - * TEST CASE TOTAL : 1 - * - * WALL CLOCK TIME : 1 - * - * CPU TYPES : ALL - * - * AUTHOR : William Roske - * - * CO-PILOT : Dave Fenner - * - * DATE STARTED : 03/30/92 - * - * INITIAL RELEASE : UNICOS 7.0 - * - * TEST CASES - * - * 1.) symlink(2) returns...(See Description) - * - * INPUT SPECIFICATIONS - * The standard options for system call tests are accepted. - * (See the parse_opts(3) man page). - * - * OUTPUT SPECIFICATIONS - *$ - * DURATION - * Terminates - with frequency and infinite modes. - * - * SIGNALS - * Uses SIGUSR1 to pause before test if option set. - * (See the parse_opts(3) man page). - * - * RESOURCES - * None - * - * ENVIRONMENTAL NEEDS - * No run-time environmental needs. - * - * SPECIAL PROCEDURAL REQUIREMENTS - * None - * - * INTERCASE DEPENDENCIES - * None - * - * DETAILED DESCRIPTION - * This is a Phase I test for the symlink(2) system call. It is intended - * to provide a limited exposure of the system call, for now. It - * should/will be extended when full functional tests are written for - * symlink(2). - * - * Setup: - * Setup signal handling. - * Pause for SIGUSR1 if option specified. - * - * Test: - * Loop if the proper options are given. - * Execute system call - * Check return code, if system call failed (return=-1) - * Log the errno and Issue a FAIL message. - * Otherwise, Issue a PASS message. - * - * Cleanup: - * Print errno log and/or timing stats if options given - * - * - *#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#**/ -#include <sys/types.h> -#include <fcntl.h> -#include <errno.h> -#include <string.h> -#include <signal.h> -#include "test.h" -#include "safe_macros.h" - -void setup(); -void cleanup(); +/*\ + * [Description] + * + * Check the basic functionality of the symlink() system call. + */ -char *TCID = "symlink02"; -int TST_TOTAL = 1; +#include "tst_test.h" -char fname[255], symlnk[255]; -int fd; +static char *fname, *symlnk; -int main(int ac, char **av) +static void verify_symlink(void) { - int lc; - - /*************************************************************** - * parse standard options - ***************************************************************/ - tst_parse_opts(ac, av, NULL, NULL); - - /*************************************************************** - * perform global setup for test - ***************************************************************/ - setup(); - - /*************************************************************** - * check looping state if -c option given - ***************************************************************/ - for (lc = 0; TEST_LOOPING(lc); lc++) { - - tst_count = 0; - - /* - * Call symlink(2) - */ - TEST(symlink(fname, symlnk)); - - /* check return code */ - if (TEST_RETURN == -1) { - tst_resm(TFAIL, "symlink(%s, %s) Failed, errno=%d : %s", - fname, symlnk, TEST_ERRNO, - strerror(TEST_ERRNO)); - } else { - SAFE_UNLINK(cleanup, symlnk); - } - } - - /*************************************************************** - * cleanup and exit - ***************************************************************/ - cleanup(); - tst_exit(); + TST_EXP_POSITIVE(symlink(fname, symlnk), "symlink(%s, %s)", + fname, symlnk); + if (TST_RET == -1) + tst_res(TFAIL, "symlink(%s, %s) Failed", fname, symlnk); + else + SAFE_UNLINK(symlnk); } -/*************************************************************** - * setup() - performs all ONE TIME setup for this test. - ***************************************************************/ -void setup(void) +static void setup(void) { + fname = tst_aprintf("tfile_%d", getpid()); - tst_sig(NOFORK, DEF_HANDLER, cleanup); - - TEST_PAUSE; - - tst_tmpdir(); - - sprintf(fname, "tfile_%d", getpid()); - if ((fd = open(fname, O_RDWR | O_CREAT, 0700)) == -1) { - tst_brkm(TBROK, cleanup, - "open(%s, O_RDWR|O_CREAT,0700) Failed, errno=%d : %s", - fname, errno, strerror(errno)); - } - - if (close(fd) == -1) { - tst_resm(TWARN, "close(%s) Failed, errno=%d : %s", - fname, errno, strerror(errno)); - } - sprintf(symlnk, "st_%d", getpid()); + symlnk = tst_aprintf("st_%d", getpid()); } -/*************************************************************** - * cleanup() - performs all ONE TIME cleanup for this test at - * completion or premature exit. - ***************************************************************/ -void cleanup(void) -{ - - tst_rmdir(); - -} +static struct tst_test test = { + .needs_tmpdir = 1, + .setup = setup, + .test_all = verify_symlink, +}; diff --git a/testcases/kernel/syscalls/symlink/symlink04.c b/testcases/kernel/syscalls/symlink/symlink04.c index 2190b3b1b..c43a03a26 100644 --- a/testcases/kernel/syscalls/symlink/symlink04.c +++ b/testcases/kernel/syscalls/symlink/symlink04.c @@ -1,193 +1,64 @@ +// SPDX-License-Identifier: GPL-2.0-or-later /* - * - * Copyright (c) International Business Machines Corp., 2001 - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See - * the GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * Copyright (c) International Business Machines Corp., 2001 + * Copyright (c) Linux Test Project, 2001-2023 + * Author: John George */ -/* - * Test Name : symlink04 - * - * Test Description : - * Verify that, symlink will succeed to creat a symbolic link of an existing - * object name path. - * - * Expected Result: - * symlink() should return value 0 on success and symbolic link of an - * existing object should be created. - * - * Algorithm: - * Setup: - * Setup signal handling. - * Create temporary directory. - * Pause for SIGUSR1 if option specified. - * - * Test: - * Loop if the proper options are given. - * Execute system call - * Check return code, if system call failed (return=-1) - * Log the errno and Issue a FAIL message. - * Otherwise, - * Verify the Functionality of system call - * if successful, - * Issue Functionality-Pass message. - * Otherwise, - * Issue Functionality-Fail message. - * Cleanup: - * Print errno log and/or timing stats if options given - * Delete the temporary directory created. - * - * Usage: <for command-line> - * symlink04 [-c n] [-e] [-f] [-i n] [-I x] [-p x] [-t] - * where, -c n : Run n copies concurrently. - * -e : Turn on errno logging. - * -f : Turn off functionality Testing. - * -i n : Execute test n times. - * -I x : Execute test for x seconds. - * -P x : Pause for x seconds between iterations. - * -t : Turn on syscall timing. - * - * History - * 07/2001 John George - * -Ported - * - * Restrictions: - * None. +/*\ + * [Description] * + * Check that a symbolic link may point to an existing file or + * to a nonexistent one. */ +#include <stdlib.h> #include <stdio.h> -#include <sys/types.h> -#include <fcntl.h> -#include <errno.h> -#include <string.h> -#include <signal.h> -#include <sys/stat.h> -#include "test.h" -#include "safe_macros.h" +#include "tst_test.h" -#define TESTFILE "testfile" -#define SYMFILE "slink_file" -#define FILE_MODE S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH +#define TESTFILE "testfile" +#define NONFILE "noexistfile" +#define SYMFILE "slink_file" -char *TCID = "symlink04"; -int TST_TOTAL = 1; +static char *testfile; +static char *nonfile; -void setup(); -void cleanup(); +static struct tcase { + char **srcfile; +} tcases[] = { + {&testfile}, + {&nonfile}, +}; -int main(int ac, char **av) +static void setup(void) { - struct stat stat_buf; /* stat structure buffer */ - int lc; - - tst_parse_opts(ac, av, NULL, NULL); - - setup(); - - for (lc = 0; TEST_LOOPING(lc); lc++) { - - tst_count = 0; - - /* - * Call symlink(2) to create a symlink of - * testfile. - */ - TEST(symlink(TESTFILE, SYMFILE)); - - if (TEST_RETURN == -1) { - tst_resm(TFAIL, "symlink(%s, %s) Failed, errno=%d : %s", - TESTFILE, SYMFILE, TEST_ERRNO, - strerror(TEST_ERRNO)); - } else { - /* - * Get the symlink file status information - * using lstat(2). - */ - if (lstat(SYMFILE, &stat_buf) < 0) { - tst_brkm(TFAIL, cleanup, "lstat(2) of " - "%s failed, error:%d", SYMFILE, - errno); - } - - /* Check if the st_mode contains a link */ - if (!S_ISLNK(stat_buf.st_mode)) { - tst_resm(TFAIL, - "symlink of %s doesn't exist", - TESTFILE); - } else { - tst_resm(TPASS, "symlink(%s, %s) " - "functionality successful", - TESTFILE, SYMFILE); - } - } - - /* Unlink the symlink file for next loop */ - SAFE_UNLINK(cleanup, SYMFILE); - tst_count++; /* incr TEST_LOOP counter */ - } - - cleanup(); - tst_exit(); - + SAFE_TOUCH(TESTFILE, 0644, NULL); } -/* - * void - * setup() - performs all ONE TIME setup for this test. - * Create a temporary directory and change directory to it. - * Create a test file under temporary directory and close it - */ -void setup(void) +static void verify_symlink(unsigned int i) { - int fd; /* file handle for testfile */ + struct tcase *tc = &tcases[i]; - tst_sig(NOFORK, DEF_HANDLER, cleanup); + struct stat stat_buf; - /* Pause if that option was specified - * TEST_PAUSE contains the code to fork the test with the -i option. - * You want to make sure you do this before you create your temporary - * directory. - */ - TEST_PAUSE; + TST_EXP_PASS(symlink(*tc->srcfile, SYMFILE)); - tst_tmpdir(); + SAFE_LSTAT(SYMFILE, &stat_buf); - /* creat/open a testfile */ - if ((fd = open(TESTFILE, O_RDWR | O_CREAT, FILE_MODE)) == -1) { - tst_brkm(TBROK, cleanup, - "open(%s, O_RDWR|O_CREAT, %#o) Failed, errno=%d : %s", - TESTFILE, FILE_MODE, errno, strerror(errno)); - } + if (!S_ISLNK(stat_buf.st_mode)) + tst_res(TFAIL, "symlink of %s doesn't exist", *tc->srcfile); - /* Close the temporary file created above */ - if (close(fd) == -1) { - tst_resm(TBROK, "close(%s) Failed, errno=%d : %s", - TESTFILE, errno, strerror(errno)); - } + SAFE_UNLINK(SYMFILE); } -/* - * void - * cleanup() - performs all ONE TIME cleanup for this test at - * completion or premature exit. - * Remove the test directory and testfile created in the setup. - */ -void cleanup(void) -{ - - tst_rmdir(); - -} +static struct tst_test test = { + .tcnt = ARRAY_SIZE(tcases), + .setup = setup, + .test = verify_symlink, + .bufs = (struct tst_buffers []) { + {&testfile, .str = TESTFILE}, + {&nonfile, .str = NONFILE}, + {}, + }, + .needs_tmpdir = 1, +}; diff --git a/testcases/kernel/syscalls/symlink/symlink05.c b/testcases/kernel/syscalls/symlink/symlink05.c deleted file mode 100644 index 83b151f5d..000000000 --- a/testcases/kernel/syscalls/symlink/symlink05.c +++ /dev/null @@ -1,180 +0,0 @@ -/* - * - * Copyright (c) International Business Machines Corp., 2001 - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See - * the GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -/* - * Test Name : symlink05 - * - * Test Description : - * Verify that, symlink will succeed to creat a symbolic link of an - * non-existing object name path. - * - * Expected Result: - * symlink() should return value 0 on success and symlink of an - * non-existing object should be created. - * - * Algorithm: - * Setup: - * Setup signal handling. - * Create temporary directory. - * Pause for SIGUSR1 if option specified. - * - * Test: - * Loop if the proper options are given. - * Execute system call - * Check return code, if system call failed (return=-1) - * Log the errno and Issue a FAIL message. - * Otherwise, - * Verify the Functionality of system call - * if successful, - * Issue Functionality-Pass message. - * Otherwise, - * Issue Functionality-Fail message. - * Cleanup: - * Print errno log and/or timing stats if options given - * Delete the temporary directory created. - * - * Usage: <for command-line> - * symlink05 [-c n] [-e] [-f] [-i n] [-I x] [-p x] [-t] - * where, -c n : Run n copies concurrently. - * -e : Turn on errno logging. - * -f : Turn off functionality Testing. - * -i n : Execute test n times. - * -I x : Execute test for x seconds. - * -P x : Pause for x seconds between iterations. - * -t : Turn on syscall timing. - * - * History - * 07/2001 John George - * -Ported - * - * Restrictions: - * This test should be run by 'non-super-user' only. - * - */ - -#include <stdio.h> -#include <sys/types.h> -#include <fcntl.h> -#include <errno.h> -#include <string.h> -#include <signal.h> -#include <sys/stat.h> - -#include "test.h" -#include "safe_macros.h" - -#define TESTFILE "testfile" -#define SYMFILE "slink_file" - -char *TCID = "symlink05"; -int TST_TOTAL = 1; - -void setup(); -void cleanup(); - -int main(int ac, char **av) -{ - struct stat stat_buf; /* stat structure buffer */ - int lc; - - tst_parse_opts(ac, av, NULL, NULL); - - setup(); - - for (lc = 0; TEST_LOOPING(lc); lc++) { - - tst_count = 0; - - /* - * Call symlink(2) to create a symlink of - * an non-existing testfile. - */ - TEST(symlink(TESTFILE, SYMFILE)); - - if (TEST_RETURN == -1) { - tst_resm(TFAIL, - "symlink(%s, %s) Failed, errno=%d : %s", - TESTFILE, SYMFILE, TEST_ERRNO, - strerror(TEST_ERRNO)); - } else { - /* - * Get the symlink file status information - * using lstat(2). - */ - if (lstat(SYMFILE, &stat_buf) < 0) { - tst_brkm(TFAIL, cleanup, "lstat(2) of " - "%s failed, error:%d", - SYMFILE, errno); - } - - /* Check if the st_mode contains a link */ - if (!S_ISLNK(stat_buf.st_mode)) { - tst_resm(TFAIL, - "symlink of %s doesn't exist", - TESTFILE); - } else { - tst_resm(TPASS, "symlink(%s, %s) " - "functionality successful", - TESTFILE, SYMFILE); - } - } - - /* Unlink the symlink file for next loop */ - SAFE_UNLINK(cleanup, SYMFILE); - tst_count++; /* incr TEST_LOOP counter */ - } - - cleanup(); - tst_exit(); - -} - -/* - * void - * setup() - performs all ONE TIME setup for this test. - * Create a temporary directory and change directory to it. - */ -void setup(void) -{ - - tst_sig(NOFORK, DEF_HANDLER, cleanup); - - /* Pause if that option was specified - * TEST_PAUSE contains the code to fork the test with the -i option. - * You want to make sure you do this before you create your temporary - * directory. - */ - TEST_PAUSE; - - tst_tmpdir(); - -} - -/* - * void - * cleanup() - performs all ONE TIME cleanup for this test at - * completion or premature exit. - * Remove the temporary directory created in the setup. - */ -void cleanup(void) -{ - - tst_rmdir(); - -} diff --git a/testcases/kernel/syscalls/timerfd/.gitignore b/testcases/kernel/syscalls/timerfd/.gitignore index ef388685d..ca6cbb1f4 100644 --- a/testcases/kernel/syscalls/timerfd/.gitignore +++ b/testcases/kernel/syscalls/timerfd/.gitignore @@ -1,6 +1,5 @@ /timerfd01 /timerfd02 -/timerfd03 /timerfd04 /timerfd_create01 /timerfd_gettime01 diff --git a/testcases/kernel/syscalls/timerfd/timerfd02.c b/testcases/kernel/syscalls/timerfd/timerfd02.c index 936cdbc53..3dabfb5c0 100644 --- a/testcases/kernel/syscalls/timerfd/timerfd02.c +++ b/testcases/kernel/syscalls/timerfd/timerfd02.c @@ -1,174 +1,51 @@ -/******************************************************************************/ -/* */ -/* Copyright (c) Ulrich Drepper <drepper@redhat.com> */ -/* Copyright (c) International Business Machines Corp., 2009 */ -/* */ -/* This program is free software; you can redistribute it and/or modify */ -/* it under the terms of the GNU General Public License as published by */ -/* the Free Software Foundation; either version 2 of the License, or */ -/* (at your option) any later version. */ -/* */ -/* This program is distributed in the hope that it will be useful, */ -/* but WITHOUT ANY WARRANTY; without even the implied warranty of */ -/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See */ -/* the GNU General Public License for more details. */ -/* */ -/* You should have received a copy of the GNU General Public License */ -/* along with this program; if not, write to the Free Software */ -/* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -/* */ -/******************************************************************************/ -/******************************************************************************/ -/* */ -/* File: timerfd02.c */ -/* */ -/* Description: This Program tests the new system call introduced in 2.6.27. */ -/* Ulrich´s comment as in: */ -/* http://git.kernel.org/?p=linux/kernel/git/torvalds/linux-2.6.git;a=commit;h=11fcb6c14676023d0bd437841f5dcd670e7990a0 */ -/* says: */ -/* The timerfd_create syscall already has a flags parameter. It just is */ -/* unused so far. This patch changes this by introducing the TFD_CLOEXEC */ -/* flag to set the close-on-exec flag for the returned file descriptor. A new */ -/* name TFD_CLOEXEC is introduced which in this implementation must have the */ -/* same value as O_CLOEXEC. */ -/* The following test must be adjusted for architectures other than x86 and */ -/* x86-64 and in case the syscall numbers changed. */ -/* */ -/* Usage: <for command-line> */ -/* timerfd02 [-c n] [-e][-i n] [-I x] [-p x] [-t] */ -/* where, -c n : Run n copies concurrently. */ -/* -e : Turn on errno logging. */ -/* -i n : Execute test n times. */ -/* -I x : Execute test for x seconds. */ -/* -P x : Pause for x seconds between iterations. */ -/* -t : Turn on syscall timing. */ -/* */ -/* Total Tests: 1 */ -/* */ -/* Test Name: timerfd02 */ -/* */ -/* Author: Ulrich Drepper <drepper@redhat.com> */ -/* */ -/* History: Created - Jan 08 2009 - Ulrich Drepper <drepper@redhat.com> */ -/* Ported to LTP */ -/* - Jan 08 2009 - Subrata <subrata@linux.vnet.ibm.com> */ -/******************************************************************************/ - -#include <stdio.h> -#include <time.h> -#include <unistd.h> -#include <sys/syscall.h> -#include <errno.h> - -#include "test.h" +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * Copyright (c) Ulrich Drepper <drepper@redhat.com> + * Copyright (c) International Business Machines Corp., 2009 + * Copyright (C) 2023 SUSE LLC Andrea Cervesato <andrea.cervesato@suse.com> + */ +/*\ + * [Description] + * + * This test verifies that: + * - TFD_CLOEXEC sets the close-on-exec file status flag on the new open file + * - TFD_NONBLOCK sets the O_NONBLOCK file status flag on the new open file + */ + +#include "tst_test.h" +#include "tst_safe_timerfd.h" #include "lapi/fcntl.h" #include "lapi/syscalls.h" -#define TFD_CLOEXEC O_CLOEXEC +static int fdesc; -char *TCID = "timerfd02"; -int testno; -int TST_TOTAL = 1; +static struct test_case_t { + int flags; + int check; + int expected; +} tcases[] = { + { 0, F_GETFD, 0 }, + { TFD_CLOEXEC, F_GETFD, FD_CLOEXEC }, + { TFD_NONBLOCK, F_GETFL, O_NONBLOCK } +}; -/* Extern Global Functions */ -/******************************************************************************/ -/* */ -/* Function: cleanup */ -/* */ -/* Description: Performs all one time clean up for this test on successful */ -/* completion, premature exit or failure. Closes all temporary */ -/* files, removes all temporary directories exits the test with */ -/* appropriate return code by calling tst_exit() function. */ -/* */ -/* Input: None. */ -/* */ -/* Output: None. */ -/* */ -/* Return: On failure - Exits calling tst_exit(). Non '0' return code. */ -/* On success - Exits calling tst_exit(). With '0' return code. */ -/* */ -/******************************************************************************/ -void cleanup(void) +static void run(unsigned int i) { + struct test_case_t *tcase = &tcases[i]; - tst_rmdir(); - + TST_EXP_FD(fdesc = SAFE_TIMERFD_CREATE(CLOCK_REALTIME, tcase->flags)); + TST_EXP_EQ_LI(SAFE_FCNTL(fdesc, tcase->check) & tcase->expected, tcase->expected); + SAFE_CLOSE(fdesc); } -/* Local Functions */ -/******************************************************************************/ -/* */ -/* Function: setup */ -/* */ -/* Description: Performs all one time setup for this test. This function is */ -/* typically used to capture signals, create temporary dirs */ -/* and temporary files that may be used in the course of this */ -/* test. */ -/* */ -/* Input: None. */ -/* */ -/* Output: None. */ -/* */ -/* Return: On failure - Exits by calling cleanup(). */ -/* On success - returns 0. */ -/* */ -/******************************************************************************/ -void setup(void) +static void cleanup(void) { - /* Capture signals if any */ - /* Create temporary directories */ - TEST_PAUSE; - tst_tmpdir(); + if (fcntl(fdesc, F_GETFD) != -1) + SAFE_CLOSE(fdesc); } -int main(int argc, char *argv[]) -{ - int fd, coe; - int lc; - - tst_parse_opts(argc, argv, NULL, NULL); - setup(); - - for (lc = 0; TEST_LOOPING(lc); ++lc) { - tst_count = 0; - for (testno = 0; testno < TST_TOTAL; ++testno) { - fd = tst_syscall(__NR_timerfd_create, - CLOCK_REALTIME, 0); - if (fd == -1) { - tst_brkm(TFAIL, cleanup, - "timerfd_create(0) failed"); - } - coe = fcntl(fd, F_GETFD); - if (coe == -1) { - tst_brkm(TBROK, cleanup, "fcntl failed"); - } - if (coe & FD_CLOEXEC) { - tst_brkm(TFAIL, - cleanup, - "timerfd_create(0) set close-on-exec flag"); - } - close(fd); - - fd = tst_syscall(__NR_timerfd_create, CLOCK_REALTIME, - TFD_CLOEXEC); - if (fd == -1) { - tst_brkm(TFAIL, - cleanup, - "timerfd_create(TFD_CLOEXEC) failed"); - } - coe = fcntl(fd, F_GETFD); - if (coe == -1) { - tst_brkm(TBROK, cleanup, "fcntl failed"); - } - if ((coe & FD_CLOEXEC) == 0) { - tst_brkm(TFAIL, - cleanup, - "timerfd_create(TFD_CLOEXEC) set close-on-exec flag"); - } - close(fd); - tst_resm(TPASS, "timerfd_create(TFD_CLOEXEC) Passed"); - cleanup(); - } - } - tst_exit(); -} +static struct tst_test test = { + .test = run, + .tcnt = ARRAY_SIZE(tcases), + .cleanup = cleanup, +}; diff --git a/testcases/kernel/syscalls/timerfd/timerfd03.c b/testcases/kernel/syscalls/timerfd/timerfd03.c deleted file mode 100644 index 89dec325f..000000000 --- a/testcases/kernel/syscalls/timerfd/timerfd03.c +++ /dev/null @@ -1,170 +0,0 @@ -/******************************************************************************/ -/* */ -/* Copyright (c) Ulrich Drepper <drepper@redhat.com> */ -/* Copyright (c) International Business Machines Corp., 2009 */ -/* */ -/* This program is free software; you can redistribute it and/or modify */ -/* it under the terms of the GNU General Public License as published by */ -/* the Free Software Foundation; either version 2 of the License, or */ -/* (at your option) any later version. */ -/* */ -/* This program is distributed in the hope that it will be useful, */ -/* but WITHOUT ANY WARRANTY; without even the implied warranty of */ -/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See */ -/* the GNU General Public License for more details. */ -/* */ -/* You should have received a copy of the GNU General Public License */ -/* along with this program; if not, write to the Free Software */ -/* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -/* */ -/******************************************************************************/ -/******************************************************************************/ -/* */ -/* File: timerfd03.c */ -/* */ -/* Description: This Program tests the new system call introduced in 2.6.27. */ -/* Ulrich´s comment as in: */ -/* http://git.kernel.org/?p=linux/kernel/git/torvalds/linux-2.6.git;a=commit;h=6b1ef0e60d42f2fdaec26baee8327eb156347b4f */ -/* which says: */ -/* This patch adds support for the TFD_NONBLOCK flag to timerfd_create. The */ -/* additional changes needed are minimal. The following test must be adjusted */ -/* for architectures other than x86 and x86-64 and in case the syscall numbers*/ -/* changed. */ -/* */ -/* Usage: <for command-line> */ -/* timerfd03 [-c n] [-e][-i n] [-I x] [-p x] [-t] */ -/* where, -c n : Run n copies concurrently. */ -/* -e : Turn on errno logging. */ -/* -i n : Execute test n times. */ -/* -I x : Execute test for x seconds. */ -/* -P x : Pause for x seconds between iterations. */ -/* -t : Turn on syscall timing. */ -/* */ -/* Total Tests: 1 */ -/* */ -/* Test Name: timerfd03 */ -/* */ -/* Author: Ulrich Drepper <drepper@redhat.com> */ -/* */ -/* History: Created - Jan 13 2009 - Ulrich Drepper <drepper@redhat.com> */ -/* Ported to LTP */ -/* - Jan 13 2009 - Subrata <subrata@linux.vnet.ibm.com> */ -/******************************************************************************/ -#include <stdio.h> -#include <time.h> -#include <unistd.h> -#include <sys/syscall.h> -#include <errno.h> - -#include "test.h" -#include "lapi/fcntl.h" -#include "lapi/syscalls.h" - -#define TFD_NONBLOCK O_NONBLOCK - -char *TCID = "timerfd03"; -int testno; -int TST_TOTAL = 1; - -/* Extern Global Functions */ -/******************************************************************************/ -/* */ -/* Function: cleanup */ -/* */ -/* Description: Performs all one time clean up for this test on successful */ -/* completion, premature exit or failure. Closes all temporary */ -/* files, removes all temporary directories exits the test with */ -/* appropriate return code by calling tst_exit() function. */ -/* */ -/* Input: None. */ -/* */ -/* Output: None. */ -/* */ -/* Return: On failure - Exits calling tst_exit(). Non '0' return code. */ -/* On success - Exits calling tst_exit(). With '0' return code. */ -/* */ -/******************************************************************************/ -void cleanup(void) -{ - - tst_rmdir(); - -} - -/* Local Functions */ -/******************************************************************************/ -/* */ -/* Function: setup */ -/* */ -/* Description: Performs all one time setup for this test. This function is */ -/* typically used to capture signals, create temporary dirs */ -/* and temporary files that may be used in the course of this */ -/* test. */ -/* */ -/* Input: None. */ -/* */ -/* Output: None. */ -/* */ -/* Return: On failure - Exits by calling cleanup(). */ -/* On success - returns 0. */ -/* */ -/******************************************************************************/ -void setup(void) -{ - /* Capture signals if any */ - /* Create temporary directories */ - TEST_PAUSE; - tst_tmpdir(); -} - -int main(int argc, char *argv[]) -{ - int fd, fl; - int lc; - - tst_parse_opts(argc, argv, NULL, NULL); - setup(); - - for (lc = 0; TEST_LOOPING(lc); ++lc) { - tst_count = 0; - for (testno = 0; testno < TST_TOTAL; ++testno) { - fd = tst_syscall(__NR_timerfd_create, - CLOCK_REALTIME, 0); - if (fd == -1) { - tst_brkm(TFAIL, cleanup, - "timerfd_create(0) failed"); - } - fl = fcntl(fd, F_GETFL); - if (fl == -1) { - tst_brkm(TBROK, cleanup, "fcntl failed"); - } - if (fl & O_NONBLOCK) { - tst_brkm(TFAIL, - cleanup, - "timerfd_create(0) set non-blocking mode"); - } - close(fd); - - fd = tst_syscall(__NR_timerfd_create, CLOCK_REALTIME, - TFD_NONBLOCK); - if (fd == -1) { - tst_brkm(TFAIL, - cleanup, - "timerfd_create(TFD_NONBLOCK) failed"); - } - fl = fcntl(fd, F_GETFL); - if (fl == -1) { - tst_brkm(TBROK, cleanup, "fcntl failed"); - } - if ((fl & O_NONBLOCK) == 0) { - tst_brkm(TFAIL, - cleanup, - "timerfd_create(TFD_NONBLOCK) set non-blocking mode"); - } - close(fd); - tst_resm(TPASS, "timerfd_create(TFD_NONBLOCK) PASSED"); - cleanup(); - } - } - tst_exit(); -} diff --git a/testcases/kernel/syscalls/umount/umount01.c b/testcases/kernel/syscalls/umount/umount01.c index d05296dce..264c8f7d7 100644 --- a/testcases/kernel/syscalls/umount/umount01.c +++ b/testcases/kernel/syscalls/umount/umount01.c @@ -2,12 +2,15 @@ /* * Copyright (c) Wipro Technologies Ltd, 2002. All Rights Reserved. * Author: Nirmala Devi Dhanasekar <nirmala.devi@wipro.com> + * Copyright (c) Linux Test Project, 2002-2023 + */ + +/*\ + * [Description] * - * Phase I test for the umount(2) system call. - * It is intended to provide a limited exposure of the system call. + * Check the basic functionality of the umount(2) system call. */ -#include <errno.h> #include <sys/mount.h> #include "tst_test.h" @@ -23,7 +26,7 @@ static void verify_umount(void) mount_flag = 1; } - TEST(umount(MNTPOINT)); + TST_EXP_PASS(umount(MNTPOINT)); if (TST_RET != 0 && TST_ERR == EBUSY) { tst_res(TINFO, "umount() Failed with EBUSY " @@ -31,12 +34,6 @@ static void verify_umount(void) "is probing newly mounted dirs"); } - if (TST_RET != 0) { - tst_res(TFAIL | TTERRNO, "umount() Failed"); - return; - } - - tst_res(TPASS, "umount() Passed"); mount_flag = 0; } diff --git a/testcases/kernel/syscalls/umount/umount02.c b/testcases/kernel/syscalls/umount/umount02.c index 34a38c998..acc35e8a4 100644 --- a/testcases/kernel/syscalls/umount/umount02.c +++ b/testcases/kernel/syscalls/umount/umount02.c @@ -2,20 +2,24 @@ /* * Copyright (c) Wipro Technologies Ltd, 2002. All Rights Reserved. * Copyright (c) 2014 Cyril Hrubis <chrubis@suse.cz> + * Copyright (c) Linux Test Project, 2002-2023 * Author: Nirmala Devi Dhanasekar <nirmala.devi@wipro.com> + */ + +/*\ + * [Description] * * Check for basic errors returned by umount(2) system call. * * Verify that umount(2) returns -1 and sets errno to - * 1) EBUSY if it cannot be umounted, because dir is still busy. - * 2) EFAULT if specialfile or device file points to invalid address space. - * 3) ENOENT if pathname was empty or has a nonexistent component. - * 4) EINVAL if specialfile or device is invalid or not a mount point. - * 5) ENAMETOOLONG if pathname was longer than MAXPATHLEN. + * + * 1. EBUSY if it cannot be umounted, because dir is still busy. + * 2. EFAULT if specialfile or device file points to invalid address space. + * 3. ENOENT if pathname was empty or has a nonexistent component. + * 4. EINVAL if specialfile or device is invalid or not a mount point. + * 5. ENAMETOOLONG if pathname was longer than MAXPATHLEN. */ -#include <errno.h> -#include <string.h> #include <sys/mount.h> #include "tst_test.h" @@ -41,21 +45,7 @@ static void verify_umount(unsigned int n) { struct tcase *tc = &tcases[n]; - TEST(umount(tc->mntpoint)); - - if (TST_RET != -1) { - tst_res(TFAIL, "umount() succeeds unexpectedly"); - return; - } - - if (tc->exp_errno != TST_ERR) { - tst_res(TFAIL | TTERRNO, "umount() should fail with %s", - tst_strerrno(tc->exp_errno)); - return; - } - - tst_res(TPASS | TTERRNO, "umount() fails as expected: %s", - tc->err_desc); + TST_EXP_FAIL(umount(tc->mntpoint), tc->exp_errno); } static void setup(void) diff --git a/testcases/kernel/syscalls/umount/umount03.c b/testcases/kernel/syscalls/umount/umount03.c index 1cef06fa1..3260312f7 100644 --- a/testcases/kernel/syscalls/umount/umount03.c +++ b/testcases/kernel/syscalls/umount/umount03.c @@ -1,17 +1,19 @@ // SPDX-License-Identifier: GPL-2.0-or-later /* * Copyright (c) Wipro Technologies Ltd, 2002. All Rights Reserved. + * Copyright (c) Linux Test Project, 2002-2023 * Author: Nirmala Devi Dhanasekar <nirmala.devi@wipro.com> + */ + +/*\ + * [Description] * - * Verify that umount(2) returns -1 and sets errno to EPERM if the user + * Verify that umount(2) returns -1 and sets errno to EPERM if the user * is not the super-user. */ -#include <errno.h> #include <pwd.h> #include <sys/mount.h> -#include <sys/types.h> -#include <unistd.h> #include "tst_test.h" #define MNTPOINT "mntpoint" @@ -20,19 +22,7 @@ static int mount_flag; static void verify_umount(void) { - TEST(umount(MNTPOINT)); - - if (TST_RET != -1) { - tst_res(TFAIL, "umount() succeeds unexpectedly"); - return; - } - - if (TST_ERR != EPERM) { - tst_res(TFAIL | TTERRNO, "umount() should fail with EPERM"); - return; - } - - tst_res(TPASS | TTERRNO, "umount() fails as expected"); + TST_EXP_FAIL(umount(MNTPOINT), EPERM); } static void setup(void) diff --git a/testcases/kernel/syscalls/utils/compat_16.mk b/testcases/kernel/syscalls/utils/compat_16.mk index e81a00c40..71a8cc56f 100644 --- a/testcases/kernel/syscalls/utils/compat_16.mk +++ b/testcases/kernel/syscalls/utils/compat_16.mk @@ -60,7 +60,7 @@ MAKE_TARGETS += $(addsuffix _16,$(MAKE_TARGETS)) # (no .h file, no TST_USE_NEWER64_SYSCALL def). DEF_16 := TST_USE_COMPAT16_SYSCALL -ifneq ($(COMPAT_TST_16_H),1) +ifeq ($(USE_LEGACY_COMPAT_16_H),1) COMPAT_16_H := $(abs_srcdir)/../utils/compat_16.h else COMPAT_16_H := $(abs_srcdir)/../utils/compat_tst_16.h diff --git a/testcases/kernel/syscalls/wait4/wait402.c b/testcases/kernel/syscalls/wait4/wait402.c index 39b170253..36fba7378 100644 --- a/testcases/kernel/syscalls/wait4/wait402.c +++ b/testcases/kernel/syscalls/wait4/wait402.c @@ -1,101 +1,36 @@ +// SPDX-License-Identifier: GPL-2.0-or-later /* - * - * Copyright (c) International Business Machines Corp., 2001 - * Copyright (c) 2012 Cyril Hrubis <chrubis@suse.cz> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See - * the GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * Copyright (c) International Business Machines Corp., 2001 + * Copyright (c) 2012 Cyril Hrubis <chrubis@suse.cz> + * Copyright (c) Linux Test Project, 2001-2015 + * Copyright (c) 2023 Ioannis Bonatakis <ybonatakis@suse.com> */ - /* - * wait402 - check for ECHILD errno when using an illegal pid value - */ - -#include "test.h" +/*\ + * [Description] + * + * Check for ECHILD errno when call wait4(2) with an invalid pid value. + */ -#include <errno.h> -#define _USE_BSD -#include <sys/types.h> -#include <sys/resource.h> +#include "tst_test.h" #include <sys/wait.h> -#include <stdlib.h> -#include <string.h> - -char *TCID = "wait402"; -int TST_TOTAL = 1; - -static void cleanup(void); -static void setup(void); - -static long get_pid_max(void) -{ - long pid_max; - - SAFE_FILE_SCANF(NULL, "/proc/sys/kernel/pid_max", "%ld", &pid_max); - return pid_max; -} +static pid_t pid_max; -int main(int ac, char **av) +static void run(void) { - int lc; - pid_t epid = get_pid_max() + 1; - - int status = 1; + int status; struct rusage rusage; - tst_parse_opts(ac, av, NULL, NULL); - - setup(); - - for (lc = 0; TEST_LOOPING(lc); lc++) { - tst_count = 0; - - TEST(wait4(epid, &status, 0, &rusage)); - - if (TEST_RETURN == 0) { - tst_brkm(TFAIL, cleanup, - "call failed to produce expected error - errno = %d - %s", - TEST_ERRNO, strerror(TEST_ERRNO)); - } - - switch (TEST_ERRNO) { - case ECHILD: - tst_resm(TPASS, - "received expected failure - errno = %d - %s", - TEST_ERRNO, strerror(TEST_ERRNO)); - break; - default: - tst_brkm(TFAIL, cleanup, - "call failed to produce expected " - "error - errno = %d - %s", TEST_ERRNO, - strerror(TEST_ERRNO)); - } - } - - cleanup(); - tst_exit(); + TST_EXP_FAIL2(wait4(pid_max + 1, &status, 0, &rusage), ECHILD); } static void setup(void) { - - tst_sig(FORK, DEF_HANDLER, cleanup); - - TEST_PAUSE; + SAFE_FILE_SCANF("/proc/sys/kernel/pid_max", "%d\n", &pid_max); } -static void cleanup(void) -{ -} +static struct tst_test test = { + .test_all = run, + .setup = setup, +}; diff --git a/testcases/kernel/syscalls/writev/writev07.c b/testcases/kernel/syscalls/writev/writev07.c index b725f08db..3dda1caa4 100644 --- a/testcases/kernel/syscalls/writev/writev07.c +++ b/testcases/kernel/syscalls/writev/writev07.c @@ -4,20 +4,26 @@ * Copyright (c) Linux Test Project, 2016 */ -/* - * Test Description: - * Verify writev() behaviour with partially valid iovec list. - * Kernel <4.8 used to shorten write up to first bad invalid - * iovec. Starting with 4.8, a writev with short data (under - * page size) is likely to get shorten to 0 bytes and return - * EFAULT. +/*\ + * [Description] + * + * Verify writev() behaviour with partially valid iovec list. + * Kernel <4.8 used to shorten write up to first bad invalid + * iovec. Starting with 4.8, a writev with short data (under + * page size) is likely to get shorten to 0 bytes and return + * EFAULT. + * + * This test doesn't make assumptions how much will write get + * shortened. It only tests that file content/offset after + * syscall corresponds to return value of writev(). * - * This test doesn't make assumptions how much will write get - * shortened. It only tests that file content/offset after - * syscall corresponds to return value of writev(). + * See: [RFC] writev() semantics with invalid iovec in the middle + * https://marc.info/?l=linux-kernel&m=147388891614289&w=2. * - * See: [RFC] writev() semantics with invalid iovec in the middle - * https://marc.info/?l=linux-kernel&m=147388891614289&w=2 + * This is also regression test for kernel commits: + * + * * 20c64ec83a9f ("iomap: fix a regression for partial write errors") + * * 3ac974796e5d ("iomap: fix short copy in iomap_write_iter()") */ #include <errno.h> @@ -138,4 +144,9 @@ static struct tst_test test = { .needs_tmpdir = 1, .setup = setup, .test_all = test_writev, + .tags = (const struct tst_tag[]) { + {"linux-git", "20c64ec83a9f"}, + {"linux-git", "3ac974796e5d"}, + {}, + } }; |